481 lines
13 KiB
Lua
481 lines
13 KiB
Lua
BattleLogic = {}
|
||
|
||
local floor = math.floor
|
||
local min = math.min
|
||
local max = math.min
|
||
local objList = BattleDictionary.New()
|
||
|
||
local curUid
|
||
local curBuffId
|
||
local curFrame
|
||
|
||
local playerMP
|
||
local enemyMP
|
||
|
||
local playerAggro
|
||
local enemyAggro
|
||
|
||
local playerSkillUsable
|
||
local enemySkillUsable
|
||
|
||
BattleLogic.IsEnd = false
|
||
BattleLogic.Result = -1
|
||
BattleLogic.Event = BattleEvent.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
|
||
|
||
BattleLogic.Event:ClearEvent()
|
||
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
|
||
playerMP = min(playerMP + mp, 100)
|
||
else
|
||
enemyMP = min(playerMP + mp, 100)
|
||
end
|
||
end
|
||
|
||
function BattleLogic.GetMP(camp)
|
||
return camp == 0 and playerMP or enemyMP
|
||
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
|
||
end
|
||
|
||
function BattleLogic.SetAggro(role, duration)
|
||
if role.camp == 1 then
|
||
playerAggro = role
|
||
if enemySkillUsable then
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.ZoomChange, role, max(duration/2, 0.3))
|
||
end
|
||
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, 0)
|
||
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, 0)
|
||
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)
|
||
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.RemoveObj(uid)
|
||
local role = objList.kvList[uid]
|
||
if role then
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.RemoveRole, role)
|
||
role:Dispose()
|
||
rolePool:Put(role)
|
||
objList:Remove(uid)
|
||
end
|
||
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
|
||
BattleLogic.RemoveObj(objList.vList[objList.size].uid)
|
||
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.RemoveObj(objList.vList[index].uid)
|
||
else
|
||
index = index + 1
|
||
end
|
||
end
|
||
end
|
||
|
||
local tmpObj, index, bMyAllDead, bEnemyAllDead
|
||
|
||
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 --自动手动
|
||
for i=1, objList.size do
|
||
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
|
||
end
|
||
end
|
||
end
|
||
|
||
index = 1
|
||
while index <= tbActionList.size do
|
||
if tbActionList.buffer[index][1] <= curFrame then
|
||
tbActionList.buffer[index][2]()
|
||
actionPool:Put(tbActionList.buffer[index])
|
||
tbActionList:Remove(index)
|
||
else
|
||
index = index + 1
|
||
end
|
||
end
|
||
|
||
if playerMP == 100 and playerSkillUsable then
|
||
local teamSkill = playerTeamSkillList[playerTeamSkillIndex]
|
||
if teamSkill then
|
||
teamSkill:Cast()
|
||
playerTeamSkillIndex = playerTeamSkillIndex + 1
|
||
if playerTeamSkillIndex > #playerTeamSkillList then
|
||
playerTeamSkillIndex = 1
|
||
end
|
||
end
|
||
playerMP = 0
|
||
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
|
||
end
|
||
enemyMP = 0
|
||
end
|
||
|
||
bMyAllDead = true
|
||
bEnemyAllDead = true
|
||
for i=1, objList.size do
|
||
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.CurOrder = BattleLogic.CurOrder + 1
|
||
BattleLogic.Event:DispatchEvent(BattleEventName.BattleOrderChange, BattleLogic.CurOrder)
|
||
BattleLogic.StartOrder()
|
||
end
|
||
end
|
||
end
|
||
|
||
--Debug专用
|
||
function BattleLogic.SetDebug()
|
||
local v
|
||
for i=1, objList.size do
|
||
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 |