diff --git a/data/monster-slots.json b/data/monster-slots.json new file mode 100644 index 0000000..494d402 --- /dev/null +++ b/data/monster-slots.json @@ -0,0 +1,6 @@ +[ + { "x": -480, "y": 300 }, + { "x": -160, "y": 300 }, + { "x": 160, "y": 300 }, + { "x": 480, "y": 300 } +] diff --git a/tools/deck/gen-slaydeck.mjs b/tools/deck/gen-slaydeck.mjs index a5ed3f1..35d2140 100644 --- a/tools/deck/gen-slaydeck.mjs +++ b/tools/deck/gen-slaydeck.mjs @@ -256,6 +256,9 @@ function entity({ id, path, modelId, entryId, componentNames, components, displa } function upsertUi() { + if (SLOTS.length < MAX_MONSTERS) { + throw new Error(`[gen-slaydeck] monster-slots.json 항목(${SLOTS.length}) < MAX_MONSTERS(${MAX_MONSTERS})`); + } const ui = JSON.parse(readFileSync(UI_FILE, 'utf8')); const E = ui.ContentProto.Entities; ui.ContentProto.Entities = E.filter((e) => !e.path.startsWith('/ui/DefaultGroup/DeckHud') && !e.path.startsWith('/ui/DefaultGroup/CombatHud') && !e.path.startsWith('/ui/DefaultGroup/RewardHud') && !e.path.startsWith('/ui/DefaultGroup/MapHud') && !e.path.startsWith('/ui/DefaultGroup/ShopHud') && !e.path.startsWith('/ui/DefaultGroup/RestHud') && !e.path.startsWith('/ui/DefaultGroup/MainMenu')); @@ -432,40 +435,73 @@ function upsertUi() { sprite({ color: TRANSPARENT }), ], })); - combat.push(entity({ - id: guid('cmb', 1), - path: '/ui/DefaultGroup/CombatHud/EnemyBg', - modelId: 'uisprite', - entryId: 'UISprite', - componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent', - displayOrder: 0, - components: [ - transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 380, y: 170 }, pos: { x: 0, y: 300 }, align: ALIGN_CENTER }), - sprite({ color: PANEL_BG, type: 1 }), - ], - })); - const enemyTexts = [ - ['EnemyName', { x: 0, y: 358 }, { x: 360, y: 44 }, ACTIVE_ENEMY.name, 28, true, GOLD], - ['EnemyHp', { x: 0, y: 316 }, { x: 360, y: 40 }, `HP ${ACTIVE_ENEMY.maxHp}/${ACTIVE_ENEMY.maxHp}`, 24, true, { r: 1, g: 1, b: 1, a: 1 }], - ['EnemyBlock', { x: 0, y: 280 }, { x: 360, y: 36 }, '방어 0', 20, false, { r: 0.6, g: 0.8, b: 1, a: 1 }], - ['EnemyIntent', { x: 0, y: 244 }, { x: 360, y: 38 }, intentText(ACTIVE_ENEMY.intents[0]), 22, true, { r: 1, g: 0.72, b: 0.5, a: 1 }], - ]; - let cmbN = 2; - for (const [suffix, pos, size, value, fontSize, bold, color] of enemyTexts) { - combat.push(entity({ - id: guid('cmb', cmbN++), - path: `/ui/DefaultGroup/CombatHud/${suffix}`, - modelId: 'uitext', - entryId: 'UIText', - componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent', - displayOrder: enemyTexts.findIndex(([s]) => s === suffix) + 1, + const SLOT_W = 140, SLOT_H = 96; + for (let i = 1; i <= MAX_MONSTERS; i++) { + const base = `/ui/DefaultGroup/CombatHud/MonsterSlot${i}`; + const slot = entity({ + id: guid('cmb', 40 + i), + path: base, + modelId: 'uisprite', entryId: 'UISprite', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent', + displayOrder: 20 + i, components: [ - transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size, pos }), + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: SLOT_W, y: SLOT_H }, pos: { x: (i - 2.5) * 320, y: 300 } }), + sprite({ color: { r: 0, g: 0, b: 0, a: 0.0001 }, type: 1, raycast: true }), + button(), + ], + }); + slot.jsonString.enable = false; + combat.push(slot); + combat.push(entity({ + id: guid('cmb', 60 + i), path: `${base}/Name`, modelId: 'uitext', entryId: 'UIText', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent', + displayOrder: 0, + components: [ + transform({ parentW: SLOT_W, parentH: SLOT_H, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: SLOT_W, y: 30 }, pos: { x: 0, y: 34 } }), sprite({ color: TRANSPARENT }), - text({ value, fontSize, bold, color }), + text({ value: '', fontSize: 20, bold: true, color: GOLD, alignment: 4 }), + ], + })); + combat.push(entity({ + id: guid('cmb', 80 + i), path: `${base}/Hp`, modelId: 'uitext', entryId: 'UIText', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent', + displayOrder: 1, + components: [ + transform({ parentW: SLOT_W, parentH: SLOT_H, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: SLOT_W, y: 26 }, pos: { x: 0, y: 6 } }), + sprite({ color: TRANSPARENT }), + text({ value: '', fontSize: 18, bold: true, color: { r: 1, g: 1, b: 1, a: 1 }, alignment: 4 }), + ], + })); + combat.push(entity({ + id: guid('cmb', 100 + i), path: `${base}/HpBarBg`, modelId: 'uisprite', entryId: 'UISprite', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent', + displayOrder: 2, + components: [ + transform({ parentW: SLOT_W, parentH: SLOT_H, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 120, y: 14 }, pos: { x: 0, y: -14 } }), + sprite({ color: { r: 0.18, g: 0.05, b: 0.06, a: 1 }, type: 1 }), + ], + })); + combat.push(entity({ + id: guid('cmb', 120 + i), path: `${base}/HpBarFill`, modelId: 'uisprite', entryId: 'UISprite', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent', + displayOrder: 3, + components: [ + transform({ parentW: SLOT_W, parentH: SLOT_H, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0, y: 0.5 }, size: { x: 120, y: 14 }, pos: { x: -60, y: -14 } }), + sprite({ color: { r: 0.86, g: 0.35, b: 0.32, a: 1 }, type: 1 }), + ], + })); + combat.push(entity({ + id: guid('cmb', 140 + i), path: `${base}/Intent`, modelId: 'uitext', entryId: 'UIText', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent', + displayOrder: 4, + components: [ + transform({ parentW: SLOT_W, parentH: SLOT_H, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: SLOT_W + 40, y: 24 }, pos: { x: 0, y: -36 } }), + sprite({ color: TRANSPARENT }), + text({ value: '', fontSize: 17, bold: true, color: { r: 1, g: 0.72, b: 0.5, a: 1 }, alignment: 4 }), ], })); } + let cmbN = 2; combat.push(entity({ id: guid('cmb', cmbN++), path: '/ui/DefaultGroup/CombatHud/PlayerBg',