feat(falukant): add character visual representation and settings
All checks were successful
Deploy to production / deploy (push) Successful in 2m53s

- Introduced FalukantCharacterVisual component to display character portraits and 3D figures based on user settings.
- Updated DirectorInfo, ChurchView, PoliticsView, and other components to utilize the new character visual component.
- Added visual settings management for users, allowing selection between portrait styles and display modes (portraits, 3D, or both).
- Implemented age rules for engagement and marriage in the backend, ensuring compliance with specified age limits.
- Created a new settings view for Falukant to manage visual preferences.
- Added new images for medieval character portraits.
- Updated translations for new settings and features in multiple languages.
This commit is contained in:
Torsten Schulz (local)
2026-07-24 10:55:19 +02:00
parent c13339f771
commit 16703f467f
36 changed files with 811 additions and 49 deletions

View File

@@ -37,6 +37,18 @@ class SettingsService extends BaseService{
adult_verification_status: { datatype: 'string', setting: 'account', orderId: 910, minAge: 18 },
adult_verification_request: { datatype: 'string', setting: 'account', orderId: 911, minAge: 18 },
adult_upload_blocked: { datatype: 'bool', setting: 'account', orderId: 912, minAge: 18 },
falukantPortraitStyle: {
datatype: 'singleselect',
setting: 'falukant',
orderId: 920,
options: ['classic', 'medieval']
},
falukantFigureMode: {
datatype: 'singleselect',
setting: 'falukant',
orderId: 921,
options: ['portraits', '3d', 'both']
},
};
const definition = specialTypes[description];
if (!definition) {
@@ -59,9 +71,38 @@ class SettingsService extends BaseService{
immutable: false
}
});
if (Array.isArray(definition.options) && definition.options.length > 0) {
let orderId = 1;
for (const option of definition.options) {
await UserParamValue.findOrCreate({
where: {
userParamTypeId: paramType.id,
value: option
},
defaults: {
userParamTypeId: paramType.id,
value: option,
orderId: orderId++
}
});
}
}
return paramType;
}
async ensureSettingsGroup(type) {
const groupDefinitions = {
falukant: ['falukantPortraitStyle', 'falukantFigureMode']
};
const descriptions = groupDefinitions[type];
if (!descriptions) {
return;
}
for (const description of descriptions) {
await this.ensureSpecialUserParamType(description);
}
}
parseAdultVerificationRequest(value) {
if (!value) return null;
try {
@@ -298,6 +339,7 @@ class SettingsService extends BaseService{
}
async filterSettings(hashedUserId, type) {
await this.ensureSettingsGroup(type);
const user = await this.getUserByHashedId(hashedUserId);
const userParams = await this.getUserParams(user.id, ['birthdate', 'gender']);
let birthdate = null;