generated from root/miduo_server
1840 lines
69 KiB
Lua
1840 lines
69 KiB
Lua
BattleUtil = {}
|
||
-- local GameSetting = ConfigManager.GetConfig(ConfigName.GameSetting)
|
||
--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")
|
||
|
||
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() then
|
||
table.insert(tempArr, r)
|
||
end
|
||
end
|
||
table.sort(tempArr, function(a, b)
|
||
return a.position < b.position
|
||
end)
|
||
return tempArr
|
||
end
|
||
--> 选择中排
|
||
function BattleUtil.ChooseMRow(arr)
|
||
local tempArr = {}
|
||
for _, r in ipairs(arr) do
|
||
if r.position > 3 and r.position <= 6 and not r:IsRealDead() 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 > 6 and not r:IsRealDead() then
|
||
table.insert(tempArr, r)
|
||
end
|
||
end
|
||
table.sort(tempArr, function(a, b)
|
||
return a.position < b.position
|
||
end)
|
||
return tempArr
|
||
end
|
||
--> 选择前两排
|
||
function BattleUtil.ChooseF2Row(arr)
|
||
local tempArr = {}
|
||
for _, r in ipairs(arr) do
|
||
if r.position <= 6 and not r:IsRealDead() then
|
||
table.insert(tempArr, r)
|
||
end
|
||
end
|
||
table.sort(tempArr, function(a, b)
|
||
return a.position < b.position
|
||
end)
|
||
return tempArr
|
||
end
|
||
--> 选择后两排
|
||
function BattleUtil.ChooseB2Row(arr)
|
||
local tempArr = {}
|
||
for _, r in ipairs(arr) do
|
||
if r.position > 3 and not r:IsRealDead() 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 then
|
||
table.insert(tempArr, role)
|
||
end
|
||
end
|
||
table.sort(tempArr, function(a, b)
|
||
return a.position < b.position
|
||
end)
|
||
return tempArr
|
||
end
|
||
--> 数量最多列 0第三
|
||
function BattleUtil.GetMaxCol(arr)
|
||
local tempArr = {0, 0, 0}
|
||
for _, role in ipairs(arr) do
|
||
local idx = role.position % 3
|
||
if idx == 0 then
|
||
tempArr[3] = tempArr[3] + 1
|
||
else
|
||
tempArr[idx] = tempArr[idx] + 1
|
||
end
|
||
|
||
end
|
||
local maxNum = -1
|
||
local col = -1
|
||
for i = 1, #tempArr do
|
||
if tempArr[i] > maxNum then
|
||
col = i
|
||
maxNum = tempArr[i]
|
||
if i == 3 then
|
||
col = 0
|
||
end
|
||
end
|
||
end
|
||
return col
|
||
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.SortByProfessionId(arr, sort, _professionId)
|
||
-- 角色职业
|
||
-- 1、防御
|
||
-- 2、高爆
|
||
-- 3、穿甲
|
||
-- 4,辅助
|
||
BattleUtil.Sort(arr, function(a, b)
|
||
local aa = a.professionId == _professionId and 1 or 0
|
||
local bb = b.professionId == _professionId and 1 or 0
|
||
|
||
if sort == 1 then return aa > bb else return aa < bb end
|
||
end)
|
||
|
||
return arr
|
||
end
|
||
|
||
function BattleUtil.ShuffleDead(arr)
|
||
|
||
local hpZero = {}
|
||
for i = 1, #arr do
|
||
if arr[i]:GetRoleData(RoleDataName.Hp) <= 0 then
|
||
table.insert(hpZero, arr[i])
|
||
end
|
||
end
|
||
Random.RandomList(hpZero)
|
||
local idx = 0
|
||
for i = 1, #arr do
|
||
if arr[i]:GetRoleData(RoleDataName.Hp) <= 0 then
|
||
idx = idx + 1
|
||
arr[i] = hpZero[idx]
|
||
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.excludeSelfList(arr,role)
|
||
local tempArr = {}
|
||
for _, r in ipairs(arr) do
|
||
if not r:Equle(role) and not r:IsRealDead() then
|
||
table.insert(tempArr, r)
|
||
end
|
||
end
|
||
table.sort(tempArr, function(a, b)
|
||
return a.position < b.position
|
||
end)
|
||
return tempArr
|
||
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 role.ctrl_chaos then --< 混乱自残
|
||
return {role}
|
||
end
|
||
|
||
|
||
-- 选择类型
|
||
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 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() then --嘲讽时对仇恨目标生效
|
||
return {role.lockTarget}
|
||
end
|
||
if role.ctrl_blind then --致盲时仇恨目标变随机
|
||
arr = RoleManager.Query(function (r) return r.camp ~= role.camp end)
|
||
BattleUtil.RandomList(arr)
|
||
return {arr[1]}
|
||
end
|
||
return {RoleManager.GetAggro(role)}
|
||
elseif chooseType == 5 then --< 我方阵亡
|
||
arr = RoleManager.QueryDead(function (r) return r.camp == role.camp end)
|
||
elseif chooseType == 6 then --< 我方全体
|
||
arr = RoleManager.Query(function (r) return r.camp == role.camp end, true)
|
||
elseif chooseType == 7 then --< 我方阵亡可复活英雄
|
||
local reliveFunc = function (ro)
|
||
return (ro.IsDead or ro.isRealDead) and ro.reliveFilter
|
||
end
|
||
arr = RoleManager.Query(function (r) return r.camp == role.camp and reliveFunc(r) and r.isDead end,true)
|
||
|
||
if arr==nil or #arr==0 then
|
||
arr =RoleManager.Query(function (r) return r.camp == role.camp end, false)
|
||
|
||
end
|
||
else
|
||
arr = RoleManager.Query()
|
||
end
|
||
|
||
--选择范围
|
||
if chooseLimit == 0 then --选择全体不做任何操作
|
||
|
||
elseif chooseLimit == 1 then-- 前排
|
||
local tempArr = BattleUtil.ChooseFRow(arr)
|
||
if #tempArr == 0 then
|
||
tempArr = BattleUtil.ChooseMRow(arr)
|
||
end
|
||
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.ChooseMRow(arr)
|
||
end
|
||
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
|
||
elseif chooseLimit == 4 then --< 前二
|
||
local tempArr = BattleUtil.ChooseF2Row(arr)
|
||
if #tempArr == 0 then -- 没有选择最后一排
|
||
tempArr = BattleUtil.ChooseBRow(arr)
|
||
end
|
||
arr = tempArr
|
||
elseif chooseLimit == 5 then --< 后二
|
||
local tempArr = BattleUtil.ChooseB2Row(arr)
|
||
if #tempArr == 0 then -- 没有选择第一排
|
||
tempArr = BattleUtil.ChooseFRow(arr)
|
||
end
|
||
arr = tempArr
|
||
elseif chooseLimit == 6 then --< 全体,优先4职业
|
||
elseif chooseLimit == 7 then --< 人数最多列
|
||
local tempArr = BattleUtil.ChooseCol(arr, BattleUtil.GetMaxCol(arr))
|
||
arr = tempArr
|
||
elseif chooseLimit == 8 then --< 除自己外
|
||
local tempArr = BattleUtil.excludeSelfList(arr,role)
|
||
if #tempArr == 0 then
|
||
tempArr = arr
|
||
end
|
||
-- LogError("#tempArr"..#tempArr)
|
||
arr = tempArr
|
||
elseif chooseLimit == 9 then --< 9全体,优先2职业
|
||
arr = BattleUtil.SortByProfessionId(arr, sort, 2)
|
||
end
|
||
|
||
if chooseWeight == 9 then --< 随机某属性 定死或走表
|
||
chooseWeight = Random.RangeInt(1, 6)
|
||
end
|
||
-- 选择条件
|
||
if chooseWeight == 0 or role.ctrl_blind then --致盲时排序无效
|
||
BattleUtil.RandomList(arr)
|
||
elseif chooseWeight == 1 then -- 生命值
|
||
BattleUtil.SortByProp(arr, RoleDataName.Hp, sort)
|
||
if chooseType == 6 then
|
||
BattleUtil.ShuffleDead(arr)
|
||
end
|
||
elseif chooseWeight == 2 then -- 血量百分比
|
||
BattleUtil.SortByHpFactor(arr, sort)
|
||
elseif chooseWeight == 3 then -- 攻击力
|
||
arr = BattleUtil.SortByProp(arr, RoleDataName.Attack, sort)
|
||
-- RoleManager.LogRoles("attack",arr)
|
||
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 -- 对位
|
||
arr = RoleManager.GetArrAggroList(role, arr)
|
||
elseif chooseWeight == 11 then --< 防御
|
||
arr = BattleUtil.SortByProfessionId(arr, sort, 1)
|
||
elseif chooseWeight == 12 then --< 高爆
|
||
arr = BattleUtil.SortByProfessionId(arr, sort, 2)
|
||
elseif chooseWeight == 13 then --< 穿甲
|
||
arr = BattleUtil.SortByProfessionId(arr, sort, 3)
|
||
elseif chooseWeight == 14 then --< 辅助
|
||
arr = BattleUtil.SortByProfessionId(arr, sort, 4)
|
||
elseif chooseWeight == 21 then --< 负面状态(控制状态、减益状态和持续伤害状态)
|
||
local searchFunc = function(role)
|
||
local list = BattleLogic.BuffMgr:GetBuff(role, function (buff)
|
||
return buff.type == BuffName.Control or buff.isDeBuff or buff.type == BuffName.DOT
|
||
end)
|
||
return list and #list > 0
|
||
end
|
||
arr = RoleManager.Query(searchFunc, false)
|
||
end
|
||
|
||
if chooseLimit == 6 then --< 全体,优先4职业
|
||
local tempArr = {}
|
||
for i = 1, #arr do
|
||
if arr[i].roleData.professionId == 4 then
|
||
table.insert(tempArr, arr[i])
|
||
end
|
||
end
|
||
for i = 1, #arr do
|
||
if arr[i].roleData.professionId ~= 4 then
|
||
table.insert(tempArr, arr[i])
|
||
end
|
||
end
|
||
arr = tempArr
|
||
-- elseif chooseLimit == 8 then --< 除自己
|
||
-- local tempArr = {}
|
||
-- for _, r in ipairs(arr) do
|
||
-- if not (r == role) then
|
||
-- table.insert(tempArr, r)
|
||
-- end
|
||
-- end
|
||
-- table.sort(tempArr, function(a, b)
|
||
-- return a.position < b.position
|
||
-- end)
|
||
-- arr = tempArr
|
||
elseif chooseLimit == 9 then --< 全体,优先2职业
|
||
local tempArr = {}
|
||
for i = 1, #arr do
|
||
if arr[i].roleData.professionId == 2 then
|
||
table.insert(tempArr, arr[i])
|
||
end
|
||
end
|
||
for i = 1, #arr do
|
||
if arr[i].roleData.professionId ~= 2 then
|
||
table.insert(tempArr, arr[i])
|
||
end
|
||
end
|
||
arr = tempArr
|
||
end
|
||
|
||
local finalArr = {}
|
||
|
||
if sort == 3 then --< 3随机(可重复,单体最多被选3次)
|
||
local randArr = {}
|
||
local randtimes = num == 0 and #arr or num
|
||
local randTimesArr = {}
|
||
for i = 1, #arr do
|
||
table.insert(randTimesArr, 0)
|
||
end
|
||
|
||
|
||
local idx = 0
|
||
while #randArr < randtimes
|
||
do
|
||
while true
|
||
do
|
||
local randIdx = Random.RangeInt(1, #arr)
|
||
if randTimesArr[randIdx] >= 3 then
|
||
break
|
||
end
|
||
randTimesArr[randIdx] = randTimesArr[randIdx] + 1
|
||
table.insert(randArr, arr[randIdx])
|
||
|
||
break
|
||
end
|
||
idx = idx + 1
|
||
if idx > 5 then
|
||
break
|
||
end
|
||
end
|
||
|
||
finalArr = randArr
|
||
else
|
||
--> 不随机按顺序
|
||
if num == 0 then
|
||
finalArr = arr
|
||
else
|
||
for i = 1, num do
|
||
if arr[i] then
|
||
table.insert(finalArr, arr[i])
|
||
end
|
||
end
|
||
end
|
||
end
|
||
--LogError(string.format("chooseid: %s chooseType:== %s chooseLimit:== %s chooseWeight:== %s sort:== %s num:== %s,"
|
||
--,tostring(chooseId),tostring(chooseType),tostring(chooseLimit),tostring(chooseWeight),tostring(sort),tostring(num)))
|
||
-- LogError("chooseType:"..chooseType)
|
||
-- LogError("chooseLimit:"..chooseLimit)
|
||
-- LogError("chooseWeight:"..chooseWeight)
|
||
-- LogError("sort:"..sort)
|
||
-- LogError("num:"..num)
|
||
|
||
-- table.sort(finalArr, function(a, b)
|
||
-- return a.position < b.position
|
||
-- end)
|
||
|
||
return finalArr
|
||
end
|
||
|
||
--> 打乱角色队列
|
||
function BattleUtil.ShufferRoles(arr,singleTime)
|
||
if not arr or #arr==0 then return nil end
|
||
local num = Random.RangeInt(1,5) --> 打乱次数
|
||
local randArr = {}
|
||
local randtimes = num == 0 and #arr or num
|
||
local randTimesArr = {}
|
||
for i = 1, #arr do
|
||
table.insert(randTimesArr, 0)
|
||
end
|
||
|
||
local idx = 0
|
||
while #randArr < randtimes
|
||
do
|
||
while true
|
||
do
|
||
local randIdx = Random.RangeInt(1, #arr)
|
||
if randTimesArr[randIdx] >= singleTime then
|
||
break
|
||
end
|
||
randTimesArr[randIdx] = randTimesArr[randIdx] + 1
|
||
table.insert(randArr, arr[randIdx])
|
||
|
||
break
|
||
end
|
||
idx = idx + 1
|
||
if idx > 5 then
|
||
break
|
||
end
|
||
end
|
||
|
||
return randArr
|
||
end
|
||
|
||
--> 选择单个对象
|
||
function BattleUtil.ChooseOneTarget(role, chooseId, excludeAttackList)
|
||
|
||
|
||
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 role.ctrl_chaos then --< 混乱自残
|
||
|
||
return role
|
||
end
|
||
|
||
-- 选择类型
|
||
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 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() then --嘲讽时对仇恨目标生效
|
||
return role.lockTarget
|
||
end
|
||
if role.ctrl_blind then --致盲时仇恨目标变随机
|
||
arr = RoleManager.Query(function (r) return r.camp ~= role.camp end)
|
||
BattleUtil.RandomList(arr)
|
||
return arr[1]
|
||
end
|
||
return RoleManager.GetAggro(role)
|
||
elseif chooseType == 5 then --< 我方阵亡
|
||
arr = RoleManager.QueryDead(function (r) return r.camp == role.camp end)
|
||
elseif chooseType == 6 then --< 我方全体
|
||
arr = RoleManager.Query(function (r) return r.camp == role.camp end, true)
|
||
else
|
||
arr = RoleManager.Query()
|
||
end
|
||
|
||
--选择范围
|
||
if chooseLimit == 0 then --选择全体不做任何操作
|
||
|
||
elseif chooseLimit == 1 then-- 前排
|
||
local tempArr = BattleUtil.ChooseFRow(arr)
|
||
if #tempArr == 0 then
|
||
tempArr = BattleUtil.ChooseMRow(arr)
|
||
end
|
||
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.ChooseMRow(arr)
|
||
end
|
||
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
|
||
elseif chooseLimit == 4 then --< 前二
|
||
local tempArr = BattleUtil.ChooseF2Row(arr)
|
||
if #tempArr == 0 then -- 没有选择最后一排
|
||
tempArr = BattleUtil.ChooseBRow(arr)
|
||
end
|
||
arr = tempArr
|
||
elseif chooseLimit == 5 then --< 后二
|
||
local tempArr = BattleUtil.ChooseB2Row(arr)
|
||
if #tempArr == 0 then -- 没有选择第一排
|
||
tempArr = BattleUtil.ChooseFRow(arr)
|
||
end
|
||
arr = tempArr
|
||
elseif chooseLimit == 6 then --< 全体,优先4职业
|
||
elseif chooseLimit == 7 then --< 人数最多列
|
||
local tempArr = BattleUtil.ChooseCol(arr, BattleUtil.GetMaxCol(arr))
|
||
arr = tempArr
|
||
elseif chooseLimit == 8 then --< 除自己外
|
||
elseif chooseLimit == 9 then --< 9全体,优先2职业
|
||
end
|
||
|
||
if chooseWeight == 9 then --< 随机某属性 定死或走表
|
||
chooseWeight = Random.RangeInt(1, 6)
|
||
end
|
||
-- 选择条件
|
||
if chooseWeight == 0 or role.ctrl_blind then --致盲时排序无效
|
||
BattleUtil.RandomList(arr)
|
||
elseif chooseWeight == 1 then -- 生命值
|
||
BattleUtil.SortByProp(arr, RoleDataName.Hp, sort)
|
||
if chooseType == 6 then
|
||
BattleUtil.ShuffleDead(arr)
|
||
end
|
||
elseif chooseWeight == 2 then -- 血量百分比
|
||
BattleUtil.SortByHpFactor(arr, sort)
|
||
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 -- 对位
|
||
arr = RoleManager.GetArrAggroList(role, arr)
|
||
end
|
||
|
||
if chooseLimit == 6 then --< 全体,优先4职业
|
||
local tempArr = {}
|
||
for i = 1, #arr do
|
||
if arr[i].roleData.professionId == 4 then
|
||
table.insert(tempArr, arr[i])
|
||
end
|
||
end
|
||
for i = 1, #arr do
|
||
if arr[i].roleData.professionId ~= 4 then
|
||
table.insert(tempArr, arr[i])
|
||
end
|
||
end
|
||
arr = tempArr
|
||
elseif chooseLimit == 8 then --< 除自己
|
||
local tempArr = {}
|
||
for _, r in ipairs(arr) do
|
||
if not (r == role) then
|
||
table.insert(tempArr, r)
|
||
end
|
||
end
|
||
table.sort(tempArr, function(a, b)
|
||
return a.position < b.position
|
||
end)
|
||
arr = tempArr
|
||
elseif chooseLimit == 9 then --< 全体,优先2职业
|
||
local tempArr = {}
|
||
for i = 1, #arr do
|
||
if arr[i].roleData.professionId == 2 then
|
||
table.insert(tempArr, arr[i])
|
||
end
|
||
end
|
||
for i = 1, #arr do
|
||
if arr[i].roleData.professionId ~= 2 then
|
||
table.insert(tempArr, arr[i])
|
||
end
|
||
end
|
||
arr = tempArr
|
||
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
|
||
|
||
--> 刨除
|
||
for i = #finalArr, 1, -1 do
|
||
for j = 1, #excludeAttackList do
|
||
if excludeAttackList[j].uid == finalArr[i].uid then
|
||
table.remove(finalArr, i)
|
||
break
|
||
end
|
||
end
|
||
end
|
||
|
||
if #finalArr <= 0 then
|
||
return nil
|
||
end
|
||
|
||
if sort == 3 then --< 随机类型
|
||
local idx = Random.RangeInt(1, #finalArr)
|
||
return finalArr[idx]
|
||
else
|
||
return finalArr[1]
|
||
end
|
||
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)
|
||
for i=1, defRole.shield.size do
|
||
local buff = defRole.shield.buffer[i]
|
||
damage = buff:CountShield(damage, atkRole)
|
||
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
|
||
|
||
|
||
-- 秒杀
|
||
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 and not defRole:IsDead() then
|
||
defRole:SetDead()
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleDead, atkRole)
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleKill, defRole)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoleDead, defRole, atkRole)
|
||
|
||
atkRole.Event:DispatchEvent(BattleEventName.Seckill, defRole)
|
||
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
|
||
|
||
end
|
||
|
||
-- 计算真实伤害
|
||
function BattleUtil.ApplyDamage(skill, atkRole, defRole, damage, bCrit, damageType, dotType, changeIsForbear)
|
||
|
||
if defRole.position == 99999 then
|
||
return
|
||
end
|
||
bCrit = bCrit or false
|
||
if atkRole.ctrl_seal then --封印 无法暴击
|
||
bCrit = false
|
||
end
|
||
--加入被动效果
|
||
local damagingFunc = function(dmgDeduction)
|
||
|
||
|
||
damage = floor(damage - dmgDeduction)
|
||
end
|
||
SYSLog(string.format("ApplyDamage === damage: %s, damageType: %s,",tostring(damage),tostring(damageType)))
|
||
atkRole.Event:DispatchEvent(BattleEventName.PassiveDamaging, damagingFunc, defRole, damage, skill, dotType, bCrit)
|
||
defRole.Event:DispatchEvent(BattleEventName.PassiveBeDamaging, damagingFunc, atkRole, damage, skill, dotType, bCrit)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.PassiveDamaging, damagingFunc, atkRole, defRole, damage, skill, dotType, bCrit)
|
||
|
||
-- 计算护盾减伤
|
||
|
||
|
||
damage = BattleUtil.CalShield(atkRole, defRole, damage)
|
||
SYSLog(string.format("ApplyDamage CalShield === damage: %s, damageType: %s,",tostring(damage),tostring(damageType)))
|
||
|
||
-- 造成的最终伤害
|
||
local damagingFunc = function(dmgDeduction)
|
||
|
||
|
||
damage = floor(damage - dmgDeduction)
|
||
end
|
||
--SYSLog(string.format("ApplyDamage CalShield final === damage: %s, damageType: %s,",tostring(damage),tostring(damageType)))
|
||
atkRole.Event:DispatchEvent(BattleEventName.FinalDamage, damagingFunc, defRole, damage, skill, dotType, bCrit, damageType)
|
||
defRole.Event:DispatchEvent(BattleEventName.FinalBeDamage, damagingFunc, atkRole, damage, skill, dotType, bCrit, damageType)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.FinalDamage, damagingFunc, atkRole, defRole, damage, skill, dotType, bCrit, damageType)
|
||
|
||
return BattleUtil.FinalDamage(skill, atkRole, defRole, damage, bCrit, damageType, dotType, changeIsForbear)
|
||
end
|
||
|
||
|
||
--检测是否有是金翅大鹏有不灭效果
|
||
function BattleUtil.CheckIsNoDead(target)
|
||
if target then
|
||
return target:IsAssignHeroAndHeroStar(10086,10)==false and BattleLogic.BuffMgr:HasBuff(target,BuffName.NoDead)==false
|
||
end
|
||
return false
|
||
end
|
||
|
||
|
||
|
||
function BattleUtil.FinalDamage(skill, atkRole, defRole, damage, bCrit, damageType, dotType, changeIsForbear)
|
||
|
||
if damage < 0 then damage = 0 end
|
||
local finalDmg = defRole.data:SubValue(RoleDataName.Hp, damage)
|
||
|
||
if atkRole.ctrl_seal then --封印 无法暴击
|
||
bCrit = false
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleBeSeal, defRole, damage, bCrit, finalDmg, damageType, skill)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleSeal, atkRole, damage, bCrit, finalDmg, damageType, skill)
|
||
end
|
||
|
||
if finalDmg >= 0 then
|
||
if defRole:GetRoleData(RoleDataName.Hp) <= 0 and not defRole:IsDead() then
|
||
defRole:SetDead()
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleDead, atkRole)
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleKill, defRole, damage, bCrit, damageType, dotType, skill)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoleDead, defRole, atkRole)
|
||
end
|
||
|
||
--被伤害是要知道是不是受克制
|
||
local isForbear, damageAdd, hitAdd = BattleUtil.CheckForbear(atkRole, defRole)
|
||
isForbear = changeIsForbear == nil and isForbear or changeIsForbear
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleDamage, defRole, damage, bCrit, finalDmg, damageType, dotType, skill,atkRole)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeDamaged, atkRole, damage, bCrit, finalDmg, damageType, dotType, skill, isForbear,defRole)
|
||
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)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeHit, atkRole, damage, bCrit, finalDmg, damageType, skill)
|
||
end
|
||
end
|
||
|
||
--
|
||
-- BattleLogManager.Log(
|
||
-- "Final Damage",
|
||
-- "acamp", atkRole.camp,
|
||
-- "apos", atkRole.position,
|
||
-- "tcamp", defRole.camp,
|
||
-- "tpos", defRole.position,
|
||
-- "damage", damage,
|
||
-- "dotType", tostring(dotType)
|
||
-- )
|
||
|
||
|
||
return finalDmg, damage
|
||
end
|
||
|
||
|
||
--执行完整的命中,伤害,暴击计算,返回命中,暴击 simple不包含事件仅做计算用
|
||
function BattleUtil.CalSimpleDamage(skill, atkRole, defRole, damageType, baseFactor, ignoreDef, dotType,SimpleCaculate)
|
||
|
||
if defRole.position == 99999 then
|
||
return
|
||
end
|
||
-- 判断是否命中
|
||
if skill and not skill:CheckTargetIsHit(defRole) 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
|
||
-- 如果是队伍技能,计算真实伤害,则damageType为伤害值
|
||
-- if atkRole.isTeam and not defRole:IsDead() then
|
||
-- return BattleUtil.ApplyDamage(skill, atkRole, defRole, damageType), false
|
||
-- end
|
||
-- 计算技能额外伤害系数加成
|
||
SYSLog(string.format("baseFactor 1 === baseFactor: %s",baseFactor))
|
||
baseFactor = baseFactor or 1
|
||
baseFactor = BattleUtil.ErrorCorrection(baseFactor)
|
||
SYSLog(string.format("baseFactor 2 === baseFactor: %s",baseFactor))
|
||
local baseDamage
|
||
-- 防御(据伤害类型决定)
|
||
--> damageType depracated 只有物防
|
||
local defence = defRole:GetRoleData(RoleDataName.PhysicalDefence)
|
||
-- 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)
|
||
local onIgnoreDefFactor = function(outIgnoreDef)
|
||
ignoreDef = 1 - math.max(0, outIgnoreDef)
|
||
end
|
||
-- 基础伤害 = 攻击力 - 防御力
|
||
-- baseDamage = max(attack - BattleUtil.FP_Mul(0.5, defence, ignoreDef), 0)
|
||
-- baseDamage = max(attack - BattleUtil.FP_Mul(defence, ignoreDef), 0)
|
||
|
||
baseDamage = attack * (1 - (BattleUtil.FP_Mul(defence, ignoreDef) / (defence + 598 + 2 * defRole:GetRoleData(RoleDataName.Level))))
|
||
-- baseDamage = attack * (1 - (BattleUtil.FP_Mul(defence, ignoreDef) / (defence + GameSetting[1].DefenseLevvalue2 + GameSetting[1].DefenseLevvalue1 * defRole:GetRoleData(RoleDataName.Level))))
|
||
|
||
-- 基础伤害增加系数 --< 伤害加成
|
||
local addDamageFactor = atkRole:GetRoleData(RoleDataName.DamageBocusFactor) - defRole:GetRoleData(RoleDataName.DamageReduceFactor)
|
||
|
||
-- 是否暴击: 暴击率 = 自身暴击率 - 对方抗暴率
|
||
local bCrit = false
|
||
local critRandom = Random.Range01()
|
||
local critCondition = clamp(atkRole:GetRoleData(RoleDataName.Crit) - defRole:GetRoleData(RoleDataName.Tenacity), 0, 1)
|
||
bCrit = critRandom <= critCondition
|
||
bCrit = bCrit or defRole.isFlagCrit == true -- 必定暴击
|
||
--< 封印状态大于必定暴击 锁死无法暴击
|
||
if atkRole.ctrl_seal then bCrit=false end
|
||
defRole.Event:DispatchEvent(BattleEventName.FlagCritReset)
|
||
|
||
--> 暴击抵抗 miss次数
|
||
local onCritMiss = function(newbCrit)
|
||
bCrit = newbCrit
|
||
end
|
||
-- 计算暴伤害系数
|
||
local critDamageFactor = 0
|
||
local critDamageReduceFactor = 0 -- 暴击伤害减免
|
||
--计算暴击
|
||
if bCrit then
|
||
--加入被动效果 触发暴击被动
|
||
local cl = {}
|
||
local onCritDamageReduceFactor = function(v, ct)
|
||
if v then
|
||
table.insert(cl, {v, ct})
|
||
end
|
||
end
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.CritDamageReduceFactor, onCritDamageReduceFactor, atkRole, defRole)
|
||
critDamageReduceFactor = max(BattleUtil.CountChangeList(critDamageReduceFactor, cl), 0)
|
||
|
||
-- 计算额外暴击伤害
|
||
-- critDamageFactor = 1.3 + atkRole:GetRoleData(RoleDataName.CritDamageFactor) - critDamageReduceFactor
|
||
critDamageFactor = max(atkRole:GetRoleData(RoleDataName.CritDamageFactor) - defRole:GetRoleData(RoleDataName.CriDamageReduceRate) - critDamageReduceFactor, 0)
|
||
|
||
end
|
||
|
||
local atkProFactor = 0
|
||
local defProFactor = 0
|
||
if defRole.professionId == 1 then --< 防御
|
||
atkProFactor = atkRole:GetRoleData(RoleDataName.DamageToDefender)
|
||
elseif defRole.professionId == 2 then --< 高爆
|
||
atkProFactor = atkRole:GetRoleData(RoleDataName.DamageToMage)
|
||
elseif defRole.professionId == 3 then --< 穿甲
|
||
atkProFactor = atkRole:GetRoleData(RoleDataName.DamageToFighter)
|
||
elseif defRole.professionId == 4 then --< 辅助
|
||
atkProFactor = atkRole:GetRoleData(RoleDataName.DamageToHealer)
|
||
end
|
||
if atkRole.professionId == 1 then --< 防御
|
||
defProFactor = defRole:GetRoleData(RoleDataName.DefenceFromDefender)
|
||
elseif atkRole.professionId == 2 then --< 高爆
|
||
defProFactor = defRole:GetRoleData(RoleDataName.DefenceFromMage)
|
||
elseif atkRole.professionId == 3 then --< 穿甲
|
||
defProFactor = defRole:GetRoleData(RoleDataName.DefenceFromFighter)
|
||
elseif atkRole.professionId == 4 then --< 辅助
|
||
defProFactor = defRole:GetRoleData(RoleDataName.DefenceFromHealer)
|
||
end
|
||
local professionFactor = atkProFactor - defProFactor
|
||
|
||
--> 克制
|
||
local isForbear, damageAdd, hitAdd = BattleUtil.CheckForbear(atkRole, defRole)
|
||
local forbearFactor = 0
|
||
if isForbear then
|
||
forbearFactor = forbearFactor + damageAdd
|
||
end
|
||
|
||
-- 老公式
|
||
--local fixDamage = floor(BattleUtil.FP_Mul(baseDamage, baseFactor, addDamageFactor, critDamageFactor))
|
||
--> 修改公式
|
||
--> 物
|
||
-- (自己攻击 - 目标护甲)*(自己56暴击伤害 - 目标113暴击抵抗)*(自己114物伤加成/116法伤加成 - 目标115物伤减免/117法伤减免)
|
||
-- *(1+ 自己职业伤害124\125\126\127 -目标职业减伤130\131\132\133)*(自己51伤害加成-目标52伤害减免)*(1+阵营克制系数)
|
||
--> 法
|
||
-- (自己攻击 - 目标护甲)*(自己56暴击伤害 - 目标113暴击抵抗)*(自己114物伤加成/116法伤加成 - 目标115物伤减免/117法伤减免)
|
||
-- *(1+ 自己职业伤害124\125\126\127 -目标职业减伤130\131\132\133)*(1 + 自己123技能伤害)*(自己51伤害加成-目标52伤害减免)*(1+阵营克制系数)
|
||
-- 老公式END
|
||
|
||
local fixDamage = 0
|
||
-- 公式伤害 = 基础伤害 * 基础伤害系数 * (1 + 增伤系数 + 爆伤系数 + 职业系数 + 物理损伤系数 + 克制系数)
|
||
if damageType == 1 then
|
||
local physicalDamageFactor = atkRole:GetRoleData(RoleDataName.PhysicalDamage) - defRole:GetRoleData(RoleDataName.PhysicalImmune)
|
||
fixDamage = floor(BattleUtil.FP_Mul(baseDamage, baseFactor, (1 + addDamageFactor+critDamageFactor+professionFactor+physicalDamageFactor+forbearFactor)))
|
||
SYSLog(string.format("damageType 1 === baseDamage: %s, baseFactor: %s, addDamageFactor: %s, critDamageFactor: %s, professionFactor: %s, physicalDamageFactor: %s, forbearFactor: %s",
|
||
tostring(baseDamage), tostring(baseFactor), tostring(addDamageFactor), tostring(critDamageFactor), tostring(professionFactor), tostring(physicalDamageFactor), tostring(forbearFactor)))
|
||
-- 公式伤害 = 基础伤害 * 基础伤害系数 * (1 +增伤系数 + 爆伤系数 + 职业系数 + 魔法损伤系数 + 技能 + 克制系数)
|
||
elseif damageType == 2 then
|
||
local magicDamageFactor = atkRole:GetRoleData(RoleDataName.MagicDamage) - defRole:GetRoleData(RoleDataName.MagicImmune)
|
||
local skillFactor = atkRole:GetRoleData(RoleDataName.SkillDamage)
|
||
fixDamage = floor(BattleUtil.FP_Mul(baseDamage, baseFactor, (1 + addDamageFactor+critDamageFactor+professionFactor+magicDamageFactor+skillFactor+forbearFactor)))
|
||
SYSLog(string.format("damageType 2 === baseDamage: %s, baseFactor: %s, addDamageFactor: %s, critDamageFactor: %s, professionFactor: %s, magicDamageFactor: %s, skillFactor: %s, forbearFactor: %s",
|
||
tostring(baseDamage), tostring(baseFactor), tostring(addDamageFactor), tostring(critDamageFactor), tostring(professionFactor), tostring(magicDamageFactor), tostring(skillFactor), tostring(forbearFactor)))
|
||
end
|
||
|
||
fixDamage = max(floor(attack * 0.1), fixDamage)
|
||
|
||
if SimpleCaculate then --未计算护盾等返回的伤害指数 不触发伤害
|
||
return fixDamage, bCrit
|
||
end
|
||
|
||
local finalDmg = 0 --计算实际造成的扣血
|
||
local dmg = 0 --< 造成伤害值
|
||
if not defRole:IsRealDead() then
|
||
--finalDmg = BattleUtil.ApplyDamage(skill, atkRole, defRole, fixDamage, bCrit, damageType, dotType)
|
||
finalDmg, dmg = BattleUtil.TriggerDamage(skill, atkRole, defRole, fixDamage, bCrit, damageType, dotType)
|
||
end
|
||
|
||
-- RoleManager.LogCa(
|
||
-- "frame:"..BattleLogic.CurFrame(),
|
||
-- "finalDmg:"..finalDmg,
|
||
-- "bCrit:",bCrit,
|
||
-- "dmg:",dmg
|
||
-- )
|
||
|
||
return finalDmg, bCrit, dmg
|
||
end
|
||
|
||
|
||
|
||
|
||
--执行完整的命中,伤害,暴击计算,返回命中,暴击
|
||
--skill造成伤害的技能 atkRole攻击者 defRole受击者 damageType伤害类型 baseFactor伤害系数 ignoreDef无视防御参数 dotType是持续伤害类型
|
||
function BattleUtil.CalDamage(skill, atkRole, defRole, damageType, baseFactor, ignoreDef, dotType)
|
||
|
||
if defRole.position == 99999 then
|
||
return
|
||
end
|
||
-- 判断是否命中
|
||
if skill and not skill:CheckTargetIsHit(defRole) 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
|
||
-- 如果是队伍技能,计算真实伤害,则damageType为伤害值
|
||
-- if atkRole.isTeam and not defRole:IsDead() then
|
||
-- return BattleUtil.ApplyDamage(skill, atkRole, defRole, damageType), false
|
||
-- end
|
||
-- 计算技能额外伤害系数加成
|
||
SYSLog(string.format("baseFactor 1 === baseFactor: %s === attackrole: %s ",baseFactor,atkRole.roleId))
|
||
baseFactor = baseFactor or 1
|
||
-- 计算技能额外伤害系数加成
|
||
SYSLog(string.format("baseFactor 2 === baseFactor: %s",baseFactor))
|
||
local factorFunc = function(exFactor) baseFactor = baseFactor + exFactor end
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleDamageBefore, defRole, factorFunc, damageType, skill,baseFactor,atkRole)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeDamagedBefore, atkRole, factorFunc, damageType, skill,baseFactor,defRole)
|
||
baseFactor = BattleUtil.ErrorCorrection(baseFactor)
|
||
SYSLog(string.format("baseFactor 3 === baseFactor: %s",baseFactor))
|
||
local baseDamage
|
||
-- 防御(据伤害类型决定)
|
||
--> damageType depracated 只有物防
|
||
local defence = defRole:GetRoleData(RoleDataName.PhysicalDefence)
|
||
-- 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)
|
||
local onIgnoreDefFactor = function(outIgnoreDef)
|
||
ignoreDef = 1 - math.max(0, outIgnoreDef)
|
||
end
|
||
atkRole.Event:DispatchEvent(BattleEventName.IgnoreDefFactor, onIgnoreDefFactor, atkRole, defRole)
|
||
defRole.Event:DispatchEvent(BattleEventName.BeIgnoreDefFactor, onIgnoreDefFactor, atkRole, defRole)
|
||
-- 基础伤害 = 攻击力 - 防御力
|
||
-- baseDamage = max(attack - BattleUtil.FP_Mul(0.5, defence, ignoreDef), 0)
|
||
-- baseDamage = max(attack - BattleUtil.FP_Mul(defence, ignoreDef), 0)
|
||
-- LogError(" defence:"..defence)
|
||
baseDamage = attack * (1 - (BattleUtil.FP_Mul(defence, ignoreDef) / (defence + 598 + 2 * defRole:GetRoleData(RoleDataName.Level))))
|
||
-- baseDamage = attack * (1 - (BattleUtil.FP_Mul(defence, ignoreDef) / (defence + GameSetting[1].DefenseLevvalue2 + GameSetting[1].DefenseLevvalue1 * defRole:GetRoleData(RoleDataName.Level))))
|
||
-- LogError(" baseDamage:"..baseDamage)
|
||
-- 基础伤害增加系数 --< 伤害加成
|
||
local addDamageFactor = atkRole:GetRoleData(RoleDataName.DamageBocusFactor) - defRole:GetRoleData(RoleDataName.DamageReduceFactor)
|
||
|
||
-- 是否暴击: 暴击率 = 自身暴击率 - 对方抗暴率
|
||
local bCrit = false
|
||
local critRandom = Random.Range01()
|
||
local critCondition = clamp(atkRole:GetRoleData(RoleDataName.Crit) - defRole:GetRoleData(RoleDataName.Tenacity), 0, 1)
|
||
bCrit = critRandom <= critCondition
|
||
bCrit = bCrit or defRole.isFlagCrit == true -- 必定暴击
|
||
if atkRole.ctrl_seal then --封印 无法暴击
|
||
bCrit = false
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleBeSeal)
|
||
end
|
||
defRole.Event:DispatchEvent(BattleEventName.FlagCritReset)
|
||
|
||
--> 暴击抵抗 miss次数
|
||
local onCritMiss = function(newbCrit)
|
||
bCrit = newbCrit
|
||
end
|
||
atkRole.Event:DispatchEvent(BattleEventName.CritMiss, onCritMiss, atkRole, defRole, bCrit)
|
||
defRole.Event:DispatchEvent(BattleEventName.BeCritMiss, onCritMiss, atkRole, defRole, bCrit)
|
||
-- 计算暴伤害系数
|
||
local critDamageFactor = 0
|
||
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)
|
||
defRole.Event:DispatchEvent(BattleEventName.CritDamageReduceFactor, onCritDamageReduceFactor, atkRole, defRole)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.CritDamageReduceFactor, onCritDamageReduceFactor, atkRole, defRole)
|
||
critDamageReduceFactor = max(BattleUtil.CountChangeList(critDamageReduceFactor, cl), 0)
|
||
|
||
-- 计算额外暴击伤害
|
||
-- critDamageFactor = 1.3 + atkRole:GetRoleData(RoleDataName.CritDamageFactor) - critDamageReduceFactor
|
||
critDamageFactor = max(atkRole:GetRoleData(RoleDataName.CritDamageFactor) - defRole:GetRoleData(RoleDataName.CriDamageReduceRate) - critDamageReduceFactor, 0)
|
||
|
||
--加入被动效果 触发暴击被动
|
||
local critFunc = function(critEx) critDamageFactor = critEx end
|
||
atkRole.Event:DispatchEvent(BattleEventName.PassiveCriting, critFunc)
|
||
end
|
||
|
||
local atkProFactor = 0
|
||
local defProFactor = 0
|
||
if defRole.professionId == 1 then --< 防御
|
||
atkProFactor = atkRole:GetRoleData(RoleDataName.DamageToDefender)
|
||
elseif defRole.professionId == 2 then --< 高爆
|
||
atkProFactor = atkRole:GetRoleData(RoleDataName.DamageToMage)
|
||
elseif defRole.professionId == 3 then --< 穿甲
|
||
atkProFactor = atkRole:GetRoleData(RoleDataName.DamageToFighter)
|
||
elseif defRole.professionId == 4 then --< 辅助
|
||
atkProFactor = atkRole:GetRoleData(RoleDataName.DamageToHealer)
|
||
end
|
||
if atkRole.professionId == 1 then --< 防御
|
||
defProFactor = defRole:GetRoleData(RoleDataName.DefenceFromDefender)
|
||
elseif atkRole.professionId == 2 then --< 高爆
|
||
defProFactor = defRole:GetRoleData(RoleDataName.DefenceFromMage)
|
||
elseif atkRole.professionId == 3 then --< 穿甲
|
||
defProFactor = defRole:GetRoleData(RoleDataName.DefenceFromFighter)
|
||
elseif atkRole.professionId == 4 then --< 辅助
|
||
defProFactor = defRole:GetRoleData(RoleDataName.DefenceFromHealer)
|
||
end
|
||
local professionFactor = atkProFactor - defProFactor
|
||
|
||
--> 克制
|
||
local isForbear, damageAdd, hitAdd = BattleUtil.CheckForbear(atkRole, defRole)
|
||
local forbearFactor = 0
|
||
if isForbear then
|
||
forbearFactor = forbearFactor + damageAdd
|
||
end
|
||
|
||
-- 老公式
|
||
--local fixDamage = floor(BattleUtil.FP_Mul(baseDamage, baseFactor, addDamageFactor, critDamageFactor))
|
||
--> 修改公式
|
||
--> 物
|
||
-- (自己攻击 - 目标护甲)*(自己56暴击伤害 - 目标113暴击抵抗)*(自己114物伤加成/116法伤加成 - 目标115物伤减免/117法伤减免)
|
||
-- *(1+ 自己职业伤害124\125\126\127 -目标职业减伤130\131\132\133)*(自己51伤害加成-目标52伤害减免)*(1+阵营克制系数)
|
||
--> 法
|
||
-- (自己攻击 - 目标护甲)*(自己56暴击伤害 - 目标113暴击抵抗)*(自己114物伤加成/116法伤加成 - 目标115物伤减免/117法伤减免)
|
||
-- *(1+ 自己职业伤害124\125\126\127 -目标职业减伤130\131\132\133)*(1 + 自己123技能伤害)*(自己51伤害加成-目标52伤害减免)*(1+阵营克制系数)
|
||
-- 老公式END
|
||
|
||
local fixDamage = 0
|
||
-- 公式伤害 = 基础伤害 * 基础伤害系数 * (1 + 增伤系数 + 爆伤系数 + 职业系数 + 物理损伤系数 + 克制系数)
|
||
if damageType == 1 then
|
||
local physicalDamageFactor = atkRole:GetRoleData(RoleDataName.PhysicalDamage) - defRole:GetRoleData(RoleDataName.PhysicalImmune)
|
||
fixDamage = floor(BattleUtil.FP_Mul(baseDamage, baseFactor, (1 + addDamageFactor+critDamageFactor+professionFactor+physicalDamageFactor+forbearFactor)))
|
||
SYSLog(string.format("damageType 1 === baseDamage: %s, baseFactor: %s, addDamageFactor: %s, critDamageFactor: %s, professionFactor: %s, physicalDamageFactor: %s, forbearFactor: %s",
|
||
tostring(baseDamage), tostring(baseFactor), tostring(addDamageFactor), tostring(critDamageFactor), tostring(professionFactor), tostring(physicalDamageFactor), tostring(forbearFactor)))
|
||
-- 公式伤害 = 基础伤害 * 基础伤害系数 * (1 +增伤系数 + 爆伤系数 + 职业系数 + 魔法损伤系数 + 技能 + 克制系数)
|
||
elseif damageType == 2 then
|
||
local magicDamageFactor = atkRole:GetRoleData(RoleDataName.MagicDamage) - defRole:GetRoleData(RoleDataName.MagicImmune)
|
||
local skillFactor = atkRole:GetRoleData(RoleDataName.SkillDamage)
|
||
fixDamage = floor(BattleUtil.FP_Mul(baseDamage, baseFactor, (1 + addDamageFactor+critDamageFactor+professionFactor+magicDamageFactor+skillFactor+forbearFactor)))
|
||
SYSLog(string.format("damageType 2 === baseDamage: %s, baseFactor: %s, addDamageFactor: %s, critDamageFactor: %s, professionFactor: %s, magicDamageFactor: %s, skillFactor: %s, forbearFactor: %s",
|
||
tostring(baseDamage), tostring(baseFactor), tostring(addDamageFactor), tostring(critDamageFactor), tostring(professionFactor), tostring(magicDamageFactor), tostring(skillFactor), tostring(forbearFactor)))
|
||
end
|
||
|
||
|
||
-- 公式计算完成
|
||
local damageFunc = function(damage) fixDamage = damage end
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleDamageAfter, defRole, damageFunc, fixDamage)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeDamagedAfter, atkRole, damageFunc, fixDamage)
|
||
|
||
|
||
fixDamage = max(floor(attack * 0.1), fixDamage)
|
||
|
||
|
||
|
||
local finalDmg = 0 --计算实际造成的扣血
|
||
local dmg = 0 --< 造成伤害值
|
||
if not defRole:IsRealDead() then
|
||
--finalDmg = BattleUtil.ApplyDamage(skill, atkRole, defRole, fixDamage, bCrit, damageType, dotType)
|
||
finalDmg, dmg = BattleUtil.TriggerDamage(skill, atkRole, defRole, fixDamage, bCrit, damageType, dotType)
|
||
end
|
||
return finalDmg, bCrit, dmg
|
||
end
|
||
|
||
function BattleUtil.TriggerDamage(skill, atkRole, defRole, damage, bCrit, damageType, dotType)
|
||
if atkRole.ctrl_seal then --封印 无法暴击
|
||
bCrit = false
|
||
end
|
||
--> 应对触发伤害 效果 被动
|
||
local damagingFunc = function(dmgDeduction)
|
||
damage = damage - dmgDeduction
|
||
end
|
||
SYSLog(string.format("TriggerDamage === damage: %s, dmgDeduction: %s,",tostring(damage),tostring(damageType)))
|
||
atkRole.Event:DispatchEvent(BattleEventName.TriggerDamaging, damagingFunc, defRole, damage, skill, dotType, bCrit)
|
||
defRole.Event:DispatchEvent(BattleEventName.TriggerBeDamaging, damagingFunc, atkRole, damage, skill, dotType, bCrit)
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.TriggerDamaging, damagingFunc, atkRole, defRole, damage, skill, dotType, bCrit)
|
||
return BattleUtil.ApplyDamage(skill, atkRole, defRole, damage, bCrit, damageType, dotType)
|
||
end
|
||
|
||
function BattleUtil.CalTreat(castRole, targetRole, value, baseFactor)
|
||
if targetRole.ctrl_noheal or targetRole:IsDead() then --禁疗和死亡无法加血
|
||
return
|
||
end
|
||
targetRole.Event:DispatchEvent(BattleEventName.RoleBeHealed, castRole)
|
||
BattleUtil.ApplyTreat(castRole, targetRole, value, baseFactor)
|
||
end
|
||
|
||
function BattleUtil.ApplyTreat(castRole, targetRole, value, baseFactor)
|
||
if targetRole.ctrl_noheal or targetRole:IsDead() then --禁疗和死亡无法加血
|
||
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)
|
||
targetRole.Event:DispatchEvent(BattleEventName.PassiveBeTreatedFactor, treatFactorFunc, castRole)
|
||
|
||
local factor = castRole:GetRoleData(RoleDataName.TreatFacter)
|
||
local factor2 = targetRole:GetRoleData(RoleDataName.CureFacter)
|
||
|
||
-- 是否修理暴击
|
||
local bTreatCrit = false
|
||
local critRandom = Random.Range01()
|
||
local critCondition = clamp(castRole:GetRoleData(RoleDataName.HealCritical), 0, 1)
|
||
bTreatCrit = critRandom <= critCondition
|
||
|
||
local treatCritFactor = 1
|
||
if bTreatCrit then
|
||
treatCritFactor = 1 + castRole:GetRoleData(RoleDataName.HealCriEffect)
|
||
end
|
||
|
||
-- local baseTreat = BattleUtil.FP_Mul(value, baseFactor, factor, factor2)
|
||
--> 改
|
||
--> 自己攻击(即治疗value) * (1+自己58治疗加成 + 目标57受疗加成)*自己129治疗暴击效果
|
||
local baseTreat = BattleUtil.FP_Mul(value, baseFactor, (1 + factor + factor2), treatCritFactor)
|
||
|
||
--加入被动效果
|
||
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)
|
||
-- LogError("baseTreat:"..baseTreat)
|
||
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)
|
||
-- else
|
||
-- targetRole.data:AddValue(RoleDataName.Hp, 0)
|
||
-- castRole.Event:DispatchEvent(BattleEventName.RoleTreat, targetRole, 0, 0)
|
||
-- targetRole.Event:DispatchEvent(BattleEventName.RoleBeTreated, castRole, 0, 0)
|
||
|
||
|
||
|
||
|
||
|
||
--
|
||
-- BattleLogManager.Log(
|
||
-- "Final Damage",
|
||
-- "acamp", castRole.camp,
|
||
-- "apos", castRole.position,
|
||
-- "tcamp", targetRole.camp,
|
||
-- "tpos", targetRole.position,
|
||
-- "value", value
|
||
-- )
|
||
end
|
||
|
||
|
||
|
||
-- 检测命中
|
||
function BattleUtil.CheckIsHit(atkRole, defRole)
|
||
-- 是否命中: 命中 = 自身命中率 - 对方闪避率
|
||
local isHit = false
|
||
local hitRandom = Random.Range01()
|
||
|
||
|
||
|
||
--> 克制
|
||
local isForbear, damageAdd, hitAdd = BattleUtil.CheckForbear(atkRole, defRole)
|
||
local addHit = 0
|
||
if isForbear then
|
||
addHit = addHit + hitAdd
|
||
end
|
||
local hitCondition = clamp(atkRole:GetRoleData(RoleDataName.Hit) + addHit - defRole:GetRoleData(RoleDataName.Dodge), 0, 1)
|
||
isHit = hitRandom <= hitCondition
|
||
--如果攻击方和防守方是同一阵营 直接命中
|
||
isHit = atkRole.camp == defRole.camp and true or isHit
|
||
return isHit
|
||
end
|
||
|
||
--> 克制
|
||
function BattleUtil.CheckForbear(atkRole, defRole)
|
||
local damageAdd = 0.25
|
||
local hitAdd = 0.2
|
||
-- 1 Y系
|
||
-- 2 S系
|
||
-- 3 F系
|
||
-- 4 M系
|
||
-- 5 D系
|
||
local arrForbear = {[1] = 3, [2] = 1, [3] = 2, [4] = 5, [5] = 4}
|
||
local tempChecker = nil
|
||
local ChangeForbear=function(forceBear)
|
||
tempChecker = forceBear
|
||
end
|
||
atkRole.Event:DispatchEvent(BattleEventName.RoleCheckForbear, atkRole,defRole,ChangeForbear)
|
||
defRole.Event:DispatchEvent(BattleEventName.RoleBeCheckForbear, atkRole,defRole,ChangeForbear)
|
||
if tempChecker ~= nil then
|
||
return tempChecker,damageAdd, hitAdd
|
||
end
|
||
if atkRole and defRole then
|
||
return arrForbear[atkRole.element] == defRole.element, damageAdd, hitAdd
|
||
else
|
||
return false, damageAdd, hitAdd
|
||
end
|
||
end
|
||
|
||
|
||
function BattleUtil.RandomAction(rand, action)
|
||
if Random.Range01() <= rand and action then
|
||
action()
|
||
return true
|
||
end
|
||
return false
|
||
end
|
||
|
||
function BattleUtil.RandomAction2(rand, action)
|
||
if BattleLogic.RoundRandom <= 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)
|
||
--> 技能控制几率 + 自己118控制几率 - 目标119控制抵抗
|
||
rand = BattleUtil.CountChangeList(rand, cl) + caster:GetRoleData(RoleDataName.ControlProbability) - target:GetRoleData(RoleDataName.ControlResist)
|
||
|
||
--修改最终控制几率
|
||
local function fixControl(deRand)
|
||
rand = deRand
|
||
end
|
||
caster.Event:DispatchEvent(BattleEventName.PassiveRandomFinalControl, fixControl, rand, ctrl, target)
|
||
target.Event:DispatchEvent(BattleEventName.PassiveBeRandomFinalControl, fixControl,rand, ctrl, target)
|
||
|
||
return BattleUtil.RandomAction(rand, function()
|
||
local buff = Buff.Create(caster, BuffName.Control, round, ctrl)
|
||
|
||
target:AddBuff(buff)
|
||
end)
|
||
end
|
||
|
||
--
|
||
function BattleUtil.RandomDot(rand, dot, caster, target, round, interval, damage, func)
|
||
|
||
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 = BattleUtil.CountChangeList(damage, dcl)
|
||
|
||
return BattleUtil.RandomAction(rand, function()
|
||
local buff = Buff.Create(caster, BuffName.DOT, round, interval, dot, damage)
|
||
if func then func(buff) end
|
||
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.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
|
||
|
||
--> 还原属性
|
||
function BattleUtil.RevertProp(role, prop, value, ct)
|
||
if ct == 3 or ct == 4 then
|
||
role.data:AddValue(BattlePropList[prop], value)
|
||
elseif ct == 2 then
|
||
role.data:SubPencentValue(BattlePropList[prop], value)
|
||
else
|
||
role.data:SubDeltaValue(BattlePropList[prop], value)
|
||
end
|
||
end
|
||
|
||
-- 规范基础伤害效果修改方法
|
||
function BattleUtil.ChangeBaseSkillDamage(role,percent,damagetype,ct)
|
||
-- 由于仅修改原始参数每次修改会叠加 所以增加镜像数据镜像为原始数据不会修改
|
||
local tempBaseDamgePercent = 1
|
||
local tempBaseDamgeType = 1
|
||
for i=9, #role.skillArrayBase[1] do
|
||
local v = role.skillArrayBase[1][i]
|
||
for j=2, #v do
|
||
for k=2, #v[j] do
|
||
if k == 2 then
|
||
tempBaseDamgePercent = v[j][k]
|
||
elseif k == 3 then
|
||
tempBaseDamgeType = v[j][k]
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
for i=9, #role.skillArray[1] do
|
||
local v = role.skillArray[1][i]
|
||
for j=2, #v do
|
||
for k=2, #v[j] do
|
||
if k == 2 then
|
||
if ct == 1 then --加算
|
||
v[j][k] = tempBaseDamgePercent + percent
|
||
elseif ct == 2 then --乘加算(百分比属性加算)
|
||
v[j][k] = tempBaseDamgePercent + floor(tempBaseDamgePercent * percent)
|
||
elseif ct == 3 then --减算
|
||
v[j][k] = tempBaseDamgePercent - percent
|
||
elseif ct == 4 then --乘减算(百分比属性减算)
|
||
v[j][k] = tempBaseDamgePercent - floor(tempBaseDamgePercent * percent)
|
||
end
|
||
v[j][k] = tempBaseDamgePercent * percent; --会叠加
|
||
elseif k == 3 then
|
||
v[j][k] = damagetype;
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 规范基础伤害效果修改方法
|
||
function BattleUtil.ChangeSkillArrayDamage(skillArray,percent,damagetype,ct)
|
||
-- 由于仅修改原始参数每次修改会叠加 所以增加镜像数据镜像为原始数据不会修改
|
||
local tempBaseDamgePercent = 1
|
||
local tempBaseDamgeType = 1
|
||
local skillArrayBase = BattleUtil.cloneTable(skillArray)
|
||
for i=9, #skillArrayBase[1] do
|
||
local v =skillArrayBase[1][i]
|
||
for j=2, #v do
|
||
for k=2, #v[j] do
|
||
if k == 2 then
|
||
tempBaseDamgePercent = v[j][k]
|
||
elseif k == 3 then
|
||
tempBaseDamgeType = v[j][k]
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
for i=9, #skillArray[1] do
|
||
local v = skillArray[1][i]
|
||
for j=2, #v do
|
||
for k=2, #v[j] do
|
||
if k == 2 then
|
||
if ct == 1 then --加算
|
||
v[j][k] = tempBaseDamgePercent + percent
|
||
elseif ct == 2 then --乘加算(百分比属性加算)
|
||
v[j][k] = tempBaseDamgePercent + floor(tempBaseDamgePercent * percent)
|
||
elseif ct == 3 then --减算
|
||
v[j][k] = tempBaseDamgePercent - percent
|
||
elseif ct == 4 then --乘减算(百分比属性减算)
|
||
v[j][k] = tempBaseDamgePercent - floor(tempBaseDamgePercent * percent)
|
||
end
|
||
v[j][k] = tempBaseDamgePercent * percent; --会叠加
|
||
elseif k == 3 then
|
||
v[j][k] = damagetype;
|
||
end
|
||
end
|
||
end
|
||
end
|
||
return skillArray
|
||
end
|
||
|
||
|
||
-- 规范基础伤害效果还原方法 基础伤害固定只有2个参数 参照effect 1
|
||
function BattleUtil.RevertBaseSkillDamage(role)
|
||
-- 由于仅修改原始参数每次修改会叠加 所以增加镜像数据镜像为原始数据不会修改
|
||
local tempBaseDamgePercent = 1
|
||
local tempBaseDamgeType = 1
|
||
for i=9, #role.skillArrayBase[1] do
|
||
local v = role.skillArrayBase[1][i]
|
||
for j=2, #v do
|
||
for k=2, #v[j] do
|
||
if k == 2 then
|
||
tempBaseDamgePercent = v[j][k]
|
||
elseif k == 3 then
|
||
tempBaseDamgeType = v[j][k]
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
for i=9, #role.skillArray[1] do
|
||
local v = role.skillArray[1][i]
|
||
for j=2, #v do
|
||
for k=2, #v[j] do
|
||
if k == 2 then
|
||
v[j][k] = tempBaseDamgePercent
|
||
elseif k == 3 then
|
||
v[j][k] = tempBaseDamgeType;
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
--> 条件下增加属性
|
||
function BattleUtil.AddPropOnFunc(role, prop, value, ct,func)
|
||
if func and func(role) then
|
||
BattleUtil.AddProp(role, prop, value, ct)
|
||
end
|
||
end
|
||
|
||
--> 条件下还原属性
|
||
function BattleUtil.RevertPropOnFunc(role, prop, value, ct,func)
|
||
if func and func(role) then
|
||
BattleUtil.RevertProp(role, prop, value, ct)
|
||
end
|
||
end
|
||
|
||
-- 触发某一方法后注销此方法 -- 方法统一参数 @role @args
|
||
function BattleUtil.TirggerOnceAtEvent(role,func,_tirggerBattleEventName,args)
|
||
local SubFunc
|
||
SubFunc = function()
|
||
if func then func(role,args) end
|
||
role.Event:RemoveEvent(_tirggerBattleEventName, SubFunc)
|
||
end
|
||
role.Event:AddEvent(_tirggerBattleEventName, SubFunc)
|
||
end
|
||
|
||
--克隆表单
|
||
function BattleUtil.cloneTable(object)
|
||
local lookup_table = {}
|
||
local function _copy(object)
|
||
if type(object) ~= "table" then
|
||
return object
|
||
elseif lookup_table[object] then
|
||
return lookup_table[object]
|
||
end
|
||
local newObject = {}
|
||
lookup_table[object] = newObject
|
||
for key, value in pairs(object) do
|
||
newObject[_copy(key)] = _copy(value)
|
||
end
|
||
return setmetatable(newObject, getmetatable(object))
|
||
end
|
||
return _copy(object)
|
||
end
|
||
|
||
-- 逻辑回合触发某一方法后注销此方法 -- 方法统一参数 @role @args
|
||
function BattleUtil.LogicTrigerOnceAtEvent(role,func,_tirggerBattleEventName,args)
|
||
local SubFunc
|
||
SubFunc = function()
|
||
if func then func(role,args) end
|
||
BattleLogic.Event:RemoveEvent(_tirggerBattleEventName, SubFunc)
|
||
end
|
||
BattleLogic.Event:AddEvent(_tirggerBattleEventName, SubFunc)
|
||
end |