test: 공백지 시나리오의 비급 확장 범위를 고정
Ref의 시나리오별 전투 특기 아이템 계약과 Core 리소스 합성 범위를 문서화한다. 일반 공백지로 공통 확장이 누출되지 않고 특수 공백지의 개별 목록과 수량이 보존되는지 회귀 테스트한다.
This commit is contained in:
@@ -5,6 +5,16 @@ import { describe, expect, it } from 'vitest';
|
|||||||
|
|
||||||
import { loadScenarioDefinitionById, resolveScenarioDefaultsPath } from '../src/scenario/scenarioLoader.js';
|
import { loadScenarioDefinitionById, resolveScenarioDefaultsPath } from '../src/scenario/scenarioLoader.js';
|
||||||
|
|
||||||
|
type LoadedScenario = Awaited<ReturnType<typeof loadScenarioDefinitionById>>;
|
||||||
|
|
||||||
|
const readItemSlot = (scenario: LoadedScenario, slot: string): Record<string, number> => {
|
||||||
|
const allItems = scenario.config.const.allItems as Record<string, Record<string, number>> | undefined;
|
||||||
|
return allItems?.[slot] ?? {};
|
||||||
|
};
|
||||||
|
|
||||||
|
const readAvailableSpecialWar = (scenario: LoadedScenario): string[] =>
|
||||||
|
(scenario.config.const.availableSpecialWar as string[] | undefined) ?? [];
|
||||||
|
|
||||||
describe('tracked scenario resources', () => {
|
describe('tracked scenario resources', () => {
|
||||||
it('loads every scenario through its composed resource graph', async () => {
|
it('loads every scenario through its composed resource graph', async () => {
|
||||||
const scenarioRoot = path.dirname(resolveScenarioDefaultsPath());
|
const scenarioRoot = path.dirname(resolveScenarioDefaultsPath());
|
||||||
@@ -35,4 +45,36 @@ describe('tracked scenario resources', () => {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('keeps the buyable war-special pack scoped to each Ref scenario contract', async () => {
|
||||||
|
const [ordinaryBlank, legacySecretBlank, mirrorBlank, multiUnitBlank, moreEffectBlank, composedAddon] =
|
||||||
|
await Promise.all(
|
||||||
|
[0, 902, 910, 912, 913, 2141].map((scenarioId) => loadScenarioDefinitionById(scenarioId))
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Object.keys(readItemSlot(ordinaryBlank, 'item')).filter((key) => key.startsWith('event_전투특기_'))
|
||||||
|
).toEqual([]);
|
||||||
|
|
||||||
|
const legacySecretItems = readItemSlot(legacySecretBlank, 'item');
|
||||||
|
expect(Object.keys(legacySecretItems).filter((key) => key.startsWith('event_전투특기_'))).toHaveLength(19);
|
||||||
|
expect(legacySecretItems).not.toHaveProperty('event_전투특기_견고');
|
||||||
|
expect(readAvailableSpecialWar(legacySecretBlank)).not.toContain('che_견고');
|
||||||
|
|
||||||
|
const mirrorItems = readItemSlot(mirrorBlank, 'item');
|
||||||
|
expect(Object.keys(mirrorItems).filter((key) => key.startsWith('event_전투특기_'))).toHaveLength(19);
|
||||||
|
expect(mirrorItems).not.toHaveProperty('event_전투특기_척사');
|
||||||
|
expect(readAvailableSpecialWar(mirrorBlank)).not.toContain('che_척사');
|
||||||
|
|
||||||
|
const multiUnitItems = readItemSlot(multiUnitBlank, 'item');
|
||||||
|
expect(Object.keys(multiUnitItems).filter((key) => key.startsWith('event_전투특기_'))).toHaveLength(19);
|
||||||
|
expect(multiUnitItems).not.toHaveProperty('event_전투특기_견고');
|
||||||
|
|
||||||
|
const moreEffectItems = readItemSlot(moreEffectBlank, 'item');
|
||||||
|
const composedAddonItems = readItemSlot(composedAddon, 'item');
|
||||||
|
expect(Object.keys(moreEffectItems).filter((key) => key.startsWith('event_전투특기_'))).toHaveLength(20);
|
||||||
|
expect(Object.keys(composedAddonItems).filter((key) => key.startsWith('event_전투특기_'))).toHaveLength(20);
|
||||||
|
expect(readItemSlot(moreEffectBlank, 'horse').che_명마_07_백마).toBe(4);
|
||||||
|
expect(readItemSlot(composedAddon, 'horse').che_명마_07_백마).toBe(2);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -58,6 +58,26 @@
|
|||||||
시나리오 80개 중 70개가 확장을 사용합니다. 구매 가능한 전특·유니크 표를
|
시나리오 80개 중 70개가 확장을 사용합니다. 구매 가능한 전특·유니크 표를
|
||||||
사용하는 10개 시나리오는 같은 item 확장을 참조합니다.
|
사용하는 10개 시나리오는 같은 item 확장을 참조합니다.
|
||||||
|
|
||||||
|
## 적용 범위와 Ref 차이
|
||||||
|
|
||||||
|
Ref에는 설치 시 선택한 시나리오에 별도 기능 팩을 덧붙이는 전역 애드온 단계가
|
||||||
|
없습니다. 각 `scenario_*.json`이 `const.allItems`와
|
||||||
|
`const.availableSpecialWar`를 직접 소유하고, `Scenario::buildConf()`가 그 값을
|
||||||
|
`GameConst`에 반영합니다.
|
||||||
|
|
||||||
|
Core의 `extends`는 이 중복 값을 소스에서 재사용하기 위한 합성 기능입니다.
|
||||||
|
설치 시 임의의 시나리오에 전역으로 적용되는 옵션이 아니며, 해당
|
||||||
|
`scenario_*.json`이 확장을 명시한 경우에만 로더와 Gateway 미리보기가 합성합니다.
|
||||||
|
따라서 일반 공백지 시나리오에는
|
||||||
|
`extensions/items/buyable-war-special-uniques.json`이 암묵적으로 적용되지 않습니다.
|
||||||
|
|
||||||
|
공백지 중 `scenario_902`(천지비급), `scenario_910`(거울세계),
|
||||||
|
`scenario_912`(다병종), `scenario_913`(무한대흥)은 Ref 자체가 전투 특기 아이템
|
||||||
|
풀을 직접 정의합니다. 이 네 시나리오는 최신 공통 확장과 항목 또는 유니크 수량이
|
||||||
|
서로 달라 직접 정의를 유지합니다. 특히 902·912는 `견고`가 없는 19종, 910은
|
||||||
|
`척사`가 없는 19종이며, 913은 20종이지만 일부 유니크 수량이 공통 확장의 2개가
|
||||||
|
아닌 4개입니다. 이를 공통 확장으로 바꾸면 Ref 설치 결과가 달라집니다.
|
||||||
|
|
||||||
## 검증
|
## 검증
|
||||||
|
|
||||||
확장 파일을 추가하거나 합성 순서를 바꾼 뒤 다음 검사를 실행해 주세요.
|
확장 파일을 추가하거나 합성 순서를 바꾼 뒤 다음 검사를 실행해 주세요.
|
||||||
|
|||||||
Reference in New Issue
Block a user