1923 lines
73 KiB
Lua
1923 lines
73 KiB
Lua
BattleUtil = {}
|
||
--local BattleUtil = BattleUtil
|
||
local floor = math.floor
|
||
local max = math.max
|
||
local min = math.min
|
||
--local Random = Random
|
||
--local RoleDataName = RoleDataName
|
||
--local BattleEventName = BattleEventName
|
||
BattleUtil.Passivity = require("Modules/Battle/Logic/Base/Passivity")
|
||
|
||
function table_removebyvalue(array, value, removeall)
|
||
local c, i, max = 0, 1, #array
|
||
while i <= max do
|
||
if array[i] == value then
|
||
table.remove(array, i)
|
||
c = c + 1
|
||
i = i - 1
|
||
max = max - 1
|
||
if not removeall then
|
||
break
|
||
end
|
||
end
|
||
i = i + 1
|
||
end
|
||
return c
|
||
end
|
||
|
||
local function clamp(v, minValue, maxValue)
|
||
if v < minValue then
|
||
return minValue
|
||
end
|
||
if v > maxValue then
|
||
return maxValue
|
||
end
|
||
return v
|
||
end
|
||
|
||
function BattleUtil.ErrorCorrection(f) --进行精度处理,避免前后端计算不一致
|
||
return floor(f * 100000 + 0.5) / 100000
|
||
end
|
||
|
||
function BattleUtil.FP_Mul(...)
|
||
local f = 1
|
||
for i, v in ipairs { ... } do
|
||
f = floor(f * v * 100000 + 0.5) / 100000
|
||
end
|
||
return f
|
||
end
|
||
|
||
-- 选择前排
|
||
function BattleUtil.ChooseFRow(arr)
|
||
local tempArr = {}
|
||
for _, r in ipairs(arr) do
|
||
--不是放逐
|
||
if r.position <= 3 and not r:IsRealDead() and not r.isExile then
|
||
table.insert(tempArr, r)
|
||
end
|
||
end
|
||
table.sort(tempArr, function(a, b)
|
||
return a.position < b.position
|
||
end)
|
||
return tempArr
|
||
end
|
||
|
||
-- 选择后排
|
||
function BattleUtil.ChooseBRow(arr)
|
||
local tempArr = {}
|
||
for _, r in ipairs(arr) do
|
||
if r.position > 3 and not r:IsRealDead() and not r.isExile then
|
||
table.insert(tempArr, r)
|
||
end
|
||
end
|
||
table.sort(tempArr, function(a, b)
|
||
return a.position < b.position
|
||
end)
|
||
return tempArr
|
||
end
|
||
|
||
-- 选择一列(col == 0 表示第三列哦)
|
||
function BattleUtil.ChooseCol(arr, col)
|
||
local tempArr = {}
|
||
for _, role in ipairs(arr) do
|
||
if role.position % 3 == col and not role.isExile then
|
||
table.insert(tempArr, role)
|
||
end
|
||
end
|
||
table.sort(tempArr, function(a, b)
|
||
return a.position < b.position
|
||
end)
|
||
return tempArr
|
||
end
|
||
|
||
-- 选择两列
|
||
function BattleUtil.ChooseTowCol(arr)
|
||
local teamArr = {}
|
||
--第一列
|
||
local oneArr = {}
|
||
for _, role in ipairs(arr) do
|
||
if role.position % 3 == 1 then
|
||
table.insert(oneArr, role)
|
||
end
|
||
end
|
||
local one = #oneArr
|
||
--第二列
|
||
local twoArr = {}
|
||
for _, role in ipairs(arr) do
|
||
if role.position % 3 == 2 then
|
||
table.insert(twoArr, role)
|
||
end
|
||
end
|
||
local two = #twoArr
|
||
--第三列
|
||
local threeArr = {}
|
||
for _, role in ipairs(arr) do
|
||
if role.position % 3 == 0 then
|
||
table.insert(threeArr, role)
|
||
end
|
||
end
|
||
local three = #threeArr
|
||
--如果每列人数相同,就选前两列
|
||
if one == two and two == three then
|
||
for key, value in pairs(oneArr) do
|
||
table.insert(teamArr, value)
|
||
end
|
||
for key, value in pairs(twoArr) do
|
||
table.insert(teamArr, value)
|
||
end
|
||
else
|
||
--如果第一列数量>第二列数量就把第一列选入
|
||
if one > two then
|
||
if one > 0 then
|
||
for key, value in pairs(oneArr) do
|
||
table.insert(teamArr, value)
|
||
end
|
||
end
|
||
--如果第二列数量>=第三列数量就把第二列选入
|
||
if two >= three then
|
||
if two > 0 then
|
||
for key, value in pairs(twoArr) do
|
||
table.insert(teamArr, value)
|
||
end
|
||
end
|
||
else
|
||
--如果第三列数量>第二列数量就把第三列选入
|
||
if three > 0 then
|
||
for key, value in pairs(threeArr) do
|
||
table.insert(teamArr, value)
|
||
end
|
||
end
|
||
end
|
||
else
|
||
--如果第二列数量>第一列数量就把第二列选入
|
||
if two > 0 then
|
||
for key, value in pairs(twoArr) do
|
||
table.insert(teamArr, value)
|
||
end
|
||
end
|
||
--如果第一列数量>第三列数量就把第一列选入
|
||
if one >= three then
|
||
if one > 0 then
|
||
for key, value in pairs(oneArr) do
|
||
table.insert(teamArr, value)
|
||
end
|
||
end
|
||
else
|
||
--如果第三列数量>第一列数量就把第三列选入
|
||
if three > 0 then
|
||
for key, value in pairs(threeArr) do
|
||
table.insert(teamArr, value)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
|
||
table.sort(teamArr, function(a, b)
|
||
return a.position < b.position
|
||
end)
|
||
return teamArr
|
||
end
|
||
|
||
-- 根据属性排序
|
||
function BattleUtil.SortByProp(arr, prop, sort)
|
||
BattleUtil.Sort(arr, function(a, b)
|
||
local r1 = a:GetRoleData(prop)
|
||
local r2 = b:GetRoleData(prop)
|
||
if sort == 1 then return r1 > r2 else return r1 < r2 end
|
||
end)
|
||
return arr
|
||
end
|
||
|
||
-- 按百分比血量排序
|
||
function BattleUtil.SortByHpFactor(arr, sort)
|
||
BattleUtil.Sort(arr, function(a, b)
|
||
local r1 = a:GetRoleData(RoleDataName.Hp) / a:GetRoleData(RoleDataName.MaxHp)
|
||
local r2 = b:GetRoleData(RoleDataName.Hp) / b:GetRoleData(RoleDataName.MaxHp)
|
||
if sort == 1 then return r1 > r2 else return r1 < r2 end
|
||
end)
|
||
return arr
|
||
end
|
||
|
||
-- 按百分比血量排序
|
||
function BattleUtil.SortByHpFactorAndHp(arr, sort)
|
||
BattleUtil.Sort(arr, function(a, b)
|
||
local r1 = a:GetRoleData(RoleDataName.Hp) / a:GetRoleData(RoleDataName.MaxHp)
|
||
local r2 = b:GetRoleData(RoleDataName.Hp) / b:GetRoleData(RoleDataName.MaxHp)
|
||
if sort == 1 then
|
||
if r1 == r2 then
|
||
return a:GetRoleData(RoleDataName.Hp) < b:GetRoleData(RoleDataName.Hp)
|
||
else
|
||
return r1 > r2
|
||
end
|
||
else
|
||
if r1 == r2 then
|
||
return a:GetRoleData(RoleDataName.Hp) < b:GetRoleData(RoleDataName.Hp)
|
||
else
|
||
return r1 < r2
|
||
end
|
||
end
|
||
end)
|
||
return arr
|
||
end
|
||
|
||
--移除队列有不灭的单位
|
||
function BattleUtil.RemoveNoDeadRole(arr)
|
||
for i = 1, #arr do
|
||
local role = arr[i]
|
||
if BattleLogic.BuffMgr:HasBuff(role, BuffName.NoDead) then
|
||
table_removebyvalue(arr, role)
|
||
end
|
||
end
|
||
end
|
||
|
||
--按怒气排序
|
||
function BattleUtil.SortByPos(arr, sort)
|
||
BattleUtil.Sort(arr, function(a, b)
|
||
local r1 = a.Rage
|
||
local r2 = b.Rage
|
||
if sort == 1 then
|
||
return a.position > b.position
|
||
else
|
||
return a.position < b.position
|
||
end
|
||
end)
|
||
return arr
|
||
end
|
||
|
||
--按怒气排序
|
||
function BattleUtil.SortByRage(arr, sort)
|
||
BattleUtil.Sort(arr, function(a, b)
|
||
local r1 = a.Rage
|
||
local r2 = b.Rage
|
||
if sort == 1 then
|
||
if r1 == r2 then
|
||
return a.position > b.position
|
||
else
|
||
return r1 > r2
|
||
end
|
||
else
|
||
if r1 == r2 then
|
||
return a.position > b.position
|
||
else
|
||
return r1 < r2
|
||
end
|
||
end
|
||
end)
|
||
return arr
|
||
end
|
||
|
||
-- 获取技能最大目标数
|
||
function BattleUtil.GetMaxTargetNum(chooseId)
|
||
local chooseType = floor(chooseId / 100000) % 10
|
||
local chooseLimit = floor(chooseId / 10000) % 10
|
||
local chooseWeight = floor(chooseId / 100) % 100
|
||
local sort = floor(chooseId / 10) % 10
|
||
local num = chooseId % 10
|
||
|
||
--
|
||
if chooseType == 3 or chooseType == 4 then
|
||
return 1
|
||
else
|
||
if num == 0 then
|
||
if chooseLimit == 0 then
|
||
if chooseWeight == 7 then
|
||
return 4
|
||
elseif chooseLimit == 8 then
|
||
return 1
|
||
else
|
||
return 6
|
||
end
|
||
elseif chooseLimit == 1 or chooseLimit == 2 then
|
||
return 3
|
||
elseif chooseLimit == 3 then
|
||
return 2
|
||
end
|
||
else
|
||
return num
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleUtil.GetSkillData(skillId, skinId)
|
||
local skillConfig = ConfigManager.TryGetConfigData(ConfigName.SkillLogicConfig, skillId)
|
||
if not skillId or not skillConfig then
|
||
return
|
||
end
|
||
local skill = { skillId }
|
||
--skill = {skillId, 命中时间, 持续时间, 伤害次数, {目标id1, 效果1, 效果2, ...},{目标id2, 效果3, 效果4, ...}, ...}
|
||
--效果 = {效果类型id, 效果参数1, 效果参数2, ...}
|
||
|
||
local target = skillConfig.Target
|
||
local effectList = skillConfig.Effect
|
||
local effectArgsList = skillConfig.EffectValue
|
||
|
||
local eid = BattleUtil.GetCombatIdBySkin(skillId, skinId or 0)
|
||
local EffectCombat = ConfigManager.TryGetConfigData(ConfigName.CombatControl, eid)
|
||
skill[1] = skillId
|
||
skill[2] = EffectCombat.KeyFrame / 1000
|
||
skill[3] = EffectCombat.SkillDuration / 1000
|
||
skill[4] = EffectCombat.SkillNumber
|
||
|
||
local index = 1
|
||
for i = 1, #effectList do
|
||
local effectGroup = { target[i][1] } -- 效果目标
|
||
for j = 1, #effectList[i] do
|
||
local effect = { effectList[i][j] } -- 效果Id
|
||
for k = 1, #effectArgsList[index] do
|
||
effect[k + 1] = effectArgsList[index][k] -- 效果参数
|
||
end
|
||
effectGroup[j + 1] = effect
|
||
index = index + 1
|
||
end
|
||
skill[i + 4] = effectGroup
|
||
end
|
||
return skill
|
||
end
|
||
|
||
-- 获取技能表现id
|
||
function BattleUtil.GetCombatIdBySkin(skillId, skinId)
|
||
local skillConfig = ConfigManager.TryGetConfigData(ConfigName.SkillLogicConfig, skillId)
|
||
local effectIds = skillConfig.SkillDisplay
|
||
local eid = 0
|
||
local skin = skinId or 0
|
||
if effectIds then
|
||
for i = 1, #effectIds do
|
||
if effectIds[i][1] == skin then
|
||
eid = effectIds[i][2]
|
||
end
|
||
end
|
||
end
|
||
if eid == 0 then
|
||
eid = effectIds[1][2]
|
||
end
|
||
return eid
|
||
end
|
||
|
||
--
|
||
function BattleUtil.ChooseTarget(role, chooseId, queryType)
|
||
local chooseType = floor(chooseId / 100000) % 10
|
||
local chooseLimit = floor(chooseId / 10000) % 10
|
||
local chooseWeight = floor(chooseId / 100) % 100
|
||
local sort = floor(chooseId / 10) % 10
|
||
local num = chooseId % 10
|
||
local arr
|
||
-- 选择类型
|
||
if chooseType == 1 then
|
||
if queryType and queryType == 1 then
|
||
arr = RoleManager.QueryNoDead(function(r) return r.camp == role.camp end)
|
||
else
|
||
arr = RoleManager.Query(function(r) return r.camp == role.camp end)
|
||
end
|
||
elseif chooseType == 2 then
|
||
if role.lockTarget and not role.lockTarget:IsRealDead() and not role.lockTarget.isExile then --嘲讽时对单个敌军生效
|
||
return { role.lockTarget }
|
||
end
|
||
arr = RoleManager.Query(function(r) return r.camp ~= role.camp end)
|
||
elseif chooseType == 3 then
|
||
if role.ctrl_blind then --致盲时自身变随机友军
|
||
arr = RoleManager.Query(function(r) return r.camp == role.camp end)
|
||
BattleUtil.RandomList(arr)
|
||
return { arr[1] }
|
||
end
|
||
return { role }
|
||
elseif chooseType == 4 then
|
||
if role.lockTarget and not role.lockTarget:IsRealDead() and not role.lockTarget.isExile then --嘲讽时对仇恨目标生效
|
||
return { role.lockTarget }
|
||
end
|
||
if role.ctrl_blind then --致盲时仇恨目标变随机
|
||
arr = RoleManager.Query(function(r) return r.camp ~= role.camp end)
|
||
BattleUtil.RandomList(arr)
|
||
return { arr[1] }
|
||
end
|
||
return { RoleManager.GetAggro(role) }
|
||
elseif chooseType == 5 then --神兵对应的英雄
|
||
local weaponer = RoleManager.GetRoleByCampAndPos(role.camp, role.position)
|
||
return { weaponer }
|
||
else
|
||
arr = RoleManager.Query()
|
||
end
|
||
|
||
--选择范围
|
||
if chooseLimit == 0 then --选择全体不做任何操作
|
||
elseif chooseLimit == 1 then -- 前排
|
||
local tempArr = BattleUtil.ChooseFRow(arr)
|
||
if #tempArr == 0 then -- 没有选择后排
|
||
tempArr = BattleUtil.ChooseBRow(arr)
|
||
end
|
||
arr = tempArr
|
||
elseif chooseLimit == 2 then -- 后排
|
||
local tempArr = BattleUtil.ChooseBRow(arr)
|
||
if #tempArr == 0 then -- 没有选择前排
|
||
tempArr = BattleUtil.ChooseFRow(arr)
|
||
end
|
||
arr = tempArr
|
||
elseif chooseLimit == 3 then -- 对列
|
||
local target = RoleManager.GetAggro(role)
|
||
if target then
|
||
local myCol = target.position % 3
|
||
local tempArr = BattleUtil.ChooseCol(arr, myCol)
|
||
if #tempArr == 0 then -- 对列没有人,按顺序找到有人得列
|
||
for i = 1, 3 do
|
||
local col = i % 3 -- 0 表示第三列嗷
|
||
tempArr = BattleUtil.ChooseCol(arr, col)
|
||
if #tempArr ~= 0 then
|
||
break
|
||
end
|
||
end
|
||
end
|
||
arr = tempArr
|
||
end
|
||
elseif chooseLimit == 4 then -- 处于灼烧状态
|
||
local tempArr = {}
|
||
for i = 1, #arr do
|
||
if BattleLogic.BuffMgr:HasBuff(arr[i], BuffName.DOT, function(buff) return buff.damageType == DotType.Burn end, role, 1) then
|
||
table.insert(tempArr, arr[i])
|
||
end
|
||
end
|
||
arr = tempArr
|
||
elseif chooseLimit == 5 then -- 人阵营
|
||
local tempArr = {}
|
||
for i = 1, #arr do
|
||
if arr[i].element == BattleRoleElementType.REN then
|
||
table.insert(tempArr, arr[i])
|
||
end
|
||
end
|
||
arr = tempArr
|
||
elseif chooseLimit == 6 then --两纵排单位
|
||
local tempArr = BattleUtil.ChooseTowCol(arr)
|
||
arr = tempArr
|
||
elseif chooseLimit == 7 then --佛阵营
|
||
local tempArr = {}
|
||
for i = 1, #arr do
|
||
if arr[i].element == BattleRoleElementType.FO then
|
||
table.insert(tempArr, arr[i])
|
||
end
|
||
end
|
||
arr = tempArr
|
||
end
|
||
|
||
-- 选择条件
|
||
if chooseWeight == 0 or role.ctrl_blind then --致盲时排序无效
|
||
BattleUtil.RandomList(arr)
|
||
elseif chooseWeight == 1 then -- 生命值
|
||
if sort ~= 0 then
|
||
BattleUtil.SortByProp(arr, RoleDataName.Hp, sort)
|
||
end
|
||
elseif chooseWeight == 2 then -- 血量百分比(不含不灭)
|
||
BattleUtil.SortByHpFactor(arr, sort)
|
||
--选血量百分比最低的 不选择有不灭的,如果伤害要选有不灭的 需处理
|
||
BattleUtil.RemoveNoDeadRole(arr)
|
||
elseif chooseWeight == 3 then -- 攻击力
|
||
BattleUtil.SortByProp(arr, RoleDataName.Attack, sort)
|
||
elseif chooseWeight == 4 then -- 防御
|
||
BattleUtil.SortByProp(arr, RoleDataName.PhysicalDefence, sort)
|
||
elseif chooseWeight == 5 then -- 护甲
|
||
BattleUtil.SortByProp(arr, RoleDataName.PhysicalDefence, sort)
|
||
elseif chooseWeight == 6 then -- 魔抗
|
||
BattleUtil.SortByProp(arr, RoleDataName.MagicDefence, sort)
|
||
elseif chooseWeight == 7 then -- 对位及其相邻目标
|
||
arr = RoleManager.GetNeighbor(role, chooseType)
|
||
elseif chooseWeight == 8 then -- 对位
|
||
if num == 1 then
|
||
arr = RoleManager.GetAggroHero(role, arr)
|
||
else
|
||
arr = RoleManager.GetArrAggroList(role, arr)
|
||
end
|
||
-- elseif chooseWeight == 9 then -- 展位距离
|
||
-- BattleUtil.Sort(arr, function(a, b)
|
||
-- local r1 = math.abs(role.position - a.position) * 10 + a.position
|
||
-- local r2 = math.abs(role.position - b.position) * 10 + b.position
|
||
-- if sort == 1 then return r1 > r2 else return r1 < r2 end
|
||
-- end)
|
||
elseif chooseWeight == 9 then --攻击最高且没被放逐过
|
||
local list = role.exileTargets
|
||
local tempArr = {}
|
||
local team = RoleManager.Query(function(r) return r.camp ~= role.camp end)
|
||
if list then
|
||
for key, value in pairs(team) do
|
||
if not value:IsRealDead() and not BattleUtil.ChecklistIsContainValue(role.exileTargets, value) then
|
||
--return arr[i]
|
||
table.insert(tempArr, value)
|
||
end
|
||
end
|
||
end
|
||
BattleUtil.SortByProp(tempArr, RoleDataName.Attack, sort)
|
||
arr = tempArr
|
||
elseif chooseWeight == 10 then --剩余血量百分比低于25%且生命绝对值最小
|
||
return { BattleUtil.GetHpPctLessThanPctHero(arr, 0.25) }
|
||
elseif chooseWeight == 11 then --剩余血量百分比低于32%且生命绝对值最小
|
||
return { BattleUtil.GetHpPctLessThanPctHero(arr, 0.32) }
|
||
elseif chooseWeight == 12 then --剩余血量百分比低于40%且生命绝对值最小
|
||
return { BattleUtil.GetHpPctLessThanPctHero(arr, 0.40) }
|
||
elseif chooseWeight == 13 then --剩余血量百分比低于50%且生命绝对值最小
|
||
return { BattleUtil.GetHpPctLessThanPctHero(arr, 0.50) }
|
||
elseif chooseWeight == 14 then --我方战位最靠前的单位 的对位及相邻
|
||
local list = nil
|
||
list = RoleManager.Query(function(r) return r.camp == role.camp end)
|
||
if list and #list > 0 then
|
||
arr = RoleManager.GetNeighbor(list[1], chooseType)
|
||
end
|
||
elseif chooseWeight == 15 then --我方阵亡
|
||
--BattleUtil.WaitForTrigger(BattleLogic.GameDeltaTime,function()
|
||
local aaa = RoleManager.GetDeadRole(role.camp)
|
||
if aaa ~= nil then
|
||
--LogError(aaa.position)
|
||
end
|
||
if aaa then
|
||
aaa.isRealDead = false
|
||
arr = {}
|
||
table.insert(arr, aaa)
|
||
BattleUtil.SortByPos(arr, sort)
|
||
return { arr[1] }
|
||
end
|
||
--end)
|
||
elseif chooseWeight == 16 then --(血量百分比 含不灭)
|
||
BattleUtil.SortByHpFactor(arr, sort)
|
||
elseif chooseWeight == 17 then --怒气
|
||
if sort ~= 0 then
|
||
--BattleUtil.SortByProp(arr, RoleDataName.Hp, sort)
|
||
BattleUtil.SortByRage(arr, sort)
|
||
end
|
||
elseif chooseWeight == 18 then --剩余血量百分比低于30%且生命绝对值最小
|
||
return { BattleUtil.GetHpPctLessThanPctHero(arr, 0.30) }
|
||
elseif chooseWeight == 19 then --剩余血量百分比低于35%且生命绝对值最小
|
||
return { BattleUtil.GetHpPctLessThanPctHero(arr, 0.35) }
|
||
elseif chooseWeight == 20 then --剩余血量百分比低于35%且生命绝对值最小
|
||
return { BattleUtil.GetHpPctLessThanPctHero(arr, 0.45) }
|
||
end
|
||
local finalArr = {}
|
||
if num == 0 then
|
||
finalArr = arr
|
||
else
|
||
for i = 1, num do
|
||
if arr[i] then
|
||
table.insert(finalArr, arr[i])
|
||
end
|
||
end
|
||
end
|
||
|
||
-- table.sort(finalArr, function(a, b)
|
||
-- return a.position < b.position
|
||
-- end)
|
||
|
||
return finalArr
|
||
end
|
||
|
||
--获取生命百分比少于指定百分比且生命置最少
|
||
function BattleUtil.GetHpPctLessThanPctHero(arr, pct)
|
||
local hp = 0
|
||
local hero = nil
|
||
for i = 1, #arr do
|
||
local aaa = arr[i]
|
||
local curHp = aaa:GetRoleData(RoleDataName.Hp)
|
||
local r1 = curHp / aaa:GetRoleData(RoleDataName.MaxHp)
|
||
if r1 < pct then
|
||
if hero == nil then
|
||
hero = aaa
|
||
hp = curHp
|
||
else
|
||
if curHp < hp then
|
||
hero = aaa
|
||
hp = curHp
|
||
end
|
||
end
|
||
end
|
||
end
|
||
return hero
|
||
end
|
||
|
||
function BattleUtil.CreateBuffId(skill, index)
|
||
local id = 0
|
||
if skill.preAI then --主动技能生成buff
|
||
id = skill.owner.uid * 10000 + index
|
||
else --被动技能生成buff
|
||
id = skill.owner.uid * 1000 + index
|
||
end
|
||
return id
|
||
end
|
||
|
||
-- 计算命中率
|
||
function BattleUtil.CalHit(atkRole, defRole)
|
||
--命中率 = clamp(自身命中率-敌方闪避率,0,1)
|
||
local hit = atkRole:GetRoleData(RoleDataName.Hit)
|
||
local dodge = defRole:GetRoleData(RoleDataName.Dodge)
|
||
|
||
local bHit = Random.Range01() <= clamp(hit - dodge, 0, 1)
|
||
|
||
if bHit then
|
||
else
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleDodge)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeDodge)
|
||
end
|
||
return bHit
|
||
end
|
||
|
||
-- 计算护盾
|
||
function BattleUtil.CalShield(atkRole, defRole, damage, skill)
|
||
for i = 1, defRole.shield.size do
|
||
local buff = defRole.shield.buffer[i]
|
||
damage = buff:CountShield(damage, atkRole, skill)
|
||
end
|
||
return damage
|
||
end
|
||
|
||
-- 计算护盾
|
||
function BattleUtil.CalAllReduceShield(atkRole, defRole, damage, skill)
|
||
for i = 1, defRole.shield.size do
|
||
local buff = defRole.shield.buffer[i]
|
||
damage = buff:CountAllReduce(damage, atkRole, skill)
|
||
end
|
||
return damage
|
||
end
|
||
|
||
-- 提前计算护盾后伤害
|
||
function BattleUtil.PreCountShield(defRole, damage)
|
||
for i = 1, defRole.shield.size do
|
||
local buff = defRole.shield.buffer[i]
|
||
damage = buff:PreCountShield(damage)
|
||
end
|
||
return damage
|
||
end
|
||
|
||
--检测是否为boss
|
||
function BattleUtil.CheckIsBoss(role)
|
||
if not role then
|
||
return false
|
||
end
|
||
if role.enemyType == EnemyType.Boss then
|
||
--弹免疫
|
||
role.Event:DispatchEvent(BattleEventName.ShowHintText, BattleArtFontType.Immune)
|
||
return true
|
||
else
|
||
return false
|
||
end
|
||
end
|
||
|
||
-- 秒杀
|
||
function BattleUtil.Seckill(skill, atkRole, defRole)
|
||
-- 灵兽无效
|
||
if defRole.type == BattleUnitType.Monster or defRole.type == BattleUnitType.Player or defRole.type == BattleUnitType.Weapon then
|
||
return
|
||
end
|
||
--检测伪不灭
|
||
|
||
local damage = defRole:GetRoleData(RoleDataName.Hp)
|
||
local realDamage = damage
|
||
local damagingFunc = function(dmgDeduction)
|
||
realDamage = dmgDeduction
|
||
damage = realDamage
|
||
end
|
||
defRole.Event:DispatchEvent(BattleEventName.CheckFalseNoDead, damagingFunc, atkRole, realDamage, skill)
|
||
local finalDmg = defRole.data:SubValue(RoleDataName.Hp, damage)
|
||
if finalDmg >= 0 then
|
||
if defRole:GetRoleData(RoleDataName.Hp) <= 0 and not defRole:IsDead() then
|
||
defRole:SetDead(damage)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleDead, atkRole, skill)
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleKill, defRole, skill)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoleDead, defRole, atkRole)
|
||
|
||
atkRole.Event:DispatchEvent(BattleEventName.Seckill, defRole, damage, nil, finalDmg)
|
||
defRole.Event:DispatchEvent(BattleEventName.BeSeckill, atkRole)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.Seckill, atkRole, defRole)
|
||
end
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleDamage, defRole, damage, false, finalDmg, 0, false, skill)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeDamaged, atkRole, damage, false, finalDmg, 0, false, skill)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RoleDamage, atkRole, defRole, damage, false, finalDmg, 0, false,
|
||
skill)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RoleBeDamaged, defRole, atkRole, damage, false, finalDmg, 0,
|
||
false, skill)
|
||
if skill then
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleHit, defRole, damage, nil, finalDmg, nil, skill)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeHit, atkRole, damage, nil, finalDmg, nil, skill)
|
||
end
|
||
end
|
||
-- 用于记录统计
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RecordSecKill, atkRole, defRole)
|
||
end
|
||
|
||
-- 秒杀定额血量
|
||
function BattleUtil.SeckillHP(skill, atkRole, defRole, pro)
|
||
-- 灵兽无效
|
||
if defRole.type == BattleUnitType.Monster or defRole.type == BattleUnitType.Player or defRole.type == BattleUnitType.Weapon then
|
||
return
|
||
end
|
||
local damage = floor(BattleUtil.FP_Mul(defRole:GetRoleData(RoleDataName.MaxHp), pro))
|
||
local realDamage = damage
|
||
local damagingFunc = function(dmgDeduction)
|
||
realDamage = dmgDeduction
|
||
damage = realDamage
|
||
end
|
||
defRole.Event:DispatchEvent(BattleEventName.CheckFalseNoDead, damagingFunc, atkRole, realDamage, skill)
|
||
local finalDmg = defRole.data:SubValue(RoleDataName.Hp, damage)
|
||
if finalDmg >= 0 then
|
||
if defRole:GetRoleData(RoleDataName.Hp) <= 0 and not defRole:IsDead() then
|
||
defRole:SetDead(damage)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleDead, atkRole)
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleKill, defRole, skill)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoleDead, defRole, atkRole)
|
||
atkRole.Event:DispatchEvent(BattleEventName.Seckill, defRole, damage, nil, finalDmg)
|
||
defRole.Event:DispatchEvent(BattleEventName.BeSeckill, atkRole)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.Seckill, atkRole, defRole)
|
||
end
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleDamage, defRole, damage, false, finalDmg, 0, false, skill)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeDamaged, atkRole, damage, false, finalDmg, 0, false, skill)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RoleDamage, atkRole, defRole, damage, false, finalDmg, 0, false,
|
||
skill)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RoleBeDamaged, defRole, atkRole, damage, false, finalDmg, 0,
|
||
false, skill)
|
||
if skill then
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleHit, defRole, damage, nil, finalDmg, nil, skill)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeHit, atkRole, damage, nil, finalDmg, nil, skill)
|
||
end
|
||
end
|
||
-- 用于记录统计
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RecordSecKill, atkRole, defRole)
|
||
end
|
||
|
||
-- 计算真实伤害
|
||
function BattleUtil.ApplyDamage(skill, atkRole, defRole, damage, bCrit, damageType, dotType, isDirect)
|
||
LogError("vvvvvvvvvvvvvvvvvvvvv" .. damage)
|
||
if defRole == nil then
|
||
return
|
||
end
|
||
-- 灵兽无效
|
||
if defRole.type == BattleUnitType.Monster or defRole.type == BattleUnitType.Player or defRole.type == BattleUnitType.Weapon then
|
||
return
|
||
end
|
||
|
||
bCrit = bCrit or false
|
||
damageType = damageType or 0
|
||
|
||
-- 计算护盾减伤
|
||
|
||
damage = BattleUtil.CalShield(atkRole, defRole, damage, skill)
|
||
--加入被动效果
|
||
local damagingFunc = function(dmgDeduction)
|
||
damage = damage - dmgDeduction
|
||
end
|
||
atkRole.Event:DispatchEvent(BattleEventName.PassiveDamaging, damagingFunc, defRole, damage, skill, dotType, bCrit,
|
||
damageType, dotType, isDirect)
|
||
defRole.Event:DispatchEvent(BattleEventName.PassiveBeDamaging, damagingFunc, atkRole, damage, skill, dotType, bCrit)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.PassiveDamaging, damagingFunc, atkRole, defRole, damage, skill,
|
||
dotType, bCrit, damageType, dotType, isDirect)
|
||
|
||
-- 造成的最终伤害
|
||
local damagingFunc = function(dmgDeduction)
|
||
damage = damage - dmgDeduction
|
||
end
|
||
atkRole.Event:DispatchEvent(BattleEventName.FinalDamage, damagingFunc, defRole, damage, skill, dotType, bCrit,
|
||
damageType)
|
||
defRole.Event:DispatchEvent(BattleEventName.FinalBeDamage, damagingFunc, atkRole, damage, skill, dotType, bCrit,
|
||
damageType)
|
||
defRole.Event:DispatchEvent(BattleEventName.FinalBeDamageEnd, damagingFunc, atkRole, damage, skill, dotType, bCrit,
|
||
damageType, isDirect)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.FinalDamage, damagingFunc, atkRole, defRole, damage, skill, dotType,
|
||
bCrit, damageType)
|
||
|
||
--
|
||
return BattleUtil.FinalDamage(skill, atkRole, defRole, damage, bCrit, damageType, dotType, isDirect)
|
||
end
|
||
|
||
-- 计算真实伤害(没有被动增伤)
|
||
function BattleUtil.ApplyDamageNoPassive(skill, atkRole, defRole, damage, bCrit, damageType, dotType, isDirect)
|
||
-- 灵兽无效
|
||
if defRole.type == BattleUnitType.Monster or defRole.type == BattleUnitType.Player then
|
||
return
|
||
end
|
||
-- 计算护盾减伤
|
||
damage = BattleUtil.CalShield(atkRole, defRole, damage, skill)
|
||
-- 造成的最终伤害
|
||
local damagingFunc = function(dmgDeduction)
|
||
--不计算增伤只计算减伤
|
||
if dmgDeduction < 0 then
|
||
return
|
||
end
|
||
damage = damage - dmgDeduction
|
||
end
|
||
|
||
--atkRole.Event:DispatchEvent(BattleEventName.PassiveDamaging, damagingFunc, defRole, damage, skill, dotType, bCrit,damageType, dotType,isDirect)
|
||
defRole.Event:DispatchEvent(BattleEventName.PassiveBeDamaging, damagingFunc, atkRole, damage, skill, dotType, bCrit)
|
||
--BattleLogic.Event:DispatchEvent(BattleEventName.PassiveDamaging, damagingFunc, atkRole, defRole, damage, skill, dotType, bCrit,damageType, dotType,isDirect)
|
||
|
||
|
||
--atkRole.Event:DispatchEvent(BattleEventName.FinalDamage, damagingFunc, defRole, damage, skill, dotType, bCrit, damageType)
|
||
defRole.Event:DispatchEvent(BattleEventName.FinalBeDamage, damagingFunc, atkRole, damage, skill, dotType, bCrit,
|
||
damageType)
|
||
defRole.Event:DispatchEvent(BattleEventName.FinalBeDamageEnd, damagingFunc, atkRole, damage, skill, dotType, bCrit,
|
||
damageType, isDirect)
|
||
--BattleLogic.Event:DispatchEvent(BattleEventName.FinalDamage, damagingFunc, atkRole, defRole, damage, skill, dotType, bCrit, damageType)
|
||
--
|
||
-- return BattleUtil.FinalDamage(skill, atkRole, defRole, damage, bCrit, damageType, dotType,isDirect)
|
||
if damage < 0 then damage = 0 end
|
||
|
||
if skill and skill.type == BattleSkillType.Special then
|
||
skill.owner.superSkillDamage = damage
|
||
end
|
||
--计算血量防护
|
||
local realDamage = damage
|
||
--血量防护只会防直接伤害 也能防护间接伤害 2023/01/11
|
||
if defRole.bloodShield then
|
||
realDamage = math.abs(defRole.bloodShield:CountBloodValue(damage, atkRole))
|
||
-- damage=realDamage
|
||
end
|
||
--检测历战之躯
|
||
-- 造成的最终伤害
|
||
local damagingFunc = function(dmgDeduction)
|
||
realDamage = realDamage - dmgDeduction
|
||
damage = realDamage
|
||
end
|
||
defRole.Event:DispatchEvent(BattleEventName.CheckLiZhanZhiQu, damagingFunc, atkRole, realDamage, skill, dotType,
|
||
bCrit, damageType, isDirect)
|
||
local isImmune = BattleUtil.CheckDamageIsImmune(atkRole, defRole)
|
||
if isImmune then
|
||
realDamage = 0
|
||
damage = 0
|
||
end
|
||
--御甲过滤后的伤害只会处理扣血 by: wangzhenxing shihongyi 2021/09/27
|
||
--检测伪不灭
|
||
local damagingFunc = function(dmgDeduction)
|
||
realDamage = dmgDeduction
|
||
damage = realDamage
|
||
end
|
||
defRole.Event:DispatchEvent(BattleEventName.CheckFalseNoDead, damagingFunc, atkRole, realDamage, skill, dotType,
|
||
bCrit, damageType, isDirect)
|
||
|
||
local isToDied = false
|
||
--检测时空猪八戒格挡致死伤害
|
||
local checkDamageShift = function(isDead)
|
||
isToDied = isDead
|
||
end
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.CheckDamShift, checkDamageShift, atkRole, realDamage, defRole, skill)
|
||
--格挡成功
|
||
if isToDied then
|
||
return
|
||
end
|
||
|
||
local finalDmg = defRole.data:SubValue(RoleDataName.Hp, realDamage)
|
||
if finalDmg >= 0 then
|
||
if defRole:GetRoleData(RoleDataName.Hp) <= 0 and not defRole:IsDead() then
|
||
defRole:SetDead(damage)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleDead, atkRole)
|
||
--atkRole.Event:DispatchEvent(BattleEventName.RoleKill, defRole,skill)
|
||
--BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoleDead, defRole, atkRole,skill,dotType)
|
||
end
|
||
|
||
--atkRole.Event:DispatchEvent(BattleEventName.RoleDamage, defRole, damage, bCrit, finalDmg, damageType, dotType, skill)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeDamaged, atkRole, damage, bCrit, finalDmg, damageType, dotType,
|
||
skill, isImmune)
|
||
--BattleLogic.Event:DispatchEvent(BattleEventName.RoleDamage, atkRole, defRole, damage, bCrit, finalDmg, damageType, dotType, skill)
|
||
--BattleLogic.Event:DispatchEvent(BattleEventName.RoleBeDamaged, defRole, atkRole, damage, bCrit, finalDmg, damageType, dotType, skill)
|
||
if bCrit then
|
||
--atkRole.Event:DispatchEvent(BattleEventName.RoleCrit, defRole, damage, bCrit, finalDmg, damageType, skill)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeCrit, atkRole, damage, bCrit, finalDmg, damageType, skill)
|
||
end
|
||
if skill then
|
||
--atkRole.Event:DispatchEvent(BattleEventName.RoleHit, defRole, damage, bCrit, finalDmg, damageType, skill,isDirect)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeHit, atkRole, damage, bCrit, finalDmg, damageType, skill,
|
||
isDirect)
|
||
--如果目标是主燃烧目标 or 目标身上有燃烧效果
|
||
if atkRole.curMainTarget == defRole or BattleLogic.BuffMgr:HasBuff(defRole, BuffName.DOT, function(buff) return
|
||
buff.damageType == 1 end) then
|
||
--atkRole.Event:DispatchEvent(BattleEventName.HitRoleInBurn,skill,defRole)
|
||
end
|
||
end
|
||
--如果不是技能带的伤害,并且是直接伤害就,,,,,
|
||
--用于处理不触发特性并且是直接伤害的伤害 isDirect 暂时先为bool值,后期可根据需求做修改扩展 by:王振兴 2020/10/12 16:18
|
||
if isDirect and not skill then
|
||
--atkRole.Event:DispatchEvent(BattleEventName.RoleHit, defRole, damage, bCrit, finalDmg, damageType, skill,isDirect)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeHit, atkRole, damage, bCrit, finalDmg, damageType, skill,
|
||
isDirect)
|
||
end
|
||
end
|
||
|
||
-- 战斗记录用
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RecordDamage, atkRole, defRole, damage)
|
||
--
|
||
BattleLogManager.Log(
|
||
"Final Damage",
|
||
"acamp", atkRole.camp,
|
||
"apos", atkRole.position,
|
||
"tcamp", defRole.camp,
|
||
"tpos", defRole.position,
|
||
"damage", damage,
|
||
"dotType", tostring(dotType)
|
||
)
|
||
return damage
|
||
end
|
||
|
||
-- 怒气计算
|
||
function BattleUtil.CalRage(caster, target, value, countType, isBorrow)
|
||
if target == nil then
|
||
return
|
||
end
|
||
-- 角色身上有无敌盾,不扣除怒气 by:wangzhenxing 2020/08/10 14:56
|
||
if (countType == 3 or countType == 4) -- 降怒
|
||
and (target.isImmuneReduceRage -- 免疫降怒 或者 有无敌盾
|
||
or BattleLogic.BuffMgr:HasBuff(target, BuffName.Shield, function(buff) return buff.shieldType and
|
||
buff.shieldType == ShieldTypeName.AllReduce end))
|
||
then
|
||
return
|
||
end
|
||
if (countType == 1 or countType == 2) and target.isSuppress and caster ~= target then
|
||
return
|
||
end
|
||
local lastRage = target.Rage
|
||
--如果每回合减的怒气超过了每回合上限就不再减怒
|
||
if (countType == 3 or countType == 4) and target.RoundMaxSubRage ~= 0 and target.RoundMaxSubRage <= target.AllSubRage then
|
||
return
|
||
end
|
||
--这个减的怒气+已经间的怒气> 怒气限制
|
||
if (countType == 3 or countType == 4) and target.RoundMaxSubRage ~= 0 and value + target.AllSubRage > target.RoundMaxSubRage then
|
||
value = target.RoundMaxSubRage - target.AllSubRage
|
||
end
|
||
local changeRage = function(num)
|
||
value = num
|
||
end
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.ChangeRoleRage, changeRage, caster, target, value, countType)
|
||
-- 操作怒气
|
||
local deltaRage = target:AddRage(value, countType)
|
||
if (countType == 3 or countType == 4) and target.RoundMaxSubRage ~= 0 then
|
||
target.AllSubRage = target.AllSubRage - deltaRage
|
||
end
|
||
if value == 0 then
|
||
return
|
||
end
|
||
caster.Event:DispatchEvent(BattleEventName.RecordRageChange, caster, target, deltaRage, countType, value, lastRage,
|
||
isBorrow)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RecordRageChange, caster, target, deltaRage, countType, value,
|
||
lastRage, isBorrow)
|
||
-- 用于记录统计
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RecordRage, caster, target, deltaRage)
|
||
end
|
||
|
||
--检测是否有是金翅大鹏有不灭效果
|
||
function BattleUtil.CheckIsNoDead(target)
|
||
if target then
|
||
return target.isHaveNoDead or BattleLogic.BuffMgr:HasBuff(target, BuffName.NoDead)
|
||
end
|
||
return false
|
||
end
|
||
|
||
--检测列表是否包含值
|
||
function BattleUtil.ChecklistIsContainValue(_list, _value)
|
||
if _list and _value then
|
||
for key, value in pairs(_list) do
|
||
if value == _value then
|
||
return true
|
||
end
|
||
end
|
||
end
|
||
return false
|
||
end
|
||
|
||
-- 根据id获取额外技能
|
||
function BattleUtil.GetExtraSkillbyId(id)
|
||
if id == 1 then
|
||
return ExtraReleaseSkill.skill1
|
||
elseif id == 2 then
|
||
return ExtraReleaseSkill.skill2
|
||
elseif id == 3 then
|
||
return ExtraReleaseSkill.skill3
|
||
elseif id == 4 then
|
||
return ExtraReleaseSkill.skill4
|
||
elseif id == 5 then
|
||
return ExtraReleaseSkill.skill5
|
||
elseif id == 6 then
|
||
return ExtraReleaseSkill.skill6
|
||
end
|
||
end
|
||
|
||
function BattleUtil.FinalDamage(skill, atkRole, defRole, damage, bCrit, damageType, dotType, isDirect)
|
||
-- 灵兽无效
|
||
if defRole.type == BattleUnitType.Monster or defRole.type == BattleUnitType.Player or defRole.type == BattleUnitType.Weapon then
|
||
return
|
||
end
|
||
if damage < 0 then damage = 0 end
|
||
|
||
if skill and skill.type == BattleSkillType.Special then
|
||
skill.owner.superSkillDamage = damage
|
||
end
|
||
--计算血量防护
|
||
local realDamage = damage
|
||
--血量防护只会防直接伤害 也能防护间接伤害 2023/01/11
|
||
if defRole.bloodShield then
|
||
realDamage = math.abs(defRole.bloodShield:CountBloodValue(damage, atkRole))
|
||
-- damage=realDamage
|
||
end
|
||
--检测历战之躯
|
||
-- 造成的最终伤害
|
||
local damagingFunc = function(dmgDeduction)
|
||
realDamage = realDamage - dmgDeduction
|
||
damage = realDamage
|
||
end
|
||
defRole.Event:DispatchEvent(BattleEventName.CheckLiZhanZhiQu, damagingFunc, atkRole, realDamage, skill, dotType,
|
||
bCrit, damageType, isDirect)
|
||
local isImmune = BattleUtil.CheckDamageIsImmune(atkRole, defRole)
|
||
if isImmune then
|
||
realDamage = 0
|
||
damage = 0
|
||
end
|
||
--检测伪不灭
|
||
local damagingFunc = function(dmgDeduction)
|
||
realDamage = dmgDeduction
|
||
damage = realDamage
|
||
end
|
||
defRole.Event:DispatchEvent(BattleEventName.CheckFalseNoDead, damagingFunc, atkRole, realDamage, skill, dotType,
|
||
bCrit, damageType, isDirect)
|
||
|
||
local isToDied = false
|
||
--检测时空猪八戒格挡致死伤害
|
||
local checkDamageShift = function(isDead)
|
||
isToDied = isDead
|
||
end
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.CheckDamShift, checkDamageShift, atkRole, realDamage, defRole, skill)
|
||
--格挡成功
|
||
if isToDied then
|
||
return
|
||
end
|
||
|
||
|
||
--御甲过滤后的伤害只会处理扣血 by: wangzhenxing shihongyi 2021/09/27
|
||
local finalDmg = defRole.data:SubValue(RoleDataName.Hp, realDamage)
|
||
if finalDmg >= 0 then
|
||
if defRole:GetRoleData(RoleDataName.Hp) <= 0 and not defRole:IsDead() then
|
||
defRole:SetDead(damage)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleDead, atkRole)
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleKill, defRole, skill)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoleDead, defRole, atkRole, skill, dotType)
|
||
end
|
||
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleDamage, defRole, damage, bCrit, finalDmg, damageType, dotType,
|
||
skill)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeDamaged, atkRole, damage, bCrit, finalDmg, damageType, dotType,
|
||
skill, isImmune)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RoleDamage, atkRole, defRole, damage, bCrit, finalDmg, damageType,
|
||
dotType, skill)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RoleBeDamaged, defRole, atkRole, damage, bCrit, finalDmg,
|
||
damageType, dotType, skill)
|
||
if bCrit then
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleCrit, defRole, damage, bCrit, finalDmg, damageType, skill)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeCrit, atkRole, damage, bCrit, finalDmg, damageType, skill)
|
||
end
|
||
if skill then
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleHit, defRole, damage, bCrit, finalDmg, damageType, skill,
|
||
isDirect)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeHit, atkRole, damage, bCrit, finalDmg, damageType, skill,
|
||
isDirect)
|
||
--如果目标是主燃烧目标 or 目标身上有燃烧效果
|
||
if atkRole.curMainTarget == defRole or BattleLogic.BuffMgr:HasBuff(defRole, BuffName.DOT, function(buff) return
|
||
buff.damageType == 1 end) then
|
||
atkRole.Event:DispatchEvent(BattleEventName.HitRoleInBurn, skill, defRole)
|
||
end
|
||
end
|
||
--如果不是技能带的伤害,并且是直接伤害就,,,,,
|
||
--用于处理不触发特性并且是直接伤害的伤害 isDirect 暂时先为bool值,后期可根据需求做修改扩展 by:王振兴 2020/10/12 16:18
|
||
if isDirect and not skill then
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleHit, defRole, damage, bCrit, finalDmg, damageType, skill,
|
||
isDirect)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeHit, atkRole, damage, bCrit, finalDmg, damageType, skill,
|
||
isDirect)
|
||
end
|
||
end
|
||
|
||
-- 战斗记录用
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RecordDamage, atkRole, defRole, damage)
|
||
--
|
||
BattleLogManager.Log(
|
||
"Final Damage",
|
||
"acamp", atkRole.camp,
|
||
"apos", atkRole.position,
|
||
"tcamp", defRole.camp,
|
||
"tpos", defRole.position,
|
||
"damage", damage,
|
||
"dotType", tostring(dotType)
|
||
)
|
||
BattleLogic.AddRoundTriggerTime()
|
||
return finalDmg
|
||
end
|
||
|
||
--计算盾的最终伤害
|
||
function BattleUtil.FinalDamageCountShield(skill, atkRole, defRole, damage, bCrit, damageType, dotType, isDirect)
|
||
-- 灵兽无效
|
||
if defRole.type == BattleUnitType.Monster or defRole.type == BattleUnitType.Player then
|
||
return
|
||
end
|
||
-- 计算无敌盾减伤
|
||
damage = BattleUtil.CalAllReduceShield(atkRole, defRole, damage, skill)
|
||
|
||
if damage < 0 then damage = 0 end
|
||
--计算主角增伤
|
||
if atkRole.type == BattleUnitType.Monster and atkRole.isPlayer then
|
||
damage = floor(damage * (1 + atkRole:GetRoleData(RoleDataName.DamageBocusFactor)))
|
||
end
|
||
if skill and skill.type == BattleSkillType.Special then
|
||
skill.owner.superSkillDamage = damage
|
||
end
|
||
--计算血量防护
|
||
local realDamage = damage
|
||
--血量防护只会防直接伤害 也能防护间接伤害 2023/01/11
|
||
if defRole.bloodShield then
|
||
realDamage = math.abs(defRole.bloodShield:CountBloodValue(damage, atkRole))
|
||
-- damage=realDamage
|
||
end
|
||
--检测历战之躯
|
||
-- 造成的最终伤害
|
||
local damagingFunc = function(dmgDeduction)
|
||
realDamage = realDamage - dmgDeduction
|
||
damage = realDamage
|
||
end
|
||
defRole.Event:DispatchEvent(BattleEventName.CheckLiZhanZhiQu, damagingFunc, atkRole, realDamage, skill, dotType,
|
||
bCrit, damageType, isDirect)
|
||
--LogError("最后扣除伤害=="..realDamage)
|
||
--御甲过滤后的伤害只会处理扣血 by: wangzhenxing shihongyi 2021/09/27
|
||
local isImmune = BattleUtil.CheckDamageIsImmune(atkRole, defRole)
|
||
if isImmune then
|
||
realDamage = 0
|
||
damage = 0
|
||
end
|
||
--检测伪不灭
|
||
local damagingFunc = function(dmgDeduction)
|
||
realDamage = dmgDeduction
|
||
damage = realDamage
|
||
end
|
||
defRole.Event:DispatchEvent(BattleEventName.CheckFalseNoDead, damagingFunc, atkRole, realDamage, skill, dotType,
|
||
bCrit, damageType, isDirect)
|
||
|
||
local isToDied = false
|
||
--检测时空猪八戒格挡致死伤害
|
||
local checkDamageShift = function(isDead)
|
||
isToDied = isDead
|
||
end
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.CheckDamShift, checkDamageShift, atkRole, realDamage, defRole, skill)
|
||
--格挡成功
|
||
if isToDied then
|
||
return
|
||
end
|
||
|
||
local finalDmg = defRole.data:SubValue(RoleDataName.Hp, realDamage)
|
||
if finalDmg >= 0 then
|
||
if defRole:GetRoleData(RoleDataName.Hp) <= 0 and not defRole:IsDead() then
|
||
defRole:SetDead(damage)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleDead, atkRole)
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleKill, defRole, skill)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoleDead, defRole, atkRole, skill, dotType)
|
||
end
|
||
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleDamage, defRole, damage, bCrit, finalDmg, damageType, dotType,
|
||
skill)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeDamaged, atkRole, damage, bCrit, finalDmg, damageType, dotType,
|
||
skill, isImmune)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RoleDamage, atkRole, defRole, damage, bCrit, finalDmg, damageType,
|
||
dotType, skill)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RoleBeDamaged, defRole, atkRole, damage, bCrit, finalDmg,
|
||
damageType, dotType, skill)
|
||
if bCrit then
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleCrit, defRole, damage, bCrit, finalDmg, damageType, skill)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeCrit, atkRole, damage, bCrit, finalDmg, damageType, skill)
|
||
end
|
||
if skill then
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleHit, defRole, damage, bCrit, finalDmg, damageType, skill,
|
||
isDirect)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeHit, atkRole, damage, bCrit, finalDmg, damageType, skill,
|
||
isDirect)
|
||
--如果目标是主燃烧目标 or 目标身上有燃烧效果
|
||
if atkRole.curMainTarget == defRole or BattleLogic.BuffMgr:HasBuff(defRole, BuffName.DOT, function(buff) return
|
||
buff.damageType == 1 end) then
|
||
atkRole.Event:DispatchEvent(BattleEventName.HitRoleInBurn, skill, defRole)
|
||
end
|
||
end
|
||
--如果不是技能带的伤害,并且是直接伤害就,,,,,
|
||
--用于处理不触发特性并且是直接伤害的伤害 isDirect 暂时先为bool值,后期可根据需求做修改扩展 by:王振兴 2020/10/12 16:18
|
||
if isDirect and not skill then
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleHit, defRole, damage, bCrit, finalDmg, damageType, skill,
|
||
isDirect)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeHit, atkRole, damage, bCrit, finalDmg, damageType, skill,
|
||
isDirect)
|
||
end
|
||
end
|
||
|
||
-- 战斗记录用
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RecordDamage, atkRole, defRole, damage)
|
||
--
|
||
BattleLogManager.Log(
|
||
"Final Damage",
|
||
"acamp", atkRole.camp,
|
||
"apos", atkRole.position,
|
||
"tcamp", defRole.camp,
|
||
"tpos", defRole.position,
|
||
"damage", damage,
|
||
"dotType", tostring(dotType)
|
||
)
|
||
|
||
return finalDmg
|
||
end
|
||
|
||
--检测伤害是否免疫
|
||
function BattleUtil.CheckDamageIsImmune(atkRole, defRole)
|
||
local isImmune = false
|
||
|
||
local GetIsImmune = function(isTrue)
|
||
isImmune = isTrue
|
||
end
|
||
defRole.Event:DispatchEvent(BattleEventName.CheckDamageIsImmune, GetIsImmune, atkRole, defRole)
|
||
return isImmune
|
||
end
|
||
|
||
--执行完整的命中,伤害,暴击计算,返回命中,暴击
|
||
--skill造成伤害的技能 atkRole攻击者 defRole受击者 damageType伤害类型 baseFactor伤害系数 ignoreDef无视防御参数 dotType是持续伤害类型
|
||
function BattleUtil.CalDamage(skill, atkRole, defRole, damageType, baseFactor, ignoreDef, dotType)
|
||
-- 灵兽无效
|
||
if defRole.type == BattleUnitType.Monster or defRole.type == BattleUnitType.Player then
|
||
return
|
||
end
|
||
|
||
-- 是否暴击: 暴击率 = 自身暴击率 - 对方抗暴率
|
||
local bCrit = false
|
||
local critRandom = Random.Range01()
|
||
--特殊处理 白骨精附加的普攻不会必定暴击
|
||
local mustCrit = atkRole.mustCrit
|
||
if atkRole.roleId == 10091 and skill and skill.type == BattleSkillType.Normal and skill.isAdd then
|
||
mustCrit = false
|
||
end
|
||
local addCrit = 0
|
||
local isMustHit = false
|
||
-- 计算被动对暴击概率的影响
|
||
local critFunc = function(df, dt, hit)
|
||
addCrit = BattleUtil.CountValue(addCrit, df, dt)
|
||
isMustHit = hit
|
||
end
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.TemporaryChangeCrit, critFunc, atkRole, defRole, skill)
|
||
local critCondition = clamp(
|
||
atkRole:GetRoleData(RoleDataName.Crit) + addCrit - defRole:GetRoleData(RoleDataName.Tenacity), 0, 1)
|
||
bCrit = critRandom <= critCondition
|
||
--处理达摩神魂被动必定命中
|
||
if not bCrit or addCrit == 0 then
|
||
isMustHit = false
|
||
end
|
||
|
||
bCrit = mustCrit or bCrit or defRole.isFlagCrit == true -- 必定暴击
|
||
|
||
-- 判断是否命中
|
||
if not isMustHit then
|
||
if (skill and not skill:CheckTargetIsHit(defRole) and atkRole.type == BattleUnitType.Role) then
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.HitMiss, atkRole, defRole, skill)
|
||
atkRole.Event:DispatchEvent(BattleEventName.HitMiss, defRole, skill)
|
||
defRole.Event:DispatchEvent(BattleEventName.BeHitMiss, atkRole, skill)
|
||
return 0
|
||
end
|
||
end
|
||
|
||
-- 如果是队伍技能,计算真实伤害,则damageType为伤害值
|
||
if atkRole.isTeam and not defRole:IsDead() then
|
||
return BattleUtil.ApplyDamage(skill, atkRole, defRole, damageType), false
|
||
end
|
||
-- 计算技能额外伤害系数加成
|
||
baseFactor = baseFactor or 1
|
||
local factorFunc = function(exFactor) baseFactor = baseFactor + exFactor end
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleDamageBefore, defRole, factorFunc, damageType, skill)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeDamagedBefore, atkRole, factorFunc, damageType, skill)
|
||
baseFactor = BattleUtil.ErrorCorrection(baseFactor)
|
||
|
||
local baseDamage
|
||
-- 防御(据伤害类型决定)
|
||
local defence = 0
|
||
if damageType == 1 then --1 物理 2 魔法
|
||
defence = defRole:GetRoleData(RoleDataName.PhysicalDefence)
|
||
else
|
||
defence = defRole:GetRoleData(RoleDataName.MagicDefence)
|
||
end
|
||
--检测增伤buff加成
|
||
local buffAddAttack = 0
|
||
local list = BattleLogic.BuffMgr:GetBuff(atkRole, function(buff)
|
||
return buff.type == BuffName.AddAttack and buff.atkType == damageType
|
||
end)
|
||
for key, value in pairs(list) do
|
||
buffAddAttack = BattleUtil.CountValue(buffAddAttack, value.value1, value.ct)
|
||
end
|
||
baseFactor = baseFactor + buffAddAttack
|
||
--处理神印追加技能伤害按比例减少
|
||
if skill and skill.AttactScale and skill.AttactScale ~= 0 then
|
||
baseFactor = baseFactor * skill.AttactScale
|
||
end
|
||
if ignoreDef == nil then
|
||
ignoreDef = 0
|
||
end
|
||
-- 攻击力
|
||
LogError("ffffffffffffffffff"..RoleDataName.Attack)
|
||
local attack = atkRole:GetRoleData(RoleDataName.Attack) + atkRole.addAttack
|
||
local ignoreFunc = function(v1, ct)
|
||
ignoreDef = BattleUtil.CountValue(ignoreDef, v1, ct)
|
||
end
|
||
atkRole.Event:DispatchEvent(BattleEventName.PassiveChangeIgnoreDef, ignoreFunc)
|
||
-- 无视防御系数
|
||
ignoreDef = 1 - (ignoreDef or 0)
|
||
-- 基础伤害 = 攻击力 - 防御力
|
||
baseDamage = max(attack - BattleUtil.FP_Mul(2, defence, ignoreDef), 0)
|
||
|
||
local defDMGRef = defRole:GetRoleData(RoleDataName.DamageReduceFactor)
|
||
local changeDefDMGFac = function(v1, ct)
|
||
if ct == CountTypeName.Sub and defDMGRef == 0 then
|
||
return
|
||
end
|
||
defDMGRef = BattleUtil.CountValue(defDMGRef, v1, ct)
|
||
end
|
||
atkRole.Event:DispatchEvent(BattleEventName.PassiveChangeDefDMGReFac, changeDefDMGFac)
|
||
if defDMGRef < 0 then
|
||
defDMGRef = 0
|
||
end
|
||
-- 基础伤害增加系数
|
||
local addDamageFactor = 1 + atkRole:GetRoleData(RoleDataName.DamageBocusFactor) - defDMGRef
|
||
|
||
-- 计算暴伤害系数
|
||
local critDamageFactor = 1
|
||
local critDamageReduceFactor = 0 -- 暴击伤害减免
|
||
--计算暴击
|
||
if bCrit then
|
||
--加入被动效果 触发暴击被动
|
||
local cl = {}
|
||
local onCritDamageReduceFactor = function(v, ct)
|
||
if v then
|
||
table.insert(cl, { v, ct })
|
||
end
|
||
end
|
||
atkRole.Event:DispatchEvent(BattleEventName.CritDamageReduceFactor, onCritDamageReduceFactor, atkRole, defRole,
|
||
skill)
|
||
defRole.Event:DispatchEvent(BattleEventName.CritDamageReduceFactor, onCritDamageReduceFactor, atkRole, defRole,
|
||
skill)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.CritDamageReduceFactor, onCritDamageReduceFactor, atkRole,
|
||
defRole, skill)
|
||
critDamageReduceFactor = max(BattleUtil.CountChangeList(critDamageReduceFactor, cl), 0)
|
||
|
||
local critDamageAddFactor = 0
|
||
--加入被动效果 触发暴击被动
|
||
local cl2 = {}
|
||
local onCritDamageAddFactor = function(v, ct)
|
||
if v then
|
||
table.insert(cl2, { v, ct })
|
||
end
|
||
end
|
||
atkRole.Event:DispatchEvent(BattleEventName.PassiveAddCritDamageFactor, onCritDamageAddFactor, atkRole, defRole,
|
||
skill)
|
||
critDamageAddFactor = max(BattleUtil.CountChangeList(critDamageAddFactor, cl2), 0)
|
||
-- 计算额外暴击伤害
|
||
critDamageFactor = 1.3 + atkRole:GetRoleData(RoleDataName.CritDamageBonus) -
|
||
defRole:GetRoleData(RoleDataName.CritDamageReduce) + critDamageAddFactor - critDamageReduceFactor
|
||
--加入被动效果 触发暴击被动 废弃不用
|
||
-- local critFunc = function(critEx) critDamageFactor = critEx end
|
||
-- atkRole.Event:DispatchEvent(BattleEventName.PassiveCriting, critFunc,skill)
|
||
end
|
||
|
||
-- 计算克制伤害系数
|
||
local MieKangFactor = 1
|
||
if BattleLogic.GetIsPvP() and atkRole.type == BattleUnitType.Role and defRole.type == BattleUnitType.Role then
|
||
MieKangFactor = MieKangFactor + atkRole:GetRoleData(BattleMieProp[defRole.element]) -
|
||
defRole:GetRoleData(BattleKangProp[atkRole.element])
|
||
end
|
||
|
||
|
||
-- 公式伤害 = 基础伤害 * 基础伤害系数 * 增伤系数 * 爆伤系数 * 克制伤害系数
|
||
local fixDamage = floor(BattleUtil.FP_Mul(baseDamage, baseFactor, addDamageFactor, critDamageFactor, MieKangFactor))
|
||
|
||
-- 公式计算完成
|
||
local damageFunc = function(damage) fixDamage = damage end
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleDamageAfter, defRole, damageFunc, fixDamage, skill)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeDamagedAfter, atkRole, damageFunc, fixDamage)
|
||
|
||
fixDamage = max(floor(attack * 0.1), fixDamage)
|
||
|
||
local finalDmg = 0 --计算实际造成的扣血
|
||
if not defRole:IsRealDead() then
|
||
finalDmg = BattleUtil.ApplyDamage(skill, atkRole, defRole, fixDamage, bCrit, damageType, dotType)
|
||
end
|
||
return finalDmg, bCrit
|
||
end
|
||
|
||
function BattleUtil.CalTreat(castRole, targetRole, value, baseFactor, skill)
|
||
if targetRole == nil then
|
||
return
|
||
end
|
||
-- 灵兽无效
|
||
if targetRole.type == BattleUnitType.Monster or targetRole.type == BattleUnitType.Player or targetRole.type == BattleUnitType.Weapon then
|
||
return
|
||
end
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.DisposeRoleCtrl_noheal, castRole, targetRole)
|
||
if targetRole.ctrl_noheal or targetRole:IsDead() then --禁疗和死亡无法加血
|
||
--禁疗并且没有死亡的单位显示血量+0 不走后面代码,防止触发后面的被动 by:王振兴 2021/1/27
|
||
if targetRole.ctrl_noheal and not targetRole:IsDead() then
|
||
targetRole.Event:DispatchEvent(BattleEventName.RoleBeTreated, castRole, 0, 0)
|
||
end
|
||
return
|
||
end
|
||
local mustCrit = castRole.mustCrit
|
||
-- 是否暴击: 暴击率 = 自身暴击率 - 对方抗暴率
|
||
local bCrit = false
|
||
local critRandom = Random.Range01()
|
||
local critCondition = castRole:GetRoleData(RoleDataName.Crit)
|
||
bCrit = critRandom <= critCondition
|
||
bCrit = mustCrit or bCrit or targetRole.isFlagCrit == true -- 必定暴击
|
||
-- 计算暴伤害系数
|
||
local critDamageFactor = 1
|
||
--计算暴击
|
||
if bCrit then
|
||
--伤害有个+1.3 不知道干什么用的就给去了 by:wangxhenxing 2020/10/10 18:46
|
||
critDamageFactor = 1.3 + castRole:GetRoleData(RoleDataName.CritDamageBonus)
|
||
end
|
||
-- 基础伤害增加系数
|
||
local addDamageFactor = 1 + castRole:GetRoleData(RoleDataName.DamageBocusFactor)
|
||
targetRole.Event:DispatchEvent(BattleEventName.RoleBeHealed, castRole)
|
||
BattleUtil.ApplyTreat(castRole, targetRole, value, baseFactor, critDamageFactor, addDamageFactor, skill)
|
||
end
|
||
|
||
--没有暴击得治疗
|
||
function BattleUtil.CalTreatNoCrit(castRole, targetRole, value, baseFactor, skill)
|
||
if targetRole == nil then
|
||
return
|
||
end
|
||
-- 灵兽无效
|
||
if targetRole == nil then
|
||
return
|
||
end
|
||
if targetRole.type == BattleUnitType.Monster or targetRole.type == BattleUnitType.Player then
|
||
return
|
||
end
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.DisposeRoleCtrl_noheal, castRole, targetRole)
|
||
if targetRole.ctrl_noheal or targetRole:IsDead() then --禁疗和死亡无法加血
|
||
--禁疗并且没有死亡的单位显示血量+0 不走后面代码,防止触发后面的被动 by:王振兴 2021/1/27
|
||
if targetRole.ctrl_noheal and not targetRole:IsDead() then
|
||
targetRole.Event:DispatchEvent(BattleEventName.RoleBeTreated, castRole, 0, 0)
|
||
end
|
||
return
|
||
end
|
||
|
||
-- 计算暴伤害系数
|
||
local critDamageFactor = 1
|
||
|
||
-- 基础伤害增加系数
|
||
local addDamageFactor = 1 + castRole:GetRoleData(RoleDataName.DamageBocusFactor)
|
||
targetRole.Event:DispatchEvent(BattleEventName.RoleBeHealed, castRole)
|
||
BattleUtil.ApplyTreat(castRole, targetRole, value, baseFactor, critDamageFactor, addDamageFactor, skill)
|
||
end
|
||
|
||
function BattleUtil.FinalTreat(castRole, targetRole, value, baseFactor, skill)
|
||
if targetRole == nil then
|
||
return
|
||
end
|
||
-- 灵兽无效
|
||
if targetRole.type == BattleUnitType.Monster or targetRole.type == BattleUnitType.Player then
|
||
return
|
||
end
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.DisposeRoleCtrl_noheal, castRole, targetRole)
|
||
if targetRole.ctrl_noheal or targetRole:IsDead() then --禁疗和死亡无法加血
|
||
--禁疗并且没有死亡的单位显示血量+0 不走后面代码,防止触发后面的被动 by:王振兴 2021/1/27
|
||
if targetRole.ctrl_noheal and not targetRole:IsDead() then
|
||
targetRole.Event:DispatchEvent(BattleEventName.RoleBeTreated, castRole, 0, 0)
|
||
end
|
||
return
|
||
end
|
||
targetRole.Event:DispatchEvent(BattleEventName.RoleBeHealed, castRole)
|
||
local maxHp = targetRole:GetRoleData(RoleDataName.MaxHp)
|
||
local hp = targetRole:GetRoleData(RoleDataName.Hp)
|
||
baseFactor = baseFactor or 1
|
||
local baseTreat = BattleUtil.FP_Mul(value, baseFactor)
|
||
|
||
--baseTreat = BattleUtil.CountChangeList(baseTreat, cl)
|
||
-- 取整
|
||
local baseTreat = floor(baseTreat + 0.5)
|
||
local isVoid = false
|
||
local treatVoidFunc = function(_void)
|
||
isVoid = _void
|
||
end
|
||
targetRole.Event:DispatchEvent(BattleEventName.CheckTreatVoid, treatVoidFunc, baseTreat, castRole)
|
||
if isVoid then
|
||
return
|
||
end
|
||
local treat = min(baseTreat, maxHp - hp)
|
||
if treat > 0 then
|
||
targetRole.data:AddValue(RoleDataName.Hp, treat)
|
||
end
|
||
|
||
castRole.Event:DispatchEvent(BattleEventName.RoleTreat, targetRole, treat, baseTreat, skill)
|
||
targetRole.Event:DispatchEvent(BattleEventName.RoleBeTreated, castRole, treat, baseTreat, skill)
|
||
--添加发送到battleLogic的治疗消息,用于计算总的战斗伤害值
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RoleBeTreated, castRole, treat, baseTreat)
|
||
-- 战斗记录用
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RecordTreat, castRole, targetRole, baseTreat)
|
||
BattleLogManager.Log(
|
||
"Final Treat",
|
||
"acamp", castRole.camp,
|
||
"apos", castRole.position,
|
||
"tcamp", targetRole.camp,
|
||
"tpos", targetRole.position,
|
||
"value", value
|
||
)
|
||
end
|
||
|
||
function BattleUtil.ApplyTreat(castRole, targetRole, value, baseFactor, critDamageFactor, addDamageFactor, skill)
|
||
if targetRole == nil then
|
||
return
|
||
end
|
||
-- 灵兽无效
|
||
if targetRole.type == BattleUnitType.Monster then
|
||
return
|
||
end
|
||
if addDamageFactor == nil then
|
||
addDamageFactor = 1
|
||
end
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.DisposeRoleCtrl_noheal, castRole, targetRole)
|
||
if targetRole.ctrl_noheal or targetRole:IsDead() then --禁疗和死亡无法加血
|
||
--禁疗并且没有死亡的单位显示血量+0 不走后面代码,防止触发后面的被动 by:王振兴 2021/1/27
|
||
if targetRole.ctrl_noheal and not targetRole:IsDead() then
|
||
targetRole.Event:DispatchEvent(BattleEventName.RoleBeTreated, castRole, 0, 0)
|
||
end
|
||
return
|
||
end
|
||
baseFactor = baseFactor or 1
|
||
--处理神印追加的技能
|
||
if skill and skill.AttactScale and skill.AttactScale ~= 0 then
|
||
baseFactor = baseFactor * skill.AttactScale
|
||
end
|
||
critDamageFactor = critDamageFactor or 1
|
||
local maxHp = targetRole:GetRoleData(RoleDataName.MaxHp)
|
||
local hp = targetRole:GetRoleData(RoleDataName.Hp)
|
||
|
||
-- 计算被动对治疗系数的影响
|
||
local treatFactorFunc = function(df, dt)
|
||
baseFactor = BattleUtil.CountValue(baseFactor, df, dt)
|
||
end
|
||
castRole.Event:DispatchEvent(BattleEventName.PassiveTreatingFactor, treatFactorFunc, targetRole, skill)
|
||
targetRole.Event:DispatchEvent(BattleEventName.PassiveBeTreatedFactor, treatFactorFunc, castRole)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.PassiveTreatingFactor, treatFactorFunc, targetRole, skill)
|
||
local factor = castRole.isTeam and 1 or castRole:GetRoleData(RoleDataName.TreatFacter) --释放者为team则不计算治疗加成属性
|
||
if factor == 0 then
|
||
factor = 1
|
||
end
|
||
local factor2 = targetRole:GetRoleData(RoleDataName.CureFacter)
|
||
local baseTreat = BattleUtil.FP_Mul(value, baseFactor, factor, factor2, critDamageFactor, addDamageFactor)
|
||
--加入被动效果
|
||
local cl = {}
|
||
local function treatingFunc(v, ct)
|
||
if v then
|
||
table.insert(cl, { v, ct })
|
||
end
|
||
end
|
||
-- local treatingFunc = function(exFactor) baseTreat = floor(baseTreat * (exFactor + 1) + 0.5) end
|
||
castRole.Event:DispatchEvent(BattleEventName.PassiveTreating, treatingFunc, targetRole)
|
||
targetRole.Event:DispatchEvent(BattleEventName.PassiveBeTreated, treatingFunc, castRole)
|
||
baseTreat = BattleUtil.CountChangeList(baseTreat, cl)
|
||
|
||
-- 取整
|
||
local baseTreat = floor(baseTreat + 0.5)
|
||
local isVoid = false
|
||
local treatVoidFunc = function(_void)
|
||
isVoid = _void
|
||
end
|
||
targetRole.Event:DispatchEvent(BattleEventName.CheckTreatVoid, treatVoidFunc, baseTreat, castRole)
|
||
if isVoid then
|
||
return
|
||
end
|
||
local treat = min(baseTreat, maxHp - hp)
|
||
if treat > 0 then
|
||
targetRole.data:AddValue(RoleDataName.Hp, treat)
|
||
end
|
||
castRole.Event:DispatchEvent(BattleEventName.RoleTreat, targetRole, treat, baseTreat, skill)
|
||
targetRole.Event:DispatchEvent(BattleEventName.RoleBeTreated, castRole, treat, baseTreat, skill)
|
||
--添加发送到battleLogic的治疗消息,用于计算总的战斗伤害值
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RoleBeTreated, castRole, treat, baseTreat)
|
||
-- 战斗记录用
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RecordTreat, castRole, targetRole, baseTreat)
|
||
BattleLogManager.Log(
|
||
"Final Treat",
|
||
"acamp", castRole.camp,
|
||
"apos", castRole.position,
|
||
"tcamp", targetRole.camp,
|
||
"tpos", targetRole.position,
|
||
"value", value
|
||
)
|
||
BattleLogic.AddRoundTriggerTime()
|
||
end
|
||
|
||
-- 检测命中
|
||
function BattleUtil.CheckIsHit(atkRole, defRole, skill)
|
||
-- 是否命中: 命中 = 自身命中率 - 对方闪避率
|
||
local isHit = false
|
||
local mustHit = atkRole.mustHit
|
||
--特殊处理 白骨精附加的普攻不会必定暴击
|
||
if atkRole.roleId == 10091 and skill and skill.type == BattleSkillType.Normal and skill.isAdd then
|
||
mustHit = false
|
||
end
|
||
local hitRandom = Random.Range01()
|
||
local addHit = 0
|
||
local addHitFunc = function(v1, ct)
|
||
addHit = BattleUtil.CountValue(addHit, v1, ct)
|
||
end
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.PassiveChangeRoleHit, addHitFunc, atkRole, defRole)
|
||
local hitCondition = clamp(atkRole:GetRoleData(RoleDataName.Hit) + addHit - defRole:GetRoleData(RoleDataName.Dodge),
|
||
0, 1)
|
||
isHit = hitRandom <= hitCondition
|
||
return mustHit or defRole.beMustHit or isHit
|
||
end
|
||
|
||
function BattleUtil.AddBlood(target, value)
|
||
if not target.isBanBlood then
|
||
if target.bloodShield then
|
||
--BattleLogic.WaitForTrigger(BattleLogic.GameDeltaTime*2,function()
|
||
target.bloodShield:AddValue(value)
|
||
--end)
|
||
else
|
||
local buff = Buff.Create(target, BuffName.Blood, 0, value)
|
||
target:AddBuff(buff)
|
||
target.bloodShield = buff
|
||
target.bloodShield:AddValue(value)
|
||
--target.bloodShield:star
|
||
end
|
||
else
|
||
target.Event:DispatchEvent(BattleEventName.ShowHintText, BattleArtFontType.Blood)
|
||
end
|
||
BattleLogic.AddRoundTriggerTime()
|
||
end
|
||
|
||
--获取table的长度
|
||
function BattleUtil.LengthOfTable(table)
|
||
if not table then
|
||
return 0
|
||
end
|
||
local length = 0
|
||
for i, v in pairs(table) do
|
||
length = length + 1
|
||
end
|
||
return length
|
||
end
|
||
|
||
function BattleUtil.RandomAction(rand, action)
|
||
if Random.Range01() <= rand and action then
|
||
action()
|
||
return true
|
||
end
|
||
return false
|
||
end
|
||
|
||
--
|
||
function BattleUtil.RandomControl(rand, ctrl, caster, target, round, skill)
|
||
local cl = {}
|
||
local function _CallBack(v, ct)
|
||
if v then
|
||
table.insert(cl, { v, ct })
|
||
end
|
||
end
|
||
caster.Event:DispatchEvent(BattleEventName.PassiveRandomControl, _CallBack, ctrl, target, rand)
|
||
target.Event:DispatchEvent(BattleEventName.PassiveBeRandomControl, _CallBack, ctrl, target)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.PassiveBeRandomControl, _CallBack, ctrl, caster, target)
|
||
rand = BattleUtil.CountChangeList(rand, cl)
|
||
local list = BattleLogic.BuffMgr:GetBuff(target, function(buff)
|
||
return buff.type == BuffName.BreakArmor and buff.signType == 4
|
||
end)
|
||
for key, value in pairs(list) do
|
||
rand = BattleUtil.CountValue(rand, value.signValue2, value.signValue1)
|
||
end
|
||
local buff = Buff.Create(caster, BuffName.Control, round, ctrl)
|
||
local isAdd = BattleUtil.RandomAction(rand, function()
|
||
target:AddBuff(buff)
|
||
end)
|
||
if not isAdd then
|
||
buff.target = target
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RoleAddBuffFail, buff)
|
||
end
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RoleAddCtrlBuff, buff, isAdd, caster, target, skill)
|
||
return isAdd
|
||
end
|
||
|
||
--
|
||
function BattleUtil.RandomDot(rand, dot, caster, target, round, interval, damage, skill)
|
||
local cl = {}
|
||
local dcl = {}
|
||
local function _CallBack(v, ct, dv, dct)
|
||
if v then
|
||
table.insert(cl, { v, ct })
|
||
end
|
||
if dv then
|
||
table.insert(dcl, { dv, dct })
|
||
end
|
||
end
|
||
caster.Event:DispatchEvent(BattleEventName.PassiveRandomDot, _CallBack, dot)
|
||
target.Event:DispatchEvent(BattleEventName.PassiveBeRandomDot, _CallBack, dot)
|
||
rand = BattleUtil.CountChangeList(rand, cl)
|
||
damage = floor(BattleUtil.CountChangeList(damage, dcl))
|
||
|
||
return BattleUtil.RandomAction(rand, function()
|
||
local buff = Buff.Create(caster, BuffName.DOT, round, interval, dot, damage)
|
||
buff.skill = skill
|
||
buff.isRealDamage = true
|
||
target:AddBuff(buff)
|
||
end)
|
||
end
|
||
|
||
function BattleUtil.RandomList(arr)
|
||
if #arr <= 1 then return end
|
||
local index
|
||
for i = #arr, 1, -1 do
|
||
index = Random.RangeInt(1, i)
|
||
arr[i], arr[index] = arr[index], arr[i]
|
||
end
|
||
end
|
||
|
||
function BattleUtil.Sort(arr, comp)
|
||
if #arr <= 1 then return arr end
|
||
for i = 1, #arr do
|
||
for j = #arr, i + 1, -1 do
|
||
if comp(arr[j - 1], arr[j]) then
|
||
arr[j - 1], arr[j] = arr[j], arr[j - 1]
|
||
end
|
||
end
|
||
end
|
||
return arr
|
||
end
|
||
|
||
function BattleUtil.GetPropertyName(type)
|
||
if type == 1 then
|
||
return RoleDataName.Strength
|
||
elseif type == 2 then
|
||
return RoleDataName.Energy
|
||
elseif type == 3 then
|
||
return RoleDataName.Vitality
|
||
elseif type == 4 then
|
||
return RoleDataName.Dexterity
|
||
elseif type == 5 then
|
||
return RoleDataName.Speed
|
||
elseif type == 6 then
|
||
return RoleDataName.PhysicalAttack
|
||
elseif type == 7 then
|
||
return RoleDataName.MagicAttack
|
||
elseif type == 8 then
|
||
return RoleDataName.PhysicalDefence
|
||
elseif type == 9 then
|
||
return RoleDataName.MagicDefence
|
||
end
|
||
end
|
||
|
||
function BattleUtil.GetHPPencent(role)
|
||
return role:GetRoleData(RoleDataName.Hp) / role:GetRoleData(RoleDataName.MaxHp)
|
||
end
|
||
|
||
-- 计算数值
|
||
function BattleUtil.CountValue(v1, v2, ct)
|
||
local v = v1
|
||
if ct == 1 then --加算
|
||
v = v + v2
|
||
elseif ct == 2 then --乘加算(百分比属性加算)
|
||
v = v * (1 + v2)
|
||
elseif ct == 3 then --减算
|
||
v = v - v2
|
||
elseif ct == 4 then --乘减算(百分比属性减算)
|
||
v = v * (1 - v2)
|
||
elseif ct == 5 then -- 覆盖
|
||
v = v2
|
||
end
|
||
-- 做一个正确性检测
|
||
-- v = BattleUtil.ErrorCorrection(v)
|
||
return v
|
||
end
|
||
|
||
-- 计算数值改变
|
||
function BattleUtil.CountChangeList(v, changeList)
|
||
local aplist = {}
|
||
local splist = {}
|
||
local cplist = {}
|
||
local fv = v
|
||
-- 先算绝对值
|
||
for _, change in ipairs(changeList) do
|
||
local cv = change[1]
|
||
local ct = change[2]
|
||
if ct then
|
||
if ct == 1 or ct == 3 then
|
||
fv = BattleUtil.CountValue(fv, cv, ct)
|
||
elseif ct == 2 then
|
||
table.insert(aplist, change)
|
||
elseif ct == 4 then
|
||
table.insert(splist, change)
|
||
elseif ct == 5 then
|
||
table.insert(cplist, change)
|
||
end
|
||
end
|
||
end
|
||
-- 加乘(对基数进行加乘)
|
||
for _, change in ipairs(aplist) do
|
||
local cv = change[1]
|
||
local ct = change[2]
|
||
fv = fv + (BattleUtil.CountValue(v, cv, ct) - v)
|
||
end
|
||
-- 减乘(对最终数值进行减乘算)
|
||
for _, change in ipairs(splist) do
|
||
local cv = change[1]
|
||
local ct = change[2]
|
||
fv = BattleUtil.CountValue(fv, cv, ct)
|
||
end
|
||
-- 覆盖
|
||
for _, change in ipairs(cplist) do
|
||
local cv = change[1]
|
||
local ct = change[2]
|
||
fv = BattleUtil.CountValue(fv, cv, ct)
|
||
end
|
||
return fv
|
||
end
|
||
|
||
-- 检测技能伤害治疗加乘
|
||
function BattleUtil.CheckSkillDamageHeal(f, caster, target)
|
||
local cl = {}
|
||
local function _CallBack(v, ct)
|
||
if v then
|
||
table.insert(cl, { v, ct })
|
||
end
|
||
end
|
||
caster.Event:DispatchEvent(BattleEventName.PassiveSkillDamageHeal, _CallBack)
|
||
target.Event:DispatchEvent(BattleEventName.PassiveBeSkillDamageHeal, _CallBack)
|
||
f = BattleUtil.CountChangeList(f, cl)
|
||
|
||
return f
|
||
end
|
||
|
||
-- 检测技能伤害治疗加乘
|
||
function BattleUtil.CheckSeckill(bf, kf, caster, target)
|
||
local bcl = {}
|
||
local kcl = {}
|
||
local function _CallBack(bv, bct, kv, kct)
|
||
if bv and bct then
|
||
table.insert(bcl, { bv, bct })
|
||
end
|
||
if kv and kct then
|
||
table.insert(kcl, { kv, kct })
|
||
end
|
||
end
|
||
caster.Event:DispatchEvent(BattleEventName.PassiveSeckill, _CallBack, target)
|
||
target.Event:DispatchEvent(BattleEventName.PassiveBeSeckill, _CallBack)
|
||
bf = BattleUtil.CountChangeList(bf, bcl)
|
||
kf = BattleUtil.CountChangeList(kf, kcl)
|
||
|
||
return bf, kf
|
||
end
|
||
|
||
-- 获取位置类型
|
||
-- 1 前排
|
||
-- 2 后排
|
||
function BattleUtil.GetRolePosType(pos)
|
||
if pos <= 3 then
|
||
return 1
|
||
elseif pos > 3 then
|
||
return 2
|
||
end
|
||
end
|
||
|
||
-- 根据位置类型获取数据
|
||
function BattleUtil.GetRoleListByPosType(camp, posType)
|
||
if posType == 1 then
|
||
return RoleManager.Query(function(r) return r.camp == camp and r.position <= 3 end)
|
||
elseif posType == 2 then
|
||
return RoleManager.Query(function(r) return r.camp == camp and r.position > 3 end)
|
||
end
|
||
end
|
||
|
||
-- 通用增加属性的方法
|
||
function BattleUtil.AddProp(role, prop, value, ct)
|
||
if ct == 1 then --加算
|
||
role.data:AddValue(BattlePropList[prop], value)
|
||
elseif ct == 2 then --乘加算(百分比属性加算)
|
||
role.data:AddPencentValue(BattlePropList[prop], value)
|
||
elseif ct == 3 then --减算
|
||
role.data:SubValue(BattlePropList[prop], value)
|
||
elseif ct == 4 then --乘减算(百分比属性减算)
|
||
role.data:SubPencentValue(BattlePropList[prop], value)
|
||
end
|
||
end
|
||
|
||
-- 比较值(默认返回true)
|
||
-- 0:不比较返回默认true
|
||
-- 1:大于
|
||
-- 2:小于
|
||
-- 3:等于
|
||
-- 4:大于等于
|
||
-- 5:小于等于
|
||
function BattleUtil.CompareValue(v1, v2, comType)
|
||
if comType == 1 then
|
||
return v1 > v2
|
||
elseif comType == 2 then
|
||
return v1 < v2
|
||
elseif comType == 3 then
|
||
return v1 == v2
|
||
elseif comType == 4 then
|
||
return v1 >= v2
|
||
elseif comType == 5 then
|
||
return v1 <= v2
|
||
end
|
||
return true
|
||
end
|
||
|
||
function BattleUtil.IsUserDataNull(userData)
|
||
if (userData == nil) then -- 如果 userdata 是 nil,则为空
|
||
return true
|
||
else
|
||
local metatable = getmetatable(userData)
|
||
return metatable == "null_userdata_metatable" -- 否则检查元表
|
||
end
|
||
end
|