fix tied conflict conquest order
This commit is contained in:
@@ -13,7 +13,16 @@ import type {
|
||||
WarAftermathTechContext,
|
||||
WarDiplomacyDelta,
|
||||
} from './types.js';
|
||||
import { clamp, clampMin, getMetaNumber, parseConflict, round, simpleSerialize } from './utils.js';
|
||||
import {
|
||||
clamp,
|
||||
clampMin,
|
||||
getMetaNumber,
|
||||
parseConflict,
|
||||
readConflictOrder,
|
||||
round,
|
||||
simpleSerialize,
|
||||
sortConflictEntries,
|
||||
} from './utils.js';
|
||||
|
||||
const META_DEAD = 'dead';
|
||||
const MAX_EXP_LEVEL = 255;
|
||||
@@ -124,15 +133,10 @@ const resolveConquerNation = (city: City, attackerNationId: number, nations: Nat
|
||||
return attackerNationId;
|
||||
}
|
||||
const activeNationIds = new Set(nations.map((nation) => nation.id));
|
||||
const entries = Object.entries(conflict)
|
||||
.map(([key, value]) => [Number(key), value] as const)
|
||||
.filter(
|
||||
([key, value]) =>
|
||||
Number.isFinite(key) &&
|
||||
typeof value === 'number' &&
|
||||
(key === attackerNationId || activeNationIds.has(key))
|
||||
)
|
||||
.sort(([, lhs], [, rhs]) => rhs - lhs);
|
||||
const entries = sortConflictEntries(conflict, readConflictOrder(city.meta)).filter(
|
||||
([key, value]) =>
|
||||
Number.isFinite(key) && typeof value === 'number' && (key === attackerNationId || activeNationIds.has(key))
|
||||
);
|
||||
if (!entries.length) {
|
||||
return attackerNationId;
|
||||
}
|
||||
@@ -396,6 +400,7 @@ const resolveConquerCity = <TriggerState extends GeneralTriggerState>(
|
||||
defenderCity.security = round(defenderCity.security * 0.7);
|
||||
defenderCity.nationId = conquerNationId;
|
||||
defenderCity.conflict = {};
|
||||
defenderCity.meta.conflict_order = [];
|
||||
|
||||
if (defenderCity.level > 3) {
|
||||
defenderCity.defence = config.defaultCityWall;
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { City, Nation } from '@sammo-ts/logic/domain/entities.js';
|
||||
import type { ActionLogger } from '@sammo-ts/logic/logging/actionLogger.js';
|
||||
import type { WarEngineConfig } from '../types.js';
|
||||
import type { WarCrewType } from '../crewType.js';
|
||||
import { clampMin, round, parseConflict, sortConflict } from '../utils.js';
|
||||
import { clampMin, parseConflict, readConflictOrder, round, sortConflict, sortConflictEntries } from '../utils.js';
|
||||
import { WarUnit } from './base.js';
|
||||
|
||||
// 도시 성벽 전투 유닛(legacy WarUnitCity 포팅).
|
||||
@@ -144,6 +144,12 @@ export class WarUnitCity extends WarUnit {
|
||||
|
||||
let dead = Math.max(1, this.dead);
|
||||
let isNew = false;
|
||||
const conflictOrder = readConflictOrder(this.city.meta).filter((id) => conflict[id] !== undefined);
|
||||
for (const id of Object.keys(conflict).map(Number)) {
|
||||
if (!conflictOrder.includes(id)) {
|
||||
conflictOrder.push(id);
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(conflict).length === 0 || this.getHP() === 0) {
|
||||
dead *= 1.05;
|
||||
@@ -157,10 +163,13 @@ export class WarUnitCity extends WarUnit {
|
||||
conflict[nationId] += dead;
|
||||
} else {
|
||||
conflict[nationId] = dead;
|
||||
conflictOrder.push(nationId);
|
||||
isNew = true;
|
||||
}
|
||||
|
||||
const sorted = sortConflict(conflict);
|
||||
const sortedEntries = sortConflictEntries(conflict, conflictOrder);
|
||||
this.city.meta.conflict_order = sortedEntries.map(([id]) => id);
|
||||
const sorted = sortConflict(conflict, conflictOrder);
|
||||
this.city.conflict = sorted;
|
||||
|
||||
return isNew;
|
||||
|
||||
@@ -77,6 +77,31 @@ export const parseConflict = (raw: TriggerValue | undefined): Record<number, num
|
||||
return Object.keys(result).length ? result : null;
|
||||
};
|
||||
|
||||
export const readConflictOrder = (meta: Record<string, TriggerValue>): number[] => {
|
||||
const raw = meta.conflict_order;
|
||||
if (!Array.isArray(raw)) {
|
||||
return [];
|
||||
}
|
||||
return raw.filter((value): value is number => typeof value === 'number' && Number.isInteger(value) && value > 0);
|
||||
};
|
||||
|
||||
export const sortConflictEntries = (
|
||||
conflict: Record<number, number>,
|
||||
preferredOrder: number[] = []
|
||||
): Array<readonly [number, number]> => {
|
||||
const orderIndex = new Map(preferredOrder.map((nationId, index) => [nationId, index]));
|
||||
return Object.entries(conflict)
|
||||
.map(([key, value], index) => [Number(key), value, index] as const)
|
||||
.filter(([key, value]) => Number.isFinite(key) && typeof value === 'number')
|
||||
.sort(
|
||||
([lhsKey, lhsValue, lhsIndex], [rhsKey, rhsValue, rhsIndex]) =>
|
||||
rhsValue - lhsValue ||
|
||||
(orderIndex.get(lhsKey) ?? preferredOrder.length + lhsIndex) -
|
||||
(orderIndex.get(rhsKey) ?? preferredOrder.length + rhsIndex)
|
||||
)
|
||||
.map(([key, value]) => [key, value] as const);
|
||||
};
|
||||
|
||||
export const stringifyConflict = (conflict: Record<number, number> | null): string => {
|
||||
if (!conflict) {
|
||||
return '{}';
|
||||
@@ -94,14 +119,12 @@ export const stringifyConflict = (conflict: Record<number, number> | null): stri
|
||||
return JSON.stringify(ordered);
|
||||
};
|
||||
|
||||
export const sortConflict = (conflict: Record<number, number>): Record<number, number> => {
|
||||
export const sortConflict = (
|
||||
conflict: Record<number, number>,
|
||||
preferredOrder: number[] = []
|
||||
): Record<number, number> => {
|
||||
const ordered: Record<number, number> = {};
|
||||
const entries = Object.entries(conflict)
|
||||
.map(([key, value]) => [Number(key), value] as const)
|
||||
.filter(([key, value]) => Number.isFinite(key) && typeof value === 'number')
|
||||
.sort(([, lhs], [, rhs]) => rhs - lhs);
|
||||
|
||||
for (const [key, value] of entries) {
|
||||
for (const [key, value] of sortConflictEntries(conflict, preferredOrder)) {
|
||||
ordered[key] = value;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user