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

579 lines
16 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 skillManualQueue = BattleQueue.New()
local playerTeamDummyRole = {camp = 0, Event = BattleLogic.Event, isTeam = true, curSkill = nil, isDebug = false}
local enemyTeamDummyRole = {camp = 1, Event = BattleLogic.Event, isTeam = true, curSkill = nil, isDebug = false}
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 --战斗最大用时,超时判负
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(maxTime, data, optionData)
if BattleLogic.IsOpenBattleRecord then
record = {}
end
maxFrame = BattleLogic.GameFrameRate * maxTime
fightData = data
if optionData then
optionRecord = optionData
else
optionRecord = {}
end
BattleLogic.CurOrder = 0
BattleLogic.TotalOrder = #data.enemyData
BattleLogic.Clear()
skillManualQueue:Clear()
curUid = 0
curBuffId = 0
curFrame = 0
playerMP = 0
enemyMP = 0
playerTeamDummyRole.isDebug = false
enemyTeamDummyRole.isDebug = false
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], 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], 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], 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.CanManualTeamSkill()
local teamSkill = playerTeamSkillList[playerTeamSkillIndex]
return not isAuto and playerMP == 100 and teamSkill and teamSkill.sp >= teamSkill.spPass
end
function BattleLogic.GetTeamSkillCDPass()
local teamSkill = playerTeamSkillList[playerTeamSkillIndex]
if not teamSkill then
return 1
end
return teamSkill.sp / teamSkill.spPass
end
function BattleLogic.GenerateBuffId()
curBuffId = curBuffId + 1
return curBuffId
end
function BattleLogic.AddRole(roleData)
curUid = curUid + 1
local role = rolePool:Get()
role:Init(curUid, roleData)
objList:Add(curUid, role)
if not role.isDead then
BattleLogic.Event:DispatchEvent(BattleEventName.AddRole, role)
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 = BattleUtil.ErrorCorrection(delayTime)
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.GetTeamSkillCaster(camp)
return camp == 0 and playerTeamDummyRole or enemyTeamDummyRole
end
--执行操作逻辑
function BattleLogic.ExecuteOption(option)
local opType = option[2]
local opArg = option[3]
if opType == 1 then --全局自动手动
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
skillManualQueue:Enqueue(role.skill)
end
elseif opType == 3 then --释放superSkill
local role = objList.kvList[opArg]
if role and role.superSkill then
skillManualQueue:Enqueue(role.superSkill)
end
elseif opType == 4 then --释放teamSkill
BattleLogic.CastTeamSkill(0)
elseif opType == 5 then --设置teamSkill自动手动
isAuto = opArg == 1
elseif opType == 6 then --切换单个角色自动手动 arg == uid * 10 + auto(0手动1自动)
local auto = opArg % 10
local uid = floor(opArg / 10)
if objList.kvList[uid] then
objList.kvList[uid].Auto = auto == 1
end
end
end
function BattleLogic.HasObj(obj)
return obj and objList.kvList[obj.uid]
end
function BattleLogic.CurFrame()
return curFrame
end
function BattleLogic.Query(func, inCludeDeadRole)
local list = {}
local index = 1
if func then
for i=1, objList.size do
local v = objList.vList[i]
if func(v) and (inCludeDeadRole or 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
BattleLogic.ExecuteOption(optionRecord[i])
end
end
if playerSkillUsable and skillManualQueue.size > 0 then --手动操作的技能进入队列,等待释放
skillManualQueue:Dequeue():Cast()
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
for i=1, #playerTeamSkillList do
playerTeamSkillList[i].sp = min(playerTeamSkillList[i].sp + 1, playerTeamSkillList[i].spPass)
end
for i=1, #enemyTeamSkillList do
enemyTeamSkillList[i].sp = min(enemyTeamSkillList[i].sp + 1, enemyTeamSkillList[i].spPass)
end
if playerMP == 100 and playerSkillUsable and isAuto then
local teamSkill = playerTeamSkillList[playerTeamSkillIndex]
if teamSkill.sp >= teamSkill.spPass then
BattleLogic.CastTeamSkill(0)
end
end
if enemyMP == 100 and enemySkillUsable then
local teamSkill = enemyTeamSkillList[enemyTeamSkillIndex]
if teamSkill.sp >= teamSkill.spPass then
BattleLogic.CastTeamSkill(1)
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
function BattleLogic.ResetTeamSkillCD(camp)
local skill = camp == 0 and playerTeamDummyRole.curSkill or enemyTeamDummyRole.curSkill
if skill then
skill.spPass = floor(skill.cd % 100 * BattleLogic.GameFrameRate)
skill.sp = skill.spPass
end
end
function BattleLogic.CastTeamSkill(camp)
if camp == 0 then
local teamSkill = playerTeamSkillList[playerTeamSkillIndex]
if teamSkill then
teamSkill:Cast()
if playerTeamSkillIndex == #playerTeamSkillList then
playerTeamSkillIndex = 1
else
playerTeamSkillIndex = playerTeamSkillIndex + 1
end
playerMP = 0
end
else
local teamSkill = enemyTeamSkillList[enemyTeamSkillIndex]
if teamSkill then
teamSkill:Cast()
if enemyTeamSkillIndex == #enemyTeamSkillList then
enemyTeamSkillIndex = 1
else
enemyTeamSkillIndex = enemyTeamSkillIndex + 1
end
enemyMP = 0
end
end
end
--Debug专用
function BattleLogic.SetDebug()
for i=1, objList.size do
local v = objList.vList[i]
v.IsDebug = not v.IsDebug
end
playerTeamDummyRole.isDebug = not playerTeamDummyRole.isDebug
enemyTeamDummyRole.isDebug = not enemyTeamDummyRole.isDebug
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.RecordDamage(args)
local str = ""
for i=1, #args do
str = str..tostring(args[i]) .. (i == #args and "" or "#")
end
table.insert(record, string.format("frame:%d, damageArgs:%s", curFrame, str))
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