Rework story engine flow and reorganize project docs
Some checks failed
CI / verify (push) Has been cancelled
Some checks failed
CI / verify (push) Has been cancelled
This commit is contained in:
@@ -16,9 +16,9 @@ import {
|
||||
} from '../../data/characterPresets';
|
||||
import { getEquipmentBonuses } from '../../data/equipmentEffects';
|
||||
import {
|
||||
getClosestMonster,
|
||||
getClosestHostileNpc,
|
||||
getFacingTowardPlayer,
|
||||
settleMonsterAnimations,
|
||||
settleHostileNpcAnimations,
|
||||
} from '../../data/hostileNpcs';
|
||||
import { getFunctionEffect } from '../../data/stateFunctions';
|
||||
import type {
|
||||
@@ -27,7 +27,7 @@ import type {
|
||||
CombatDelivery,
|
||||
CompanionState,
|
||||
GameState,
|
||||
SceneMonster,
|
||||
SceneHostileNpc,
|
||||
StoryOption,
|
||||
} from '../../types';
|
||||
import {
|
||||
@@ -209,7 +209,7 @@ function buildCombatTurnOrder(
|
||||
});
|
||||
});
|
||||
|
||||
state.sceneMonsters.forEach(monster => {
|
||||
state.sceneHostileNpcs.forEach(monster => {
|
||||
actorTimings.set(getCombatActorKey('monster', monster.id), {
|
||||
actor: 'monster',
|
||||
id: monster.id,
|
||||
@@ -226,7 +226,7 @@ function buildCombatTurnOrder(
|
||||
if (item.actor === 'companion') {
|
||||
return state.companions.some(companion => companion.npcId === item.id && isCompanionAlive(companion));
|
||||
}
|
||||
return state.sceneMonsters.some(monster => monster.id === item.id && monster.hp > 0);
|
||||
return state.sceneHostileNpcs.some(monster => monster.id === item.id && monster.hp > 0);
|
||||
});
|
||||
|
||||
if (availableActors.length === 0) break;
|
||||
@@ -278,7 +278,7 @@ function tickSkillCooldowns(character: Character, cooldowns: Record<string, numb
|
||||
);
|
||||
}
|
||||
|
||||
export function getFacingForPlayer(playerX: number, monster: SceneMonster | null) {
|
||||
export function getFacingForPlayer(playerX: number, monster: SceneHostileNpc | null) {
|
||||
if (!monster) return 'right' as const;
|
||||
return monster.xMeters >= playerX ? 'right' : 'left';
|
||||
}
|
||||
@@ -295,8 +295,8 @@ export function getSkillStrikeX(skill: CharacterSkillDefinition, attackerX: numb
|
||||
: getMeleeStrikeX(attackerX, defenderX);
|
||||
}
|
||||
|
||||
export function resetCombatPresentation(monsters: SceneMonster[], playerX: number) {
|
||||
return settleMonsterAnimations(monsters).map(monster => ({
|
||||
export function resetCombatPresentation(monsters: SceneHostileNpc[], playerX: number) {
|
||||
return settleHostileNpcAnimations(monsters).map(monster => ({
|
||||
...monster,
|
||||
facing: getFacingTowardPlayer(monster.xMeters, playerX),
|
||||
characterAnimation: undefined,
|
||||
@@ -349,18 +349,12 @@ export function buildBattlePlan({
|
||||
resetStageMs: number;
|
||||
minTurnCount: number;
|
||||
}): BattlePlan {
|
||||
const resolvedSceneMonsters =
|
||||
state.sceneMonsters.length > 0
|
||||
? state.sceneMonsters
|
||||
: (state.sceneHostileNpcs ?? []);
|
||||
const battleState: GameState = {
|
||||
...state,
|
||||
sceneMonsters: resolvedSceneMonsters,
|
||||
sceneHostileNpcs: resolvedSceneMonsters,
|
||||
};
|
||||
const targetMonster = getClosestMonster(
|
||||
const targetMonster = getClosestHostileNpc(
|
||||
battleState.playerX,
|
||||
battleState.sceneMonsters,
|
||||
battleState.sceneHostileNpcs,
|
||||
);
|
||||
if (!targetMonster) {
|
||||
return {
|
||||
@@ -369,7 +363,6 @@ export function buildBattlePlan({
|
||||
finalState: {
|
||||
...battleState,
|
||||
inBattle: false,
|
||||
sceneMonsters: [],
|
||||
sceneHostileNpcs: [],
|
||||
companions: resetCompanionCombatPresentation(state.companions),
|
||||
animationState: AnimationState.IDLE,
|
||||
@@ -398,7 +391,7 @@ export function buildBattlePlan({
|
||||
cooldowns: Record<string, number>;
|
||||
}>();
|
||||
|
||||
battleState.sceneMonsters.forEach(monster => {
|
||||
battleState.sceneHostileNpcs.forEach(monster => {
|
||||
const npcCharacterId = monster.encounter?.characterId ?? null;
|
||||
const npcCharacter = npcCharacterId ? getCharacterById(npcCharacterId) : null;
|
||||
if (!npcCharacter) return;
|
||||
@@ -413,12 +406,8 @@ export function buildBattlePlan({
|
||||
let simulatedState: GameState = {
|
||||
...applyRecoveryEffectToState(battleState, character, option.functionId),
|
||||
companions: resetCompanionCombatPresentation(battleState.companions),
|
||||
sceneMonsters: resetCombatPresentation(
|
||||
battleState.sceneMonsters,
|
||||
battleState.playerX,
|
||||
),
|
||||
sceneHostileNpcs: resetCombatPresentation(
|
||||
battleState.sceneMonsters,
|
||||
battleState.sceneHostileNpcs,
|
||||
battleState.playerX,
|
||||
),
|
||||
activeCombatEffects: [],
|
||||
@@ -429,7 +418,7 @@ export function buildBattlePlan({
|
||||
const turns: BattlePlanStep[] = [];
|
||||
|
||||
for (const [turnIndex, turn] of turnOrder.entries()) {
|
||||
const currentTarget = getClosestMonster(simulatedState.playerX, simulatedState.sceneMonsters);
|
||||
const currentTarget = getClosestHostileNpc(simulatedState.playerX, simulatedState.sceneHostileNpcs);
|
||||
if (!currentTarget) break;
|
||||
|
||||
if (turn.actor === 'player') {
|
||||
@@ -465,7 +454,7 @@ export function buildBattlePlan({
|
||||
const damage = isNpcSpar ? 1 : damageResult!.damage;
|
||||
const wouldEndSpar = isNpcSpar && currentTarget.hp - damage <= 1;
|
||||
|
||||
const resolvedMonsters = simulatedState.sceneMonsters.map(monster =>
|
||||
const resolvedMonsters = simulatedState.sceneHostileNpcs.map(monster =>
|
||||
monster.id === currentTarget.id
|
||||
? {
|
||||
...monster,
|
||||
@@ -479,7 +468,7 @@ export function buildBattlePlan({
|
||||
const remainingMonsters = defeated
|
||||
? resolvedMonsters.filter(monster => !(monster.id === currentTarget.id && monster.hp <= 0))
|
||||
: resolvedMonsters;
|
||||
const nextTarget = getClosestMonster(originalPlayerX, remainingMonsters);
|
||||
const nextTarget = getClosestHostileNpc(originalPlayerX, remainingMonsters);
|
||||
|
||||
simulatedState = {
|
||||
...simulatedState,
|
||||
@@ -494,7 +483,7 @@ export function buildBattlePlan({
|
||||
activeCombatEffects: [],
|
||||
playerMana: Math.max(0, simulatedState.playerMana - selectedSkill.manaCost),
|
||||
playerSkillCooldowns: appliedCooldowns,
|
||||
sceneMonsters: remainingMonsters.map(monster => ({
|
||||
sceneHostileNpcs: remainingMonsters.map(monster => ({
|
||||
...monster,
|
||||
characterAnimation: undefined,
|
||||
combatMode: undefined,
|
||||
@@ -537,7 +526,7 @@ export function buildBattlePlan({
|
||||
if (!companionCharacter) continue;
|
||||
|
||||
const companionX = getCompanionAnchorX(simulatedState.playerX, simulatedState.companions, companion.npcId);
|
||||
const targetMonster = getClosestMonster(companionX, simulatedState.sceneMonsters);
|
||||
const targetMonster = getClosestHostileNpc(companionX, simulatedState.sceneHostileNpcs);
|
||||
if (!targetMonster) break;
|
||||
|
||||
const cooledDown = tickSkillCooldowns(companionCharacter, companion.skillCooldowns);
|
||||
@@ -584,7 +573,7 @@ export function buildBattlePlan({
|
||||
const damage = isNpcSpar ? 1 : damageResult!.damage;
|
||||
const wouldEndSpar = isNpcSpar && targetMonster.hp - damage <= 1;
|
||||
|
||||
const resolvedMonsters = simulatedState.sceneMonsters.map(monster =>
|
||||
const resolvedMonsters = simulatedState.sceneHostileNpcs.map(monster =>
|
||||
monster.id === targetMonster.id
|
||||
? {
|
||||
...monster,
|
||||
@@ -609,7 +598,7 @@ export function buildBattlePlan({
|
||||
skillCooldowns: appliedCooldowns,
|
||||
}),
|
||||
),
|
||||
sceneMonsters: remainingMonsters.map(monster => ({
|
||||
sceneHostileNpcs: remainingMonsters.map(monster => ({
|
||||
...monster,
|
||||
characterAnimation: undefined,
|
||||
combatMode: undefined,
|
||||
@@ -643,7 +632,7 @@ export function buildBattlePlan({
|
||||
continue;
|
||||
}
|
||||
|
||||
const actingMonster = simulatedState.sceneMonsters.find(monster => monster.id === turn.id && monster.hp > 0);
|
||||
const actingMonster = simulatedState.sceneHostileNpcs.find(monster => monster.id === turn.id && monster.hp > 0);
|
||||
if (!actingMonster) continue;
|
||||
|
||||
const randomTarget = chooseRandomPartyTarget(simulatedState);
|
||||
@@ -698,7 +687,7 @@ export function buildBattlePlan({
|
||||
simulatedState = {
|
||||
...damagedState,
|
||||
companions: resetCompanionCombatPresentation(damagedState.companions),
|
||||
sceneMonsters: simulatedState.sceneMonsters.map(monster => ({
|
||||
sceneHostileNpcs: simulatedState.sceneHostileNpcs.map(monster => ({
|
||||
...monster,
|
||||
xMeters: monster.id === actingMonster.id ? originalMonsterX : monster.xMeters,
|
||||
animation: 'idle' as const,
|
||||
@@ -753,7 +742,7 @@ export function buildBattlePlan({
|
||||
simulatedState = {
|
||||
...damagedState,
|
||||
companions: resetCompanionCombatPresentation(damagedState.companions),
|
||||
sceneMonsters: simulatedState.sceneMonsters.map(monster => ({
|
||||
sceneHostileNpcs: simulatedState.sceneHostileNpcs.map(monster => ({
|
||||
...monster,
|
||||
xMeters: monster.id === actingMonster.id ? originalMonsterX : monster.xMeters,
|
||||
animation: 'idle' as const,
|
||||
@@ -800,12 +789,8 @@ export function buildBattlePlan({
|
||||
scrollWorld: false,
|
||||
inBattle: simulatedState.currentNpcBattleOutcome === 'spar_complete'
|
||||
? false
|
||||
: simulatedState.sceneMonsters.length > 0,
|
||||
sceneMonsters: resetCombatPresentation(simulatedState.sceneMonsters, simulatedState.playerX),
|
||||
sceneHostileNpcs: resetCombatPresentation(
|
||||
simulatedState.sceneMonsters,
|
||||
simulatedState.playerX,
|
||||
),
|
||||
: simulatedState.sceneHostileNpcs.length > 0,
|
||||
sceneHostileNpcs: resetCombatPresentation(simulatedState.sceneHostileNpcs, simulatedState.playerX),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user