2019-03-12 14:05:45 +08:00
|
|
|
|
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
|
2019-09-02 16:32:32 +08:00
|
|
|
|
BattleUtil.Passivity = require("Modules/Battle/Logic/Base/Passivity")
|
2019-03-12 14:05:45 +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
|
|
|
|
|
|
2019-08-06 20:55:47 +08:00
|
|
|
|
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
|
|
|
|
|
if BattleLogic.IsOpenBattleRecord then
|
2019-11-13 19:06:21 +08:00
|
|
|
|
BattleLogic.RecordMul({...})
|
2019-08-06 20:55:47 +08:00
|
|
|
|
end
|
|
|
|
|
return f
|
|
|
|
|
end
|
|
|
|
|
|
2020-04-10 14:52:41 +08:00
|
|
|
|
-- 选择前排
|
|
|
|
|
function BattleUtil.ChooseFRow(arr)
|
|
|
|
|
local tempArr = {}
|
|
|
|
|
for _, r in ipairs(arr) do
|
|
|
|
|
if r.position <= 3 and not r.isDead then
|
|
|
|
|
table.insert(tempArr, r)
|
|
|
|
|
end
|
|
|
|
|
end
|
2020-04-16 16:27:42 +08:00
|
|
|
|
table.sort(tempArr, function(a, b)
|
|
|
|
|
return a.position < b.position
|
|
|
|
|
end)
|
2020-04-10 14:52:41 +08:00
|
|
|
|
return tempArr
|
|
|
|
|
end
|
|
|
|
|
-- 选择后排
|
|
|
|
|
function BattleUtil.ChooseBRow(arr)
|
|
|
|
|
local tempArr = {}
|
|
|
|
|
for _, r in ipairs(arr) do
|
|
|
|
|
if r.position > 3 and not r.isDead then
|
|
|
|
|
table.insert(tempArr, r)
|
|
|
|
|
end
|
|
|
|
|
end
|
2020-04-16 16:27:42 +08:00
|
|
|
|
table.sort(tempArr, function(a, b)
|
|
|
|
|
return a.position < b.position
|
|
|
|
|
end)
|
2020-04-10 14:52:41 +08:00
|
|
|
|
return tempArr
|
|
|
|
|
end
|
|
|
|
|
-- 选择一列(col == 0 表示第三列哦)
|
|
|
|
|
function BattleUtil.ChooseCol(arr, col)
|
|
|
|
|
local tempArr = {}
|
|
|
|
|
for _, role in ipairs(arr) do
|
|
|
|
|
if role.position % 3 == col then
|
|
|
|
|
table.insert(tempArr, role)
|
|
|
|
|
end
|
|
|
|
|
end
|
2020-04-16 16:27:42 +08:00
|
|
|
|
table.sort(tempArr, function(a, b)
|
|
|
|
|
return a.position < b.position
|
|
|
|
|
end)
|
2020-04-10 14:52:41 +08:00
|
|
|
|
return tempArr
|
|
|
|
|
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
|
2020-04-21 20:51:31 +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.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
|
2020-04-10 14:52:41 +08:00
|
|
|
|
|
2020-04-21 20:51:31 +08:00
|
|
|
|
--
|
|
|
|
|
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
|
2020-04-10 14:52:41 +08:00
|
|
|
|
|
2020-04-21 20:51:31 +08:00
|
|
|
|
--
|
2019-06-05 11:29:24 +08:00
|
|
|
|
function BattleUtil.ChooseTarget(role, chooseId)
|
2020-04-10 14:52:41 +08:00
|
|
|
|
local chooseType = floor(chooseId / 100000) % 10
|
|
|
|
|
local chooseLimit = floor(chooseId / 10000) % 10
|
|
|
|
|
local chooseWeight = floor(chooseId / 100) % 100
|
2019-06-05 11:29:24 +08:00
|
|
|
|
local sort = floor(chooseId / 10) % 10
|
|
|
|
|
local num = chooseId % 10
|
|
|
|
|
local arr
|
2020-04-10 14:52:41 +08:00
|
|
|
|
-- 选择类型
|
2019-06-05 11:29:24 +08:00
|
|
|
|
if chooseType == 1 then
|
|
|
|
|
arr = BattleLogic.Query(function (r) return r.camp == role.camp end)
|
|
|
|
|
elseif chooseType == 2 then
|
2019-07-12 15:29:53 +08:00
|
|
|
|
if role.lockTarget and not role.lockTarget.isDead and num == 1 then --嘲讽时对单个敌军生效
|
2019-06-05 11:29:24 +08:00
|
|
|
|
return {role.lockTarget}
|
|
|
|
|
end
|
|
|
|
|
arr = BattleLogic.Query(function (r) return r.camp ~= role.camp end)
|
|
|
|
|
elseif chooseType == 3 then
|
|
|
|
|
if role.ctrl_blind then --致盲时自身变随机友军
|
|
|
|
|
arr = BattleLogic.Query(function (r) return r.camp == role.camp end)
|
|
|
|
|
BattleUtil.RandomList(arr)
|
|
|
|
|
return {arr[1]}
|
|
|
|
|
end
|
|
|
|
|
return {role}
|
|
|
|
|
elseif chooseType == 4 then
|
2019-07-12 15:29:53 +08:00
|
|
|
|
if role.lockTarget and not role.lockTarget.isDead then --嘲讽时对仇恨目标生效
|
2019-06-05 11:29:24 +08:00
|
|
|
|
return {role.lockTarget}
|
|
|
|
|
end
|
|
|
|
|
if role.ctrl_blind then --致盲时仇恨目标变随机
|
|
|
|
|
arr = BattleLogic.Query(function (r) return r.camp ~= role.camp end)
|
|
|
|
|
BattleUtil.RandomList(arr)
|
|
|
|
|
return {arr[1]}
|
|
|
|
|
end
|
2019-10-23 13:40:57 +08:00
|
|
|
|
return {BattleLogic.GetAggro(role)}
|
2019-06-05 11:29:24 +08:00
|
|
|
|
else
|
|
|
|
|
arr = BattleLogic.Query()
|
|
|
|
|
end
|
|
|
|
|
|
2020-04-10 14:52:41 +08:00
|
|
|
|
--选择范围
|
|
|
|
|
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 myCol = role.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
|
|
|
|
|
|
|
|
|
|
-- 选择条件
|
2019-06-05 11:29:24 +08:00
|
|
|
|
if chooseWeight == 0 or role.ctrl_blind then --致盲时排序无效
|
|
|
|
|
BattleUtil.RandomList(arr)
|
2020-04-10 14:52:41 +08:00
|
|
|
|
elseif chooseWeight == 1 then -- 生命值
|
|
|
|
|
BattleUtil.SortByProp(arr, RoleDataName.Hp, sort)
|
|
|
|
|
elseif chooseWeight == 2 then -- 血量百分比
|
2020-04-21 20:51:31 +08:00
|
|
|
|
BattleUtil.SortByHpFactor(arr, sort)
|
2020-04-10 14:52:41 +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 -- 对位及其相邻目标
|
2019-10-23 13:40:57 +08:00
|
|
|
|
arr = BattleLogic.GetNeighbor(role, chooseType)
|
2020-04-16 16:27:42 +08:00
|
|
|
|
elseif chooseWeight == 8 then -- 对位
|
|
|
|
|
arr = BattleLogic.GetArrAggroList(role, arr)
|
2020-04-10 14:52:41 +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)
|
2019-06-05 11:29:24 +08:00
|
|
|
|
end
|
2020-04-16 16:27:42 +08:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
return finalArr
|
2019-06-05 11:29:24 +08:00
|
|
|
|
end
|
|
|
|
|
|
2020-04-10 14:52:41 +08:00
|
|
|
|
|
2019-03-12 14:05:45 +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
|
|
|
|
|
|
2020-04-10 14:52:41 +08:00
|
|
|
|
-- 计算命中率
|
2019-03-12 14:05:45 +08:00
|
|
|
|
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-04-10 14:52:41 +08:00
|
|
|
|
-- 计算护盾
|
2019-03-12 14:05:45 +08:00
|
|
|
|
function BattleUtil.CalShield(atkRole, defRole, damage)
|
2019-03-21 14:33:56 +08:00
|
|
|
|
for i=1, defRole.shield.size do
|
2019-04-17 21:04:32 +08:00
|
|
|
|
local buff = defRole.shield.buffer[i]
|
2020-04-10 14:52:41 +08:00
|
|
|
|
damage = buff:CountShield(damage, atkRole)
|
|
|
|
|
-- buff.atk = atkRole
|
|
|
|
|
-- if damage < buff.shieldValue then
|
|
|
|
|
-- buff.shieldValue = buff.shieldValue - damage
|
|
|
|
|
-- buff.damageSum = buff.damageSum + damage
|
|
|
|
|
-- return 0
|
|
|
|
|
-- else
|
|
|
|
|
-- buff.damageSum = buff.damageSum + buff.shieldValue
|
|
|
|
|
-- damage = damage - buff.shieldValue
|
|
|
|
|
-- buff.shieldValue = 0
|
|
|
|
|
-- buff.disperse = true
|
|
|
|
|
-- end
|
2019-03-12 14:05:45 +08:00
|
|
|
|
end
|
|
|
|
|
return damage
|
|
|
|
|
end
|
|
|
|
|
|
2020-04-21 20:51:31 +08:00
|
|
|
|
|
|
|
|
|
-- 秒杀
|
|
|
|
|
function BattleUtil.Seckill(skill, atkRole, defRole)
|
|
|
|
|
local damage = defRole:GetRoleData(RoleDataName.Hp)
|
|
|
|
|
local finalDmg = defRole.data:SubValue(RoleDataName.Hp, damage)
|
|
|
|
|
if finalDmg >= 0 then
|
|
|
|
|
if defRole:GetRoleData(RoleDataName.Hp) <= 0 then
|
|
|
|
|
defRole.isDead = true
|
|
|
|
|
BattleLogic.BuffMgr:ClearBuff(defRole)
|
|
|
|
|
defRole.Event:DispatchEvent(BattleEventName.RoleDead, atkRole)
|
|
|
|
|
atkRole.Event:DispatchEvent(BattleEventName.RoleKill, defRole)
|
|
|
|
|
BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoleDead, defRole, atkRole)
|
|
|
|
|
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)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2020-04-10 14:52:41 +08:00
|
|
|
|
-- 计算真实伤害
|
|
|
|
|
function BattleUtil.ApplyDamage(skill, atkRole, defRole, damage, bCrit, damageType, isDot)
|
2019-05-07 20:01:07 +08:00
|
|
|
|
bCrit = bCrit or false
|
|
|
|
|
damageType = damageType or 0
|
2019-05-18 17:20:57 +08:00
|
|
|
|
isDot = isDot or false
|
2019-05-09 17:50:38 +08:00
|
|
|
|
|
2020-04-16 16:27:42 +08:00
|
|
|
|
-- if atkRole.isTeam then
|
|
|
|
|
-- --max(技能基础伤害*(1+已方异妖伤害加成-目标异妖伤害减免),30%×技能基础伤害)
|
|
|
|
|
-- local arr = BattleLogic.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
|
2019-05-07 20:01:07 +08:00
|
|
|
|
|
|
|
|
|
--加入被动效果
|
|
|
|
|
local damagingFunc = function(dmgDeduction) damage = damage - dmgDeduction end
|
2020-04-16 16:27:42 +08:00
|
|
|
|
atkRole.Event:DispatchEvent(BattleEventName.PassiveDamaging, damagingFunc, defRole, damage, skill)
|
|
|
|
|
defRole.Event:DispatchEvent(BattleEventName.PassiveBeDamaging, damagingFunc, atkRole, damage, skill)
|
2019-05-07 20:01:07 +08:00
|
|
|
|
|
2020-04-10 14:52:41 +08:00
|
|
|
|
-- 计算护盾减伤
|
|
|
|
|
damage = BattleUtil.CalShield(atkRole, defRole, damage)
|
|
|
|
|
|
2020-04-16 16:27:42 +08:00
|
|
|
|
if damage >= 0 then
|
2019-05-07 20:01:07 +08:00
|
|
|
|
local finalDmg = defRole.data:SubValue(RoleDataName.Hp, damage)
|
2020-04-16 16:27:42 +08:00
|
|
|
|
if finalDmg >= 0 then
|
2019-05-07 20:01:07 +08:00
|
|
|
|
if defRole:GetRoleData(RoleDataName.Hp) <= 0 then
|
|
|
|
|
defRole.isDead = true
|
|
|
|
|
BattleLogic.BuffMgr:ClearBuff(defRole)
|
2019-10-23 13:40:57 +08:00
|
|
|
|
defRole.Event:DispatchEvent(BattleEventName.RoleDead, atkRole)
|
2019-10-24 15:24:18 +08:00
|
|
|
|
atkRole.Event:DispatchEvent(BattleEventName.RoleKill, defRole)
|
2019-10-23 13:40:57 +08:00
|
|
|
|
BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoleDead, defRole, atkRole)
|
2019-04-16 14:32:11 +08:00
|
|
|
|
end
|
2019-05-13 09:51:36 +08:00
|
|
|
|
|
2020-04-10 14:52:41 +08:00
|
|
|
|
atkRole.Event:DispatchEvent(BattleEventName.RoleDamage, defRole, damage, bCrit, finalDmg, damageType, isDot, skill)
|
|
|
|
|
defRole.Event:DispatchEvent(BattleEventName.RoleBeDamaged, atkRole, damage, bCrit, finalDmg, damageType, isDot, skill)
|
|
|
|
|
BattleLogic.Event:DispatchEvent(BattleEventName.RoleDamage, atkRole, defRole, damage, bCrit, finalDmg, damageType, isDot, skill)
|
|
|
|
|
BattleLogic.Event:DispatchEvent(BattleEventName.RoleBeDamaged, defRole, atkRole, damage, bCrit, finalDmg, damageType, isDot, skill)
|
2019-05-13 09:51:36 +08:00
|
|
|
|
if bCrit then
|
2020-04-16 16:27:42 +08:00
|
|
|
|
atkRole.Event:DispatchEvent(BattleEventName.RoleCrit, defRole, damage, bCrit, finalDmg, damageType, skill)
|
|
|
|
|
defRole.Event:DispatchEvent(BattleEventName.RoleBeCrit, atkRole, damage, bCrit, finalDmg, damageType, skill)
|
2019-05-13 09:51:36 +08:00
|
|
|
|
end
|
2019-05-18 17:20:57 +08:00
|
|
|
|
if not isDot then
|
2020-04-16 16:27:42 +08:00
|
|
|
|
atkRole.Event:DispatchEvent(BattleEventName.RoleHit, defRole, damage, bCrit, finalDmg, damageType, skill)
|
|
|
|
|
defRole.Event:DispatchEvent(BattleEventName.RoleBeHit, atkRole, damage, bCrit, finalDmg, damageType, skill)
|
2019-05-18 17:20:57 +08:00
|
|
|
|
end
|
2019-03-12 14:05:45 +08:00
|
|
|
|
end
|
2019-05-07 20:01:07 +08:00
|
|
|
|
return finalDmg
|
|
|
|
|
else
|
|
|
|
|
return damage
|
2019-03-12 14:05:45 +08:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--执行完整的命中,伤害,暴击计算,返回命中,暴击
|
2020-04-10 14:52:41 +08:00
|
|
|
|
--skill造成伤害的技能 atkRole攻击者 defRole受击者 damageType伤害类型 baseFactor伤害系数 ignoreDef无视防御参数 isDot是否是dot
|
|
|
|
|
function BattleUtil.CalDamage(skill, atkRole, defRole, damageType, baseFactor, ignoreDef, isDot)
|
2019-05-18 17:20:57 +08:00
|
|
|
|
if atkRole.isTeam and not defRole.isDead then --如果是队伍技能,计算真实伤害,则damageType为伤害值
|
2020-04-10 14:52:41 +08:00
|
|
|
|
return BattleUtil.ApplyDamage(skill, atkRole, defRole, damageType), false
|
2019-03-21 14:33:56 +08:00
|
|
|
|
end
|
2020-04-10 14:52:41 +08:00
|
|
|
|
|
|
|
|
|
-- 计算技能额外伤害系数加成
|
2019-05-07 20:01:07 +08:00
|
|
|
|
baseFactor = baseFactor or 1
|
|
|
|
|
local factorFunc = function(exFactor) baseFactor = baseFactor + exFactor end
|
2020-04-16 16:27:42 +08:00
|
|
|
|
atkRole.Event:DispatchEvent(BattleEventName.RoleDamageBefore, defRole, factorFunc, damageType, skill)
|
|
|
|
|
defRole.Event:DispatchEvent(BattleEventName.RoleBeDamagedBefore, atkRole, factorFunc, damageType, skill)
|
2019-11-13 19:06:21 +08:00
|
|
|
|
baseFactor = BattleUtil.ErrorCorrection(baseFactor)
|
2019-05-07 20:01:07 +08:00
|
|
|
|
|
2019-03-12 14:05:45 +08:00
|
|
|
|
local bCrit = false
|
|
|
|
|
local baseDamage
|
2020-04-10 14:52:41 +08:00
|
|
|
|
-- 是否暴击: 暴击率 = 自身暴击率 - 对方抗暴率
|
2020-04-16 16:27:42 +08:00
|
|
|
|
local critRandom = Random.Range01()
|
|
|
|
|
local critCondition = clamp(atkRole:GetRoleData(RoleDataName.Crit)-defRole:GetRoleData(RoleDataName.Tenacity), 0, 1)
|
|
|
|
|
bCrit = critRandom <= critCondition
|
2020-04-10 14:52:41 +08:00
|
|
|
|
bCrit = bCrit or defRole.isFlagCrit == true -- 必定暴击
|
|
|
|
|
-- 防御(据伤害类型决定)
|
2019-03-12 14:05:45 +08:00
|
|
|
|
local defence = 0
|
|
|
|
|
if damageType == 1 then --1 物理 2 魔法
|
|
|
|
|
defence = defRole:GetRoleData(RoleDataName.PhysicalDefence)
|
|
|
|
|
else
|
|
|
|
|
defence = defRole:GetRoleData(RoleDataName.MagicDefence)
|
|
|
|
|
end
|
2020-04-10 14:52:41 +08:00
|
|
|
|
-- 攻击力
|
2019-06-19 16:43:02 +08:00
|
|
|
|
local attack = atkRole:GetRoleData(RoleDataName.Attack)
|
2020-04-10 14:52:41 +08:00
|
|
|
|
-- 无视防御系数
|
|
|
|
|
ignoreDef = 1 - (ignoreDef or 0)
|
|
|
|
|
|
2019-03-12 14:05:45 +08:00
|
|
|
|
--计算暴击
|
2019-10-23 23:37:04 +08:00
|
|
|
|
if bCrit then
|
2020-04-10 14:52:41 +08:00
|
|
|
|
-- 计算额外暴击伤害
|
2019-03-12 14:05:45 +08:00
|
|
|
|
local critDamageFactor = atkRole:GetRoleData(RoleDataName.CritDamageFactor)
|
2020-04-10 14:52:41 +08:00
|
|
|
|
--加入被动效果 触发暴击被动
|
2019-05-07 20:01:07 +08:00
|
|
|
|
local critFunc = function(critEx) critDamageFactor = critEx end
|
|
|
|
|
atkRole.Event:DispatchEvent(BattleEventName.PassiveCriting, critFunc)
|
2020-04-10 14:52:41 +08:00
|
|
|
|
--计算基础伤害:伤害 = 攻击力 * 暴击伤害系数 - 防御 *(1 - 无视防御系数)
|
2019-08-06 20:55:47 +08:00
|
|
|
|
baseDamage = max(BattleUtil.FP_Mul(attack, critDamageFactor) - BattleUtil.FP_Mul(0.5, defence, ignoreDef), 0)
|
2019-03-12 14:05:45 +08:00
|
|
|
|
else
|
2019-08-06 20:55:47 +08:00
|
|
|
|
baseDamage = max(attack - BattleUtil.FP_Mul(0.5, defence, ignoreDef), 0)
|
2019-03-12 14:05:45 +08:00
|
|
|
|
end
|
2019-08-06 20:55:47 +08:00
|
|
|
|
|
2020-04-10 14:52:41 +08:00
|
|
|
|
-- 自身属性对应对方的属性伤害减免系数
|
2019-04-01 19:49:18 +08:00
|
|
|
|
local elementDamageReduceFactor = RoleDataName.FireDamageReduceFactor
|
|
|
|
|
if atkRole.element == 1 then
|
|
|
|
|
elementDamageReduceFactor = RoleDataName.FireDamageReduceFactor
|
|
|
|
|
elseif atkRole.element == 2 then
|
|
|
|
|
elementDamageReduceFactor = RoleDataName.WindDamageReduceFactor
|
|
|
|
|
elseif atkRole.element == 3 then
|
|
|
|
|
elementDamageReduceFactor = RoleDataName.IceDamageReduceFactor
|
|
|
|
|
elseif atkRole.element == 4 then
|
|
|
|
|
elementDamageReduceFactor = RoleDataName.LandDamageReduceFactor
|
|
|
|
|
elseif atkRole.element == 5 then
|
|
|
|
|
elementDamageReduceFactor = RoleDataName.LightDamageReduceFactor
|
|
|
|
|
elseif atkRole.element == 6 then
|
|
|
|
|
elementDamageReduceFactor = RoleDataName.DarkDamageReduceFactor
|
|
|
|
|
end
|
|
|
|
|
|
2019-08-06 20:55:47 +08:00
|
|
|
|
--伤害 =(基础伤害*(1+己伤害加成-目标伤害减免)*(1+己方属性伤害加成-目标属性伤害减免),10%*己攻)
|
|
|
|
|
baseDamage = BattleUtil.FP_Mul(baseDamage, baseFactor,
|
|
|
|
|
1 + atkRole:GetRoleData(RoleDataName.DamageBocusFactor) - defRole:GetRoleData(RoleDataName.DamageReduceFactor),
|
|
|
|
|
(1 + atkRole:GetRoleData(RoleDataName.ElementDamageBocusFactor) - defRole:GetRoleData(elementDamageReduceFactor)))
|
2019-10-23 23:37:04 +08:00
|
|
|
|
|
2020-02-03 11:36:01 +08:00
|
|
|
|
--属性克制关系:光暗互克,火克风,风克地,地克水,水克火
|
2020-04-16 16:27:42 +08:00
|
|
|
|
-- local atkEle = atkRole.roleData.element
|
|
|
|
|
-- local defEle = defRole.roleData.element
|
|
|
|
|
-- local restrain = atkEle == 1 and defEle == 2 or
|
|
|
|
|
-- atkEle == 4 and defEle == 3 or
|
|
|
|
|
-- atkEle == 2 and defEle == 4 or
|
|
|
|
|
-- atkEle == 3 and defEle == 1 or
|
|
|
|
|
-- atkEle == 5 and defEle == 6 or
|
|
|
|
|
-- atkEle == 6 and defEle == 5
|
|
|
|
|
|
|
|
|
|
-- if restrain then
|
|
|
|
|
-- baseDamage = floor(max(BattleUtil.FP_Mul(1.25, baseDamage), BattleUtil.FP_Mul(0.1, attack)))
|
|
|
|
|
-- else
|
|
|
|
|
-- baseDamage = floor(max(baseDamage, BattleUtil.FP_Mul(0.1, attack)))
|
|
|
|
|
-- end
|
|
|
|
|
|
|
|
|
|
-- 计算
|
|
|
|
|
baseDamage = floor(max(baseDamage, BattleUtil.FP_Mul(0.1, attack)))
|
2019-03-21 14:33:56 +08:00
|
|
|
|
|
2020-04-10 14:52:41 +08:00
|
|
|
|
-- 计算额外伤害数值加成
|
2019-12-02 10:11:58 +08:00
|
|
|
|
local damageFunc = function(damage) baseDamage = damage end
|
|
|
|
|
atkRole.Event:DispatchEvent(BattleEventName.RoleDamageAfter, defRole, damageFunc, baseDamage)
|
|
|
|
|
defRole.Event:DispatchEvent(BattleEventName.RoleBeDamagedAfter, atkRole, damageFunc, baseDamage)
|
2019-03-21 14:33:56 +08:00
|
|
|
|
|
2019-03-12 14:05:45 +08:00
|
|
|
|
local finalDmg = 0 --计算实际造成的扣血
|
|
|
|
|
if not defRole.isDead then
|
2020-04-10 14:52:41 +08:00
|
|
|
|
finalDmg = BattleUtil.ApplyDamage(skill, atkRole, defRole, baseDamage, bCrit, damageType, isDot)
|
2019-03-12 14:05:45 +08:00
|
|
|
|
end
|
|
|
|
|
return finalDmg, bCrit
|
|
|
|
|
end
|
|
|
|
|
|
2019-05-07 20:01:07 +08:00
|
|
|
|
function BattleUtil.CalTreat(castRole, targetRole, value, baseFactor)
|
2019-05-10 19:31:20 +08:00
|
|
|
|
if targetRole.ctrl_noheal or targetRole.isDead then --禁疗和死亡无法加血
|
2019-04-17 21:04:32 +08:00
|
|
|
|
return
|
|
|
|
|
end
|
2019-05-07 20:01:07 +08:00
|
|
|
|
targetRole.Event:DispatchEvent(BattleEventName.RoleBeHealed, castRole)
|
|
|
|
|
BattleUtil.ApplyTreat(castRole, targetRole, value, baseFactor)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function BattleUtil.ApplyTreat(castRole, targetRole, value, baseFactor)
|
2019-03-26 20:19:15 +08:00
|
|
|
|
baseFactor = baseFactor or 1
|
2019-03-12 14:05:45 +08:00
|
|
|
|
local maxHp = targetRole:GetRoleData(RoleDataName.MaxHp)
|
|
|
|
|
local hp = targetRole:GetRoleData(RoleDataName.Hp)
|
2019-06-20 15:47:36 +08:00
|
|
|
|
|
2020-04-16 16:27:42 +08:00
|
|
|
|
-- 计算被动对治疗系数的影响
|
|
|
|
|
local treatFactorFunc = function(dt, df)
|
|
|
|
|
baseFactor = BattleUtil.CountValue(baseFactor, df, dt)
|
|
|
|
|
end
|
|
|
|
|
castRole.Event:DispatchEvent(BattleEventName.PassiveTreatingFactor, treatFactorFunc, targetRole)
|
|
|
|
|
targetRole.Event:DispatchEvent(BattleEventName.PassiveBeTreatedFactor, treatFactorFunc, castRole)
|
|
|
|
|
|
2019-06-20 15:47:36 +08:00
|
|
|
|
local factor = castRole.isTeam and 1 or castRole:GetRoleData(RoleDataName.TreatFacter) --释放者为team则不计算治疗加成属性
|
2019-05-13 09:51:36 +08:00
|
|
|
|
local factor2 = targetRole:GetRoleData(RoleDataName.CureFacter)
|
2019-08-06 20:55:47 +08:00
|
|
|
|
local baseTreat = floor(BattleUtil.FP_Mul(value, baseFactor, factor, factor2) + 0.5)
|
2019-05-07 20:01:07 +08:00
|
|
|
|
|
|
|
|
|
--加入被动效果
|
|
|
|
|
local treatingFunc = function(exFactor) baseTreat = floor(baseTreat * (exFactor + 1) + 0.5) end
|
2019-09-01 12:11:18 +08:00
|
|
|
|
castRole.Event:DispatchEvent(BattleEventName.PassiveTreating, treatingFunc, targetRole)
|
|
|
|
|
targetRole.Event:DispatchEvent(BattleEventName.PassiveBeTreated, treatingFunc, castRole)
|
2019-05-07 20:01:07 +08:00
|
|
|
|
local treat = min(baseTreat, maxHp - hp)
|
|
|
|
|
if treat > 0 then
|
|
|
|
|
targetRole.data:AddValue(RoleDataName.Hp, treat)
|
|
|
|
|
end
|
2020-04-16 16:27:42 +08:00
|
|
|
|
castRole.Event:DispatchEvent(BattleEventName.RoleTreat, targetRole, treat, baseTreat)
|
|
|
|
|
targetRole.Event:DispatchEvent(BattleEventName.RoleBeTreated, castRole, treat, baseTreat)
|
2019-03-12 14:05:45 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function BattleUtil.RandomAction(rand, action)
|
|
|
|
|
if Random.Range01() <= rand and action then
|
|
|
|
|
action()
|
|
|
|
|
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
|
|
|
|
|
|
2019-03-22 18:36:24 +08:00
|
|
|
|
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
|
|
|
|
|
|
2019-03-12 14:05:45 +08:00
|
|
|
|
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)
|
2019-05-07 20:01:07 +08:00
|
|
|
|
return role:GetRoleData(RoleDataName.Hp) / role:GetRoleData(RoleDataName.MaxHp)
|
2019-03-12 14:05:45 +08:00
|
|
|
|
end
|
|
|
|
|
|
2020-04-10 14:52:41 +08:00
|
|
|
|
-- 计算数值
|
|
|
|
|
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)
|
|
|
|
|
end
|
|
|
|
|
-- 做一个正确性检测
|
|
|
|
|
-- v = BattleUtil.ErrorCorrection(v)
|
|
|
|
|
return v
|
|
|
|
|
end
|