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

1411 lines
52 KiB
Lua
Raw Normal View History

2021-04-20 13:58:00 +08:00
BattleUtil = {}
2020-05-09 13:31:21 +08:00
--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")
2021-09-07 19:43:08 +08:00
local 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
2020-05-09 13:31:21 +08:00
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
2020-05-09 13:31:21 +08:00
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
2020-05-09 13:31:21 +08:00
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
2020-05-09 13:31:21 +08:00
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
2020-05-09 13:31:21 +08:00
-- 根据属性排序
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
-- 按百分比血量排序
2020-05-09 13:31:21 +08:00
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
2021-09-07 19:43:08 +08:00
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
2020-05-09 13:31:21 +08:00
-- 获取技能最大目标数
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)
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
arr = RoleManager.Query(function (r) return r.camp == role.camp end)
elseif chooseType == 2 then
if role.lockTarget and not role.lockTarget:IsRealDead() and not role.lockTarget.isExile and num == 1 then --嘲讽时对单个敌军生效
2020-05-09 13:31:21 +08:00
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 --嘲讽时对仇恨目标生效
2020-05-09 13:31:21 +08:00
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-- 对列
2020-08-18 09:26:24 +08:00
local target=RoleManager.GetAggro(role)
if target then
local myCol = target.position % 3
local tempArr = BattleUtil.ChooseCol(arr, myCol)
if #tempArr == 0 then -- 对列没有人,按顺序找到有人得列
2020-05-09 13:31:21 +08:00
for i = 1, 3 do
local col = i % 3 -- 0 表示第三列嗷
tempArr = BattleUtil.ChooseCol(arr, col)
if #tempArr ~= 0 then
break
end
end
2020-08-18 09:26:24 +08:00
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
2020-05-09 13:31:21 +08:00
end
-- 选择条件
if chooseWeight == 0 or role.ctrl_blind then --致盲时排序无效
BattleUtil.RandomList(arr)
elseif chooseWeight == 1 then -- 生命值
BattleUtil.SortByProp(arr, RoleDataName.Hp, sort)
elseif chooseWeight == 2 then -- 血量百分比
BattleUtil.SortByHpFactor(arr, sort)
--选血量百分比最低的 不选择有不灭的,如果伤害要选有不灭的 需处理
BattleUtil.RemoveNoDeadRole(arr)
2020-05-09 13:31:21 +08:00
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 -- 对位
2020-08-26 13:11:00 +08:00
if num==1 then
arr=RoleManager.GetAggroHero(role,arr)
else
arr = RoleManager.GetArrAggroList(role, arr)
end
2020-05-09 13:31:21 +08:00
-- 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)
2020-05-09 13:31:21 +08:00
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
2020-06-18 20:39:29 +08:00
-- table.sort(finalArr, function(a, b)
-- return a.position < b.position
-- end)
2020-05-09 13:31:21 +08:00
return finalArr
end
--获取生命百分比少于指定百分比且生命置最少
function BattleUtil.GetHpPctLessThanPctHero(arr,pct)
local hp=0
local hero=nil
for i = 1, #arr[i] 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
2020-05-09 13:31:21 +08:00
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
-- 计算护盾
2020-11-14 14:43:40 +08:00
function BattleUtil.CalShield(atkRole, defRole, damage,skill)
2020-05-09 13:31:21 +08:00
for i=1, defRole.shield.size do
local buff = defRole.shield.buffer[i]
2020-11-14 14:43:40 +08:00
damage = buff:CountShield(damage, atkRole,skill)
2020-05-25 19:16:23 +08:00
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
2020-05-25 19:16:23 +08:00
-- 提前计算护盾后伤害
function BattleUtil.PreCountShield(defRole, damage)
for i=1, defRole.shield.size do
local buff = defRole.shield.buffer[i]
damage = buff:PreCountShield(damage)
2020-05-09 13:31:21 +08:00
end
return damage
end
2020-09-25 12:22:12 +08:00
--检测是否为boss
function BattleUtil.CheckIsBoss(role)
if not role then
return false
2020-09-25 12:22:12 +08:00
end
if role.enemyType==EnemyType.Boss then
2020-09-25 12:22:12 +08:00
--弹免疫
role.Event:DispatchEvent(BattleEventName.ShowHintText, BattleArtFontType.Immune)
2020-09-25 12:22:12 +08:00
return true
else
return false
end
end
2020-05-09 13:31:21 +08:00
-- 秒杀
function BattleUtil.Seckill(skill, atkRole, defRole)
2020-11-01 15:46:48 +08:00
-- 灵兽无效
2021-10-20 21:33:37 +08:00
if defRole.type == BattleUnitType.Monster or defRole.type == BattleUnitType.Player then
2020-11-01 15:46:48 +08:00
return
end
2020-05-09 13:31:21 +08:00
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)
2020-05-09 13:31:21 +08:00
BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoleDead, defRole, atkRole)
atkRole.Event:DispatchEvent(BattleEventName.Seckill, defRole,damage,nil,finalDmg)
2020-05-09 13:31:21 +08:00
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
2021-01-16 14:41:10 +08:00
-- 用于记录统计
BattleLogic.Event:DispatchEvent(BattleEventName.RecordSecKill, atkRole, defRole)
2020-05-09 13:31:21 +08:00
end
-- 秒杀定额血量
2021-01-16 14:41:10 +08:00
function BattleUtil.SeckillHP(skill, atkRole, defRole, pro)
-- 灵兽无效
2021-10-20 21:33:37 +08:00
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
2021-01-16 14:41:10 +08:00
-- 用于记录统计
BattleLogic.Event:DispatchEvent(BattleEventName.RecordSecKill, atkRole, defRole)
end
2020-05-09 13:31:21 +08:00
-- 计算真实伤害
2020-10-17 18:35:52 +08:00
function BattleUtil.ApplyDamage(skill, atkRole, defRole, damage, bCrit, damageType, dotType,isDirect)
2020-11-01 15:46:48 +08:00
-- 灵兽无效
2021-10-20 21:33:37 +08:00
if defRole.type == BattleUnitType.Monster or defRole.type == BattleUnitType.Player then
2020-11-01 15:46:48 +08:00
return
end
2020-05-09 13:31:21 +08:00
bCrit = bCrit or false
damageType = damageType or 0
-- if atkRole.isTeam then
-- --max技能基础伤害*1+已方异妖伤害加成-目标异妖伤害减免30%×技能基础伤害)
-- local arr = RoleManager.Query(function (r) return r.camp == atkRole.camp end)
-- local n = 0
-- for i=1, #arr do
-- n = n + arr[i]:GetRoleData(RoleDataName.TeamDamageBocusFactor)
-- end
-- damage = floor(max(damage * (1 + n / #arr - defRole:GetRoleData(RoleDataName.TeamDamageReduceFactor)), 0.3 * damage))
-- end
--加入被动效果
local damagingFunc = function(dmgDeduction)
damage = damage - dmgDeduction
end
atkRole.Event:DispatchEvent(BattleEventName.PassiveDamaging, damagingFunc, defRole, damage, skill, dotType, bCrit,damageType, dotType,isDirect)
2020-05-09 13:31:21 +08:00
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)
2020-05-09 13:31:21 +08:00
-- 计算护盾减伤
2020-11-14 14:43:40 +08:00
damage = BattleUtil.CalShield(atkRole, defRole, damage,skill)
2020-05-09 13:31:21 +08:00
-- 造成的最终伤害
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)
2020-05-09 13:31:21 +08:00
BattleLogic.Event:DispatchEvent(BattleEventName.FinalDamage, damagingFunc, atkRole, defRole, damage, skill, dotType, bCrit, damageType)
--
2020-10-17 18:35:52 +08:00
return BattleUtil.FinalDamage(skill, atkRole, defRole, damage, bCrit, damageType, dotType,isDirect)
2020-05-09 13:31:21 +08:00
end
2021-10-09 18:23:45 +08:00
-- 计算真实伤害(没有被动增伤)
function BattleUtil.ApplyDamageNoPassive(skill, atkRole, defRole, damage, bCrit, damageType, dotType,isDirect)
-- 灵兽无效
2021-10-20 21:33:37 +08:00
if defRole.type == BattleUnitType.Monster or defRole.type == BattleUnitType.Player then
2021-10-09 18:23:45 +08:00
return
end
-- 计算护盾减伤
damage = BattleUtil.CalShield(atkRole, defRole, damage,skill)
-- 造成的最终伤害
local damagingFunc = function(dmgDeduction)
damage = damage - dmgDeduction
end
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
2020-07-29 12:41:15 +08:00
2021-01-16 14:41:10 +08:00
-- 怒气计算
function BattleUtil.CalRage(caster, target, value, countType,isBorrow)
2021-01-16 14:41:10 +08:00
-- 角色身上有无敌盾,不扣除怒气 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
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
2021-01-16 14:41:10 +08:00
-- 操作怒气
local deltaRage = target:AddRage(value, countType)
if (countType==3 or countType==4) and target.RoundMaxSubRage~=0 then
target.AllSubRage=target.AllSubRage-deltaRage
end
BattleLogic.Event:DispatchEvent(BattleEventName.RecordRageChange, caster, target, deltaRage,countType,value,lastRage,isBorrow)
2021-01-16 14:41:10 +08:00
-- 用于记录统计
BattleLogic.Event:DispatchEvent(BattleEventName.RecordRage, caster, target, deltaRage)
end
2020-07-29 12:41:15 +08:00
--检测是否有是金翅大鹏有不灭效果
function BattleUtil.CheckIsNoDead(target)
if target then
return target.isHaveNoDead or BattleLogic.BuffMgr:HasBuff(target,BuffName.NoDead)
2020-07-29 12:41:15 +08:00
end
2020-09-25 12:22:12 +08:00
return false
2020-07-29 12:41:15 +08:00
end
2021-01-16 14:41:10 +08:00
--检测列表是否包含值
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
2020-07-29 12:41:15 +08:00
-- 根据id获取额外技能
function BattleUtil.GetExtraSkillbyId(id)
2020-09-25 12:22:12 +08:00
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
2020-11-14 19:20:06 +08:00
elseif id==5 then
return ExtraReleaseSkill.skill5
elseif id==6 then
return ExtraReleaseSkill.skill6
2020-09-25 12:22:12 +08:00
end
end
2020-10-17 18:35:52 +08:00
function BattleUtil.FinalDamage(skill, atkRole, defRole, damage, bCrit, damageType, dotType,isDirect)
2020-11-01 15:46:48 +08:00
-- 灵兽无效
2021-10-20 21:33:37 +08:00
if defRole.type == BattleUnitType.Monster or defRole.type == BattleUnitType.Player then
2020-11-01 15:46:48 +08:00
return
end
2020-05-09 13:31:21 +08:00
if damage < 0 then damage = 0 end
if skill and skill.type==BattleSkillType.Special then
skill.owner.superSkillDamage=damage
end
--计算血量防护
2021-08-12 15:42:31 +08:00
local realDamage=damage
--血量防护只会防直接伤害
if defRole.bloodShield and skill then
realDamage=math.abs(defRole.bloodShield:CountBloodValue(damage))
2021-09-27 13:47:27 +08:00
-- damage=realDamage
end
2021-09-27 13:47:27 +08:00
--御甲过滤后的伤害只会处理扣血 by: wangzhenxing shihongyi 2021/09/27
local finalDmg = defRole.data:SubValue(RoleDataName.Hp,realDamage)
2020-05-09 13:31:21 +08:00
if finalDmg >= 0 then
if defRole:GetRoleData(RoleDataName.Hp) <= 0 and not defRole:IsDead() then
defRole:SetDead(damage)
2020-05-09 13:31:21 +08:00
defRole.Event:DispatchEvent(BattleEventName.RoleDead, atkRole)
atkRole.Event:DispatchEvent(BattleEventName.RoleKill, defRole,skill)
BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoleDead, defRole, atkRole,skill,dotType)
2020-05-09 13:31:21 +08:00
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)
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
2020-05-09 13:31:21 +08:00
end
2020-10-17 18:35:52 +08:00
--如果不是技能带的伤害,并且是直接伤害就,,,,,
--用于处理不触发特性并且是直接伤害的伤害 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)
2020-10-17 18:35:52 +08:00
end
2020-05-09 13:31:21 +08:00
end
2020-06-18 20:39:29 +08:00
2021-01-16 14:41:10 +08:00
-- 战斗记录用
BattleLogic.Event:DispatchEvent(BattleEventName.RecordDamage, atkRole, defRole, damage)
2020-06-18 20:39:29 +08:00
--
BattleLogManager.Log(
"Final Damage",
"acamp", atkRole.camp,
"apos", atkRole.position,
"tcamp", defRole.camp,
"tpos", defRole.position,
"damage", damage,
"dotType", tostring(dotType)
)
2020-05-09 13:31:21 +08:00
return finalDmg
end
2021-10-20 21:33:37 +08:00
--计算盾的最终伤害
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.CalShield(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
--血量防护只会防直接伤害
if defRole.bloodShield and skill then
realDamage=math.abs(defRole.bloodShield:CountBloodValue(damage))
-- 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)
2021-10-20 21:33:37 +08:00
--御甲过滤后的伤害只会处理扣血 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)
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
2020-05-09 13:31:21 +08:00
--执行完整的命中,伤害,暴击计算,返回命中,暴击
--skill造成伤害的技能 atkRole攻击者 defRole受击者 damageType伤害类型 baseFactor伤害系数 ignoreDef无视防御参数 dotType是持续伤害类型
function BattleUtil.CalDamage(skill, atkRole, defRole, damageType, baseFactor, ignoreDef, dotType)
2020-11-01 15:46:48 +08:00
-- 灵兽无效
2021-10-20 21:33:37 +08:00
if defRole.type == BattleUnitType.Monster or defRole.type == BattleUnitType.Player then
2020-11-01 15:46:48 +08:00
return
end
2020-07-08 21:19:34 +08:00
-- 判断是否命中
if skill and not skill:CheckTargetIsHit(defRole) and atkRole.type==BattleUnitType.Role then
2020-07-08 21:19:34 +08:00
BattleLogic.Event:DispatchEvent(BattleEventName.HitMiss, atkRole, defRole, skill)
atkRole.Event:DispatchEvent(BattleEventName.HitMiss, defRole, skill)
defRole.Event:DispatchEvent(BattleEventName.BeHitMiss, atkRole, skill)
2020-07-09 15:18:02 +08:00
return 0
2020-07-08 21:19:34 +08:00
end
-- 如果是队伍技能计算真实伤害则damageType为伤害值
if atkRole.isTeam and not defRole:IsDead() then
2020-05-09 13:31:21 +08:00
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
-- 攻击力
local attack = atkRole:GetRoleData(RoleDataName.Attack)
-- 无视防御系数
ignoreDef = 1 - (ignoreDef or 0)
2020-05-25 19:16:23 +08:00
-- 基础伤害 = 攻击力 - 防御力
baseDamage = max(attack - BattleUtil.FP_Mul(defence, ignoreDef), 0)
2020-05-09 13:31:21 +08:00
2020-05-25 19:16:23 +08:00
-- 基础伤害增加系数
local addDamageFactor = 1 + atkRole:GetRoleData(RoleDataName.DamageBocusFactor) - defRole:GetRoleData(RoleDataName.DamageReduceFactor)
-- 是否暴击: 暴击率 = 自身暴击率 - 对方抗暴率
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
2020-05-25 19:16:23 +08:00
local critCondition = clamp(atkRole:GetRoleData(RoleDataName.Crit) - defRole:GetRoleData(RoleDataName.Tenacity), 0, 1)
bCrit = critRandom <= critCondition
bCrit =mustCrit or bCrit or defRole.isFlagCrit == true -- 必定暴击
2020-05-25 19:16:23 +08:00
-- 计算暴伤害系数
local critDamageFactor = 1
local critDamageReduceFactor = 0 -- 暴击伤害减免
2020-05-09 13:31:21 +08:00
--计算暴击
if bCrit then
2020-05-25 19:16:23 +08:00
--加入被动效果 触发暴击被动
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)
defRole.Event:DispatchEvent(BattleEventName.CritDamageReduceFactor, onCritDamageReduceFactor, atkRole, defRole)
BattleLogic.Event:DispatchEvent(BattleEventName.CritDamageReduceFactor, onCritDamageReduceFactor, atkRole, defRole)
critDamageReduceFactor = max(BattleUtil.CountChangeList(critDamageReduceFactor, cl), 0)
2020-05-09 13:31:21 +08:00
-- 计算额外暴击伤害
2020-05-25 19:16:23 +08:00
critDamageFactor = 1.3 + atkRole:GetRoleData(RoleDataName.CritDamageFactor) - critDamageReduceFactor
2020-05-09 13:31:21 +08:00
--加入被动效果 触发暴击被动
local critFunc = function(critEx) critDamageFactor = critEx end
atkRole.Event:DispatchEvent(BattleEventName.PassiveCriting, critFunc,skill)
2020-05-25 19:16:23 +08:00
end
-- 公式伤害 = 基础伤害 * 基础伤害系数 * 增伤系数 * 爆伤系数
local fixDamage = floor(BattleUtil.FP_Mul(baseDamage, baseFactor, addDamageFactor, critDamageFactor))
2020-05-09 13:31:21 +08:00
2020-05-25 19:16:23 +08:00
-- 公式计算完成
local damageFunc = function(damage) fixDamage = damage end
atkRole.Event:DispatchEvent(BattleEventName.RoleDamageAfter, defRole, damageFunc, fixDamage,skill)
2020-05-25 19:16:23 +08:00
defRole.Event:DispatchEvent(BattleEventName.RoleBeDamagedAfter, atkRole, damageFunc, fixDamage)
2020-05-09 13:31:21 +08:00
2020-06-08 13:57:30 +08:00
fixDamage = max(floor(attack * 0.1), fixDamage)
2020-05-09 13:31:21 +08:00
local finalDmg = 0 --计算实际造成的扣血
if not defRole:IsRealDead() then
2020-05-25 19:16:23 +08:00
finalDmg = BattleUtil.ApplyDamage(skill, atkRole, defRole, fixDamage, bCrit, damageType, dotType)
2020-05-09 13:31:21 +08:00
end
return finalDmg, bCrit
end
function BattleUtil.CalTreat(castRole, targetRole, value, baseFactor,skill)
2020-11-01 15:46:48 +08:00
-- 灵兽无效
2021-10-20 21:33:37 +08:00
if targetRole.type == BattleUnitType.Monster or targetRole.type == BattleUnitType.Player then
2020-11-01 15:46:48 +08:00
return
end
BattleLogic.Event:DispatchEvent(BattleEventName.DisposeRoleCtrl_noheal, castRole,targetRole)
2020-05-09 13:31:21 +08:00
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
2020-05-09 13:31:21 +08:00
return
end
2020-11-01 15:46:48 +08:00
-- 是否暴击: 暴击率 = 自身暴击率 - 对方抗暴率
local bCrit = false
local critRandom = Random.Range01()
local critCondition = castRole:GetRoleData(RoleDataName.Crit)
bCrit = critRandom <= critCondition
bCrit = bCrit or targetRole.isFlagCrit == true -- 必定暴击
2020-10-17 18:35:52 +08:00
-- 计算暴伤害系数
local critDamageFactor = 1
--计算暴击
if bCrit then
--伤害有个+1.3 不知道干什么用的就给去了 by:wangxhenxing 2020/10/10 18:46
critDamageFactor = 1.3 + castRole:GetRoleData(RoleDataName.CritDamageFactor)
end
-- 基础伤害增加系数
local addDamageFactor = 1 + castRole:GetRoleData(RoleDataName.DamageBocusFactor)
2020-05-09 13:31:21 +08:00
targetRole.Event:DispatchEvent(BattleEventName.RoleBeHealed, castRole)
BattleUtil.ApplyTreat(castRole, targetRole, value, baseFactor,critDamageFactor,addDamageFactor,skill)
2020-05-09 13:31:21 +08:00
end
function BattleUtil.FinalTreat(castRole, targetRole, value, baseFactor,skill)
-- 灵兽无效
2021-10-20 21:33:37 +08:00
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)
targetRole.Event:DispatchEvent(BattleEventName.RoleBeTreated, castRole, treat, baseTreat)
--添加发送到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
2020-05-09 13:31:21 +08:00
function BattleUtil.ApplyTreat(castRole, targetRole, value, baseFactor,critDamageFactor,addDamageFactor,skill)
2020-11-01 15:46:48 +08:00
-- 灵兽无效
if targetRole.type == BattleUnitType.Monster then
return
end
BattleLogic.Event:DispatchEvent(BattleEventName.DisposeRoleCtrl_noheal, castRole,targetRole)
2020-05-09 13:31:21 +08:00
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
2020-05-09 13:31:21 +08:00
return
end
baseFactor = baseFactor 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)
2020-05-09 13:31:21 +08:00
targetRole.Event:DispatchEvent(BattleEventName.PassiveBeTreatedFactor, treatFactorFunc, castRole)
local factor = castRole.isTeam and 1 or castRole:GetRoleData(RoleDataName.TreatFacter) --释放者为team则不计算治疗加成属性
local factor2 = targetRole:GetRoleData(RoleDataName.CureFacter)
2020-10-17 18:35:52 +08:00
local baseTreat = BattleUtil.FP_Mul(value, baseFactor, factor, factor2,critDamageFactor,addDamageFactor)
2020-05-09 13:31:21 +08:00
--加入被动效果
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)
targetRole.Event:DispatchEvent(BattleEventName.RoleBeTreated, castRole, treat, baseTreat)
2020-09-25 12:22:12 +08:00
--添加发送到battleLogic的治疗消息用于计算总的战斗伤害值
BattleLogic.Event:DispatchEvent(BattleEventName.RoleBeTreated, castRole, treat, baseTreat)
2021-01-16 14:41:10 +08:00
-- 战斗记录用
BattleLogic.Event:DispatchEvent(BattleEventName.RecordTreat, castRole, targetRole, baseTreat)
2020-06-18 20:39:29 +08:00
BattleLogManager.Log(
"Final Treat",
2020-06-18 20:39:29 +08:00
"acamp", castRole.camp,
"apos", castRole.position,
"tcamp", targetRole.camp,
"tpos", targetRole.position,
"value", value
)
2020-05-09 13:31:21 +08:00
end
2020-07-08 21:19:34 +08:00
-- 检测命中
function BattleUtil.CheckIsHit(atkRole, defRole,skill)
2020-07-08 21:19:34 +08:00
-- 是否命中: 命中 = 自身命中率 - 对方闪避率
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
2020-07-08 21:19:34 +08:00
local hitRandom = Random.Range01()
local hitCondition = clamp(atkRole:GetRoleData(RoleDataName.Hit) - defRole:GetRoleData(RoleDataName.Dodge), 0, 1)
isHit = hitRandom <= hitCondition
return mustHit or isHit
2020-07-08 21:19:34 +08:00
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
2020-05-09 13:31:21 +08:00
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)
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)
target.Event:DispatchEvent(BattleEventName.PassiveBeRandomControl, _CallBack, ctrl, target)
rand = BattleUtil.CountChangeList(rand, cl)
2021-05-13 11:24:35 +08:00
local buff = Buff.Create(caster, BuffName.Control, round, ctrl)
local isAdd=BattleUtil.RandomAction(rand, function()
2020-05-09 13:31:21 +08:00
target:AddBuff(buff)
end)
2021-05-13 11:24:35 +08:00
if not isAdd then
buff.target=target
2021-05-13 11:24:35 +08:00
BattleLogic.Event:DispatchEvent(BattleEventName.RoleAddBuffFail,buff)
end
return isAdd
2020-05-09 13:31:21 +08:00
end
--
function BattleUtil.RandomDot(rand, dot, caster, target, round, interval, damage)
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))
2020-05-09 13:31:21 +08:00
return BattleUtil.RandomAction(rand, function()
local buff = Buff.Create(caster, BuffName.DOT, round, interval, dot, damage)
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)
2020-05-11 09:38:52 +08:00
if bv and bct then
table.insert(bcl, {bv, bct})
end
if kv and kct then
table.insert(kcl, {kv, kct})
2020-05-09 13:31:21 +08:00
end
end
caster.Event:DispatchEvent(BattleEventName.PassiveSeckill, _CallBack)
target.Event:DispatchEvent(BattleEventName.PassiveBeSeckill, _CallBack)
bf = BattleUtil.CountChangeList(bf, bcl)
kf = BattleUtil.CountChangeList(kf, kcl)
return bf, kf
end
2020-05-25 19:16:23 +08:00
-- 获取位置类型
-- 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
2020-06-03 19:09:01 +08:00
return RoleManager.Query(function (r) return r.camp == camp and r.position <= 3 end)
2020-05-25 19:16:23 +08:00
elseif posType == 2 then
2020-06-03 19:09:01 +08:00
return RoleManager.Query(function (r) return r.camp == camp and r.position > 3 end)
2020-05-25 19:16:23 +08:00
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
2020-11-01 15:46:48 +08:00
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
2020-05-25 19:16:23 +08:00
end