feat(combat-ui): 플레이어 패널(HP바·방어 뱃지) + SetHpBar 폭 인자

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 01:58:01 +09:00
parent d1f894a802
commit 24e6aca305

View File

@@ -898,37 +898,75 @@ function upsertUi() {
})); }));
} }
let cmbN = 2; let cmbN = 2;
const PP = '/ui/DefaultGroup/CombatHud/PlayerPanel';
combat.push(entity({ combat.push(entity({
id: guid('cmb', cmbN++), id: guid('cmb', 210), path: PP, modelId: 'uisprite', entryId: 'UISprite',
path: '/ui/DefaultGroup/CombatHud/PlayerBg',
modelId: 'uisprite',
entryId: 'UISprite',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent', componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
displayOrder: 5, displayOrder: 5,
components: [ components: [
transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 300, y: 110 }, pos: { x: -760, y: -260 }, align: ALIGN_CENTER }), transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 300, y: 96 }, pos: { x: -760, y: -480 }, align: ALIGN_CENTER }),
sprite({ color: PANEL_BG, type: 1 }), sprite({ color: PANEL_BG, type: 1 }),
], ],
})); }));
const playerTexts = [ combat.push(entity({
['PlayerHp', { x: -760, y: -238 }, { x: 280, y: 44 }, 'HP 80/80', 26, true, { r: 1, g: 1, b: 1, a: 1 }], id: guid('cmb', 211), path: `${PP}/Name`, modelId: 'uitext', entryId: 'UIText',
['PlayerBlock', { x: -760, y: -284 }, { x: 280, y: 38 }, '방어 0', 22, false, { r: 0.6, g: 0.8, b: 1, a: 1 }], componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent',
]; displayOrder: 0,
for (const [suffix, pos, size, value, fontSize, bold, color] of playerTexts) { components: [
combat.push(entity({ transform({ parentW: 300, parentH: 96, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 280, y: 28 }, pos: { x: 0, y: 28 } }),
id: guid('cmb', cmbN++), sprite({ color: TRANSPARENT }),
path: `/ui/DefaultGroup/CombatHud/${suffix}`, text({ value: '플레이어', fontSize: 18, bold: true, color: GOLD, alignment: 4 }),
modelId: 'uitext', ],
entryId: 'UIText', }));
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent', combat.push(entity({
displayOrder: 6 + playerTexts.findIndex(([s]) => s === suffix), id: guid('cmb', 212), path: `${PP}/HpBarBg`, modelId: 'uisprite', entryId: 'UISprite',
components: [ componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size, pos }), displayOrder: 1,
sprite({ color: TRANSPARENT }), components: [
text({ value, fontSize, bold, color }), transform({ parentW: 300, parentH: 96, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 220, y: 16 }, pos: { x: 16, y: -6 } }),
], sprite({ color: { r: 0.18, g: 0.05, b: 0.06, a: 1 }, type: 1 }),
})); ],
} }));
combat.push(entity({
id: guid('cmb', 213), path: `${PP}/HpBarFill`, modelId: 'uisprite', entryId: 'UISprite',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
displayOrder: 2,
components: [
transform({ parentW: 300, parentH: 96, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0, y: 0.5 }, size: { x: 220, y: 16 }, pos: { x: -94, y: -6 } }),
sprite({ color: { r: 0.3, g: 0.78, b: 0.36, a: 1 }, type: 1 }),
],
}));
combat.push(entity({
id: guid('cmb', 214), path: `${PP}/HpText`, modelId: 'uitext', entryId: 'UIText',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent',
displayOrder: 3,
components: [
transform({ parentW: 300, parentH: 96, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 220, y: 24 }, pos: { x: 16, y: -30 } }),
sprite({ color: TRANSPARENT }),
text({ value: '80/80', fontSize: 16, bold: true, color: { r: 1, g: 1, b: 1, a: 1 }, alignment: 4 }),
],
}));
const blockBadge = entity({
id: guid('cmb', 215), path: `${PP}/BlockBadge`, modelId: 'uisprite', entryId: 'UISprite',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
displayOrder: 4,
components: [
transform({ parentW: 300, parentH: 96, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 44, y: 40 }, pos: { x: -122, y: -12 } }),
sprite({ color: { r: 0.32, g: 0.5, b: 0.85, a: 1 }, type: 1 }),
],
});
blockBadge.jsonString.enable = false;
combat.push(blockBadge);
combat.push(entity({
id: guid('cmb', 216), path: `${PP}/BlockBadge/Value`, modelId: 'uitext', entryId: 'UIText',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent',
displayOrder: 0,
components: [
transform({ parentW: 44, parentH: 40, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 44, y: 36 }, pos: { x: 0, y: 0 } }),
sprite({ color: TRANSPARENT }),
text({ value: '0', fontSize: 18, bold: true, color: { r: 1, g: 1, b: 1, a: 1 }, alignment: 4 }),
],
}));
combat.push(entity({ combat.push(entity({
id: guid('cmb', 200), id: guid('cmb', 200),
path: '/ui/DefaultGroup/CombatHud/TopBar', path: '/ui/DefaultGroup/CombatHud/TopBar',
@@ -2349,13 +2387,15 @@ end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], N
end end
if i == self.TargetIndex then t = "[타겟] " .. t end if i == self.TargetIndex then t = "[타겟] " .. t end
self:SetText(base .. "/Intent", t) self:SetText(base .. "/Intent", t)
self:SetHpBar(base .. "/HpBarFill", m.hp, m.maxHp) self:SetHpBar(base .. "/HpBarFill", m.hp, m.maxHp, ${HP_BAR_W})
else else
self:SetEntityEnabled(base, false) self:SetEntityEnabled(base, false)
end end
end end
self:SetText("/ui/DefaultGroup/CombatHud/PlayerHp", "HP " .. string.format("%d", self.PlayerHp) .. "/" .. string.format("%d", self.PlayerMaxHp)) self:SetText("/ui/DefaultGroup/CombatHud/PlayerPanel/HpText", string.format("%d", self.PlayerHp) .. "/" .. string.format("%d", self.PlayerMaxHp))
self:SetText("/ui/DefaultGroup/CombatHud/PlayerBlock", "방어 " .. string.format("%d", self.PlayerBlock)) self:SetHpBar("/ui/DefaultGroup/CombatHud/PlayerPanel/HpBarFill", self.PlayerHp, self.PlayerMaxHp, 220)
self:SetEntityEnabled("/ui/DefaultGroup/CombatHud/PlayerPanel/BlockBadge", self.PlayerBlock > 0)
self:SetText("/ui/DefaultGroup/CombatHud/PlayerPanel/BlockBadge/Value", string.format("%d", self.PlayerBlock))
self:RenderRun()`), self:RenderRun()`),
method('SetHpBar', `local e = _EntityService:GetEntityByPath(path) method('SetHpBar', `local e = _EntityService:GetEntityByPath(path)
if e == nil or e.UITransformComponent == nil then if e == nil or e.UITransformComponent == nil then
@@ -2364,11 +2404,12 @@ end
local ratio = 0 local ratio = 0
if maxHp > 0 then ratio = hp / maxHp end if maxHp > 0 then ratio = hp / maxHp end
if ratio < 0 then ratio = 0 end if ratio < 0 then ratio = 0 end
local w = ${HP_BAR_W} * ratio local w = width * ratio
e.UITransformComponent.RectSize = Vector2(w, 14)`, [ e.UITransformComponent.RectSize = Vector2(w, 14)`, [
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' }, { Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' },
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'hp' }, { Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'hp' },
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'maxHp' }, { Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'maxHp' },
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'width' },
]), ]),
method('PositionMonsterSlot', `local m = self.Monsters[slot] method('PositionMonsterSlot', `local m = self.Monsters[slot]
if m == nil or m.entity == nil or not isvalid(m.entity) then if m == nil or m.entity == nil or not isvalid(m.entity) then