feat(falukant): add character visual representation and settings

- 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 a3f90772a7
commit 5ebcc581f9
36 changed files with 811 additions and 49 deletions

View File

@@ -27,8 +27,8 @@
</section>
<div v-if="falukantUser?.character && !falukantUser?.debtorsPrison?.inDebtorsPrison" class="imagecontainer">
<div :style="getAvatarStyle" class="avatar"></div>
<div class="house-with-character">
<div v-if="showPortraitAvatar" :style="getAvatarStyle" class="avatar"></div>
<div v-if="showCharacterFigure3d" class="house-with-character">
<div :style="getHouseStyle" class="house"></div>
<div class="character-foreground">
<Character3D
@@ -336,6 +336,13 @@ import Character3D from '@/components/Character3D.vue';
import apiClient from '@/utils/axios.js';
import { showError, showSuccess } from '@/utils/feedback.js';
import { mapState } from 'vuex';
import {
FALUKANT_VISUAL_DEFAULTS,
loadFalukantVisualSettings,
resolveFalukantPortraitAtlas,
showFalukant3dFigures,
showFalukantPortraits,
} from '@/utils/falukantVisualSettings.js';
const AVATAR_POSITIONS = {
male: {
@@ -396,14 +403,21 @@ export default {
potentialHeirs: [],
loadingHeirs: false,
pendingOverviewRefresh: null,
visualSettings: { ...FALUKANT_VISUAL_DEFAULTS },
};
},
computed: {
...mapState(['socket', 'daemonSocket', 'user']),
showPortraitAvatar() {
return showFalukantPortraits(this.visualSettings.figureMode);
},
showCharacterFigure3d() {
return showFalukant3dFigures(this.visualSettings.figureMode);
},
getAvatarStyle() {
if (!this.falukantUser || !this.falukantUser.character) return {};
const { gender, age } = this.falukantUser.character;
const imageUrl = `/images/falukant/avatar/${gender}.png`;
const imageUrl = resolveFalukantPortraitAtlas(gender, this.visualSettings.portraitStyle);
const ageGroup = this.getAgeGroup(age);
const genderData = AVATAR_POSITIONS[gender] || {};
const position = genderData.positions?.[ageGroup] || { x: 0, y: 0 };
@@ -560,6 +574,7 @@ export default {
},
},
async mounted() {
this.visualSettings = await loadFalukantVisualSettings(this.user?.id);
await this.fetchFalukantUser();
if (!this.falukantUser?.character) {
await this.fetchPotentialHeirs();