Add TitleBenefit model and integrate benefits into FalukantService: Introduced TitleBenefit for managing title-related advantages, including tax exemptions and office eligibility. Updated service methods to utilize these benefits for character reputation, tax distribution, and allowed office types, enhancing gameplay mechanics and user experience.

This commit is contained in:
Torsten Schulz (local)
2026-02-06 09:50:31 +01:00
parent a60c6d173c
commit c7a05c3213
8 changed files with 235 additions and 26 deletions

View File

@@ -9,6 +9,7 @@ import PromotionalGiftMood from "../../models/falukant/predefine/promotional_gif
import { sequelize } from '../sequelize.js';
import HouseType from '../../models/falukant/type/house.js';
import TitleOfNobility from "../../models/falukant/type/title_of_nobility.js";
import TitleBenefit from "../../models/falukant/type/title_benefit.js";
import PartyType from "../../models/falukant/type/party.js";
import MusicType from "../../models/falukant/type/music.js";
import BanquetteType from "../../models/falukant/type/banquette.js";
@@ -39,7 +40,8 @@ export const initializeFalukantTypes = async () => {
// Adelstitel VOR Haustypen initialisieren
await initializeFalukantTitlesOfNobility();
await initializeTitleBenefits();
await initializeFalukantHouseTypes();
await initializeFalukantPartyTypes();
await initializeFalukantMusicTypes();
@@ -1204,6 +1206,65 @@ export const initializeFalukantTitlesOfNobility = async () => {
}
};
/** Standesvorteile: tax_share, tax_exempt, office_eligibility, free_party_type, reputation_bonus */
async function initializeTitleBenefits() {
const titles = await TitleOfNobility.findAll({ attributes: ['id', 'labelTr', 'level'] });
const byLabel = new Map(titles.map(t => [t.labelTr, t]));
const benefits = [];
// tax_share: oberster Stand einer Region bekommt Steuer Titel mit hohem level (z.B. ab count)
const taxShareTitles = ['count', 'palsgrave', 'margrave', 'landgrave', 'ruler', 'elector', 'imperial-prince', 'duke', 'grand-duke', 'prince-regent', 'king'];
for (const label of taxShareTitles) {
const t = byLabel.get(label);
if (t) benefits.push({ titleId: t.id, benefitType: 'tax_share', parameters: {} });
}
// tax_exempt: z.B. noncivil, oder hohe Titel
const taxExemptTitles = ['noncivil', 'king', 'prince-regent'];
for (const label of taxExemptTitles) {
const t = byLabel.get(label);
if (t) benefits.push({ titleId: t.id, benefitType: 'tax_exempt', parameters: {} });
}
// office_eligibility: pro Titel eine Zeile mit allen erlaubten Ämtern (officeTypeNames)
const officeEligibility = [
{ label: 'assessor', titles: ['civil', 'sir', 'townlord', 'by', 'landlord', 'knight', 'baron', 'count', 'palsgrave', 'margrave', 'landgrave', 'ruler', 'elector', 'imperial-prince', 'duke', 'grand-duke', 'prince-regent', 'king'] },
{ label: 'council', titles: ['sir', 'townlord', 'by', 'landlord', 'knight', 'baron', 'count', 'palsgrave', 'margrave', 'landgrave', 'ruler', 'elector', 'imperial-prince', 'duke', 'grand-duke', 'prince-regent', 'king'] },
{ label: 'taxman', titles: ['townlord', 'by', 'landlord', 'knight', 'baron', 'count', 'palsgrave', 'margrave', 'landgrave', 'ruler', 'elector', 'imperial-prince', 'duke', 'grand-duke', 'prince-regent', 'king'] },
{ label: 'chancellor', titles: ['king'] }
];
const titleToOffices = new Map();
for (const { label: officeName, titles: allowedTitles } of officeEligibility) {
for (const label of allowedTitles) {
const t = byLabel.get(label);
if (t) {
const list = titleToOffices.get(t.id) || [];
if (!list.includes(officeName)) list.push(officeName);
titleToOffices.set(t.id, list);
}
}
}
for (const [titleId, officeTypeNames] of titleToOffices) {
benefits.push({ titleId, benefitType: 'office_eligibility', parameters: { officeTypeNames } });
}
// free_party_type: z.B. "wedding" für civil+ (partyTypeIds oder labelTr)
const freePartyTitles = ['sir', 'townlord', 'by', 'landlord', 'knight', 'baron', 'count', 'palsgrave', 'margrave', 'landgrave', 'ruler', 'elector', 'imperial-prince', 'duke', 'grand-duke', 'prince-regent', 'king'];
for (const label of freePartyTitles) {
const t = byLabel.get(label);
if (t) benefits.push({ titleId: t.id, benefitType: 'free_party_type', parameters: { partyTypeLabelTrs: ['wedding'] } });
}
// reputation_bonus: zufällig 515 % für ausgewählte Stände (hier: knight, count, duke)
const reputationBonusTitles = ['knight', 'count', 'duke'];
for (const label of reputationBonusTitles) {
const t = byLabel.get(label);
if (t) benefits.push({ titleId: t.id, benefitType: 'reputation_bonus', parameters: { minPercent: 5, maxPercent: 15 } });
}
for (const b of benefits) {
await TitleBenefit.findOrCreate({
where: { titleId: b.titleId, benefitType: b.benefitType },
defaults: { parameters: b.parameters }
});
}
console.log(`[Falukant] Standesvorteile (title_benefit) initialisiert: ${benefits.length} Einträge`);
}
const weatherTypes = [
{ tr: "sunny" },
{ tr: "cloudy" },