fix: Ref 유산 포인트 적립 조건을 전면 정합화한다
능동 행동 31개 호출 지점과 소유자·NPC·통일 경계를 고정하고 사용자 저장값을 함께 갱신한다.\n\n최대 내정·임관, 천통 기여, 토너먼트, 숙련·베팅·랭크 계산과 환생 정산을 공통 계산기로 통합한다.
This commit is contained in:
@@ -142,12 +142,12 @@ export const createTournamentRewardFinalizer = async (options: {
|
||||
const nameMap = new Map<number, string>();
|
||||
const generals = await db.general.findMany({
|
||||
where: { id: { in: Array.from(rewardMap.keys()) } },
|
||||
select: { id: true, userId: true, name: true },
|
||||
select: { id: true, userId: true, name: true, npcState: true },
|
||||
});
|
||||
const userMap = new Map<number, string>();
|
||||
for (const general of generals) {
|
||||
nameMap.set(general.id, general.name);
|
||||
if (general.userId) {
|
||||
if (general.userId && general.npcState < 2) {
|
||||
userMap.set(general.id, general.userId);
|
||||
}
|
||||
}
|
||||
@@ -261,6 +261,15 @@ export const createTournamentRewardFinalizer = async (options: {
|
||||
update: { value: { increment: entry.value } },
|
||||
create: { userId: entry.userId!, key: 'tournament', value: entry.value },
|
||||
});
|
||||
const general = world.getGeneralById(entry.generalId);
|
||||
if (general) {
|
||||
world.updateGeneral(entry.generalId, {
|
||||
inheritancePoints: {
|
||||
...general.inheritancePoints,
|
||||
tournament: Number(general.inheritancePoints?.tournament ?? 0) + entry.value,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -1241,21 +1241,6 @@ export const createDatabaseTurnHooks = async (
|
||||
const meta = asRecord(state.meta);
|
||||
const serverId =
|
||||
typeof meta.serverId === 'string' && meta.serverId.trim() ? meta.serverId.trim() : 'default';
|
||||
await persistGeneralLifecycleEvents(
|
||||
prisma,
|
||||
lifecycleEvents,
|
||||
meta,
|
||||
asRecord(world.getScenarioConfig().const),
|
||||
world.gameTickToDate(state.clockTick ?? state.lastTurnTick ?? 0)
|
||||
);
|
||||
|
||||
if (accessScoreResetGeneralIds.length > 0) {
|
||||
await prisma.generalAccessLog.updateMany({
|
||||
where: { generalId: { in: accessScoreResetGeneralIds } },
|
||||
data: { refreshScore: 0 },
|
||||
});
|
||||
}
|
||||
|
||||
if (inheritancePointAdjustments.length > 0) {
|
||||
const grouped = new Map<string, { userId: string; key: string; amount: number }>();
|
||||
for (const entry of inheritancePointAdjustments) {
|
||||
@@ -1275,6 +1260,20 @@ export const createDatabaseTurnHooks = async (
|
||||
});
|
||||
}
|
||||
}
|
||||
await persistGeneralLifecycleEvents(
|
||||
prisma,
|
||||
lifecycleEvents,
|
||||
meta,
|
||||
asRecord(world.getScenarioConfig().const),
|
||||
world.gameTickToDate(state.clockTick ?? state.lastTurnTick ?? 0)
|
||||
);
|
||||
|
||||
if (accessScoreResetGeneralIds.length > 0) {
|
||||
await prisma.generalAccessLog.updateMany({
|
||||
where: { generalId: { in: accessScoreResetGeneralIds } },
|
||||
data: { refreshScore: 0 },
|
||||
});
|
||||
}
|
||||
|
||||
if (deletedNationSnapshots.length > 0) {
|
||||
const nationIds = deletedNationSnapshots.map((snapshot) => snapshot.nation.id);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { asRecord, HALL_OF_FAME_TYPES, resolveLegacyTextColor, type HallOfFameType } from '@sammo-ts/common';
|
||||
import type { GamePrisma, InputJsonValue } from '@sammo-ts/infra';
|
||||
import { LogCategory, LogScope } from '@sammo-ts/logic';
|
||||
import { computeInheritanceSettlementBreakdown } from '@sammo-ts/logic/inheritance/pointCalculation.js';
|
||||
|
||||
import type { GeneralLifecycleEvent } from './inMemoryWorld.js';
|
||||
|
||||
@@ -23,14 +24,6 @@ const readWorldNumber = (record: Record<string, unknown>, key: string, fallback:
|
||||
return value === 0 && record[key] === undefined ? fallback : Math.floor(value);
|
||||
};
|
||||
|
||||
const computeDexPoint = (meta: Record<string, unknown>): number => {
|
||||
let total = 0;
|
||||
for (let dex = 1; dex <= 5; dex += 1) {
|
||||
total += readNumber(meta, `dex${dex}`);
|
||||
}
|
||||
return total * 0.001;
|
||||
};
|
||||
|
||||
const settleInheritance = async (
|
||||
prisma: GamePrisma.TransactionClient,
|
||||
event: GeneralLifecycleEvent,
|
||||
@@ -71,8 +64,6 @@ const settleInheritance = async (
|
||||
}),
|
||||
]);
|
||||
const points = new Map(rows.map((row) => [row.key, row.value]));
|
||||
const ranks = new Map(rankRows.map((row) => [row.type, row.value]));
|
||||
const rank = (key: string): number => ranks.get(key) ?? readNumber(meta, `rank_${key}`);
|
||||
const previous = points.get('previous') ?? 0;
|
||||
const randomUniqueRefund = meta.inheritRandomUnique
|
||||
? readWorldNumber(configConst, 'inheritItemRandomPoint', 3000)
|
||||
@@ -81,30 +72,45 @@ const settleInheritance = async (
|
||||
? readWorldNumber(configConst, 'inheritSpecificSpecialPoint', 4000)
|
||||
: 0;
|
||||
const refund = randomUniqueRefund + specificSpecialRefund;
|
||||
const lived = readNumber(meta, 'inherit_lived_month');
|
||||
const maxBelong = readNumber(meta, 'inherit_max_belong') * 10;
|
||||
const maxDomestic = readNumber(meta, 'max_domestic_critical');
|
||||
const active = readNumber(meta, 'inherit_active_action') * 3;
|
||||
const combat = rank('warnum') * 5;
|
||||
const sabotage = (ranks.get('firenum') ?? readNumber(meta, 'firenum')) * 20;
|
||||
const dex = computeDexPoint(meta);
|
||||
const unifier = points.get('unifier') ?? 0;
|
||||
const earned = isRebirth
|
||||
? lived + active + combat + sabotage + dex * 0.5
|
||||
: lived + maxBelong + maxDomestic + active + combat + sabotage + dex + unifier;
|
||||
const total = Math.trunc(previous + refund + earned);
|
||||
const calculationMeta = {
|
||||
...meta,
|
||||
...Object.fromEntries(rankRows.map((row) => [row.type, row.value])),
|
||||
...Object.fromEntries(rankRows.map((row) => [`rank_${row.type}`, row.value])),
|
||||
};
|
||||
const settlement = computeInheritanceSettlementBreakdown(
|
||||
{
|
||||
meta: calculationMeta,
|
||||
inheritancePoints: Object.fromEntries(points),
|
||||
},
|
||||
isRebirth
|
||||
);
|
||||
const total = Math.trunc(previous + refund + settlement.totalEarned);
|
||||
|
||||
await prisma.inheritancePoint.upsert({
|
||||
where: { userId_key: { userId, key: 'previous' } },
|
||||
update: { value: total },
|
||||
create: { userId, key: 'previous', value: total },
|
||||
});
|
||||
await prisma.inheritancePoint.deleteMany({
|
||||
where: {
|
||||
userId,
|
||||
key: isRebirth ? { notIn: ['previous', 'unifier'] } : { not: 'previous' },
|
||||
},
|
||||
});
|
||||
if (isRebirth) {
|
||||
const retainedEntries = Object.entries(settlement.retained).filter(
|
||||
([key, value]) => key === 'max_belong' || points.has(key) || value !== 0
|
||||
);
|
||||
for (const [key, value] of retainedEntries) {
|
||||
await prisma.inheritancePoint.upsert({
|
||||
where: { userId_key: { userId, key } },
|
||||
update: { value },
|
||||
create: { userId, key, value },
|
||||
});
|
||||
}
|
||||
await prisma.inheritancePoint.deleteMany({
|
||||
where: {
|
||||
userId,
|
||||
key: { notIn: ['previous', ...retainedEntries.map(([key]) => key)] },
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await prisma.inheritancePoint.deleteMany({ where: { userId, key: { not: 'previous' } } });
|
||||
}
|
||||
const serverId =
|
||||
typeof worldMeta.serverId === 'string' && worldMeta.serverId.trim() ? worldMeta.serverId.trim() : 'default';
|
||||
await prisma.inheritanceResult.create({
|
||||
@@ -117,15 +123,10 @@ const settleInheritance = async (
|
||||
value: asJson({
|
||||
previous,
|
||||
refund,
|
||||
lived_month: lived,
|
||||
max_belong: maxBelong,
|
||||
max_domestic_critical: maxDomestic,
|
||||
active_action: active,
|
||||
combat,
|
||||
sabotage,
|
||||
dex: isRebirth ? dex * 0.5 : dex,
|
||||
unifier: isRebirth ? 0 : unifier,
|
||||
...settlement.earned,
|
||||
...(isRebirth ? { retained: settlement.retained } : {}),
|
||||
rebirth: isRebirth,
|
||||
total,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,97 +1,12 @@
|
||||
const DEX_LIMIT = 1_275_975;
|
||||
|
||||
interface InheritancePointGeneral {
|
||||
meta: Record<string, unknown>;
|
||||
inheritancePoints?: Record<string, number>;
|
||||
}
|
||||
|
||||
const STORED_INHERITANCE_KEYS = [
|
||||
'lived_month',
|
||||
'max_domestic_critical',
|
||||
'active_action',
|
||||
'unifier',
|
||||
'tournament',
|
||||
] as const;
|
||||
|
||||
export const ALL_MERGED_INHERITANCE_KEYS = [
|
||||
...STORED_INHERITANCE_KEYS,
|
||||
'max_belong',
|
||||
'combat',
|
||||
'sabotage',
|
||||
'dex',
|
||||
'betting',
|
||||
] as const;
|
||||
|
||||
export type MergedInheritanceKey = (typeof ALL_MERGED_INHERITANCE_KEYS)[number];
|
||||
|
||||
const readNumber = (source: Record<string, unknown>, key: string): number => {
|
||||
const value = source[key];
|
||||
if (typeof value === 'number' && Number.isFinite(value)) return value;
|
||||
if (typeof value === 'string') {
|
||||
const parsed = Number(value);
|
||||
if (Number.isFinite(parsed)) return parsed;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
const computeDexPoint = (general: InheritancePointGeneral): number => {
|
||||
let totalDexterity = 0;
|
||||
for (let index = 1; index <= 5; index += 1) {
|
||||
let dexterity = readNumber(general.meta, `dex${index}`);
|
||||
if (dexterity > DEX_LIMIT) {
|
||||
totalDexterity += (dexterity - DEX_LIMIT) / 3;
|
||||
dexterity = DEX_LIMIT;
|
||||
}
|
||||
totalDexterity += dexterity;
|
||||
}
|
||||
return totalDexterity * 0.001;
|
||||
};
|
||||
|
||||
const computeBettingPoint = (general: InheritancePointGeneral): number => {
|
||||
const wins = readNumber(general.meta, 'betwin');
|
||||
const gold = readNumber(general.meta, 'betgold');
|
||||
const wonGold = readNumber(general.meta, 'betwingold');
|
||||
const winRate = wonGold / Math.max(1000, gold);
|
||||
return wins * 10 * winRate ** 2;
|
||||
};
|
||||
|
||||
export const computeActiveInheritancePoint = (
|
||||
general: InheritancePointGeneral,
|
||||
key: MergedInheritanceKey,
|
||||
storedOverride?: number
|
||||
): number => {
|
||||
const stored = storedOverride ?? general.inheritancePoints?.[key] ?? 0;
|
||||
switch (key) {
|
||||
case 'lived_month': {
|
||||
const value = readNumber(general.meta, 'inherit_lived_month');
|
||||
return value !== 0 ? value : stored;
|
||||
}
|
||||
case 'max_domestic_critical': {
|
||||
const value = readNumber(general.meta, 'max_domestic_critical');
|
||||
return value !== 0 ? value : stored;
|
||||
}
|
||||
case 'active_action': {
|
||||
const value = readNumber(general.meta, 'inherit_active_action');
|
||||
return value !== 0 ? value * 3 : stored;
|
||||
}
|
||||
case 'unifier':
|
||||
case 'tournament':
|
||||
return stored;
|
||||
case 'max_belong':
|
||||
return (
|
||||
Math.max(
|
||||
readNumber(general.meta, 'belong'),
|
||||
readNumber(general.meta, 'max_belong'),
|
||||
readNumber(general.meta, 'inherit_max_belong')
|
||||
) * 10
|
||||
);
|
||||
case 'combat':
|
||||
return readNumber(general.meta, 'rank_warnum') * 5;
|
||||
case 'sabotage':
|
||||
return readNumber(general.meta, 'firenum') * 20;
|
||||
case 'dex':
|
||||
return computeDexPoint(general);
|
||||
case 'betting':
|
||||
return computeBettingPoint(general);
|
||||
}
|
||||
};
|
||||
export {
|
||||
ALL_MERGED_INHERITANCE_KEYS,
|
||||
computeActiveInheritancePoint,
|
||||
computeBettingInheritancePoint,
|
||||
computeDexInheritancePoint,
|
||||
computeInheritanceSettlementBreakdown,
|
||||
LEGACY_DEX_INHERITANCE_LIMIT,
|
||||
REBIRTH_INHERITANCE_COEFFICIENTS,
|
||||
type InheritancePointGeneral,
|
||||
type InheritanceSettlementBreakdown,
|
||||
type MergedInheritanceKey,
|
||||
} from '@sammo-ts/logic/inheritance/pointCalculation.js';
|
||||
|
||||
@@ -375,8 +375,15 @@ export const createUpdateNationLevelHandler = (options: {
|
||||
});
|
||||
}
|
||||
const isUnited = readNumber(state.meta.isunited ?? state.meta.isUnited);
|
||||
if (chief?.userId && isUnited === 0) {
|
||||
world.queueInheritancePointAdjustment(chief.userId, 'unifier', 250 * levelDiff);
|
||||
if (chief?.userId && chief.npcState < 2 && isUnited === 0) {
|
||||
const amount = 250 * levelDiff;
|
||||
world.queueInheritancePointAdjustment(chief.userId, 'unifier', amount);
|
||||
world.updateGeneral(chief.id, {
|
||||
inheritancePoints: {
|
||||
...chief.inheritancePoints,
|
||||
unifier: readNumber(chief.inheritancePoints?.unifier) + amount,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -268,6 +268,7 @@ const readConfigNumber = (config: ScenarioConfig, key: string, fallback: number)
|
||||
|
||||
const cloneTurnGeneral = (general: TurnGeneral): TurnGeneral => ({
|
||||
...general,
|
||||
...(general.inheritancePoints ? { inheritancePoints: { ...general.inheritancePoints } } : {}),
|
||||
stats: { ...general.stats },
|
||||
role: {
|
||||
...general.role,
|
||||
@@ -372,6 +373,25 @@ const readMetaNumber = (meta: Record<string, unknown>, key: string, fallback: nu
|
||||
return fallback;
|
||||
};
|
||||
|
||||
const readInheritanceNumber = (value: unknown): number => {
|
||||
if (typeof value === 'number' && Number.isFinite(value)) {
|
||||
return value;
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
const parsed = Number(value);
|
||||
return Number.isFinite(parsed) ? parsed : 0;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
const canAccumulateInheritance = (
|
||||
general: Pick<TurnGeneral, 'userId' | 'npcState'>,
|
||||
worldMeta: Record<string, unknown>
|
||||
): general is Pick<TurnGeneral, 'userId' | 'npcState'> & { userId: string } =>
|
||||
Boolean(general.userId) &&
|
||||
general.npcState < 2 &&
|
||||
readMetaNumber(worldMeta, 'isunited', readMetaNumber(worldMeta, 'isUnited', 0)) === 0;
|
||||
|
||||
const readMetaBool = (meta: Record<string, unknown>, key: string, fallback = false): boolean => {
|
||||
const value = meta[key];
|
||||
if (typeof value === 'boolean') {
|
||||
@@ -1214,6 +1234,34 @@ export const createReservedTurnHandler = async (options: {
|
||||
currentGeneral = resolution.general as TurnGeneral;
|
||||
currentCity = resolution.city ?? currentCity;
|
||||
currentNation = resolution.nation ?? currentNation;
|
||||
const inheritanceEnabled = canAccumulateInheritance(currentGeneral, asRecord(context.world.meta));
|
||||
const inheritanceUserId = inheritanceEnabled ? currentGeneral.userId : null;
|
||||
if (actionKey === 'che_인재탐색') {
|
||||
const previousActive = readMetaNumber(
|
||||
asRecord(generalBeforeExecution.meta),
|
||||
'inherit_active_action',
|
||||
0
|
||||
);
|
||||
const nextActive = readMetaNumber(asRecord(currentGeneral.meta), 'inherit_active_action', 0);
|
||||
if (!inheritanceUserId) {
|
||||
currentGeneral = {
|
||||
...currentGeneral,
|
||||
meta: { ...currentGeneral.meta, inherit_active_action: previousActive },
|
||||
};
|
||||
} else if (nextActive > previousActive) {
|
||||
const pointAmount = (nextActive - previousActive) * 3;
|
||||
worldRef?.queueInheritancePointAdjustment(inheritanceUserId, 'active_action', pointAmount);
|
||||
currentGeneral = {
|
||||
...currentGeneral,
|
||||
inheritancePoints: {
|
||||
...currentGeneral.inheritancePoints,
|
||||
active_action:
|
||||
readInheritanceNumber(currentGeneral.inheritancePoints?.active_action) +
|
||||
pointAmount,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
if (!resolution.alternative && !usedFallback && resolution.completed) {
|
||||
currentGeneral = applyLegacyGeneralProgression(
|
||||
currentGeneral,
|
||||
@@ -1229,13 +1277,20 @@ export const createReservedTurnHandler = async (options: {
|
||||
!usedFallback &&
|
||||
resolution.completed &&
|
||||
definition.countsAsInheritanceActiveAction &&
|
||||
Boolean(currentGeneral.userId) &&
|
||||
currentGeneral.npcState < 2
|
||||
inheritanceUserId
|
||||
) {
|
||||
const meta = { ...currentGeneral.meta };
|
||||
const active = typeof meta.inherit_active_action === 'number' ? meta.inherit_active_action : 0;
|
||||
meta.inherit_active_action = active + 1;
|
||||
currentGeneral = { ...currentGeneral, meta };
|
||||
worldRef?.queueInheritancePointAdjustment(inheritanceUserId, 'active_action', 3);
|
||||
currentGeneral = {
|
||||
...currentGeneral,
|
||||
meta,
|
||||
inheritancePoints: {
|
||||
...currentGeneral.inheritancePoints,
|
||||
active_action: readInheritanceNumber(currentGeneral.inheritancePoints?.active_action) + 3,
|
||||
},
|
||||
};
|
||||
}
|
||||
if (
|
||||
!resolution.alternative &&
|
||||
@@ -1243,17 +1298,53 @@ export const createReservedTurnHandler = async (options: {
|
||||
!usedFallback &&
|
||||
resolution.completed &&
|
||||
executionDefinition.getInheritanceActiveActionAmount &&
|
||||
Boolean(currentGeneral.userId) &&
|
||||
currentGeneral.npcState < 2
|
||||
inheritanceEnabled
|
||||
) {
|
||||
const amount = executionDefinition.getInheritanceActiveActionAmount(actionContext, actionArgs);
|
||||
if (Number.isFinite(amount) && amount !== 0) {
|
||||
const meta = { ...currentGeneral.meta };
|
||||
const active = typeof meta.inherit_active_action === 'number' ? meta.inherit_active_action : 0;
|
||||
meta.inherit_active_action = active + amount;
|
||||
currentGeneral = { ...currentGeneral, meta };
|
||||
const pointAmount = amount * 3;
|
||||
worldRef?.queueInheritancePointAdjustment(inheritanceUserId!, 'active_action', pointAmount);
|
||||
currentGeneral = {
|
||||
...currentGeneral,
|
||||
meta,
|
||||
inheritancePoints: {
|
||||
...currentGeneral.inheritancePoints,
|
||||
active_action:
|
||||
readInheritanceNumber(currentGeneral.inheritancePoints?.active_action) +
|
||||
pointAmount,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
if (
|
||||
!resolution.alternative &&
|
||||
kind === 'general' &&
|
||||
!usedFallback &&
|
||||
resolution.completed &&
|
||||
inheritanceUserId
|
||||
) {
|
||||
const inheritancePoints = { ...currentGeneral.inheritancePoints };
|
||||
const storedDomesticMaximum = readInheritanceNumber(inheritancePoints.max_domestic_critical);
|
||||
const currentDomesticStreak = readInheritanceNumber(
|
||||
asRecord(currentGeneral.meta).max_domestic_critical
|
||||
);
|
||||
if (currentDomesticStreak > storedDomesticMaximum) {
|
||||
worldRef?.queueInheritancePointAdjustment(
|
||||
inheritanceUserId,
|
||||
'max_domestic_critical',
|
||||
currentDomesticStreak - storedDomesticMaximum
|
||||
);
|
||||
inheritancePoints.max_domestic_critical = currentDomesticStreak;
|
||||
}
|
||||
if (actionKey === 'che_건국') {
|
||||
worldRef?.queueInheritancePointAdjustment(inheritanceUserId, 'unifier', 250);
|
||||
inheritancePoints.unifier = readInheritanceNumber(inheritancePoints.unifier) + 250;
|
||||
}
|
||||
currentGeneral = { ...currentGeneral, inheritancePoints };
|
||||
}
|
||||
|
||||
if (!currentNation && resolution.created?.nations) {
|
||||
currentNation =
|
||||
@@ -1551,9 +1642,14 @@ export const createReservedTurnHandler = async (options: {
|
||||
|
||||
const lifecycleBefore = cloneTurnGeneral(currentGeneral);
|
||||
currentGeneral = cloneTurnGeneral(currentGeneral);
|
||||
if (currentGeneral.npcState < 2) {
|
||||
if (canAccumulateInheritance(currentGeneral, asRecord(context.world.meta))) {
|
||||
currentGeneral.meta.inherit_lived_month =
|
||||
readMetaNumber(currentGeneral.meta, 'inherit_lived_month', 0) + 1;
|
||||
worldRef?.queueInheritancePointAdjustment(currentGeneral.userId, 'lived_month', 1);
|
||||
currentGeneral.inheritancePoints = {
|
||||
...currentGeneral.inheritancePoints,
|
||||
lived_month: readInheritanceNumber(currentGeneral.inheritancePoints?.lived_month) + 1,
|
||||
};
|
||||
}
|
||||
const preprocessRng = new RandUtil(
|
||||
new LiteHashDRBG(
|
||||
@@ -1626,10 +1722,7 @@ export const createReservedTurnHandler = async (options: {
|
||||
currentGeneral.crew = 0;
|
||||
currentGeneral.rice = 0;
|
||||
logs.push(
|
||||
createGeneralActionLog(
|
||||
currentGeneral.id,
|
||||
'군량이 모자라 병사들이 <R>소집해제</>되었습니다!'
|
||||
)
|
||||
createGeneralActionLog(currentGeneral.id, '군량이 모자라 병사들이 <R>소집해제</>되었습니다!')
|
||||
);
|
||||
preTurnContext.skill.activate('pre.소집해제');
|
||||
}
|
||||
@@ -2125,10 +2218,7 @@ export const createReservedTurnHandler = async (options: {
|
||||
currentGeneral = resetRetiredGeneral(currentGeneral);
|
||||
lifecycleOutcome = 'retired';
|
||||
logs.push(
|
||||
createGeneralActionLog(
|
||||
currentGeneral.id,
|
||||
'나이가 들어 <R>은퇴</>하고 자손에게 자리를 물려줍니다.'
|
||||
)
|
||||
createGeneralActionLog(currentGeneral.id, '나이가 들어 <R>은퇴</>하고 자손에게 자리를 물려줍니다.')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2384,11 +2474,17 @@ export const createImmediateGeneralActionExecutor = async (options: {
|
||||
if (
|
||||
Number.isFinite(activeActionAmount) &&
|
||||
activeActionAmount !== 0 &&
|
||||
nextGeneral.userId &&
|
||||
nextGeneral.npcState < 2
|
||||
canAccumulateInheritance(nextGeneral, asRecord(state.meta))
|
||||
) {
|
||||
const pointAmount = activeActionAmount * 3;
|
||||
options.world.queueInheritancePointAdjustment(nextGeneral.userId, 'active_action', pointAmount);
|
||||
nextGeneral = {
|
||||
...nextGeneral,
|
||||
inheritancePoints: {
|
||||
...nextGeneral.inheritancePoints,
|
||||
active_action:
|
||||
readInheritanceNumber(nextGeneral.inheritancePoints?.active_action) + pointAmount,
|
||||
},
|
||||
meta: {
|
||||
...nextGeneral.meta,
|
||||
inherit_active_action:
|
||||
|
||||
Reference in New Issue
Block a user