miduo_server/luafight/Modules/Battle/Logic/Misc/BattleUtil.lua

346 lines
13 KiB
Lua
Raw Normal View History

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
local function clamp(v, minValue, maxValue)
if v < minValue then
return minValue
end
if v > maxValue then
return maxValue
end
return v
end
2019-06-05 11:29:24 +08:00
function BattleUtil.ChooseTarget(role, chooseId)
local chooseType = floor(chooseId / 10000) % 10
local chooseWeight = floor(chooseId / 100) % 10
local sort = floor(chooseId / 10) % 10
local num = chooseId % 10
local arr
if chooseType == 1 then
arr = BattleLogic.Query(function (r) return r.camp == role.camp end)
elseif chooseType == 2 then
if role.lockTarget and num == 1 then --嘲讽时对单个敌军生效
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
if role.lockTarget then --嘲讽时对仇恨目标生效
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
return {BattleLogic.GetAggro(role.camp)}
else
arr = BattleLogic.Query()
end
if chooseWeight == 0 or role.ctrl_blind then --致盲时排序无效
BattleUtil.RandomList(arr)
elseif chooseWeight == 1 then
BattleUtil.Sort(arr, function(a, b)
local r1 = a:GetRoleData(RoleDataName.Hp)
local r2 = b:GetRoleData(RoleDataName.Hp)
if sort == 1 then return r1 > r2 else return r1 < r2 end
end)
elseif chooseWeight == 2 then
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)
elseif chooseWeight == 3 then
BattleUtil.Sort(arr, function(a, b)
local r1 = a:GetRoleData(RoleDataName.Attack)
local r2 = b:GetRoleData(RoleDataName.Attack)
if sort == 1 then return r1 > r2 else return r1 < r2 end
end)
elseif chooseWeight == 4 then
BattleUtil.Sort(arr, function(a, b)
local r1 = a:GetRoleData(RoleDataName.PhysicalDefence)
local r2 = b:GetRoleData(RoleDataName.PhysicalDefence)
if sort == 1 then return r1 > r2 else return r1 < r2 end
end)
elseif chooseWeight == 5 then
BattleUtil.Sort(arr, function(a, b)
local r1 = a:GetRoleData(RoleDataName.PhysicalDefence)
local r2 = b:GetRoleData(RoleDataName.PhysicalDefence)
if sort == 1 then return r1 > r2 else return r1 < r2 end
end)
elseif chooseWeight == 6 then
BattleUtil.Sort(arr, function(a, b)
local r1 = a:GetRoleData(RoleDataName.MagicDefence)
local r2 = b:GetRoleData(RoleDataName.MagicDefence)
if sort == 1 then return r1 > r2 else return r1 < r2 end
end)
elseif chooseWeight == 7 then
BattleUtil.Sort(arr, function(a, b)
2019-06-05 15:25:06 +08:00
local r1 = a:GetSkillCD()
local r2 = b:GetSkillCD()
2019-06-05 11:29:24 +08:00
if sort == 1 then return r1 > r2 else return r1 < r2 end
end)
end
return arr
end
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
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)
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]
2019-03-21 14:33:56 +08:00
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
2019-03-12 14:05:45 +08:00
end
end
return damage
end
2019-05-18 17:20:57 +08:00
function BattleUtil.ApplyDamage(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
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
2019-05-13 09:51:36 +08:00
atkRole.Event:DispatchEvent(BattleEventName.PassiveDamaging, damagingFunc, defRole, damage)
defRole.Event:DispatchEvent(BattleEventName.PassiveBeDamaging, damagingFunc, atkRole, damage)
2019-05-07 20:01:07 +08:00
if damage > 0 then
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)
BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoleDead, defRole)
if defRole.camp == 1 then
BattleLogic.WaitForTrigger(1, function ()
BattleLogic.Event:DispatchEvent(BattleEventName.ZoomChange, BattleLogic.GetAggro(0), 1)
end)
end
2019-04-16 14:32:11 +08:00
end
2019-05-13 09:51:36 +08:00
2019-05-18 17:20:57 +08:00
atkRole.Event:DispatchEvent(BattleEventName.RoleDamage, defRole, damage, bCrit, finalDmg, damageType)
2019-05-13 09:51:36 +08:00
defRole.Event:DispatchEvent(BattleEventName.RoleBeDamaged, atkRole, damage, bCrit, finalDmg, damageType)
if bCrit then
atkRole.Event:DispatchEvent(BattleEventName.RoleCrit, defRole)
defRole.Event:DispatchEvent(BattleEventName.RoleBeCrit, atkRole)
end
2019-05-18 17:20:57 +08:00
if not isDot then
atkRole.Event:DispatchEvent(BattleEventName.RoleHit, defRole)
defRole.Event:DispatchEvent(BattleEventName.RoleBeHit, atkRole)
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
--执行完整的命中,伤害,暴击计算,返回命中,暴击
2019-05-18 17:20:57 +08:00
--atkRole攻击者 defRole受击者 damageType伤害类型 baseFactor伤害系数 ignoreDef无视防御参数 isDot是否是dot
function BattleUtil.CalDamage(atkRole, defRole, damageType, baseFactor, ignoreDef, isDot)
if atkRole.isTeam and not defRole.isDead then --如果是队伍技能计算真实伤害则damageType为伤害值
2019-03-21 14:33:56 +08:00
return BattleUtil.ApplyDamage(atkRole, defRole, damageType), false
end
2019-05-07 20:01:07 +08:00
baseFactor = baseFactor or 1
local factorFunc = function(exFactor) baseFactor = baseFactor + exFactor end
atkRole.Event:DispatchEvent(BattleEventName.RoleDamageBefore, defRole, factorFunc, damageType)
defRole.Event:DispatchEvent(BattleEventName.RoleBeDamagedBefore, atkRole, factorFunc, damageType)
2019-03-12 14:05:45 +08:00
local bCrit = false
local baseDamage
2019-03-26 15:11:47 +08:00
ignoreDef = 1 - (ignoreDef or 0)
2019-05-09 17:50:38 +08:00
bCrit = Random.Range01() <= clamp(atkRole:GetRoleData(RoleDataName.Crit)-defRole:GetRoleData(RoleDataName.Tenacity), 0, 1)
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
2019-06-19 16:43:02 +08:00
local attack = atkRole:GetRoleData(RoleDataName.Attack)
2019-03-12 14:05:45 +08:00
--计算暴击
if bCrit or defRole.isFlagCrit then
local critDamageFactor = atkRole:GetRoleData(RoleDataName.CritDamageFactor)
2019-05-07 20:01:07 +08:00
--加入被动效果
local critFunc = function(critEx) critDamageFactor = critEx end
atkRole.Event:DispatchEvent(BattleEventName.PassiveCriting, critFunc)
2019-03-26 15:11:47 +08:00
baseDamage = max(attack * critDamageFactor - 0.5 * defence * ignoreDef, 0)
2019-03-12 14:05:45 +08:00
else
2019-03-26 15:11:47 +08:00
baseDamage = max(attack - 0.5 * defence * ignoreDef, 0)
2019-03-12 14:05:45 +08:00
end
2019-03-26 15:11:47 +08:00
--伤害 =(基础伤害*1+己伤害加成-目标伤害减免)*1+己方属性伤害加成-目标属性伤害减免10%*己攻)
2019-05-09 17:50:38 +08:00
local exFactor = 1 + atkRole:GetRoleData(RoleDataName.DamageBocusFactor) - defRole:GetRoleData(RoleDataName.DamageReduceFactor)
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-05-09 17:50:38 +08:00
exFactor = exFactor * (1 + atkRole:GetRoleData(RoleDataName.ElementDamageBocusFactor) - defRole:GetRoleData(elementDamageReduceFactor))
2019-04-01 19:49:18 +08:00
2019-05-09 17:50:38 +08:00
baseDamage = baseDamage * baseFactor * exFactor
2019-04-17 21:04:32 +08:00
baseDamage = floor(max(baseDamage, 0.1 * attack))
2019-03-21 14:33:56 +08:00
local func
for i=1, atkRole.exCalDmgList.size do
func = atkRole.exCalDmgList.buffer[i]
baseDamage = func(baseDamage)
end
2019-03-12 14:05:45 +08:00
baseDamage = BattleUtil.CalShield(atkRole, defRole, baseDamage)
local finalDmg = 0 --计算实际造成的扣血
if not defRole.isDead then
2019-05-18 17:20:57 +08:00
finalDmg = BattleUtil.ApplyDamage(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
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-05-09 17:50:38 +08:00
local baseTreat = floor(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
castRole.Event:DispatchEvent(BattleEventName.PassiveTreating, treatingFunc)
local treat = min(baseTreat, maxHp - hp)
if treat > 0 then
targetRole.data:AddValue(RoleDataName.Hp, treat)
castRole.Event:DispatchEvent(BattleEventName.RoleTreat, targetRole, treat)
targetRole.Event:DispatchEvent(BattleEventName.RoleBeTreated, castRole, treat)
end
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