feat(map): 인카운터를 encounters.json 로스터 기반 모델 인스턴스 배치로 개편
MONSTER_VARIANTS 랜덤 외형 제거(외형=enemies.json appearance로 정체성 고정). buildMonsterInstance로 종별 모델(monster-<id>) 인스턴스 배치, 준비도 가드로 appearance 미보유 로스터 맵은 보존(Task 2 RUID 수확 후 재생성). gen-combat-monster는 codeblock 생성만(맵 부착은 encounters 생성기로 흡수). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011xhLoQbJvQYL65kBtDNDTy
This commit is contained in:
@@ -1,10 +1,8 @@
|
||||
import { readFileSync, writeFileSync } from 'node:fs';
|
||||
import { writeFileSync } from 'node:fs';
|
||||
|
||||
// 맵 몬스터에 적 타입(EnemyId)을 부여하고, BeginPlay 시 /common 컨트롤러에 자기등록하는 마커.
|
||||
// 카드 전투 시 컨트롤러가 등록 목록으로 인카운터를 구성한다.
|
||||
const MAP_NUMBERS = Array.from({ length: 5 }, (_, i) => i + 1); // map01~05
|
||||
const NAME_TO_ENEMY = { '주황버섯': 'orange_mushroom', '파란버섯': 'blue_mushroom' };
|
||||
const DEFAULT_ENEMY = 'orange_mushroom';
|
||||
// 카드 전투용 자기등록 마커 codeblock(CombatMonster) 생성.
|
||||
// BeginPlay 시 /common 컨트롤러에 자기등록해 인카운터를 구성한다.
|
||||
// 맵 부착 값(EnemyId/Group)은 gen-map-encounters.mjs가 인스턴스에 직접 기록한다.
|
||||
|
||||
function prop(Type, Name, DefaultValue = 'nil') {
|
||||
return { Type, DefaultValue, SyncDirection: 0, Attributes: [], Name };
|
||||
@@ -49,39 +47,5 @@ eventId = _TimerService:SetTimerRepeat(reg, 0.1)`),
|
||||
writeFileSync('RootDesk/MyDesk/CombatMonster.codeblock', JSON.stringify(cb, null, 2) + '\n', 'utf8');
|
||||
}
|
||||
|
||||
const isMonster = (e) => typeof e.componentNames === 'string' && e.componentNames.includes('script.Monster');
|
||||
|
||||
function patchMap(nn) {
|
||||
const tag = String(nn).padStart(2, '0');
|
||||
const file = `map/map${tag}.map`;
|
||||
const map = JSON.parse(readFileSync(file, 'utf8'));
|
||||
let added = 0, kept = 0;
|
||||
for (const e of map.ContentProto.Entities.filter(isMonster)) {
|
||||
const comps = e.jsonString && e.jsonString['@components'];
|
||||
if (!Array.isArray(comps)) {
|
||||
console.warn(`[gen-combat-monster] entity "${(e.jsonString && e.jsonString.name) || e.path}" has no @components — skipped`);
|
||||
continue;
|
||||
}
|
||||
const name = (e.jsonString && e.jsonString.name) || '';
|
||||
const existing = comps.find((c) => c['@type'] === 'script.CombatMonster');
|
||||
if (existing) {
|
||||
// 사용자가 메이커에서 설정한 값 보존 — 누락된 키만 기본값 채움
|
||||
if (existing.Enable === undefined) existing.Enable = true;
|
||||
if (existing.EnemyId == null) existing.EnemyId = NAME_TO_ENEMY[name] || DEFAULT_ENEMY;
|
||||
if (existing.Group == null) existing.Group = 'combat';
|
||||
kept++;
|
||||
} else {
|
||||
comps.push({ '@type': 'script.CombatMonster', Enable: true, EnemyId: NAME_TO_ENEMY[name] || DEFAULT_ENEMY, Group: 'combat' });
|
||||
added++;
|
||||
}
|
||||
const names = (e.componentNames || '').split(',').filter((s) => s && s !== 'script.CombatMonster');
|
||||
names.push('script.CombatMonster');
|
||||
e.componentNames = names.join(',');
|
||||
}
|
||||
writeFileSync(file, JSON.stringify(map, null, 2), 'utf8');
|
||||
return `map${tag}(+${added}/keep${kept})`;
|
||||
}
|
||||
|
||||
writeCodeblock();
|
||||
const patched = MAP_NUMBERS.map(patchMap);
|
||||
console.log('CombatMonster codeblock written; patched maps:', patched.join(', '));
|
||||
console.log('CombatMonster codeblock written.');
|
||||
|
||||
Reference in New Issue
Block a user