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

275 lines
11 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 BattleConst = BattleConst
--local RoleDataName = RoleDataName
--local BattleEventName = BattleEventName
local function queryExceptList(r, exceptList)
if not exceptList then return true end
for i=1, #exceptList do
if r.uid == exceptList[i].uid then
return false
end
end
return true
end
local function queryAllies(role, exceptList)
return function (r) return r.camp == role.camp and queryExceptList(r, exceptList) end
end
local function queryAlliesExceptSelf(role, exceptList)
return function (r) return r.camp == role.camp and r.uid ~= role.uid and queryExceptList(r, exceptList) end
end
local function queryEnemy(role, exceptList)
return function (r) return r.camp ~= role.camp and queryExceptList(r, exceptList) end
end
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
local num = chooseId % 10
local arr = {}
if chooseType == 1 then
arr = BattleLogic.Query(queryAllies(role, exceptList))
elseif chooseType == 2 then
if role.lockTarget and num == 1 then
return {role.lockTarget}
end
arr = BattleLogic.Query(queryEnemy(role, exceptList))
elseif chooseType == 3 then
return {role}
elseif chooseType == 4 then
return {BattleLogic.GetAggro(role.camp)}
end
if chooseWeight == 0 then
BattleUtil.RandomList(arr)
elseif chooseWeight == 1 then
table.sort(arr, function(a, b)
local r1 = a:GetRoleData(RoleDataName.Hp)
local r2 = b:GetRoleData(RoleDataName.Hp)
return sort == 1 and r1 < r2 or r1 > r2
end)
elseif chooseWeight == 2 then
table.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)
return sort == 1 and r1 < r2 or r1 > r2
end)
elseif chooseWeight == 3 then
table.sort(arr, function(a, b)
local r1 = a:GetRoleData(RoleDataName.Attack)
local r2 = b:GetRoleData(RoleDataName.Attack)
return sort == 1 and r1 < r2 or r1 > r2
end)
elseif chooseWeight == 4 then
table.sort(arr, function(a, b)
local r1 = a:GetRoleData(RoleDataName.PhysicalDefence)
local r2 = b:GetRoleData(RoleDataName.PhysicalDefence)
return sort == 1 and r1 < r2 or r1 > r2
end)
elseif chooseWeight == 5 then
table.sort(arr, function(a, b)
local r1 = a:GetRoleData(RoleDataName.PhysicalDefence)
local r2 = b:GetRoleData(RoleDataName.PhysicalDefence)
return sort == 1 and r1 < r2 or r1 > r2
end)
elseif chooseWeight == 6 then
table.sort(arr, function(a, b)
local r1 = a:GetRoleData(RoleDataName.MagicDefence)
local r2 = b:GetRoleData(RoleDataName.MagicDefence)
return sort == 1 and r1 < r2 or r1 > r2
end)
elseif chooseWeight == 7 then
table.sort(arr, function(a, b)
local r1 = a:GetRoleData(RoleDataName.MagicDefence)
local r2 = b:GetRoleData(RoleDataName.MagicDefence)
return sort == 1 and r1 < r2 or r1 > r2
end)
end
local arr2 = {}
for i=1, exceptNum do
arr2[i] = exceptList[i]
end
if #arr >= num then
for i=1+exceptNum, num == 0 and #arr or num do
arr2[i] = arr[i]
end
end
arr = arr2
return arr
end
Skill = {}
function Skill:New(role, effectData)
local o = {}
o.cd = effectData[1]
--skill = {cd, {目标id1, 效果时间, 效果1, 效果2, ...},{目标id2, 效果时间, 效果3, 效果4, ...}, ...}
--效果 = {效果类型id, 效果参数1, 效果参数2, ...}
o.effectList = {}
o.owner = role
o.sp = 0
o.spPass = 0
o.choosedList = {}
local v
for i=2, #effectData do
v = effectData[i]
local effectGroup = { 0, 0, {}} -- chooseId, duration, {effect1, effect2, ...}
effectGroup[1] = v[1] --chooseId
effectGroup[2] = v[2] --duration
for j=3, #v do --effectList
local effect = {0, {}} -- type, {args, ...}
effect[1] = v[j][1]
for k=2, #v[j] do
effect[2][k-1] = v[j][k]
end
effectGroup[3][j-2] = effect
end
o.effectList[i-1] = effectGroup
end
setmetatable(o, self)
self.__index = self
return o
end
function Skill:ResetCD()
if self.owner.superSkill == self then
if BattleLogic.SkillUsable then
self.sp = 0
self.spPass = floor(self.cd * BattleLogic.GameFrameRate)
self.owner.Event:DispatchEvent(BattleEventName.SkillCast, self)
BattleLogic.SkillUsable = false
BattleLogic.WaitForTrigger(self.cd, function()
BattleLogic.SkillUsable = true
end)
BattleLogic.AddMP(self.owner.camp, 8)
if self.owner.skill then
local skill = self.owner.skill
skill.sp = 0
skill.spPass = floor(skill.cd * BattleLogic.GameFrameRate)
end
end
else
local time = max(6-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, 4)
self.owner.Event:DispatchEvent(BattleEventName.SkillCast, self)
end
end
function Skill:Cast()
if self.owner.superSkill == self and not BattleLogic.SkillUsable then
return
end
for i=1, #self.effectList do
local effectGroup = self.effectList[i]
local chooseId = effectGroup[1]
local duration = effectGroup[2]
local arr = chooseTarget(self.owner, chooseId, self.choosedList)
if #arr > 0 then
--延迟1帧释放效果
BattleLogic.WaitForTrigger(BattleLogic.GameDeltaTime, function ()
local nn = floor(chooseId / 10000) % 10
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 then --我方aoe
self.owner.Event:DispatchEvent(BattleEventName.AOE, 0)
for j=1, #arr do
for k=1, #effectGroup[3] do
local v = effectGroup[3][k]
effect[v[1]](self.owner, arr[j], v[2], duration)
end
end
elseif chooseId == 20000 then --敌方aoe
self.owner.Event:DispatchEvent(BattleEventName.AOE, 1)
for j=1, #arr do
for k=1, #effectGroup[3] do
local v = effectGroup[3][k]
effect[v[1]](self.owner, arr[j], v[2], duration)
end
end
elseif nn == 1 then
for j=1, #arr do
for k=1, #effectGroup[3] do
local v = effectGroup[3][k]
effect[v[1]](self.owner, arr[j], v[2], duration)
end
end
else
local d = duration / (#arr + 1) --分割多人目标施加效果的时间按照1+1+..+2的时间权重占比分配
for j=1, #arr do
local index = j
local cd = j == #arr and d * 2 or d
BattleLogic.WaitForTrigger(d * (j-1), function()
local r = arr[index]
if 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
r = arr[i]
for k=1, #effectGroup[3] do
local v = effectGroup[3][k]
effect[v[1]](self.owner, r, v[2], cd)
end
return
end
end
if not r then
return
end
end
end
table.insert(self.choosedList, r)
for k=1, #effectGroup[3] do
local v = effectGroup[3][k]
effect[v[1]](self.owner, r, v[2], cd)
end
end)
end
BattleLogic.WaitForTrigger(duration, function()
self.choosedList = {}
end)
end
end)
end
end
BattleLogic.SetAggro(self.owner, 0)
self:ResetCD()
end
--表现层调用
function Skill:CanManualCast()
return not self.owner.IsDebug and self.owner.camp == 0 and not self.owner.Auto and self.sp >= self.spPass and BattleLogic.SkillUsable
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