miduo_server/luafight/Modules/Battle/Logic/BattleLogic.lua

510 lines
14 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.

BattleLogic = {}
local floor = math.floor
local min = math.min
local objList = BattleDictionary.New()
local removeObjList = BattleList.New()
local curUid
local curBuffId
local curFrame
local playerMP
local enemyMP
local playerAggro
local enemyAggro
local playerSkillUsable
local enemySkillUsable
local isAuto
BattleLogic.IsEnd = false
BattleLogic.Result = -1
BattleLogic.Event = BattleEvent.New()
BattleLogic.BuffMgr = BuffManager.New()
local playerTeamDummyRole = {camp = 0, Event = BattleLogic.Event, isTeam = true}
local enemyTeamDummyRole = {camp = 0, Event = BattleLogic.Event, isTeam = true}
local playerTeamSkillList = {}
local enemyTeamSkillList = {}
local playerTeamSkillIndex
local enemyTeamSkillIndex
local fightData
local record
local optionRecord
--是否开启战斗日志
BattleLogic.IsOpenBattleRecord = false
--逻辑帧频
BattleLogic.GameFrameRate = 30
BattleLogic.GameDeltaTime = 1 / BattleLogic.GameFrameRate
--总波次
BattleLogic.TotalOrder = 0
--当前波次
BattleLogic.CurOrder = 0
local maxFrame = BattleLogic.GameFrameRate * 300 --战斗最大用时5分钟超时判负
local actionPool = BattleObjectPool.New(function ()
return { 0, 0 }
end)
local skillPool = BattleObjectPool.New(function ()
return Skill:New()
end)
local tbActionList = BattleList.New()
local rolePool = BattleObjectPool.New(function ()
return RoleLogic.New()
end)
function BattleLogic.Init(data, optionData)
if BattleLogic.IsOpenBattleRecord then
record = {}
end
fightData = data
if optionData then
optionRecord = optionData
else
optionRecord = {}
end
BattleLogic.CurOrder = 0
BattleLogic.TotalOrder = #data.enemyData
BattleLogic.Clear()
curUid = 0
curBuffId = 0
curFrame = 0
playerMP = 0
enemyMP = 0
playerTeamSkillIndex = 1
enemyTeamSkillIndex = 1
playerSkillUsable = true
enemySkillUsable = true
isAuto = true
BattleLogic.Event:ClearEvent()
BattleLogic.BuffMgr:Init()
BattleLogic.IsEnd = false
BattleLogic.Result = -1
end
function BattleLogic.StartOrder()
BattleLogic.CurOrder = BattleLogic.CurOrder + 1
if BattleLogic.CurOrder == 1 then
for i=1, #fightData.playerData do
BattleLogic.AddRole(fightData.playerData[i])
end
for i=1, #fightData.enemyData[BattleLogic.CurOrder] do
BattleLogic.AddRole(fightData.enemyData[BattleLogic.CurOrder][i])
end
for i=1, #playerTeamSkillList do
skillPool:Put(playerTeamSkillList[i])
playerTeamSkillList[i]=nil
end
for i=1, #fightData.playerData.teamSkill do
playerTeamSkillList[i] = skillPool:Get()
playerTeamSkillList[i]:Init(playerTeamDummyRole, fightData.playerData.teamSkill[i])
playerTeamSkillList[i].isTeamSkill = true
end
for i=1, #enemyTeamSkillList do
skillPool:Put(enemyTeamSkillList[i])
enemyTeamSkillList[i]=nil
end
for i=1, #fightData.enemyData[BattleLogic.CurOrder].teamSkill do
enemyTeamSkillList[i] = skillPool:Get()
enemyTeamSkillList[i]:Init(enemyTeamDummyRole, fightData.enemyData[BattleLogic.CurOrder].teamSkill[i])
enemyTeamSkillList[i].isTeamSkill = true
end
else
BattleLogic.ClearOrder()
for i=1, #fightData.enemyData[BattleLogic.CurOrder] do
BattleLogic.AddRole(fightData.enemyData[BattleLogic.CurOrder][i])
end
for i=1, #enemyTeamSkillList do
skillPool:Put(enemyTeamSkillList[i])
enemyTeamSkillList[i]=nil
end
for i=1, #fightData.enemyData[BattleLogic.CurOrder].teamSkill do
enemyTeamSkillList[i] = skillPool:Get()
enemyTeamSkillList[i]:Init(enemyTeamDummyRole, fightData.enemyData[BattleLogic.CurOrder].teamSkill[i])
enemyTeamSkillList[i].isTeamSkill = true
end
end
BattleLogic.InitAggro()
end
function BattleLogic.AddMP(camp, mp)
if camp == 0 then
if #playerTeamSkillList > 0 then
playerMP = min(playerMP + mp, 100)
end
else
if #enemyTeamSkillList > 0 then
enemyMP = min(enemyMP + mp, 100)
end
end
end
function BattleLogic.GetMP(camp)
return camp == 0 and playerMP or enemyMP
end
function BattleLogic.GetAuto()
return isAuto
end
function BattleLogic.GenerateBuffId()
curBuffId = curBuffId + 1
return curBuffId
end
function BattleLogic.AddRole(roleData)
curUid = curUid + 1
local data = rolePool:Get()
data:Init(curUid, roleData)
objList:Add(curUid, data)
if not data.isDead then
BattleLogic.Event:DispatchEvent(BattleEventName.AddRole, data)
end
end
function BattleLogic.InitAggro()
for i=1, objList.size do
if objList.vList[i].camp == 1 then
playerAggro = objList.vList[i]
break
end
end
for i=1, objList.size do
if objList.vList[i].camp == 0 then
enemyAggro = objList.vList[i]
break
end
end
BattleLogic.Event:DispatchEvent(BattleEventName.ZoomChange, playerAggro, 1)
end
function BattleLogic.SetAggro(role)
if role.isTeam then
return
end
if role.camp == 1 then
playerAggro = role
BattleLogic.Event:DispatchEvent(BattleEventName.ZoomChange, role, 1)
else
enemyAggro = role
end
end
function BattleLogic.GetAggro(camp)
if camp == 0 then
if not playerAggro or playerAggro.isDead then
for i=1, objList.size do
if objList.vList[i].camp == 1 and not objList.vList[i].isDead then
playerAggro = objList.vList[i]
BattleLogic.SetAggro(playerAggro)
break
end
end
end
return playerAggro
else
if not enemyAggro or enemyAggro.isDead then
for i=1, objList.size do
if objList.vList[i].camp == 0 and not objList.vList[i].isDead then
enemyAggro = objList.vList[i]
BattleLogic.SetAggro(enemyAggro)
break
end
end
end
return enemyAggro
end
end
function BattleLogic.SetSkillUsable(camp, value)
if camp == 0 then
playerSkillUsable = value
else
enemySkillUsable = value
end
end
function BattleLogic.GetSkillUsable(camp)
if camp == 0 then
return playerSkillUsable
else
return enemySkillUsable
end
end
function BattleLogic.WaitForTrigger(delayTime, action)
delayTime = floor(delayTime * 100000 + 0.5) / 100000 --进行精度处理,避免前后端计算不一致
local delayFrame = floor(delayTime * BattleLogic.GameFrameRate + 0.5)
if delayFrame == 0 then --0延迟的回调直接调用
action()
return
end
local item = actionPool:Get()
item[1] = curFrame + delayFrame
item[2] = action
tbActionList:Add(item)
if BattleLogic.IsOpenBattleRecord then
BattleLogic.RecordDelayTrigger(delayTime, curFrame + delayFrame)
end
end
function BattleLogic.AddOption(opType, opArg)
table.insert(optionRecord, {curFrame + 1, opType, opArg})
end
function BattleLogic.GetOption()
return optionRecord
end
function BattleLogic.HasObj(obj)
return obj and objList.kvList[obj.uid]
end
function BattleLogic.CurFrame()
return curFrame
end
function BattleLogic.Query(func)
local list = {}
local index = 1
if func then
for i=1, objList.size do
local v = objList.vList[i]
if func(v) and not v.isDead then
list[index] = v
index = index + 1
end
end
end
return list
end
function BattleLogic.BattleEnd(result)
BattleLogic.IsEnd = true
BattleLogic.Result = result
BattleLogic.Event:DispatchEvent(BattleEventName.BattleEnd, result)
end
function BattleLogic.Clear()
while objList.size > 0 do
objList.vList[objList.size]:Dispose()
removeObjList:Add(objList.vList[objList.size])
objList:Remove(objList.vList[objList.size].uid)
end
while removeObjList.size > 0 do
rolePool:Put(removeObjList.buffer[removeObjList.size])
removeObjList:Remove(removeObjList.size)
end
while tbActionList.size > 0 do
actionPool:Put(tbActionList.buffer[tbActionList.size])
tbActionList:Remove(tbActionList.size)
end
end
function BattleLogic.ClearOrder()
local index = 1
while index <= objList.size do
if objList.vList[index].camp == 1 then
BattleLogic.Event:DispatchEvent(BattleEventName.RemoveRole, objList.vList[index])
objList.vList[index]:Dispose()
removeObjList:Add(objList.vList[index])
objList:Remove(objList.vList[index].uid)
else
index = index + 1
end
end
end
function BattleLogic.Update()
curFrame = curFrame + 1
if curFrame > maxFrame then
BattleLogic.BattleEnd(0)
return
end
for i=1, #optionRecord do
if optionRecord[i][1] == curFrame then
local opType = optionRecord[i][2]
local opArg = optionRecord[i][3]
if opType == 1 then --自动手动
isAuto = opArg == 1
for i=1, objList.size do
local tmpObj = objList.vList[i]
if tmpObj.camp == 0 then
tmpObj.Auto = opArg == 1
end
end
elseif opType == 2 then --释放skill
local role = objList.kvList[opArg]
if role and role.skill then
role.skill:Cast()
end
elseif opType == 3 then --释放superSkill
local role = objList.kvList[opArg]
if role and role.superSkill then
role.superSkill:Cast()
end
elseif opType == 4 then --释放teamSkill
local teamSkill = playerTeamSkillList[playerTeamSkillIndex]
if teamSkill then
teamSkill:Cast()
playerTeamSkillIndex = playerTeamSkillIndex + 1
if playerTeamSkillIndex > #playerTeamSkillList then
playerTeamSkillIndex = 1
end
playerMP = 0
end
end
end
end
local index = 1
while index <= tbActionList.size do
local action = tbActionList.buffer[index]
if action[1] <= curFrame then
action[2]()
actionPool:Put(action)
tbActionList:Remove(index)
else
index = index + 1
end
end
if playerMP == 100 and playerSkillUsable and isAuto then
local teamSkill = playerTeamSkillList[playerTeamSkillIndex]
if teamSkill then
teamSkill:Cast()
playerTeamSkillIndex = playerTeamSkillIndex + 1
if playerTeamSkillIndex > #playerTeamSkillList then
playerTeamSkillIndex = 1
end
playerMP = 0
end
end
if enemyMP == 100 and enemySkillUsable then
local teamSkill = enemyTeamSkillList[enemyTeamSkillIndex]
if teamSkill then
teamSkill:Cast()
enemyTeamSkillIndex = enemyTeamSkillIndex + 1
if enemyTeamSkillIndex > #enemyTeamSkillList then
enemyTeamSkillIndex = 1
end
enemyMP = 0
end
end
BattleLogic.BuffMgr:Update()
local bMyAllDead = true
local bEnemyAllDead = true
for i=1, objList.size do
local tmpObj = objList.vList[i]
if not tmpObj.isDead then
tmpObj:Update()
if tmpObj.camp == 0 then
bMyAllDead = false
else
bEnemyAllDead = false
end
end
end
if bMyAllDead then
BattleLogic.BattleEnd(0)
end
if bEnemyAllDead then
if BattleLogic.CurOrder == BattleLogic.TotalOrder then
BattleLogic.BattleEnd(1)
else
BattleLogic.Event:DispatchEvent(BattleEventName.BattleOrderChange, BattleLogic.CurOrder + 1)
BattleLogic.StartOrder()
end
end
end
--Debug专用
function BattleLogic.SetDebug()
for i=1, objList.size do
local v = objList.vList[i]
v.IsDebug = not v.IsDebug
end
end
--Debug专用
function BattleLogic.SetRoleValue(uid, name, value)
if objList.kvList[uid] then
objList.kvList[uid].data:SetValue(name, value)
end
end
--Debug专用
function BattleLogic.SetRoleDebug(uid, isDebug)
if objList.kvList[uid] then
objList.kvList[uid].IsDebug = isDebug
end
end
--Record专用
function BattleLogic.GetRecord()
return record
end
--Record专用
function BattleLogic.RecordSeed(seed)
table.insert(record, string.format("frame:%d, seed:%d", curFrame, seed))
end
--Record专用
function BattleLogic.RecordRoleProperty(uid, camp, name, value, delta)
table.insert(record, string.format("frame:%d, uid:%d, camp:%d, name:%s, value:%d, delta:%d", curFrame, uid, camp, name, value, delta))
end
--Record专用
function BattleLogic.RecordEffect(caster, target, type, args, interval)
local cUid = tostring(caster.uid) or "cTeam"
local tUid = tostring(target.uid) or "tTeam"
local str = ""
for i=1, #args do
str = str..tostring(args[i]) .. (i == #args and "" or "#")
end
table.insert(record, string.format("frame:%d, caster:%s, target:%s, effectType:%d, args:%s, interval:%d", curFrame, cUid, tUid, type, str, interval))
end
--Record专用
function BattleLogic.RecordDelayTrigger(delayFrame, triggerFrame)
table.insert(record, string.format("frame:%d, delayTime:%f, triggerFrame:%d", curFrame, delayFrame, triggerFrame))
end
--Record专用
function BattleLogic.GenerateRecordFile()
local time = string.format("%d-%d-%d-%d-%d-%d",
os.date("%Y"),
os.date("%m"),
os.date("%d"),
os.date("%H"),
os.date("%M"),
os.date("%S"))
local file = io.open("BattleRecord/"..time..".txt", "a")
for i=1, #record do
file:write(record[i].."\n")
end
io.close(file)
end