84 lines
3.7 KiB
JavaScript
84 lines
3.7 KiB
JavaScript
import { readFileSync, writeFileSync } from 'node:fs';
|
|
|
|
// 맵 몬스터에 적 타입(EnemyId)을 부여하고, BeginPlay 시 /common 컨트롤러에 자기등록하는 마커.
|
|
// 카드 전투 시 컨트롤러가 등록 목록으로 인카운터를 구성한다.
|
|
const MAP_NUMBERS = Array.from({ length: 11 }, (_, i) => i + 1); // map01~11
|
|
const NAME_TO_ENEMY = { '주황버섯': 'orange_mushroom', '파란버섯': 'blue_mushroom' };
|
|
const DEFAULT_ENEMY = 'orange_mushroom';
|
|
|
|
function prop(Type, Name, DefaultValue = 'nil') {
|
|
return { Type, DefaultValue, SyncDirection: 0, Attributes: [], Name };
|
|
}
|
|
function method(Name, Code, Arguments = [], ExecSpace = 6) {
|
|
return {
|
|
Return: { Type: 'void', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: null },
|
|
Arguments, Code, Scope: 2, ExecSpace, Attributes: [], Name,
|
|
};
|
|
}
|
|
|
|
function writeCodeblock() {
|
|
const cb = {
|
|
Id: '', GameId: '', EntryKey: 'codeblock://combatmonster', ContentType: 'x-mod/codeblock',
|
|
Content: '', Usage: 0, UsePublish: 1, UseService: 0, CoreVersion: '26.5.0.0', StudioVersion: '', DynamicLoading: 0,
|
|
ContentProto: { Use: 'Json', Json: {
|
|
CoreVersion: { Major: 0, Minor: 2 }, ScriptVersion: { Major: 1, Minor: 0 },
|
|
Description: '', Id: 'CombatMonster', Language: 1, Name: 'CombatMonster', Type: 1, Source: 0, Target: null,
|
|
Properties: [prop('string', 'EnemyId', '""'), prop('string', 'Group', '"combat"'), prop('number', 'RegTries', '0')],
|
|
Methods: [
|
|
method('OnBeginPlay', `self.RegTries = 0
|
|
local eventId = 0
|
|
local function reg()
|
|
self.RegTries = self.RegTries + 1
|
|
local c = _EntityService:GetEntityByPath("/common")
|
|
if c ~= nil and c.SlayDeckController ~= nil then
|
|
c.SlayDeckController:RegisterMonster(self.Entity, self.EnemyId, self.Group)
|
|
_TimerService:ClearTimer(eventId)
|
|
elseif self.RegTries > 50 then
|
|
_TimerService:ClearTimer(eventId)
|
|
end
|
|
end
|
|
eventId = _TimerService:SetTimerRepeat(reg, 0.1)`),
|
|
],
|
|
EntityEventHandlers: [],
|
|
} },
|
|
};
|
|
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 === undefined) existing.EnemyId = NAME_TO_ENEMY[name] || DEFAULT_ENEMY;
|
|
if (existing.Group === undefined) 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(', '));
|