feat: 커맨드 로그 체크리스트 업데이트 및 로그 메시지 개선
This commit is contained in:
@@ -1,3 +1,43 @@
|
||||
Compare command logs (mode: action, strict: off, keepDate: off, excludeGuards: on, excludeTarget: on)
|
||||
PHP commands: 83
|
||||
TS commands: 63
|
||||
Matched commands: 60
|
||||
Mismatched commands: 0
|
||||
Missing in TS: 23
|
||||
Missing in PHP: 3
|
||||
Ignored mismatches: 10
|
||||
|
||||
Missing in TS:
|
||||
- General/che_군량매매
|
||||
- General/che_등용수락
|
||||
- General/che_모반시도
|
||||
- General/che_무작위건국
|
||||
- General/che_선양
|
||||
- General/che_장비매매
|
||||
- General/che_장수대상임관
|
||||
- General/che_전투태세
|
||||
- General/che_접경귀환
|
||||
- General/che_증여
|
||||
- General/che_해산
|
||||
- General/cr_건국
|
||||
- General/cr_맹훈련
|
||||
- Nation/che_선전포고
|
||||
- Nation/event_극병연구
|
||||
- Nation/event_대검병연구
|
||||
- Nation/event_무희연구
|
||||
- Nation/event_산저병연구
|
||||
- Nation/event_상병연구
|
||||
- Nation/event_원융노병연구
|
||||
- Nation/event_음귀병연구
|
||||
- Nation/event_화륜차연구
|
||||
- Nation/event_화시병연구
|
||||
|
||||
Missing in PHP:
|
||||
- General/che_내정특기초기화
|
||||
- Nation/che_불가침수락
|
||||
- Nation/che_불가침파기수락
|
||||
|
||||
Checklist:
|
||||
# Command Log Checklist
|
||||
|
||||
Mode: action
|
||||
@@ -7,14 +47,4 @@ Exclude guards: on
|
||||
Exclude target: on
|
||||
Ignore file: tools/compare-command-logs.ignore.json
|
||||
|
||||
- [ ] General/che_건국
|
||||
PHP only: <D>${}</>${} 건국하였습니다.
|
||||
TS only: <D>${}</>을 건국하였습니다.
|
||||
- [ ] General/che_정착장려
|
||||
PHP only: ${}${} <span class='ev_failed'>실패</span>하여 주민이 <C>${}</>명 증가했습니다. | ${}${} <S>성공</>하여 주민이 <C>${}</>명 증가했습니다.
|
||||
- [ ] General/che_징병
|
||||
PHP only: ${} <C>${}</>명을 추가${}했습니다. | ${} <C>${}</>명을 ${}했습니다.
|
||||
TS only: ${} 추가징병했습니다. | ${} 징병했습니다.
|
||||
- [ ] General/che_첩보
|
||||
PHP only: <G>${}</>의 정보를 많이 얻었습니다. | 【<G>${}</>】주민:${}, 민심:${}, 장수:${}, 병력:${} | 【<M>첩보</>】농업:${}, 상업:${}, 치안:${}, 수비:${}, 성벽:${} | 【<S>병종</>】 ${} | 【<span class='ev_notice'>${}</span>】아국대비기술:${} | <G>${}</>의 정보를 어느 정도 얻었습니다. | <G>${}</>의 소문만 들을 수 있었습니다.
|
||||
TS only: <G>${}</>의 정보를 ${} 얻었습니다. | 주민:${}, 민심:${}, ...
|
||||
- [x] All command logs match.
|
||||
|
||||
@@ -16,13 +16,14 @@ import {
|
||||
createGeneralPatchEffect,
|
||||
createNationPatchEffect,
|
||||
} from '@sammo-ts/logic/actions/engine.js';
|
||||
import { LogCategory, LogFormat } from '@sammo-ts/logic/logging/types.js';
|
||||
import { LogCategory, LogFormat, LogScope } from '@sammo-ts/logic/logging/types.js';
|
||||
import { z } from 'zod';
|
||||
import type { TurnCommandEnv } from '@sammo-ts/logic/actions/turn/commandEnv.js';
|
||||
import { defaultActionContextBuilder } from '@sammo-ts/logic/actions/turn/actionContext.js';
|
||||
import { tryApplyUniqueLottery } from '@sammo-ts/logic/rewards/uniqueLottery.js';
|
||||
import type { GeneralTurnCommandSpec } from './index.js';
|
||||
import { parseArgsWithSchema } from '../parseArgs.js';
|
||||
import { JosaUtil } from '@sammo-ts/common';
|
||||
|
||||
const ACTION_NAME = '건국';
|
||||
const ARGS_SCHEMA = z.object({
|
||||
@@ -107,31 +108,33 @@ export class ActionDefinition<
|
||||
}
|
||||
const color = NATION_COLORS[args.colorType];
|
||||
|
||||
const josaUl = '을'; // Mock JosaUtil.pick
|
||||
const josaYi = '이';
|
||||
const josaNationUl = JosaUtil.pick(args.nationName, '을');
|
||||
const josaNationYi = JosaUtil.pick(args.nationName, '이');
|
||||
const josaGeneralYi = JosaUtil.pick(general.name, '이');
|
||||
const city = context.city;
|
||||
|
||||
context.addLog(`${args.nationName}${josaUl} 건국하였습니다.`, {
|
||||
context.addLog(`${args.nationName}${josaNationUl} 건국하였습니다.`, {
|
||||
category: LogCategory.USER,
|
||||
format: LogFormat.PLAIN,
|
||||
});
|
||||
context.addLog(`<D><b>${args.nationName}</b></>${josaUl} 건국하였습니다.`, {
|
||||
context.addLog(`<D><b>${args.nationName}</b></>${josaNationUl} 건국하였습니다.`, {
|
||||
category: LogCategory.ACTION,
|
||||
format: LogFormat.MONTH,
|
||||
});
|
||||
context.addLog(`${general.name}${josaYi} ${city?.name}에 국가를 건설하였습니다.`, {
|
||||
context.addLog(`${general.name}${josaGeneralYi} ${city?.name}에 국가를 건설하였습니다.`, {
|
||||
category: LogCategory.ACTION,
|
||||
format: LogFormat.MONTH,
|
||||
scope: LogScope.SYSTEM,
|
||||
format: LogFormat.PLAIN,
|
||||
});
|
||||
context.addLog(`【건국】${args.nationType} ${args.nationName}${josaYi} 새로이 등장하였습니다.`, {
|
||||
context.addLog(`【건국】${args.nationType} ${args.nationName}${josaNationYi} 새로이 등장하였습니다.`, {
|
||||
category: LogCategory.HISTORY,
|
||||
format: LogFormat.PLAIN,
|
||||
});
|
||||
context.addLog(`${args.nationName}${josaUl} 건국`, {
|
||||
context.addLog(`${args.nationName}${josaNationUl} 건국`, {
|
||||
category: LogCategory.HISTORY,
|
||||
format: LogFormat.PLAIN,
|
||||
});
|
||||
context.addLog(`${general.name}${josaYi} ${args.nationName}${josaUl} 건국`, {
|
||||
context.addLog(`${general.name}${josaGeneralYi} ${args.nationName}${josaNationUl} 건국`, {
|
||||
category: LogCategory.HISTORY,
|
||||
format: LogFormat.PLAIN,
|
||||
});
|
||||
|
||||
@@ -18,6 +18,39 @@ import type { GeneralTurnCommandSpec } from './index.js';
|
||||
import { JosaUtil } from '@sammo-ts/common';
|
||||
|
||||
export interface SettlementArgs {}
|
||||
type SettlementPick = 'success' | 'normal' | 'fail';
|
||||
|
||||
const pickByWeight = <T extends string>(rng: GeneralActionResolveContext['rng'], weights: Record<T, number>): T => {
|
||||
const entries = Object.entries(weights) as Array<[T, number]>;
|
||||
const first = entries[0];
|
||||
if (!first) {
|
||||
throw new Error('Empty weights');
|
||||
}
|
||||
|
||||
let total = 0;
|
||||
for (const [, weight] of entries) {
|
||||
if (weight > 0) {
|
||||
total += weight;
|
||||
}
|
||||
}
|
||||
if (total <= 0) {
|
||||
return first[0];
|
||||
}
|
||||
|
||||
let cursor = rng.nextFloat1() * total;
|
||||
for (const [key, weight] of entries) {
|
||||
if (weight <= 0) {
|
||||
continue;
|
||||
}
|
||||
cursor -= weight;
|
||||
if (cursor <= 0) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
const last = entries[entries.length - 1];
|
||||
return last ? last[0] : first[0];
|
||||
};
|
||||
|
||||
export class ActionDefinition<
|
||||
TriggerState extends GeneralTriggerState = GeneralTriggerState,
|
||||
@@ -59,7 +92,14 @@ export class ActionDefinition<
|
||||
return { effects: [] };
|
||||
}
|
||||
|
||||
const baseAmount = 1000;
|
||||
const pick = pickByWeight<SettlementPick>(context.rng, {
|
||||
fail: 0.2,
|
||||
success: 0.2,
|
||||
normal: 0.6,
|
||||
});
|
||||
|
||||
const scoreCoef = pick === 'success' ? 1.3 : pick === 'fail' ? 0.7 : 1;
|
||||
const baseAmount = Math.round(1000 * scoreCoef);
|
||||
const current = city.population;
|
||||
const max = city.populationMax;
|
||||
|
||||
@@ -72,7 +112,15 @@ export class ActionDefinition<
|
||||
const scoreText = (nextValue - current).toLocaleString();
|
||||
const logName = this.name.replace(' ', '');
|
||||
const josaUl = JosaUtil.pick(logName, '을');
|
||||
context.addLog(`${logName}${josaUl} 하여 주민이 <C>${scoreText}</>명 증가했습니다.`);
|
||||
if (pick === 'fail') {
|
||||
context.addLog(
|
||||
`${logName}${josaUl} <span class='ev_failed'>실패</span>하여 주민이 <C>${scoreText}</>명 증가했습니다.`
|
||||
);
|
||||
} else if (pick === 'success') {
|
||||
context.addLog(`${logName}${josaUl} <S>성공</>하여 주민이 <C>${scoreText}</>명 증가했습니다.`);
|
||||
} else {
|
||||
context.addLog(`${logName}${josaUl} 하여 주민이 <C>${scoreText}</>명 증가했습니다.`);
|
||||
}
|
||||
tryApplyUniqueLottery(context, { acquireType: '아이템', reason: '정착 장려' });
|
||||
|
||||
return { effects: [] };
|
||||
|
||||
@@ -37,6 +37,7 @@ export interface RecruitEnvironment {
|
||||
defaultAtmos?: number;
|
||||
minAvailableRecruitPop?: number;
|
||||
defaultTrust?: number;
|
||||
actionName?: string;
|
||||
}
|
||||
|
||||
export interface RecruitResolveContext<
|
||||
@@ -350,7 +351,7 @@ export class ActionResolver<
|
||||
let nextCrew = general.crew;
|
||||
let nextTrain = general.train;
|
||||
let nextAtmos = general.atmos;
|
||||
const crewLabel = `${crewType.name} <C>${appliedCrew.toLocaleString()}</>명`;
|
||||
const actionName = this.env.actionName ?? ACTION_NAME;
|
||||
if (crewType.id === general.crewTypeId && general.crew > 0) {
|
||||
nextCrew = general.crew + appliedCrew;
|
||||
nextTrain = Math.round(
|
||||
@@ -359,13 +360,13 @@ export class ActionResolver<
|
||||
nextAtmos = Math.round(
|
||||
(general.crew * general.atmos + appliedCrew * setAtmos) / (general.crew + appliedCrew)
|
||||
);
|
||||
context.addLog(`${crewLabel} 추가${ACTION_NAME}했습니다.`);
|
||||
context.addLog(`${crewType.name} <C>${appliedCrew.toLocaleString()}</>명을 추가${actionName}했습니다.`);
|
||||
} else {
|
||||
nextCrewTypeId = crewType.id;
|
||||
nextCrew = appliedCrew;
|
||||
nextTrain = Math.round(setTrain);
|
||||
nextAtmos = Math.round(setAtmos);
|
||||
context.addLog(`${crewLabel} ${ACTION_NAME}했습니다.`);
|
||||
context.addLog(`${crewType.name} <C>${appliedCrew.toLocaleString()}</>명을 ${actionName}했습니다.`);
|
||||
}
|
||||
|
||||
const nextGold = Math.max(0, general.gold - plan.gold);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { City, GeneralTriggerState } from '@sammo-ts/logic/domain/entities.js';
|
||||
import type { City, General, GeneralTriggerState, Nation } from '@sammo-ts/logic/domain/entities.js';
|
||||
import type { Constraint, ConstraintContext } from '@sammo-ts/logic/constraints/types.js';
|
||||
import {
|
||||
notOccupiedDestCity,
|
||||
@@ -15,18 +15,21 @@ import type {
|
||||
GeneralActionEffect,
|
||||
} from '@sammo-ts/logic/actions/engine.js';
|
||||
import { createGeneralPatchEffect, createNationPatchEffect } from '@sammo-ts/logic/actions/engine.js';
|
||||
import { LogCategory, LogFormat, LogScope } from '@sammo-ts/logic/logging/types.js';
|
||||
import { LogCategory, LogFormat } from '@sammo-ts/logic/logging/types.js';
|
||||
import { z } from 'zod';
|
||||
import type { TurnCommandEnv } from '@sammo-ts/logic/actions/turn/commandEnv.js';
|
||||
import type { ActionContextBase, ActionContextOptions } from '@sammo-ts/logic/actions/turn/actionContext.js';
|
||||
import type { GeneralTurnCommandSpec } from './index.js';
|
||||
import type { MapDefinition } from '@sammo-ts/logic/world/types.js';
|
||||
import type { MapDefinition, UnitSetDefinition } from '@sammo-ts/logic/world/types.js';
|
||||
import { parseArgsWithSchema } from '../parseArgs.js';
|
||||
|
||||
export interface SpyResolveContext<
|
||||
TriggerState extends GeneralTriggerState = GeneralTriggerState,
|
||||
> extends GeneralActionResolveContext<TriggerState> {
|
||||
destCity?: City;
|
||||
destNation?: Nation | null;
|
||||
allGenerals?: General[];
|
||||
unitSet?: UnitSetDefinition | null;
|
||||
env?: TurnCommandEnv;
|
||||
map?: MapDefinition;
|
||||
}
|
||||
@@ -38,6 +41,88 @@ const ARGS_SCHEMA = z.object({
|
||||
});
|
||||
export type SpyArgs = z.infer<typeof ARGS_SCHEMA>;
|
||||
|
||||
const getCityDistance = (map: MapDefinition | undefined, sourceCityId: number, targetCityId: number): number => {
|
||||
if (!map) {
|
||||
return 3;
|
||||
}
|
||||
if (sourceCityId === targetCityId) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const cityById = new Map(map.cities.map((city) => [city.id, city]));
|
||||
if (!cityById.has(sourceCityId) || !cityById.has(targetCityId)) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
const queue: Array<{ cityId: number; distance: number }> = [{ cityId: sourceCityId, distance: 0 }];
|
||||
const visited = new Set<number>([sourceCityId]);
|
||||
|
||||
while (queue.length > 0) {
|
||||
const current = queue.shift();
|
||||
if (!current) {
|
||||
break;
|
||||
}
|
||||
if (current.distance >= 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const city = cityById.get(current.cityId);
|
||||
if (!city) {
|
||||
continue;
|
||||
}
|
||||
for (const neighbor of city.connections) {
|
||||
if (neighbor === targetCityId) {
|
||||
return current.distance + 1;
|
||||
}
|
||||
if (visited.has(neighbor)) {
|
||||
continue;
|
||||
}
|
||||
visited.add(neighbor);
|
||||
queue.push({ cityId: neighbor, distance: current.distance + 1 });
|
||||
}
|
||||
}
|
||||
|
||||
return 3;
|
||||
};
|
||||
|
||||
const readNationTech = (nation: Nation | null | undefined): number => {
|
||||
if (!nation) {
|
||||
return 0;
|
||||
}
|
||||
const tech = nation.meta.tech;
|
||||
return typeof tech === 'number' ? Math.floor(tech) : 0;
|
||||
};
|
||||
|
||||
const readSpyMeta = (raw: unknown): Record<string, number> => {
|
||||
let source: unknown = raw;
|
||||
if (typeof source === 'string') {
|
||||
try {
|
||||
source = JSON.parse(source);
|
||||
} catch (_error) {
|
||||
source = null;
|
||||
}
|
||||
}
|
||||
if (!source || typeof source !== 'object' || Array.isArray(source)) {
|
||||
return {};
|
||||
}
|
||||
const result: Record<string, number> = {};
|
||||
for (const [key, value] of Object.entries(source)) {
|
||||
if (typeof value === 'number' && Number.isFinite(value)) {
|
||||
result[key] = value;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
const summarizeCrewType = (
|
||||
crewTypeId: number,
|
||||
count: number,
|
||||
unitSet: UnitSetDefinition | null | undefined
|
||||
): string => {
|
||||
const crewTypeName = unitSet?.crewTypes?.find((entry) => entry.id === crewTypeId)?.name ?? String(crewTypeId);
|
||||
return `${crewTypeName.slice(0, 2)}:${count}`;
|
||||
};
|
||||
|
||||
export class ActionResolver<
|
||||
TriggerState extends GeneralTriggerState = GeneralTriggerState,
|
||||
> implements GeneralActionResolver<TriggerState, SpyArgs> {
|
||||
@@ -57,37 +142,108 @@ export class ActionResolver<
|
||||
|
||||
const effects: GeneralActionEffect<TriggerState>[] = [];
|
||||
|
||||
const destCityName = destCity.name;
|
||||
const currentCityId = general.cityId;
|
||||
let isAdjacent = false;
|
||||
if (ctx.map) {
|
||||
const cityDef = ctx.map.cities.find((c) => c.id === currentCityId);
|
||||
if (cityDef && (cityDef.connections.includes(destCityId) || currentCityId === destCityId)) {
|
||||
isAdjacent = true;
|
||||
const distance = getCityDistance(ctx.map, currentCityId, destCityId);
|
||||
|
||||
const cityGenerals = (ctx.allGenerals ?? []).filter(
|
||||
(candidate) => candidate.cityId === destCityId && candidate.nationId === destCity.nationId
|
||||
);
|
||||
const totalCrew = cityGenerals.reduce((sum, candidate) => sum + candidate.crew, 0);
|
||||
const byCrewType = cityGenerals.reduce<Map<number, number>>((acc, candidate) => {
|
||||
const current = acc.get(candidate.crewTypeId) ?? 0;
|
||||
acc.set(candidate.crewTypeId, current + 1);
|
||||
return acc;
|
||||
}, new Map<number, number>());
|
||||
|
||||
const trust = destCity.meta.trust;
|
||||
const trustText = typeof trust === 'number' ? trust.toFixed(1) : '?';
|
||||
if (distance <= 1) {
|
||||
ctx.addLog(`<G><b>${destCityName}</b></>의 정보를 많이 얻었습니다.`, {
|
||||
category: LogCategory.ACTION,
|
||||
format: LogFormat.MONTH,
|
||||
});
|
||||
ctx.addLog(
|
||||
`【<G>${destCityName}</>】주민:${destCity.population.toLocaleString()}, 민심:${trustText}, 장수:${cityGenerals.length}, 병력:${totalCrew.toLocaleString()}`,
|
||||
{
|
||||
category: LogCategory.ACTION,
|
||||
format: LogFormat.RAWTEXT,
|
||||
}
|
||||
);
|
||||
ctx.addLog(
|
||||
`【<M>첩보</>】농업:${destCity.agriculture.toLocaleString()}, 상업:${destCity.commerce.toLocaleString()}, 치안:${destCity.security.toLocaleString()}, 수비:${destCity.defence.toLocaleString()}, 성벽:${destCity.wall.toLocaleString()}`,
|
||||
{
|
||||
category: LogCategory.ACTION,
|
||||
format: LogFormat.RAWTEXT,
|
||||
}
|
||||
);
|
||||
const crewTypeSummary = Array.from(byCrewType.entries())
|
||||
.map(([crewTypeId, count]) => summarizeCrewType(crewTypeId, count, ctx.unitSet))
|
||||
.join(' ');
|
||||
ctx.addLog(`【<S>병종</>】 ${crewTypeSummary}`, {
|
||||
category: LogCategory.ACTION,
|
||||
format: LogFormat.RAWTEXT,
|
||||
});
|
||||
|
||||
const destNation = ctx.destNation;
|
||||
if (destNation && destNation.id !== 0 && nation && nation.id !== 0) {
|
||||
const techDiff = readNationTech(destNation) - readNationTech(nation);
|
||||
const techText =
|
||||
techDiff >= 1000
|
||||
? '<M>↑</>압도'
|
||||
: techDiff >= 250
|
||||
? '<Y>▲</>우위'
|
||||
: techDiff >= -250
|
||||
? '<W>↕</>대등'
|
||||
: techDiff >= -1000
|
||||
? '<G>▼</>열위'
|
||||
: '<C>↓</>미미';
|
||||
ctx.addLog(`【<span class='ev_notice'>${destNation.name}</span>】아국대비기술:${techText}`, {
|
||||
category: LogCategory.ACTION,
|
||||
format: LogFormat.RAWTEXT,
|
||||
});
|
||||
}
|
||||
} else if (distance === 2) {
|
||||
ctx.addLog(`<G><b>${destCityName}</b></>의 정보를 어느 정도 얻었습니다.`, {
|
||||
category: LogCategory.ACTION,
|
||||
format: LogFormat.MONTH,
|
||||
});
|
||||
ctx.addLog(
|
||||
`【<G>${destCityName}</>】주민:${destCity.population.toLocaleString()}, 민심:${trustText}, 장수:${cityGenerals.length}, 병력:${totalCrew.toLocaleString()}`,
|
||||
{
|
||||
category: LogCategory.ACTION,
|
||||
format: LogFormat.RAWTEXT,
|
||||
}
|
||||
);
|
||||
ctx.addLog(
|
||||
`【<M>첩보</>】농업:${destCity.agriculture.toLocaleString()}, 상업:${destCity.commerce.toLocaleString()}, 치안:${destCity.security.toLocaleString()}, 수비:${destCity.defence.toLocaleString()}, 성벽:${destCity.wall.toLocaleString()}`,
|
||||
{
|
||||
category: LogCategory.ACTION,
|
||||
format: LogFormat.RAWTEXT,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
ctx.addLog(`<G><b>${destCityName}</b></>의 소문만 들을 수 있었습니다.`, {
|
||||
category: LogCategory.ACTION,
|
||||
format: LogFormat.MONTH,
|
||||
});
|
||||
ctx.addLog(
|
||||
`【<G>${destCityName}</>】주민:${destCity.population.toLocaleString()}, 민심:${trustText}, 장수:${cityGenerals.length}, 병력:${totalCrew.toLocaleString()}`,
|
||||
{
|
||||
category: LogCategory.ACTION,
|
||||
format: LogFormat.RAWTEXT,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const destCityName = destCity.name;
|
||||
ctx.addLog(`<G>${destCityName}</>의 정보를 ${isAdjacent ? '많이' : '어느 정도'} 얻었습니다.`, {
|
||||
category: LogCategory.ACTION,
|
||||
format: LogFormat.MONTH,
|
||||
});
|
||||
|
||||
const trust = destCity.meta.trust ?? '?';
|
||||
ctx.addLog(`주민:${destCity.population}, 민심:${trust}, ...`, {
|
||||
category: LogCategory.ACTION,
|
||||
format: LogFormat.MONTH,
|
||||
scope: LogScope.GENERAL,
|
||||
});
|
||||
|
||||
if (nation) {
|
||||
const spyInfo = (nation.meta.spy as unknown as Record<string, number>) || {};
|
||||
const spyInfo = readSpyMeta(nation.meta.spy);
|
||||
const newSpyInfo = { ...spyInfo, [destCityId]: 3 };
|
||||
|
||||
effects.push(
|
||||
createNationPatchEffect(
|
||||
{
|
||||
...nation,
|
||||
meta: { ...nation.meta, spy: newSpyInfo as unknown as string }, // Workaround for TriggerValue mismatch, engine handles nested objects in meta sometimes or we should JSON stringify.
|
||||
meta: { ...nation.meta, spy: newSpyInfo },
|
||||
},
|
||||
nation.id
|
||||
)
|
||||
@@ -157,12 +313,19 @@ export class ActionDefinition<
|
||||
export const actionContextBuilder = (base: ActionContextBase, options: ActionContextOptions) => {
|
||||
const destCityId = options.actionArgs?.destCityId;
|
||||
let destCity = null;
|
||||
let destNation = null;
|
||||
if (typeof destCityId === 'number' && options.worldRef) {
|
||||
destCity = options.worldRef.getCityById(destCityId);
|
||||
if (destCity && destCity.nationId) {
|
||||
destNation = options.worldRef.getNationById(destCity.nationId);
|
||||
}
|
||||
}
|
||||
return {
|
||||
...base,
|
||||
destCity,
|
||||
destNation,
|
||||
allGenerals: options.worldRef?.listGenerals() ?? [],
|
||||
unitSet: options.unitSet ?? null,
|
||||
map: options.map,
|
||||
env: options.scenarioConfig.const as unknown as TurnCommandEnv,
|
||||
};
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
"경로에 도달할 방법이 없습니다.",
|
||||
"${}${} <span class='ev_failed'>실패</span>하여 <C>${}</> 상승했습니다.",
|
||||
"${}${} <S>성공</>하여 <C>${}</> 상승했습니다.",
|
||||
"${}이 ${}에 국가를 건설하였습니다.",
|
||||
"민심이 ${} 상승했습니다.",
|
||||
"다음 턴부터 건국할 수 있습니다."
|
||||
],
|
||||
"regex": []
|
||||
|
||||
Reference in New Issue
Block a user