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

636 lines
19 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 playerSkillUsable
local enemySkillUsable
local isAuto
BattleLogic.Type = 0 --1 故事副本 2 地图探索 3 竞技场 4 秘境boss 5 解锁秘境 6 公会战 7 血战
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 stage --战场分割阶段
local stageFrame1 = 25 * BattleLogic.GameFrameRate --前期转中期的时间点
local stageFrame2 = 40 * BattleLogic.GameFrameRate --中期转后期的时间点
local teamSkillCastTime = {15 * BattleLogic.GameFrameRate,
35 * BattleLogic.GameFrameRate,
55 * BattleLogic.GameFrameRate}
local teamSkillCastIndex
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
stage = 0
playerTeamDummyRole.isDebug = false
enemyTeamDummyRole.isDebug = false
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
stage = 1
teamSkillCastIndex = 1
playerTeamSkillIndex = 1
enemyTeamSkillIndex = 1
curFrame = 0
BattleLogic.Event:DispatchEvent(BattleEventName.BattleStageChange, stage)
if BattleLogic.CurOrder == 1 then
for i=1, #fightData.playerData do
BattleLogic.AddRole(fightData.playerData[i], i)
end
for i=1, #fightData.enemyData[BattleLogic.CurOrder] do
BattleLogic.AddRole(fightData.enemyData[BattleLogic.CurOrder][i], 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], 0)
end
for i=1, #fightData.playerData.teamPassive do
for j=1, #fightData.playerData.teamPassive[i] do
local v = fightData.playerData.teamPassive[i][j]
local id = v[1]
local args = {}
for k = 2, #v do
args[k-1] = v[k]
end
BattleUtil.Passivity[id](playerTeamDummyRole, args)
end
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], 0)
end
for i=1, #fightData.enemyData[BattleLogic.CurOrder].teamPassive do
for j=1, #fightData.enemyData[BattleLogic.CurOrder].teamPassive[i] do
local v = fightData.enemyData[BattleLogic.CurOrder].teamPassive[i][j]
local id = v[1]
local args = {}
for k = 2, #v do
args[k-1] = v[k]
end
BattleUtil.Passivity[id](enemyTeamDummyRole, args)
end
end
else
BattleLogic.ClearOrder()
for i=1, #fightData.enemyData[BattleLogic.CurOrder] do
BattleLogic.AddRole(fightData.enemyData[BattleLogic.CurOrder][i], 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], 0)
end
for i=1, #fightData.enemyData[BattleLogic.CurOrder].teamPassive do
for j=1, #fightData.enemyData[BattleLogic.CurOrder].teamPassive[i] do
local v = fightData.enemyData[BattleLogic.CurOrder].teamPassive[i][j]
local id = v[1]
local args = {}
for k = 2, #v do
args[k-1] = v[k]
end
BattleUtil.Passivity[id](enemyTeamDummyRole, args)
end
end
end
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 teamSkill
end
function BattleLogic.GetTeamSkillCastTime()
if teamSkillCastIndex > #playerTeamSkillList then
return -1
end
return teamSkillCastTime[teamSkillCastIndex] - curFrame
end
function BattleLogic.GenerateBuffId()
curBuffId = curBuffId + 1
return curBuffId
end
function BattleLogic.AddRole(roleData, position)
curUid = curUid + 1
local role = rolePool:Get()
role:Init(curUid, roleData, position)
objList:Add(curUid, role)
if not role.isDead then
BattleLogic.Event:DispatchEvent(BattleEventName.AddRole, role)
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.CurStage()
return stage
end
function BattleLogic.CurStageTime()
local time = 0
if stage == 1 then
time = stageFrame1 - curFrame
elseif stage == 2 then
time = stageFrame2 - curFrame
end
return time
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 > stageFrame1 and stage == 1 then
stage = 2
BattleLogic.Event:DispatchEvent(BattleEventName.BattleStageChange, stage)
end
if curFrame > stageFrame2 and stage == 2 then
stage = 3
BattleLogic.Event:DispatchEvent(BattleEventName.BattleStageChange, stage)
end
if curFrame > teamSkillCastTime[teamSkillCastIndex] then
if playerTeamSkillIndex == teamSkillCastIndex and playerSkillUsable then
if playerTeamSkillList[teamSkillCastIndex] then
playerTeamSkillList[teamSkillCastIndex]:Cast()
playerTeamSkillIndex = playerTeamSkillIndex + 1
end
end
if enemyTeamSkillIndex == teamSkillCastIndex and enemySkillUsable then
if enemyTeamSkillList[teamSkillCastIndex] then
enemyTeamSkillList[teamSkillCastIndex]:Cast()
enemyTeamSkillIndex = enemyTeamSkillIndex + 1
end
end
teamSkillCastIndex = min(teamSkillCastIndex + 1, #teamSkillCastTime)
end
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
local posDic = {3,2,4,1,5}
--对位规则: 1敌方相同对位 2若死亡或不存在选取相邻阵位最近且阵位索引最小的
function BattleLogic.GetAggro(camp, position)
local minNeighbor = 100
local index = 100
local target
local enemyCamp = camp == 0 and 1 or 0
for i=1, objList.size do
if objList.vList[i].camp == enemyCamp and not objList.vList[i].isDead then
if position == objList.vList[i].position then
return objList.vList[i]
else
local neighbor = math.abs(posDic[position] - posDic[objList.vList[i].position])
if neighbor < minNeighbor then
minNeighbor = neighbor
index = objList.vList[i].position
target = objList.vList[i]
elseif neighbor == minNeighbor and objList.vList[i].position < index then
minNeighbor = neighbor
index = objList.vList[i].position
target = objList.vList[i]
end
end
end
end
return target
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