This commit is contained in:
154
src/data/sceneEncounterPreviews.test.ts
Normal file
154
src/data/sceneEncounterPreviews.test.ts
Normal file
@@ -0,0 +1,154 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import {
|
||||
AnimationState,
|
||||
type Character,
|
||||
type Encounter,
|
||||
type GameState,
|
||||
WorldType,
|
||||
} from '../types';
|
||||
import { getMonsterPresetsByWorld } from './hostileNpcPresets';
|
||||
import { createSceneHostileNpc } from './hostileNpcs';
|
||||
import { buildInitialNpcState } from './npcInteractions';
|
||||
import {
|
||||
hasAutoBattleSceneEncounter,
|
||||
resolveSceneEncounterPreview,
|
||||
} from './sceneEncounterPreviews';
|
||||
|
||||
function createCharacter(): Character {
|
||||
return {
|
||||
id: 'hero',
|
||||
name: 'Hero',
|
||||
title: 'Wanderer',
|
||||
description: 'A reliable test hero.',
|
||||
backstory: 'Travels the land.',
|
||||
avatar: '/hero.png',
|
||||
portrait: '/hero-portrait.png',
|
||||
assetFolder: 'hero',
|
||||
assetVariant: 'default',
|
||||
attributes: {
|
||||
strength: 10,
|
||||
agility: 9,
|
||||
intelligence: 8,
|
||||
spirit: 7,
|
||||
},
|
||||
personality: 'steady',
|
||||
skills: [],
|
||||
adventureOpenings: {},
|
||||
};
|
||||
}
|
||||
|
||||
function createEncounter(): Encounter {
|
||||
return {
|
||||
id: 'npc-trader',
|
||||
kind: 'npc',
|
||||
npcName: 'Trader Lin',
|
||||
npcDescription: 'A traveling merchant.',
|
||||
npcAvatar: 'T',
|
||||
context: 'merchant',
|
||||
initialAffinity: 12,
|
||||
hostile: false,
|
||||
};
|
||||
}
|
||||
|
||||
function createBaseState(): GameState {
|
||||
const encounter = createEncounter();
|
||||
|
||||
return {
|
||||
worldType: WorldType.WUXIA,
|
||||
customWorldProfile: null,
|
||||
playerCharacter: createCharacter(),
|
||||
runtimeStats: {
|
||||
playTimeMs: 0,
|
||||
lastPlayTickAt: null,
|
||||
hostileNpcsDefeated: 0,
|
||||
questsAccepted: 0,
|
||||
itemsUsed: 0,
|
||||
scenesTraveled: 0,
|
||||
},
|
||||
currentScene: 'Story',
|
||||
storyHistory: [],
|
||||
characterChats: {},
|
||||
animationState: AnimationState.IDLE,
|
||||
currentEncounter: encounter,
|
||||
npcInteractionActive: false,
|
||||
currentScenePreset: {
|
||||
id: 'scene-1',
|
||||
name: 'Trail',
|
||||
description: 'A mountain trail.',
|
||||
imageSrc: '/trail.png',
|
||||
connectedSceneIds: [],
|
||||
npcs: [],
|
||||
treasureHints: [],
|
||||
},
|
||||
sceneHostileNpcs: [],
|
||||
playerX: 0,
|
||||
playerOffsetY: 0,
|
||||
playerFacing: 'right',
|
||||
playerActionMode: 'idle',
|
||||
scrollWorld: false,
|
||||
inBattle: false,
|
||||
playerHp: 100,
|
||||
playerMaxHp: 100,
|
||||
playerMana: 20,
|
||||
playerMaxMana: 20,
|
||||
playerSkillCooldowns: {},
|
||||
activeCombatEffects: [],
|
||||
playerCurrency: 0,
|
||||
playerInventory: [],
|
||||
playerEquipment: {
|
||||
weapon: null,
|
||||
armor: null,
|
||||
relic: null,
|
||||
},
|
||||
npcStates: {
|
||||
[encounter.id!]: {
|
||||
...buildInitialNpcState(encounter, WorldType.WUXIA),
|
||||
affinity: -5,
|
||||
},
|
||||
},
|
||||
quests: [],
|
||||
roster: [],
|
||||
companions: [],
|
||||
currentBattleNpcId: null,
|
||||
currentNpcBattleMode: null,
|
||||
currentNpcBattleOutcome: null,
|
||||
sparReturnEncounter: null,
|
||||
sparPlayerHpBefore: null,
|
||||
sparPlayerMaxHpBefore: null,
|
||||
sparStoryHistoryBefore: null,
|
||||
};
|
||||
}
|
||||
|
||||
describe('sceneEncounterPreviews', () => {
|
||||
it('treats negative-affinity npc encounters as immediate battles', () => {
|
||||
const state = createBaseState();
|
||||
|
||||
expect(hasAutoBattleSceneEncounter(state)).toBe(true);
|
||||
|
||||
const resolved = resolveSceneEncounterPreview(state);
|
||||
|
||||
expect(resolved.inBattle).toBe(true);
|
||||
expect(resolved.currentEncounter).toBeNull();
|
||||
expect(resolved.currentBattleNpcId).toBe('npc-trader');
|
||||
expect(resolved.currentNpcBattleMode).toBe('fight');
|
||||
expect(resolved.sceneHostileNpcs).toHaveLength(1);
|
||||
expect(resolved.sceneHostileNpcs[0]?.encounter?.npcName).toBe('Trader Lin');
|
||||
});
|
||||
|
||||
it('attaches npc encounter metadata to regular monsters', () => {
|
||||
const monsterId = getMonsterPresetsByWorld(WorldType.WUXIA)[0]?.id;
|
||||
if (!monsterId) {
|
||||
throw new Error('Expected at least one monster preset');
|
||||
}
|
||||
|
||||
const monster = createSceneHostileNpc(WorldType.WUXIA, monsterId);
|
||||
|
||||
expect(monster).not.toBeNull();
|
||||
expect(monster?.encounter?.kind).toBe('npc');
|
||||
expect(monster?.encounter?.monsterPresetId).toBe(monsterId);
|
||||
expect(monster?.encounter?.hostile).toBe(true);
|
||||
expect(monster?.encounter?.initialAffinity).toBe(-40);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user