miduo_client/Assets/ManagedResources/~Lua/Modules/Battle/Logic/Misc/BattleUtil.lua

1719 lines
65 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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.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.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 and num == 1 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)}
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 --我方阵亡
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)
end
-- return aaa
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 then
return
end
local damage = defRole:GetRoleData(RoleDataName.Hp)
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 then
return
end
local damage = floor(BattleUtil.FP_Mul(defRole:GetRoleData(RoleDataName.MaxHp),pro))
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)
if defRole==nil then
return
end
-- 灵兽无效
if defRole.type == BattleUnitType.Monster or defRole.type == BattleUnitType.Player 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 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 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
--御甲过滤后的伤害只会处理扣血 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 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 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
-- 攻击力
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 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 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 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 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