Merge pull request '타격 시퀀스와 카메라 쉐이크 타이밍 정리' (#114) from codex/attack-sequence-feel-fix into main
Reviewed-on: #114
This commit was merged in pull request #114.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -297,6 +297,7 @@ if m.block > 0 and pierce ~= true then
|
|||||||
m.block = m.block - absorbed
|
m.block = m.block - absorbed
|
||||||
dmg = dmg - absorbed
|
dmg = dmg - absorbed
|
||||||
end
|
end
|
||||||
|
self:ShakeCombatCamera()
|
||||||
m.hp = m.hp - dmg
|
m.hp = m.hp - dmg
|
||||||
if dmg > 0 then
|
if dmg > 0 then
|
||||||
local poison = self:AddPowerFieldTotal("attackPoison")
|
local poison = self:AddPowerFieldTotal("attackPoison")
|
||||||
@@ -333,6 +334,7 @@ end
|
|||||||
if m == nil then
|
if m == nil then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
self:ShakeCombatCamera()
|
||||||
m.hp = m.hp - amount
|
m.hp = m.hp - amount
|
||||||
self:ShowDmgPop(m.slot, amount)
|
self:ShowDmgPop(m.slot, amount)
|
||||||
self:MonsterHitMotion(m.slot)
|
self:MonsterHitMotion(m.slot)
|
||||||
@@ -359,6 +361,7 @@ local m = alive[math.random(1, #alive)]
|
|||||||
if m == nil then
|
if m == nil then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
self:ShakeCombatCamera()
|
||||||
m.hp = m.hp - amount
|
m.hp = m.hp - amount
|
||||||
self:ShowDmgPop(m.slot, amount)
|
self:ShowDmgPop(m.slot, amount)
|
||||||
self:MonsterHitMotion(m.slot)
|
self:MonsterHitMotion(m.slot)
|
||||||
@@ -393,6 +396,17 @@ end`, [
|
|||||||
method('DealDamageToAllMonsters', `if self.Monsters == nil then
|
method('DealDamageToAllMonsters', `if self.Monsters == nil then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
local anyAlive = false
|
||||||
|
for i = 1, #self.Monsters do
|
||||||
|
local m = self.Monsters[i]
|
||||||
|
if m ~= nil and m.alive == true then
|
||||||
|
anyAlive = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if anyAlive == true and isAttack == true then
|
||||||
|
self:ShakeCombatCamera()
|
||||||
|
end
|
||||||
local killCount = 0
|
local killCount = 0
|
||||||
for i = 1, #self.Monsters do
|
for i = 1, #self.Monsters do
|
||||||
local m = self.Monsters[i]
|
local m = self.Monsters[i]
|
||||||
@@ -572,6 +586,7 @@ end
|
|||||||
if dmg > 0 and self.PlayerIntangible ~= nil and self.PlayerIntangible > 0 and dmg > 1 then
|
if dmg > 0 and self.PlayerIntangible ~= nil and self.PlayerIntangible > 0 and dmg > 1 then
|
||||||
dmg = 1
|
dmg = 1
|
||||||
end
|
end
|
||||||
|
self:ShakeCombatCamera()
|
||||||
if dmg > 0 then
|
if dmg > 0 then
|
||||||
self.PlayerHp = self.PlayerHp - dmg
|
self.PlayerHp = self.PlayerHp - dmg
|
||||||
local reactiveBlock = self:AddPowerFieldTotal("blockOnDamaged")
|
local reactiveBlock = self:AddPowerFieldTotal("blockOnDamaged")
|
||||||
|
|||||||
@@ -313,6 +313,108 @@ if amount < 0 then
|
|||||||
end
|
end
|
||||||
self.PlayerBlock = self.PlayerBlock + amount
|
self.PlayerBlock = self.PlayerBlock + amount
|
||||||
return amount`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'base' }], 0, 'number'),
|
return amount`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'base' }], 0, 'number'),
|
||||||
|
method('RunAttackSequence', `if hitDamages == nil or #hitDamages <= 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local function countAliveMonsters()
|
||||||
|
local n = 0
|
||||||
|
if self.Monsters ~= nil then
|
||||||
|
for mi = 1, #self.Monsters do
|
||||||
|
local om = self.Monsters[mi]
|
||||||
|
if om ~= nil and om.alive == true then
|
||||||
|
n = n + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return n
|
||||||
|
end
|
||||||
|
local function randomAliveMonsterIndex()
|
||||||
|
local alive = {}
|
||||||
|
if self.Monsters ~= nil then
|
||||||
|
for mi = 1, #self.Monsters do
|
||||||
|
local om = self.Monsters[mi]
|
||||||
|
if om ~= nil and om.alive == true then
|
||||||
|
table.insert(alive, mi)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #alive <= 0 then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
return alive[math.random(1, #alive)]
|
||||||
|
end
|
||||||
|
self.FxBusy = true
|
||||||
|
local hitIndex = 1
|
||||||
|
local lockedTargetIndex = self.TargetIndex or 0
|
||||||
|
local function finishSequence()
|
||||||
|
self.FxBusy = false
|
||||||
|
self.ActiveAttackDamageVsWeakMultiplier = 1
|
||||||
|
self:RenderCombat()
|
||||||
|
self:CheckCombatEnd()
|
||||||
|
end
|
||||||
|
local function step()
|
||||||
|
if self.CombatOver == true then
|
||||||
|
finishSequence()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if countAliveMonsters() <= 0 then
|
||||||
|
finishSequence()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if hitIndex == 1 then
|
||||||
|
self.DamageDealtThisTurn = (self.DamageDealtThisTurn or 0) + (roundPlannedDamage or 0)
|
||||||
|
end
|
||||||
|
local roundKilled = false
|
||||||
|
if useAoe == true then
|
||||||
|
roundKilled = self:DealDamageToAllMonsters(hitDamages[hitIndex] or 0, true)
|
||||||
|
else
|
||||||
|
local targetIdx = lockedTargetIndex
|
||||||
|
if randomTargetEachHit == true then
|
||||||
|
targetIdx = randomAliveMonsterIndex()
|
||||||
|
end
|
||||||
|
if targetIdx ~= nil and targetIdx > 0 then
|
||||||
|
if randomTargetEachHit ~= true then
|
||||||
|
local lockedMonster = nil
|
||||||
|
if self.Monsters ~= nil then
|
||||||
|
lockedMonster = self.Monsters[targetIdx]
|
||||||
|
end
|
||||||
|
if lockedMonster == nil or lockedMonster.alive ~= true then
|
||||||
|
finishSequence()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local prev = self.TargetIndex
|
||||||
|
self.TargetIndex = targetIdx
|
||||||
|
roundKilled = self:DealDamageToTarget(hitDamages[hitIndex] or 0, pierce == true)
|
||||||
|
self.TargetIndex = prev
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:RenderCombat()
|
||||||
|
self:CheckCombatEnd()
|
||||||
|
hitIndex = hitIndex + 1
|
||||||
|
if self.CombatOver == true then
|
||||||
|
finishSequence()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if hitIndex <= #hitDamages then
|
||||||
|
_TimerService:SetTimerOnce(step, 0.2)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if repeatOnKill == true and roundKilled == true and countAliveMonsters() > 0 then
|
||||||
|
hitIndex = 1
|
||||||
|
_TimerService:SetTimerOnce(step, 0.2)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
finishSequence()
|
||||||
|
end
|
||||||
|
step()`, [
|
||||||
|
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'hitDamages' },
|
||||||
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'roundPlannedDamage' },
|
||||||
|
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'useAoe' },
|
||||||
|
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'randomTargetEachHit' },
|
||||||
|
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'pierce' },
|
||||||
|
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'repeatOnKill' },
|
||||||
|
]),
|
||||||
method('CountOtherHandSkills', `if self.Hand == nil then
|
method('CountOtherHandSkills', `if self.Hand == nil then
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
@@ -808,65 +910,7 @@ if c.kind == "Attack" then
|
|||||||
if c.class == "shiv" and self.ShivFirstDamageBonusUsed ~= true and self:HasPowerField("firstShivDamageBonus") == true then
|
if c.class == "shiv" and self.ShivFirstDamageBonusUsed ~= true and self:HasPowerField("firstShivDamageBonus") == true then
|
||||||
self.ShivFirstDamageBonusUsed = true
|
self.ShivFirstDamageBonusUsed = true
|
||||||
end
|
end
|
||||||
local function countAliveMonsters()
|
self:RunAttackSequence(hitDamages, total, useAoe, c.randomTargetEachHit == true, c.pierce == true, c.repeatOnKill == true)
|
||||||
local n = 0
|
|
||||||
if self.Monsters ~= nil then
|
|
||||||
for mi = 1, #self.Monsters do
|
|
||||||
local om = self.Monsters[mi]
|
|
||||||
if om ~= nil and om.alive == true then n = n + 1 end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return n
|
|
||||||
end
|
|
||||||
local function randomAliveMonsterIndex()
|
|
||||||
local alive = {}
|
|
||||||
if self.Monsters ~= nil then
|
|
||||||
for mi = 1, #self.Monsters do
|
|
||||||
local om = self.Monsters[mi]
|
|
||||||
if om ~= nil and om.alive == true then
|
|
||||||
table.insert(alive, mi)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #alive <= 0 then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
return alive[math.random(1, #alive)]
|
|
||||||
end
|
|
||||||
local function resolveAttackRound()
|
|
||||||
local roundKilled = false
|
|
||||||
if useAoe == true then
|
|
||||||
local killed = self:DealDamageToAllMonsters(total, true)
|
|
||||||
if killed == true then roundKilled = true end
|
|
||||||
elseif c.randomTargetEachHit == true then
|
|
||||||
for h = 1, hitN do
|
|
||||||
local targetIdx = randomAliveMonsterIndex()
|
|
||||||
if targetIdx ~= nil and targetIdx > 0 then
|
|
||||||
local prev = self.TargetIndex
|
|
||||||
self.TargetIndex = targetIdx
|
|
||||||
local killed = self:DealDamageToTarget(hitDamages[h] or 0, c.pierce == true)
|
|
||||||
self.TargetIndex = prev
|
|
||||||
if killed == true then roundKilled = true end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif hitN > 1 then
|
|
||||||
for h = 1, hitN do
|
|
||||||
local killed = self:DealDamageToTarget(hitDamages[h] or 0, c.pierce == true)
|
|
||||||
if killed == true then roundKilled = true end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local killed = self:DealDamageToTarget(total, c.pierce == true)
|
|
||||||
if killed == true then roundKilled = true end
|
|
||||||
end
|
|
||||||
return roundKilled
|
|
||||||
end
|
|
||||||
local totalDamage = 0
|
|
||||||
local roundKilled = false
|
|
||||||
repeat
|
|
||||||
roundKilled = resolveAttackRound()
|
|
||||||
totalDamage = totalDamage + total
|
|
||||||
until c.repeatOnKill ~= true or roundKilled ~= true or countAliveMonsters() <= 0
|
|
||||||
self.DamageDealtThisTurn = (self.DamageDealtThisTurn or 0) + totalDamage
|
|
||||||
end
|
end
|
||||||
if c.block ~= nil then
|
if c.block ~= nil then
|
||||||
self:AddCardBlock(c.block + (self.HolyChargeCount or 0) * (c.blockPerHolyCharge or 0))
|
self:AddCardBlock(c.block + (self.HolyChargeCount or 0) * (c.blockPerHolyCharge or 0))
|
||||||
|
|||||||
@@ -113,7 +113,6 @@ local pop = _EntityService:GetEntityByPath(base)
|
|||||||
if pop == nil then
|
if pop == nil then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local startDelay = 0.2 * (popIndex - 1)
|
|
||||||
local function showNow()
|
local function showNow()
|
||||||
self:SetEntityEnabled(base, false)
|
self:SetEntityEnabled(base, false)
|
||||||
self:SetText(base, "")
|
self:SetText(base, "")
|
||||||
@@ -193,13 +192,7 @@ local function showNow()
|
|||||||
self:SetEntityEnabled(base, false)
|
self:SetEntityEnabled(base, false)
|
||||||
end, 0.3)
|
end, 0.3)
|
||||||
end
|
end
|
||||||
if startDelay > 0 then
|
showNow()`, [
|
||||||
_TimerService:SetTimerOnce(function()
|
|
||||||
showNow()
|
|
||||||
end, startDelay)
|
|
||||||
else
|
|
||||||
showNow()
|
|
||||||
end`, [
|
|
||||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' },
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' },
|
||||||
]),
|
]),
|
||||||
@@ -211,6 +204,48 @@ else
|
|||||||
end
|
end
|
||||||
self:SetEntityEnabled(base, true)
|
self:SetEntityEnabled(base, true)
|
||||||
_TimerService:SetTimerOnce(function() self:SetEntityEnabled(base, false) end, 0.6)`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' }]),
|
_TimerService:SetTimerOnce(function() self:SetEntityEnabled(base, false) end, 0.6)`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' }]),
|
||||||
|
method('ShakeCombatCamera', `local lp = _UserService.LocalPlayer
|
||||||
|
local cam = nil
|
||||||
|
if lp ~= nil then
|
||||||
|
cam = lp.CameraComponent
|
||||||
|
end
|
||||||
|
if cam == nil then
|
||||||
|
cam = _CameraService:GetCurrentCameraComponent()
|
||||||
|
end
|
||||||
|
if cam == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.CombatCameraShakeSeq = (self.CombatCameraShakeSeq or 0) + 1
|
||||||
|
local seq = self.CombatCameraShakeSeq
|
||||||
|
local baseCameraOffset = Vector2(${CAM.cameraOffsetX}, ${CAM.cameraOffsetY})
|
||||||
|
cam.CameraOffset = baseCameraOffset
|
||||||
|
local offsets = {
|
||||||
|
Vector2(-0.22, 0),
|
||||||
|
Vector2(0.2, 0),
|
||||||
|
Vector2(-0.12, 0),
|
||||||
|
Vector2(0.06, 0),
|
||||||
|
Vector2(0, 0),
|
||||||
|
}
|
||||||
|
for i = 1, #offsets do
|
||||||
|
local delta = offsets[i]
|
||||||
|
_TimerService:SetTimerOnce(function()
|
||||||
|
local lp2 = _UserService.LocalPlayer
|
||||||
|
local cam2 = nil
|
||||||
|
if lp2 ~= nil then
|
||||||
|
cam2 = lp2.CameraComponent
|
||||||
|
end
|
||||||
|
if cam2 == nil then
|
||||||
|
cam2 = _CameraService:GetCurrentCameraComponent()
|
||||||
|
end
|
||||||
|
if cam2 == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if seq ~= self.CombatCameraShakeSeq then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
cam2.CameraOffset = Vector2(baseCameraOffset.x + delta.x, baseCameraOffset.y + delta.y)
|
||||||
|
end, 0.028 * (i - 1))
|
||||||
|
end`, []),
|
||||||
method('PlayerAttackMotion', `local lp = _UserService.LocalPlayer
|
method('PlayerAttackMotion', `local lp = _UserService.LocalPlayer
|
||||||
if lp == nil then
|
if lp == nil then
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ self.HolyChargeCount = 0
|
|||||||
self.DamagePowerStrengthUsed = false
|
self.DamagePowerStrengthUsed = false
|
||||||
self.DamageDealtThisTurn = 0
|
self.DamageDealtThisTurn = 0
|
||||||
self.DmgPopSeq = 0
|
self.DmgPopSeq = 0
|
||||||
|
self.CombatCameraShakeSeq = 0
|
||||||
self.DmgPopSlotQueue = {}
|
self.DmgPopSlotQueue = {}
|
||||||
self.FirstHpLossDone = false
|
self.FirstHpLossDone = false
|
||||||
self.ClayBlockNext = 0
|
self.ClayBlockNext = 0
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ function writeCodeblocks() {
|
|||||||
prop('number', 'TweenEventId', '0'),
|
prop('number', 'TweenEventId', '0'),
|
||||||
prop('number', 'CardHoverTweenId', '0'),
|
prop('number', 'CardHoverTweenId', '0'),
|
||||||
prop('number', 'DmgPopSeq', '0'),
|
prop('number', 'DmgPopSeq', '0'),
|
||||||
|
prop('number', 'CombatCameraShakeSeq', '0'),
|
||||||
prop('any', 'DmgPopSlotQueue'),
|
prop('any', 'DmgPopSlotQueue'),
|
||||||
prop('any', 'EndTurnHandler'),
|
prop('any', 'EndTurnHandler'),
|
||||||
prop('any', 'NewGameHandler'),
|
prop('any', 'NewGameHandler'),
|
||||||
|
|||||||
Reference in New Issue
Block a user