Fix combat target cleanup and damage popups

This commit is contained in:
2026-06-15 22:46:10 +09:00
parent 9966065409
commit 8a5b0d4f8d
3 changed files with 196 additions and 150 deletions

View File

@@ -229,7 +229,7 @@ const DAMAGE_DIGIT_RUIDS = [
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 DAMAGE_POP_DIGIT_SPACING = -4;
const MAX_MONSTERS = 4;
const HEAD_OFFSET_Y = 1.4; // 몬스터 월드 원점 위로 띄울 높이(머리 위) — world→screen 변환 전 가산
@@ -1201,22 +1201,23 @@ function upsertUi() {
text({ value: '', fontSize: 17, bold: true, color: { r: 1, g: 0.72, b: 0.5, a: 1 }, alignment: 4 }),
],
}));
const dmgPopBase = `/ui/DefaultGroup/CombatHud/DmgPop${i}`;
const dmgPop = entity({
id: guid('cmb', 250 + i), path: `${base}/DmgPop`, modelId: 'uisprite', entryId: 'UISprite',
id: guid('cmb', 250 + i), path: dmgPopBase, modelId: 'uisprite', entryId: 'UISprite',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
displayOrder: 11,
displayOrder: 80 + i,
components: [
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 }),
transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 192, y: 56 }, pos: { x: 0, y: 0 } }),
sprite({ color: TRANSPARENT, type: 1 }),
],
});
dmgPop.jsonString.enable = false;
combat.push(dmgPop);
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',
id: guid('cmb', 380 + i * 10 + d), path: `${dmgPopBase}/Digit${d + 1}`, modelId: 'uisprite', entryId: 'UISprite',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
displayOrder: 12,
displayOrder: 90 + i,
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 }),
@@ -2812,6 +2813,7 @@ function writeCodeblocks() {
prop('number', 'Turn', '0'),
prop('number', 'TweenEventId', '0'),
prop('number', 'CardHoverTweenId', '0'),
prop('number', 'DmgPopSeq', '0'),
prop('any', 'EndTurnHandler'),
prop('any', 'NewGameHandler'),
prop('any', 'WarriorSelectHandler'),
@@ -3380,6 +3382,7 @@ self.PlayerWeak = 0
self.PlayerVuln = 0
self.PlayerPowers = {}
self.FightAttackCount = 0
self.DmgPopSeq = 0
self.FirstHpLossDone = false
self.ClayBlockNext = 0
self.DiscardSelectRemaining = 0
@@ -4532,6 +4535,7 @@ if c.kind == "Attack" then
if best > 0 then
self.TargetIndex = best
self:PlayCard(slot)
self:RenderTargetFrames()
else
self:RenderTargetFrames()
end
@@ -5026,10 +5030,15 @@ if self.PlayerPowers ~= nil and #self.PlayerPowers > 0 then
end
self:SetText("/ui/DefaultGroup/CombatHud/PlayerPanel/Buffs", pb)
self:RenderRun()`),
method('ShowDmgPop', `local base = "/ui/DefaultGroup/CombatHud/MonsterSlot" .. tostring(slot) .. "/DmgPop"
method('ShowDmgPop', `local slotKey = string.format("%d", math.floor(slot or 0))
local base = "/ui/DefaultGroup/CombatHud/DmgPop" .. slotKey
local pop = _EntityService:GetEntityByPath(base)
if pop == nil then
return
end
self.DmgPopSeq = (self.DmgPopSeq or 0) + 1
local popSeq = self.DmgPopSeq
self:SetText(base, "")
self:SetEntityEnabled(base, 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
@@ -5041,6 +5050,9 @@ for i = 1, string.len(shown) do
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
self:SetEntityEnabled(base .. "/Digit" .. tostring(i), false)
end
for i = 1, ${DAMAGE_POP_MAX_DIGITS} do
local digitPath = base .. "/Digit" .. tostring(i)
local digitEntity = _EntityService:GetEntityByPath(digitPath)
@@ -5057,19 +5069,43 @@ for i = 1, ${DAMAGE_POP_MAX_DIGITS} do
end
end
end
if pop ~= nil and pop.UITransformComponent ~= nil then
pop.UITransformComponent.anchoredPosition = Vector2(0, 76)
local popPos = nil
local m = self.Monsters[slot]
if m ~= nil and m.entity ~= nil and isvalid(m.entity) and m.entity.TransformComponent ~= nil then
local wp = m.entity.TransformComponent.WorldPosition
local screen = _UILogic:WorldToScreenPosition(Vector2(wp.x, wp.y + ${HEAD_OFFSET_Y + 0.45}))
popPos = _UILogic:ScreenToUIPosition(screen)
else
local slotEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/CombatHud/MonsterSlot" .. slotKey)
if slotEntity ~= nil and slotEntity.UITransformComponent ~= nil then
local sp = slotEntity.UITransformComponent.anchoredPosition
popPos = Vector2(sp.x, sp.y + 76)
end
end
local startY = 76
if pop ~= nil and pop.UITransformComponent ~= nil then
if popPos ~= nil then
pop.UITransformComponent.anchoredPosition = popPos
else
pop.UITransformComponent.anchoredPosition = Vector2(0, 120)
end
end
self:SetEntityEnabled(base, true)
for i = 1, 6 do
_TimerService:SetTimerOnce(function()
if self.DmgPopSeq ~= popSeq then
return
end
local p = _EntityService:GetEntityByPath(base)
if p ~= nil and p.UITransformComponent ~= nil then
p.UITransformComponent.anchoredPosition = Vector2(0, startY + i * 7)
local cur = p.UITransformComponent.anchoredPosition
p.UITransformComponent.anchoredPosition = Vector2(cur.x, cur.y + 7)
end
end, 0.045 * i)
end
_TimerService:SetTimerOnce(function()
if self.DmgPopSeq ~= popSeq then
return
end
self:SetEntityEnabled(base, false)
end, 0.48)`, [
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
@@ -5084,7 +5120,10 @@ end
self:SetEntityEnabled(base, true)
_TimerService:SetTimerOnce(function() self:SetEntityEnabled(base, false) end, 0.6)`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' }]),
method('PlayerAttackMotion', `local lp = _UserService.LocalPlayer
if lp == nil or lp.StateComponent == nil then
if lp == nil then
return
end
if lp.StateComponent == nil then
return
end
pcall(function() lp.StateComponent:ChangeState("ATTACK") end)