feat(combat): render monster damage popups with digit skins
This commit is contained in:
@@ -3061,7 +3061,7 @@
|
||||
"Name": "amount"
|
||||
}
|
||||
],
|
||||
"Code": "local base = \"/ui/DefaultGroup/CombatHud/MonsterSlot\" .. tostring(slot) .. \"/DmgPop\"\nlocal pop = _EntityService:GetEntityByPath(base)\nself:SetText(base, string.format(\"%d\", amount))\nself:SetEntityEnabled(base, true)\nself:SetEntityEnabled(base .. \"/Accent\", true)\nif pop ~= nil and pop.UITransformComponent ~= nil then\n\tpop.UITransformComponent.anchoredPosition = Vector2(0, 76)\nend\nlocal startY = 76\nfor i = 1, 6 do\n\t_TimerService:SetTimerOnce(function()\n\t\tlocal p = _EntityService:GetEntityByPath(base)\n\t\tif p ~= nil and p.UITransformComponent ~= nil then\n\t\t\tp.UITransformComponent.anchoredPosition = Vector2(0, startY + i * 7)\n\t\tend\n\tend, 0.045 * i)\nend\n_TimerService:SetTimerOnce(function()\n\tself:SetEntityEnabled(base, false)\n\tself:SetEntityEnabled(base .. \"/Accent\", false)\nend, 0.48)",
|
||||
"Code": "local base = \"/ui/DefaultGroup/CombatHud/MonsterSlot\" .. tostring(slot) .. \"/DmgPop\"\nlocal pop = _EntityService:GetEntityByPath(base)\nself:SetText(base, \"\")\nself:SetEntityEnabled(base, true)\nlocal damageDigitRuids = { \"b94c19830538447f81617035d89bcc05\", \"01b023122a6f4a5789e1d4c61ff8f430\", \"57ff71d1b9eb471b9feb1c15348770c9\", \"cab92837798a42ad9143c67e93f999e1\", \"366f271f9ca94a0684083aad9298efad\", \"5c7a6ad38491466aa84bf450e0fdcf25\", \"7d82a6838e1b4f4a8a0f7420db34c985\", \"c0765bb1e47d46ffbe1df4ac19ea9b1b\", \"6ea0bfed61e149f88a9b3f22dd79774f\", \"82ad2acaae4e4b3fb87bf73635250d22\" }\nlocal shown = tostring(math.max(0, math.floor(amount)))\nif string.len(shown) > 5 then\n shown = string.sub(shown, 1, 5)\nend\nlocal digits = {}\nfor i = 1, string.len(shown) do\n table.insert(digits, tonumber(string.sub(shown, i, i)) or 0)\nend\nlocal totalW = #digits * 22 + math.max(0, #digits - 1) * 18\nlocal startX = -totalW / 2 + 22 / 2\nfor i = 1, 5 do\n local digitPath = base .. \"/Digit\" .. tostring(i)\n local digitEntity = _EntityService:GetEntityByPath(digitPath)\n if digitEntity ~= nil and digitEntity.SpriteGUIRendererComponent ~= nil then\n if digits[i] ~= nil then\n digitEntity.SpriteGUIRendererComponent.ImageRUID = damageDigitRuids[digits[i] + 1]\n digitEntity.SpriteGUIRendererComponent.Color = Color(1, 1, 1, 1)\n if digitEntity.UITransformComponent ~= nil then\n digitEntity.UITransformComponent.anchoredPosition = Vector2(startX + (i - 1) * (22 + 18), 0)\n end\n self:SetEntityEnabled(digitPath, true)\n else\n self:SetEntityEnabled(digitPath, false)\n end\n end\nend\nif pop ~= nil and pop.UITransformComponent ~= nil then\n pop.UITransformComponent.anchoredPosition = Vector2(0, 76)\nend\nlocal startY = 76\nfor i = 1, 6 do\n _TimerService:SetTimerOnce(function()\n local p = _EntityService:GetEntityByPath(base)\n if p ~= nil and p.UITransformComponent ~= nil then\n p.UITransformComponent.anchoredPosition = Vector2(0, startY + i * 7)\n end\n end, 0.045 * i)\nend\n_TimerService:SetTimerOnce(function()\n self:SetEntityEnabled(base, false)\nend, 0.48)",
|
||||
"Scope": 2,
|
||||
"ExecSpace": 6,
|
||||
"Attributes": [],
|
||||
|
||||
@@ -214,6 +214,22 @@ const GOLD = { r: 0.94, g: 0.74, b: 0.26, a: 1 };
|
||||
const ATTACK = { r: 0.86, g: 0.42, b: 0.38, a: 1 };
|
||||
const DEFEND = { r: 0.42, g: 0.55, b: 0.85, a: 1 };
|
||||
const SKILL = { r: 0.46, g: 0.68, b: 0.52, a: 1 };
|
||||
const DAMAGE_DIGIT_RUIDS = [
|
||||
'b94c19830538447f81617035d89bcc05',
|
||||
'01b023122a6f4a5789e1d4c61ff8f430',
|
||||
'57ff71d1b9eb471b9feb1c15348770c9',
|
||||
'cab92837798a42ad9143c67e93f999e1',
|
||||
'366f271f9ca94a0684083aad9298efad',
|
||||
'5c7a6ad38491466aa84bf450e0fdcf25',
|
||||
'7d82a6838e1b4f4a8a0f7420db34c985',
|
||||
'c0765bb1e47d46ffbe1df4ac19ea9b1b',
|
||||
'6ea0bfed61e149f88a9b3f22dd79774f',
|
||||
'82ad2acaae4e4b3fb87bf73635250d22',
|
||||
];
|
||||
const DAMAGE_POP_MAX_DIGITS = 5;
|
||||
const DAMAGE_POP_DIGIT_W = 22;
|
||||
const DAMAGE_POP_DIGIT_H = 32;
|
||||
const DAMAGE_POP_DIGIT_SPACING = 18;
|
||||
|
||||
const MAX_MONSTERS = 4;
|
||||
const HEAD_OFFSET_Y = 1.4; // 몬스터 월드 원점 위로 띄울 높이(머리 위) — world→screen 변환 전 가산
|
||||
@@ -1186,29 +1202,27 @@ function upsertUi() {
|
||||
],
|
||||
}));
|
||||
const dmgPop = entity({
|
||||
id: guid('cmb', 250 + i), path: `${base}/DmgPop`, modelId: 'uitext', entryId: 'UIText',
|
||||
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent',
|
||||
id: guid('cmb', 250 + i), path: `${base}/DmgPop`, modelId: 'uisprite', entryId: 'UISprite',
|
||||
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
|
||||
displayOrder: 11,
|
||||
components: [
|
||||
transform({ parentW: SLOT_W, parentH: SLOT_H, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 170, y: 52 }, pos: { x: 0, y: 76 } }),
|
||||
transform({ parentW: SLOT_W, parentH: SLOT_H, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 192, y: 56 }, pos: { x: 0, y: 76 } }),
|
||||
sprite({ color: { r: 0.12, g: 0.02, b: 0.02, a: 0.72 }, type: 1 }),
|
||||
text({ value: '', fontSize: 36, bold: true, color: { r: 1, g: 0.9, b: 0.18, a: 1 }, alignment: 4, outlineWidth: 5 }),
|
||||
],
|
||||
});
|
||||
dmgPop.jsonString.enable = false;
|
||||
combat.push(dmgPop);
|
||||
const dmgAccent = entity({
|
||||
id: guid('cmb', 380 + i), path: `${base}/DmgPop/Accent`, modelId: 'uitext', entryId: 'UIText',
|
||||
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent',
|
||||
displayOrder: 12,
|
||||
components: [
|
||||
transform({ parentW: 170, parentH: 52, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 170, y: 20 }, pos: { x: 0, y: -22 } }),
|
||||
sprite({ color: TRANSPARENT }),
|
||||
text({ value: 'DAMAGE', fontSize: 14, bold: true, color: { r: 1, g: 0.28, b: 0.16, a: 1 }, alignment: 4, outlineWidth: 2 }),
|
||||
],
|
||||
});
|
||||
dmgAccent.jsonString.enable = false;
|
||||
combat.push(dmgAccent);
|
||||
for (let d = 0; d < DAMAGE_POP_MAX_DIGITS; d++) {
|
||||
combat.push(entity({
|
||||
id: guid('cmb', 380 + i * 10 + d), path: `${base}/DmgPop/Digit${d + 1}`, modelId: 'uisprite', entryId: 'UISprite',
|
||||
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
|
||||
displayOrder: 12,
|
||||
components: [
|
||||
transform({ parentW: 192, parentH: 56, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: DAMAGE_POP_DIGIT_W, y: DAMAGE_POP_DIGIT_H }, pos: { x: 0, y: 0 } }),
|
||||
sprite({ dataId: DAMAGE_DIGIT_RUIDS[0], color: { r: 1, g: 1, b: 1, a: 1 }, type: 0 }),
|
||||
],
|
||||
}));
|
||||
}
|
||||
const mBlockBadge = entity({
|
||||
id: guid('cmb', 270 + i), path: `${base}/BlockBadge`, modelId: 'uisprite', entryId: 'UISprite',
|
||||
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
|
||||
@@ -5014,24 +5028,49 @@ self:SetText("/ui/DefaultGroup/CombatHud/PlayerPanel/Buffs", pb)
|
||||
self:RenderRun()`),
|
||||
method('ShowDmgPop', `local base = "/ui/DefaultGroup/CombatHud/MonsterSlot" .. tostring(slot) .. "/DmgPop"
|
||||
local pop = _EntityService:GetEntityByPath(base)
|
||||
self:SetText(base, string.format("%d", amount))
|
||||
self:SetText(base, "")
|
||||
self:SetEntityEnabled(base, true)
|
||||
self:SetEntityEnabled(base .. "/Accent", true)
|
||||
local damageDigitRuids = { ${DAMAGE_DIGIT_RUIDS.map(luaStr).join(', ')} }
|
||||
local shown = tostring(math.max(0, math.floor(amount)))
|
||||
if string.len(shown) > ${DAMAGE_POP_MAX_DIGITS} then
|
||||
shown = string.sub(shown, 1, ${DAMAGE_POP_MAX_DIGITS})
|
||||
end
|
||||
local digits = {}
|
||||
for i = 1, string.len(shown) do
|
||||
table.insert(digits, tonumber(string.sub(shown, i, i)) or 0)
|
||||
end
|
||||
local totalW = #digits * ${DAMAGE_POP_DIGIT_W} + math.max(0, #digits - 1) * ${DAMAGE_POP_DIGIT_SPACING}
|
||||
local startX = -totalW / 2 + ${DAMAGE_POP_DIGIT_W} / 2
|
||||
for i = 1, ${DAMAGE_POP_MAX_DIGITS} do
|
||||
local digitPath = base .. "/Digit" .. tostring(i)
|
||||
local digitEntity = _EntityService:GetEntityByPath(digitPath)
|
||||
if digitEntity ~= nil and digitEntity.SpriteGUIRendererComponent ~= nil then
|
||||
if digits[i] ~= nil then
|
||||
digitEntity.SpriteGUIRendererComponent.ImageRUID = damageDigitRuids[digits[i] + 1]
|
||||
digitEntity.SpriteGUIRendererComponent.Color = Color(1, 1, 1, 1)
|
||||
if digitEntity.UITransformComponent ~= nil then
|
||||
digitEntity.UITransformComponent.anchoredPosition = Vector2(startX + (i - 1) * (${DAMAGE_POP_DIGIT_W} + ${DAMAGE_POP_DIGIT_SPACING}), 0)
|
||||
end
|
||||
self:SetEntityEnabled(digitPath, true)
|
||||
else
|
||||
self:SetEntityEnabled(digitPath, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
if pop ~= nil and pop.UITransformComponent ~= nil then
|
||||
pop.UITransformComponent.anchoredPosition = Vector2(0, 76)
|
||||
pop.UITransformComponent.anchoredPosition = Vector2(0, 76)
|
||||
end
|
||||
local startY = 76
|
||||
for i = 1, 6 do
|
||||
_TimerService:SetTimerOnce(function()
|
||||
local p = _EntityService:GetEntityByPath(base)
|
||||
if p ~= nil and p.UITransformComponent ~= nil then
|
||||
p.UITransformComponent.anchoredPosition = Vector2(0, startY + i * 7)
|
||||
end
|
||||
end, 0.045 * i)
|
||||
_TimerService:SetTimerOnce(function()
|
||||
local p = _EntityService:GetEntityByPath(base)
|
||||
if p ~= nil and p.UITransformComponent ~= nil then
|
||||
p.UITransformComponent.anchoredPosition = Vector2(0, startY + i * 7)
|
||||
end
|
||||
end, 0.045 * i)
|
||||
end
|
||||
_TimerService:SetTimerOnce(function()
|
||||
self:SetEntityEnabled(base, false)
|
||||
self:SetEntityEnabled(base .. "/Accent", false)
|
||||
self:SetEntityEnabled(base, false)
|
||||
end, 0.48)`, [
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' },
|
||||
|
||||
2728
ui/DefaultGroup.ui
2728
ui/DefaultGroup.ui
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user