fix general military preparation parity
This commit is contained in:
@@ -18,12 +18,7 @@ import { tryApplyUniqueLottery } from '@sammo-ts/logic/rewards/uniqueLottery.js'
|
||||
import { defaultActionContextBuilder } from '@sammo-ts/logic/actions/turn/actionContext.js';
|
||||
import type { GeneralTurnCommandSpec } from './index.js';
|
||||
import { parseArgsWithSchema } from '../parseArgs.js';
|
||||
import {
|
||||
cloneItemInventory,
|
||||
ensureItemInventory,
|
||||
equipNewItem,
|
||||
removeEquippedItem,
|
||||
} from '@sammo-ts/logic/items/inventory.js';
|
||||
import { equipNewItem, removeEquippedItem } from '@sammo-ts/logic/items/inventory.js';
|
||||
|
||||
const ACTION_NAME = '장비매매';
|
||||
const ACTION_KEY = 'che_장비매매';
|
||||
@@ -167,17 +162,12 @@ export class ActionDefinition<
|
||||
const josaUl = JosaUtil.pick(itemRawName, '을');
|
||||
|
||||
const nextGold = buying ? Math.max(0, general.gold - itemCost) : general.gold + Math.floor(itemCost / 2);
|
||||
const nextGeneral = {
|
||||
...general,
|
||||
role: { ...general.role, items: { ...general.role.items } },
|
||||
itemInventory: cloneItemInventory(ensureItemInventory(general)),
|
||||
};
|
||||
if (buying) {
|
||||
equipNewItem(nextGeneral, itemType, finalItemCode, {
|
||||
equipNewItem(general, itemType, finalItemCode, {
|
||||
...(item?.initialCharges === undefined ? {} : { charges: item.initialCharges }),
|
||||
});
|
||||
} else {
|
||||
removeEquippedItem(nextGeneral, itemType);
|
||||
removeEquippedItem(general, itemType);
|
||||
}
|
||||
|
||||
if (buying) {
|
||||
@@ -198,7 +188,7 @@ export class ActionDefinition<
|
||||
const josaYi = JosaUtil.pick(general.name, '이');
|
||||
context.addLog(`<Y>${general.name}</>${josaYi} <C>${itemName}</>${josaUl} 판매했습니다!`, {
|
||||
scope: LogScope.SYSTEM,
|
||||
category: LogCategory.ACTION,
|
||||
category: LogCategory.SUMMARY,
|
||||
});
|
||||
context.addLog(
|
||||
`<R><b>【판매】</b></><D><b>${nation.name}</b></>의 <Y>${general.name}</>${josaYi} <C>${itemName}</>${josaUl} 판매했습니다!`,
|
||||
@@ -216,8 +206,6 @@ export class ActionDefinition<
|
||||
createGeneralPatchEffect<TriggerState>({
|
||||
gold: nextGold,
|
||||
experience: general.experience + 10,
|
||||
role: nextGeneral.role,
|
||||
itemInventory: nextGeneral.itemInventory,
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
@@ -68,14 +68,21 @@ export const ARGS_SCHEMA = z.preprocess(
|
||||
return { ...record, crewType };
|
||||
},
|
||||
z.object({
|
||||
crewType: z.preprocess(
|
||||
(value) => (typeof value === 'number' ? Math.floor(value) : value),
|
||||
z.number().int().positive()
|
||||
),
|
||||
amount: z.preprocess(
|
||||
(value) => (typeof value === 'number' ? Math.floor(value) : value),
|
||||
z.number().int().min(0)
|
||||
),
|
||||
crewType: z.number().int().positive(),
|
||||
amount: z.preprocess((value) => {
|
||||
if (typeof value === 'number') {
|
||||
return Number.isFinite(value) ? Math.trunc(value) : value;
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
const trimmed = value.trim();
|
||||
if (!/^[+-]?(?:(?:\d+(?:\.\d*)?)|(?:\.\d+))(?:[eE][+-]?\d+)?$/.test(trimmed)) {
|
||||
return value;
|
||||
}
|
||||
const numeric = Number(trimmed);
|
||||
return Number.isFinite(numeric) ? Math.trunc(numeric) : value;
|
||||
}
|
||||
return value;
|
||||
}, z.number().int().min(0)),
|
||||
})
|
||||
);
|
||||
export type RecruitArgs = z.infer<typeof ARGS_SCHEMA>;
|
||||
@@ -107,6 +114,10 @@ const readCityTrust = (city: City, fallback: number): number => {
|
||||
return typeof trust === 'number' ? trust : fallback;
|
||||
};
|
||||
|
||||
// 레거시 city.trust는 MariaDB FLOAT이며 다음 명령에서 6자리 유효숫자로
|
||||
// 재조회된다. 메모리 상태도 같은 persistence 경계로 정규화한다.
|
||||
const toLegacyStoredTrust = (value: number): number => Number(value.toPrecision(6));
|
||||
|
||||
const addMetaNumber = (meta: GeneralMeta, key: string, delta: number): GeneralMeta => {
|
||||
const current = typeof meta[key] === 'number' ? (meta[key] as number) : 0;
|
||||
return { ...meta, [key]: current + delta };
|
||||
@@ -365,7 +376,7 @@ export class ActionResolver<
|
||||
const nextPopulation = Math.max(city.population - recruitPop, 0);
|
||||
const baseTrust = readCityTrust(city, this.env.defaultTrust ?? DEFAULT_TRUST);
|
||||
const trustLoss = city.population > 0 ? (recruitPop / city.population / costOffset) * 100 : 0;
|
||||
const nextTrust = Math.max(baseTrust - trustLoss, 0);
|
||||
const nextTrust = toLegacyStoredTrust(Math.max(baseTrust - trustLoss, 0));
|
||||
|
||||
const actionName = this.env.actionName ?? ACTION_NAME;
|
||||
const [nextCrewTypeId, nextCrew, nextTrain, nextAtmos] =
|
||||
|
||||
Reference in New Issue
Block a user