143 lines
5.8 KiB
TypeScript
143 lines
5.8 KiB
TypeScript
import type { GeneralTriggerState } from '@sammo-ts/logic/domain/entities.js';
|
|
import { compileCrewTypeCatalog } from '@sammo-ts/logic/crewType/catalog.js';
|
|
import { createCrewTypeWarTriggerRegistry } from '@sammo-ts/logic/war/crewTypeTriggers.js';
|
|
import { createInheritBuffModules } from '@sammo-ts/logic/inheritance/inheritBuff.js';
|
|
import {
|
|
createItemActionModules,
|
|
createItemModuleRegistry,
|
|
ITEM_KEYS,
|
|
loadItemModules,
|
|
type ItemModule,
|
|
} from '@sammo-ts/logic/items/index.js';
|
|
import type { UnitSetDefinition } from '@sammo-ts/logic/world/types.js';
|
|
import type { GeneralActionModule } from './general.js';
|
|
import type { WarActionModule } from '@sammo-ts/logic/war/actions.js';
|
|
import { createOfficerLevelActionModules } from './officerLevel.js';
|
|
import {
|
|
createTraitCatalog,
|
|
DOMESTIC_TRAIT_KEYS,
|
|
EVENT_DOMESTIC_TRAIT_KEYS,
|
|
loadDomesticTraitModules,
|
|
loadEventDomesticTraitModules,
|
|
loadNationTraitModules,
|
|
loadPersonalityTraitModules,
|
|
loadWarTraitModules,
|
|
NATION_TRAIT_KEYS,
|
|
PERSONALITY_TRAIT_KEYS,
|
|
TraitGeneralActionRouter,
|
|
TraitWarActionRouter,
|
|
WAR_TRAIT_KEYS,
|
|
} from './traits/index.js';
|
|
import type { NationTraitModule } from './traits/nation/index.js';
|
|
import { createScenarioEffectActionModules } from './scenarioEffect.js';
|
|
import type { ScenarioEffectKey } from '@sammo-ts/logic/scenario/scenarioEffect.js';
|
|
|
|
export interface ActionModuleBundle<TriggerState extends GeneralTriggerState = GeneralTriggerState> {
|
|
general: RefOrderedActionStack<GeneralActionModule<TriggerState>>;
|
|
war: RefOrderedActionStack<WarActionModule<TriggerState>>;
|
|
itemModules: ItemModule<TriggerState>[];
|
|
nationTraitModules: NationTraitModule[];
|
|
}
|
|
|
|
const refActionOrderBrand: unique symbol = Symbol('RefOrderedActionStack');
|
|
|
|
export type RefOrderedActionStack<Module> = ReadonlyArray<Module> & {
|
|
readonly [refActionOrderBrand]: true;
|
|
};
|
|
|
|
interface RefActionSlots<Module> {
|
|
nation: Module;
|
|
officer: Module;
|
|
domestic: Module;
|
|
war: Module;
|
|
personality: Module;
|
|
crewType: Module | null;
|
|
inheritance: Module;
|
|
scenario: Module | null;
|
|
items: readonly Module[];
|
|
}
|
|
|
|
const markRefOrderedActionStack: <Module>(
|
|
stack: Module[]
|
|
) => asserts stack is Module[] & { readonly [refActionOrderBrand]: true } = (stack) => {
|
|
Object.defineProperty(stack, refActionOrderBrand, {
|
|
value: true,
|
|
enumerable: false,
|
|
writable: false,
|
|
});
|
|
};
|
|
|
|
// ref General::getActionList()의 소유권 순서를 한 곳에서만 조립합니다.
|
|
export const createRefOrderedActionStack = <Module>(slots: RefActionSlots<Module>): RefOrderedActionStack<Module> => {
|
|
const stack = [
|
|
slots.nation,
|
|
slots.officer,
|
|
slots.domestic,
|
|
slots.war,
|
|
slots.personality,
|
|
...(slots.crewType ? [slots.crewType] : []),
|
|
slots.inheritance,
|
|
...(slots.scenario ? [slots.scenario] : []),
|
|
...slots.items,
|
|
];
|
|
markRefOrderedActionStack(stack);
|
|
return stack;
|
|
};
|
|
|
|
// General::getActionList와 같은 소유권 순서로 실제 턴과 시뮬레이터의 모듈을 조립한다.
|
|
export const loadActionModuleBundle = async <TriggerState extends GeneralTriggerState = GeneralTriggerState>(
|
|
unitSet?: UnitSetDefinition,
|
|
scenarioEffect?: ScenarioEffectKey | null
|
|
): Promise<ActionModuleBundle<TriggerState>> => {
|
|
const [domestic, eventDomestic, war, personality, nation, itemModules] = await Promise.all([
|
|
loadDomesticTraitModules([...DOMESTIC_TRAIT_KEYS]),
|
|
loadEventDomesticTraitModules([...EVENT_DOMESTIC_TRAIT_KEYS]),
|
|
loadWarTraitModules([...WAR_TRAIT_KEYS]),
|
|
loadPersonalityTraitModules([...PERSONALITY_TRAIT_KEYS]),
|
|
loadNationTraitModules([...NATION_TRAIT_KEYS]),
|
|
loadItemModules([...ITEM_KEYS]) as Promise<ItemModule<TriggerState>[]>,
|
|
]);
|
|
const traitCatalog = createTraitCatalog<TriggerState>({
|
|
domestic: [...domestic, ...eventDomestic],
|
|
war,
|
|
personality,
|
|
nation,
|
|
});
|
|
const officer = createOfficerLevelActionModules<TriggerState>();
|
|
const items = createItemActionModules(createItemModuleRegistry(itemModules));
|
|
const inherit = createInheritBuffModules();
|
|
const scenario = createScenarioEffectActionModules<TriggerState>(scenarioEffect);
|
|
const crewTypeCatalog = unitSet?.crewTypes?.length
|
|
? compileCrewTypeCatalog(unitSet, createCrewTypeWarTriggerRegistry())
|
|
: null;
|
|
|
|
return {
|
|
general: createRefOrderedActionStack<GeneralActionModule<TriggerState>>({
|
|
nation: new TraitGeneralActionRouter('nation', traitCatalog),
|
|
officer: officer.general,
|
|
domestic: new TraitGeneralActionRouter('domestic', traitCatalog),
|
|
war: new TraitGeneralActionRouter('war', traitCatalog),
|
|
personality: new TraitGeneralActionRouter('personality', traitCatalog),
|
|
crewType: crewTypeCatalog
|
|
? (crewTypeCatalog.generalActionModule as GeneralActionModule<TriggerState>)
|
|
: null,
|
|
inheritance: inherit.general as GeneralActionModule<TriggerState>,
|
|
scenario: scenario.general,
|
|
items: items.general,
|
|
}),
|
|
war: createRefOrderedActionStack<WarActionModule<TriggerState>>({
|
|
nation: new TraitWarActionRouter('nation', traitCatalog),
|
|
officer: officer.war,
|
|
domestic: new TraitWarActionRouter('domestic', traitCatalog),
|
|
war: new TraitWarActionRouter('war', traitCatalog),
|
|
personality: new TraitWarActionRouter('personality', traitCatalog),
|
|
crewType: crewTypeCatalog ? (crewTypeCatalog.warActionModule as WarActionModule<TriggerState>) : null,
|
|
inheritance: inherit.war as WarActionModule<TriggerState>,
|
|
scenario: scenario.war,
|
|
items: items.war,
|
|
}),
|
|
itemModules,
|
|
nationTraitModules: nation,
|
|
};
|
|
};
|