miduo_server/luafight/Modules/Battle/Logic/Base/Skill.lua

324 lines
13 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters!

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

local effect = require("Modules/Battle/Logic/Base/Effect")
local floor = math.floor
local max = math.max
local min = math.min
--local BattleConst = BattleConst
--local RoleDataName = RoleDataName
--local BattleEventName = BattleEventName
local function chooseTarget(role, chooseId, exceptList)
local chooseType = floor(chooseId / 10000) % 10
local chooseWeight = floor(chooseId / 100) % 10
local sort = floor(chooseId / 10) % 10
local exceptNum = exceptList.size
local num = chooseId % 10
local arr
if chooseType == 1 then
arr = BattleLogic.Query(function (r)
for i=1, exceptList.size do
if r.uid == exceptList.buffer[i].uid then
return false
end
end
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)
for i=1, exceptList.size do
if r.uid == exceptList.buffer[i].uid then
return false
end
end
return r.camp ~= role.camp
end)
elseif chooseType == 3 then
if role.ctrl_blind then --致盲时自身变随机友军
arr = BattleLogic.Query(function (r)
for i=1, exceptList.size do
if r.uid == exceptList.buffer[i].uid then
return false
end
end
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)
for i=1, exceptList.size do
if r.uid == exceptList.buffer[i].uid then
return false
end
end
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)
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)
end
if exceptNum > 0 then
local count = #arr
for i=1, min(exceptNum, count) do
for j=count, i+1, -1 do
arr[j] = arr[j-1]
end
arr[i] = exceptList.buffer[i]
end
end
return arr
end
local effectPool = BattleObjectPool.New(function ()
return { type = 0, args = {}} -- type, {args, ...}
end)
local effectGroupPool = BattleObjectPool.New(function ()
return { chooseId = 0, duration = 0, effects = {}} -- chooseId, duration, {effect1, effect2, ...}
end)
Skill = {}
function Skill:New()
local o = {cd=0,effectList = BattleList.New(),owner=0,sp=0,spPass = 0,choosedList = BattleList.New(),isTeamSkill=false }
setmetatable(o, self)
self.__index = self
return o
end
function Skill:Init(role, effectData)
self.cd = effectData[1]
--skill = {cd, {目标id1, 效果时间, 效果1, 效果2, ...},{目标id2, 效果时间, 效果3, 效果4, ...}, ...}
--效果 = {效果类型id, 效果参数1, 效果参数2, ...}
self.effectList:Clear()
self.owner = role
self.sp = 0
self.spPass = 0
self.choosedList:Clear()
self.isTeamSkill = false
for i=2, #effectData do
local v = effectData[i]
local effectGroup = effectGroupPool:Get() -- chooseId, duration, {effect1, effect2, ...}
effectGroup.chooseId = v[1] --chooseId
effectGroup.duration = v[2] --duration
for j=3, #v do --effectList
local effect = effectPool:Get() -- type, {args, ...}
effect.type = v[j][1]
for k=2, #v[j] do
effect.args[k-1] = v[j][k]
end
effectGroup.effects[j-2] = effect
end
self.effectList:Add(effectGroup)
end
end
function Skill:Dispose()
while self.effectList.size > 0 do
local effectGroup = self.effectList.buffer[self.effectList.size]
for k=1, #effectGroup.effects do
local effect = effectGroup.effects[k]
for j=1, #effect.args do
effect.args[j] = nil
end
effectPool:Put(effect)
effectGroup.effects[k] = nil
end
effectGroupPool:Put(effectGroup)
self.effectList:Remove(self.effectList.size)
end
end
local function takeEffect(caster, target, effects, duration)
for k=1, #effects do
local e = effects[k]
effect[e.type](caster, target, e.args, duration)
if BattleLogic.IsOpenBattleRecord then
BattleLogic.RecordEffect(caster, target, e.type, e.args, duration)
end
end
end
function Skill:Cast()
for i=1, self.effectList.size do
local effectGroup = self.effectList.buffer[i]
local chooseId = effectGroup.chooseId
local arr = chooseTarget(self.owner, chooseId, self.choosedList)
if #arr > 0 then
--效果延迟1帧生效
BattleLogic.WaitForTrigger(BattleLogic.GameDeltaTime, function()
local duration = effectGroup.duration
local effects = effectGroup.effects
local nn = floor(chooseId / 10000) % 10
local count = min(chooseId % 10, #arr)
if count == 0 then
count = #arr
end
if self.owner.camp == 0 and nn == 2 then --我方释放效果开始切镜头
BattleLogic.Event:DispatchEvent(BattleEventName.ZoomIn, 0.3)
BattleLogic.WaitForTrigger(duration, function()
BattleLogic.Event:DispatchEvent(BattleEventName.ZoomOut, 0.3)
end)
end
if chooseId == 10000 or chooseId == 20000 then --10000 我方aoe 20000 敌方aoe
local camp = chooseId == 10000 and self.owner.camp or 1 - self.owner.camp
self.owner.Event:DispatchEvent(BattleEventName.AOE, camp)
for j=1, count do
takeEffect(self.owner, arr[j], effects, duration)
end
elseif nn == 1 or nn == 3 then
for j=1, count do
takeEffect(self.owner, arr[j], effects, duration)
end
else
local d = duration / (count + 1) --分割多人目标施加效果的时间按照1+1+..+2的时间权重占比分配
for j=1, count do
local index = j
local cd = j == count and d * 2 or d
BattleLogic.WaitForTrigger(d * (j-1), function()
local r = arr[index]
if not r or r.isDead then --当被选取的目标已经死亡或者没有,则重新选取,若重新选取的目标也死亡或者没有,则从之前的目标中选取第一个不死亡的
arr = chooseTarget(self.owner, chooseId, self.choosedList)
r = arr[index]
if not r then --当没有新增的被选取目标时,可能为空
for i=1, #arr do
if not arr[i].isDead then
takeEffect(self.owner, arr[i], effects, cd)
return
end
end
if not r then
return
end
end
end
self.choosedList:Add(r)
takeEffect(self.owner, r, effects, cd)
end)
end
end
end)
end
end
BattleLogic.SetAggro(self.owner)
if not self.isTeamSkill then
if self.owner.superSkill == self then
self.sp = 0
self.spPass = floor(self.cd * BattleLogic.GameFrameRate)
BattleLogic.AddMP(self.owner.camp, 10)
if self.owner.skill then
local skill = self.owner.skill
local time = max(8-self.owner:GetRoleData(RoleDataName.Speed)/(8*(self.owner:GetRoleData(RoleDataName.Level)+10)), 1.5)
skill.sp = 0
skill.spPass = floor(time * BattleLogic.GameFrameRate)
end
else
local time = max(8-self.owner:GetRoleData(RoleDataName.Speed)/(8*(self.owner:GetRoleData(RoleDataName.Level)+10)), 1.5)
self.sp = 0
self.spPass = floor(time * BattleLogic.GameFrameRate)
BattleLogic.AddMP(self.owner.camp, 8)
end
self.owner.Event:DispatchEvent(BattleEventName.SkillCast, self)
else
BattleLogic.Event:DispatchEvent(BattleEventName.SkillCast, self.cd) --队伍技能结构和其他相同只是cd项为对应异妖类型
end
--技能的施法时间计算根据当前目标id关联的持续时间取其中时间最长的一个
local duration = 0
for i=1, self.effectList.size do
duration = max(duration, self.effectList.buffer[i].duration)
end
BattleLogic.SetSkillUsable(self.owner.camp, false)
BattleLogic.WaitForTrigger(duration, function()
self.choosedList:Clear()
BattleLogic.SetSkillUsable(self.owner.camp, true)
if not self.isTeamSkill then
self.owner.Event:DispatchEvent(BattleEventName.SkillCastEnd, self)
else
BattleLogic.Event:DispatchEvent(BattleEventName.SkillCastEnd, self.cd)
end
end)
end
--表现层调用
function Skill:CanManualCast()
return self.owner:CanCastSkill() and self.owner.camp == 0 and not self.owner.Auto and self.sp >= self.spPass
end
--表现层调用
function Skill:ManualCast()
--非调试模式下,只有我方阵营角色,且处在非自动状态下可手动释放技能
local b = self:CanManualCast()
--调试模式下,可无条件手动释放技能
local b2 = self.owner.IsDebug
if b or b2 then
if self.owner.skill == self then
BattleLogic.AddOption(2, self.owner.uid)
else
BattleLogic.AddOption(3, self.owner.uid)
end
end
end