유산 랜덤 턴 초기화의 다다음 턴 적용과 분초 표시 수정

This commit is contained in:
2026-09-14 23:56:38 +00:00
parent 854a91c397
commit 380020ab2f
9 changed files with 223 additions and 25 deletions
+14 -2
View File
@@ -1905,13 +1905,25 @@ export class InMemoryTurnWorld {
schedule: this.schedule,
});
const nextTurnAt = result.nextTurnAt ?? getNextTurnAt(currentGeneral.turnTime, this.schedule);
let nextTurnAt = result.nextTurnAt ?? getNextTurnAt(currentGeneral.turnTime, this.schedule);
if (!result.deleted?.general) {
const resolvedGeneral = result.general ?? currentGeneral;
const clock = this.getGameClock();
const currentTurnTick = currentGeneral.turnTick ?? clock.dateToTick(currentGeneral.turnTime);
const nextTurnTick =
let nextTurnTick =
currentTurnTick + (clock.dateToTick(nextTurnAt) - clock.dateToTick(currentGeneral.turnTime));
const nextTurnTimeBase = readMetaNumber(resolvedGeneral.meta, 'nextTurnTimeBase');
if (nextTurnTimeBase !== null && nextTurnTimeBase >= 0) {
// Ref: addTurn → cutTurn → 새 offset. 기존 분·초를 더하지 않고
// 논리 월 경계에서 교체해야 다다음 턴과 로그가 일치한다.
// Date를 경유하면 난수의 sub-ms tick과 기존 tick 꼬리가 섞인다.
nextTurnTick =
Math.floor(nextTurnTick / GAME_TICKS_PER_TURN) * GAME_TICKS_PER_TURN +
Math.round(nextTurnTimeBase * clock.ticksPerSecond);
nextTurnAt = clock.tickToDate(nextTurnTick);
resolvedGeneral.meta = { ...resolvedGeneral.meta };
delete resolvedGeneral.meta.nextTurnTimeBase;
}
const recentWarTimeChanged =
(resolvedGeneral.recentWarTime?.getTime() ?? null) !==
(currentGeneral.recentWarTime?.getTime() ?? null);
@@ -177,9 +177,9 @@ export const buildResetStatRandomBonus = (
const formatTurnTimeBaseLabel = (value: number): string => {
const wholeSeconds = Math.trunc(value);
const hours = String(Math.trunc(wholeSeconds / 3_600)).padStart(2, '0');
const minutes = String(Math.trunc((wholeSeconds % 3_600) / 60)).padStart(2, '0');
return `${hours}:${minutes}`;
const minutes = String(Math.trunc(wholeSeconds / 60)).padStart(2, '0');
const seconds = String(wholeSeconds % 60).padStart(2, '0');
return `${minutes}:${seconds}`;
};
const resolveResetTurnTimeBase = (options: {
@@ -35,7 +35,6 @@ import {
resolveUniqueConfig,
readScenarioGeneralPoolClaim,
rollUniqueLotteryDetailed,
getNextTurnAt,
getBillByLevel,
LEGACY_DEFAULT_MAX_LEVEL,
orderLegacyActionLoggerFlush,
@@ -2196,7 +2195,7 @@ export const createReservedTurnHandler = async (options: {
aiDecisionDurationNs: generalAiDecisionDurationNs,
actionDurationNs: generalActionDurationNs,
});
let nextTurnAt = 'nextTurnAt' in generalResult ? generalResult.nextTurnAt : undefined;
const nextTurnAt = 'nextTurnAt' in generalResult ? generalResult.nextTurnAt : undefined;
options.reservedTurns.shiftGeneralTurns(currentGeneral.id, -1);
const worldMeta = asRecord(context.world.meta);
@@ -2241,13 +2240,6 @@ export const createReservedTurnHandler = async (options: {
Math.trunc(autorunLimitMinutes / turnMinutes);
}
const nextTurnTimeBase = readMetaNumber(currentGeneral.meta, 'nextTurnTimeBase', -1);
if (nextTurnTimeBase >= 0) {
const alignedNextTurn = nextTurnAt ?? getNextTurnAt(currentGeneral.turnTime, context.schedule);
nextTurnAt = new Date(alignedNextTurn.getTime() + nextTurnTimeBase * 1000);
delete currentGeneral.meta.nextTurnTimeBase;
}
const explicitlyRetired = generalResult.actionKey === 'che_은퇴' && generalResult.completed;
let lifecycleOutcome: 'active' | 'detached' | 'deleted' | 'retired' = explicitlyRetired
? 'retired'