miduo_client/Assets/ManagedResources/~Lua/Modules/Battle/Logic/BattleLogic.lua

623 lines
21 KiB
Lua
Raw Normal View History

require("Modules.Battle.Logic.HardStageCondition")
require("Modules.Battle.Logic.HardStageEventManager")
2021-04-20 13:58:00 +08:00
BattleLogic = {}
2020-05-09 13:31:21 +08:00
local floor = math.floor
local min = math.min
-- local objList = BattleDictionary.New()
local removeObjList = BattleList.New()
local MaxRound = 20
local CurRound = 0
local CurCamp = 0
local CurSkillPos = {}
local PosList = {}
local curFrame
2020-09-25 12:22:12 +08:00
BattleLogic.Type = -1 -- 0 切磋 1 故事副本 2 地图探索 3 竞技场 4 秘境boss 5 解锁秘境 6 公会战 7 血战 8 兽潮 9巅峰战
2020-05-09 13:31:21 +08:00
BattleLogic.IsEnd = false
BattleLogic.Result = -1
BattleLogic.Event = BattleEvent.New()
BattleLogic.BuffMgr = BuffManager.New()
local _IsDebug
local fightData
local record
local userData
2020-09-25 12:22:12 +08:00
--所有英雄伤害和治疗
local allHeroDamage=0
--所有怪的伤害和治疗
local allEnemyDamage=0
--关卡星级记录
local levelStarRecord
local hardStageId =0
local insertSkillRole=nil
2020-05-09 13:31:21 +08:00
--是否开启战斗日志
BattleLogic.IsOpenBattleRecord = false
--逻辑帧频
BattleLogic.GameFrameRate = 30
BattleLogic.GameDeltaTime = 1 / BattleLogic.GameFrameRate
--总波次
BattleLogic.TotalOrder = 0
--当前波次
BattleLogic.CurOrder = 0
local actionPool = BattleObjectPool.New(function ()
return { 0, 0 }
end)
local tbActionList = BattleList.New()
local rolePool = BattleObjectPool.New(function ()
return RoleLogic.New()
end)
function BattleLogic.Init(data, _userData, maxRound)
2020-05-09 13:31:21 +08:00
if BattleLogic.IsOpenBattleRecord then
record = {}
end
levelStarRecord={}
2020-05-09 13:31:21 +08:00
fightData = data
userData = _userData
hardStageId=data.nodeId
insertSkillRole=nil
2020-05-09 13:31:21 +08:00
BattleLogic.CurOrder = 0
BattleLogic.TotalOrder = #data.enemyData
BattleLogic.Clear()
curFrame = 0
CurRound = 0
MaxRound = maxRound or 20
2020-09-25 12:22:12 +08:00
allHeroDamage= 0
allEnemyDamage= 0
2020-05-09 13:31:21 +08:00
_IsDebug = false
BattleLogic.Event:ClearEvent()
BattleLogic.BuffMgr:Init()
BattleLogic.IsEnd = false
BattleLogic.Result = -1
-- 日志管理放到前面初始化
BattleLogManager.Init(fightData, userData, maxRound)
2020-05-09 13:31:21 +08:00
MonsterManager.Init()
2020-05-09 13:31:21 +08:00
RoleManager.Init()
SkillManager.Init()
2020-05-25 19:16:23 +08:00
OutDataManager.Init(fightData)
PassiveManager.Init()
HardStageEventManager.Init()
-- 监听英雄受到治疗
BattleLogic.Event:AddEvent(BattleEventName.RoleBeTreated,function (castRole, realTreat, treat)
--巅峰争霸赛和切磋超时改为只判断总伤害,不再判断总治疗
-- if castRole.camp==0 then
-- allHeroDamage=allHeroDamage+treat
-- else
-- allEnemyDamage=allEnemyDamage+treat
-- end
end)
2020-09-25 12:22:12 +08:00
--监听英雄受到攻击
BattleLogic.Event:AddEvent(BattleEventName.RoleBeDamaged,function (defRole, atkRole, damage, bCrit, finalDmg, damageType, dotType)
--我方阵营总攻击
if atkRole.camp==0 then
allHeroDamage=allHeroDamage+damage
--敌方阵营
else
allEnemyDamage=allEnemyDamage+damage
end
end)
2020-09-25 12:22:12 +08:00
end
--获取是否为pvp战斗
function BattleLogic.GetIsPvP()
if BattleLogic.Type== BATTLE_SERVER_TYPE.TOPFight or
BattleLogic.Type== BATTLE_SERVER_TYPE.Firend or
BattleLogic.Type== BATTLE_SERVER_TYPE.ArenaFight or
BattleLogic.Type== BATTLE_SERVER_TYPE.CarPersonFight or
BattleLogic.Type== BATTLE_SERVER_TYPE.CrossYuxuLunDaoFight or
2021-11-22 12:01:55 +08:00
BattleLogic.Type== BATTLE_SERVER_TYPE.NewArenaFight or
BattleLogic.Type== BATTLE_SERVER_TYPE.LINGMAIMIJING then
return true
end
return false
end
-- 获取双方所有血量
function BattleLogic.GetAllDamage()
return allHeroDamage, allEnemyDamage
end
--获取我方灵兽数据
function BattleLogic.GetPlayerMonsterData()
return fightData.playerData.monsterList
end
--获取精英副本星级记录
function BattleLogic.GetHardLevelStarRecord()
return levelStarRecord
end
2020-07-22 21:24:42 +08:00
-- 检测先手阵营
function BattleLogic.CheckFirstCamp()
-- 默认我方先手
BattleLogic.FirstCamp = 0
-- 数据不存在时,兼容老战斗数据
if not fightData.playerData.firstCamp and not fightData.enemyData[BattleLogic.CurOrder].firstCamp then
return
end
-- 敌方先手
if fightData.playerData.firstCamp == 0 and fightData.enemyData[BattleLogic.CurOrder].firstCamp == 1 then
BattleLogic.FirstCamp = 1
end
end
function BattleLogic.InitOrder()
2020-05-09 13:31:21 +08:00
BattleLogic.CurOrder = BattleLogic.CurOrder + 1
if BattleLogic.CurOrder == 1 then
local playerData = fightData.playerData
local enemyData = fightData.enemyData[BattleLogic.CurOrder]
for i=1, #playerData do
RoleManager.AddRole(playerData[i], playerData[i].position)
end
for i=1, #enemyData do
RoleManager.AddRole(enemyData[i], enemyData[i].position)
end
local playerMonsterList = fightData.playerData.monsterList
if playerMonsterList then
for i=1, #playerMonsterList do
MonsterManager.AddMonster(playerMonsterList[i])
end
end
local enemyMonsterList = fightData.enemyData[1].monsterList
if enemyMonsterList then
for i=1, #enemyMonsterList do
MonsterManager.AddMonster(enemyMonsterList[i])
end
end
2020-05-09 13:31:21 +08:00
else
RoleManager.ClearEnemy()
local orderList = fightData.enemyData[BattleLogic.CurOrder]
for i=1, #orderList do
RoleManager.AddRole(orderList[i], orderList[i].position)
end
MonsterManager.ClearEnemy()
local enemyMonsterList = orderList.monsterList
if enemyMonsterList then
for i=1, #enemyMonsterList do
MonsterManager.AddMonster(enemyMonsterList[i])
end
end
2020-05-09 13:31:21 +08:00
end
end
function BattleLogic.StartTurnRound()
BattleLogic.CheckFirstCamp()-- 检测先后手
BattleLogic.TurnRoundNextFrame()-- 开始战斗,延时一帧执行,避免战斗还没开始就释放了技能
BattleLogic.Event:DispatchEvent(BattleEventName.BattleStart)-- 战斗开始
end
function BattleLogic.StartOrder()
BattleLogic.InitOrder()
BattleLogic.StartTurnRound()
2020-05-09 13:31:21 +08:00
end
-- 获取当前轮数
function BattleLogic.GetCurRound()
-- body
return CurRound, MaxRound
end
-- 获取当前轮次信息
function BattleLogic.GetCurTurn()
-- body
return CurCamp, CurSkillPos[CurCamp]
end
2020-05-09 13:31:21 +08:00
-- 设置是否是debug
function BattleLogic.SetIsDebug(isDebug)
_IsDebug = isDebug
end
function BattleLogic.GetIsDebug()
return _IsDebug
end
-- 下一帧开始下一轮
local _TurnRoundFlag = 0
function BattleLogic.TurnRoundNextFrame()
_TurnRoundFlag = 0
end
-- 检测是否要轮转
function BattleLogic.CheckTurnRound()
if _TurnRoundFlag == 2 then
return
end
_TurnRoundFlag = _TurnRoundFlag + 1
if _TurnRoundFlag == 2 then
BattleLogic.TurnRound()
end
end
-- 开始轮转
-- debugTurn 用于判断是否是debug轮转的参数
function BattleLogic.TurnRound(debugTurn)
if BattleLogic.GetIsDebug() and not debugTurn then
BattleLogic.Event:DispatchEvent(BattleEventName.DebugStop)
return
end
-- 第一次进入 或者 本轮结束 初始化流程状态
if CurRound == 0 or (CurSkillPos[0] == 6 and CurSkillPos[1] == 6) then
if CurRound ~= 0 then
if BattleLogic.CheckHaveInsertRole() then
return
else
-- 上一轮结束
BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoundEnd, CurRound)
end
end
-- 检测一次灵兽技能
SkillManager.CheckMonsterSkill(function()
CurRound = CurRound + 1
CurCamp = BattleLogic.FirstCamp -- 判断先手阵营
CurSkillPos[0] = 0
CurSkillPos[1] = 0
--
BattleLogManager.Log(
"Round Change",
"round", CurRound
)
-- 轮数变化
BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoundChange, CurRound)
--刷新灵兽buff,回合开始前刷新如果灵兽技能是在回合后释放持续1回合配置的回合数要+1 2020/12/05 by:王振兴
BattleLogic.BuffMgr:PassMonsterUpdate()
-- 开始
BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoundStart, CurRound)
-- 检测一次灵兽技能
SkillManager.CheckMonsterSkill(function()
--轮数变化后延时0.2秒用于初始化监听回合数被动的初始化
BattleLogic.WaitForTrigger(1,function()
-- 进入新轮
BattleLogic.CheckBattleLogic()
end)
end)
2020-10-17 18:35:52 +08:00
end)
2020-05-09 13:31:21 +08:00
else
-- 检测一次灵兽技能
SkillManager.CheckMonsterSkill(function()
--轮数变化后延时0.2秒用于初始化监听回合数被动的初始化
BattleLogic.WaitForTrigger(1,function()
-- 切换阵营
if not insertSkillRole then
CurCamp = (CurCamp + 1) % 2
end
BattleLogic.CheckBattleLogic()
end)
end)
2020-05-09 13:31:21 +08:00
end
2020-10-17 18:35:52 +08:00
end
2020-05-09 13:31:21 +08:00
2020-10-17 18:35:52 +08:00
--检测战斗逻辑
function BattleLogic.CheckBattleLogic()
-- 这里再检测一次战斗结束
if CurRound > MaxRound then
return
end
BattleLogManager.Log(
2020-06-18 20:39:29 +08:00
"Camp Change",
"camp", CurCamp
)
2020-05-09 13:31:21 +08:00
-- 找到下一个释放技能的人
local SkillRole
local lastPos
--如果有插入行动的英雄,就先让插入的英雄行动
if insertSkillRole then
SkillRole =insertSkillRole
insertSkillRole=nil
--记录下正常执行行动的英雄的位置,插入英雄行动完,再按照正常顺序执行
lastPos=CurSkillPos[CurCamp]
CurSkillPos[CurCamp]=SkillRole.position
-- 如果当前位置不能释放技能也需要走buff轮转
BattleLogic.BuffMgr:TurnUpdate(1) -- 计算恢复血量
BattleLogic.BuffMgr:TurnUpdate(2) -- 计算持续伤害(除去流血)
BattleLogic.BuffMgr:TurnUpdate(3) -- 计算持续伤害(流血)
BattleLogic.BuffMgr:TurnUpdate(4) -- 计算其他buff
BattleLogic.BuffMgr:PassUpdate() -- 计算buff轮数
BattleLogic.BuffMgr:PassUpdateNoDead() -- 计算buff不灭
CurSkillPos[CurCamp]=lastPos
end
if not SkillRole then
-- 当前阵营下一释放技能的位置
local cpos = CurSkillPos[CurCamp] + 1
for p = cpos, 6 do
-- 保存当前位置
CurSkillPos[CurCamp] = p
-- 自己阵营中的位置 + 自己阵营的ID * 6 = 自己在PosList中的位置
local role = RoleManager.GetRole(CurCamp, p) --PosList[p + (CurCamp * 6)]
--角色如果被放逐不能行动 by:wangzhenxing 2020/12/23 11:35
if role and not role:IsRealDead() and not role.isExile then
SkillRole = role
break
end
-- 如果当前位置不能释放技能也需要走buff轮转
BattleLogic.BuffMgr:TurnUpdate(1) -- 计算恢复血量
BattleLogic.BuffMgr:TurnUpdate(2) -- 计算持续伤害(除去流血)
BattleLogic.BuffMgr:TurnUpdate(3) -- 计算持续伤害(流血)
BattleLogic.BuffMgr:TurnUpdate(4) -- 计算其他buff
BattleLogic.BuffMgr:PassUpdate() -- 计算buff轮数
BattleLogic.BuffMgr:PassUpdateNoDead() -- 计算buff不灭
2020-05-09 13:31:21 +08:00
end
end
2020-05-09 13:31:21 +08:00
-- 如果找不到下一个人,直接交换阵营
if not SkillRole then
2020-06-18 20:39:29 +08:00
BattleLogManager.Log( "No Skill Position" )
2020-05-09 13:31:21 +08:00
BattleLogic.TurnRoundNextFrame()
return
end
2020-06-18 20:39:29 +08:00
--
BattleLogManager.Log(
"Position Change",
"position", CurSkillPos[CurCamp]
)
2020-05-09 13:31:21 +08:00
-- 行动
SkillRole.Event:DispatchEvent(BattleEventName.RoleTurnStart, SkillRole) -- 开始行动
BattleLogic.Event:DispatchEvent(BattleEventName.RoleTurnStart, SkillRole) -- 开始行动
2020-07-08 21:19:34 +08:00
-- buff计算
BattleLogic.BuffMgr:TurnUpdate(1) -- 计算恢复血量
BattleLogic.BuffMgr:TurnUpdate(2) -- 计算持续伤害(除去流血)
-- 设置行动完成回调
SkillManager.SetTurnRoundFunc(function()
BattleLogic.BuffMgr:TurnUpdate(3) -- 计算持续伤害(流血)
BattleLogic.BuffMgr:TurnUpdate(4) -- 计算其他buff
BattleLogic.BuffMgr:PassUpdate() -- 计算buff轮数
BattleLogic.BuffMgr:PassUpdateNoDead() -- 计算buff不灭
SkillRole.Event:DispatchEvent(BattleEventName.RoleTurnEnd, SkillRole) -- 行动结束
BattleLogic.Event:DispatchEvent(BattleEventName.RoleTurnEnd, SkillRole) -- 开始行动
BattleLogic.TurnRoundNextFrame()
end)
2020-07-08 21:19:34 +08:00
2020-05-09 13:31:21 +08:00
-- 如果角色无法释放技能
if not SkillRole:IsAvailable() -- 角色不能释放技能
or (SkillRole:IsDead() -- 将死状态
and not BattleLogic.BuffMgr:HasBuff(SkillRole,BuffName.NoDead) --将死但没有不死buff
and not SkillManager.HaveMySkill(SkillRole)) -- 也没有要释放的技能
then
SkillManager.CheckTurnRound()
2020-05-09 13:31:21 +08:00
return
end
-- 释放技能后,递归交换阵营
SkillRole:CastSkill()
2020-05-09 13:31:21 +08:00
end
--检测是否有插入得英雄
function BattleLogic.CheckHaveInsertRole()
if insertSkillRole then
local SkillRole=insertSkillRole
insertSkillRole=nil
-- 如果找不到下一个人,直接交换阵营
if not SkillRole then
BattleLogManager.Log( "No Skill Position" )
BattleLogic.TurnRoundNextFrame()
return
end
--
BattleLogManager.Log(
"Position Change",
"position", CurSkillPos[CurCamp]
)
-- 行动
SkillRole.Event:DispatchEvent(BattleEventName.RoleTurnStart, SkillRole) -- 开始行动
BattleLogic.Event:DispatchEvent(BattleEventName.RoleTurnStart, SkillRole) -- 开始行动
-- buff计算
BattleLogic.BuffMgr:TurnUpdate(1) -- 计算恢复血量
BattleLogic.BuffMgr:TurnUpdate(2) -- 计算持续伤害(除去流血)
-- 设置行动完成回调
SkillManager.SetTurnRoundFunc(function()
BattleLogic.BuffMgr:TurnUpdate(3) -- 计算持续伤害(流血)
BattleLogic.BuffMgr:TurnUpdate(4) -- 计算其他buff
BattleLogic.BuffMgr:PassUpdate() -- 计算buff轮数
BattleLogic.BuffMgr:PassUpdateNoDead() -- 计算buff不灭
SkillRole.Event:DispatchEvent(BattleEventName.RoleTurnEnd, SkillRole) -- 行动结束
BattleLogic.Event:DispatchEvent(BattleEventName.RoleTurnEnd, SkillRole) -- 开始行动
BattleLogic.TurnRoundNextFrame()
end)
-- 如果角色无法释放技能
if not SkillRole:IsAvailable() -- 角色不能释放技能
or (SkillRole:IsDead() -- 将死状态
and not BattleLogic.BuffMgr:HasBuff(SkillRole,BuffName.NoDead) --将死但没有不死buff
and not SkillManager.HaveMySkill(SkillRole)) -- 也没有要释放的技能
then
SkillManager.CheckTurnRound()
return
end
-- 释放技能后,递归交换阵营
SkillRole:CastSkill()
return true
else
return false
end
end
2020-05-09 13:31:21 +08:00
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)
end
function BattleLogic.InsertSkillRole(role)
insertSkillRole=role
end
2020-05-09 13:31:21 +08:00
function BattleLogic.CurFrame()
return curFrame
end
function BattleLogic.Update()
curFrame = curFrame + 1
2020-11-20 15:07:08 +08:00
-- 强制退出
if curFrame > BattleMaxFrame then
assert(false, "Battle Time Out !!!")
BattleLogic.BattleEnd(-1)
return
end
2020-05-09 13:31:21 +08:00
local roleResult = RoleManager.GetResult()
if roleResult == 0 then
BattleLogic.BattleEnd(0)
return
end
if CurRound > MaxRound then
2021-01-16 14:41:10 +08:00
if BattleLogic.Type == BATTLE_SERVER_TYPE.TOPFight -- 巅峰赛
or BattleLogic.Type == BATTLE_SERVER_TYPE.Firend
or BattleLogic.Type == BATTLE_SERVER_TYPE.CrossYuxuLunDaoFight
or BattleLogic.Type == BATTLE_SERVER_TYPE.LINGMAIMIJING
or BattleLogic.Type == BATTLE_SERVER_TYPE.CarPersonFight
or BattleLogic.Type == BATTLE_SERVER_TYPE.NewArenaFight then -- 好友切磋
2021-01-16 14:41:10 +08:00
if allHeroDamage>allEnemyDamage then
BattleLogic.BattleEnd(1)
else
BattleLogic.BattleEnd(0)
end
2020-09-25 12:22:12 +08:00
else
BattleLogic.BattleEnd(0)
end
2020-05-09 13:31:21 +08:00
return
end
if roleResult == 1 then
if BattleLogic.CurOrder == BattleLogic.TotalOrder then
BattleLogic.BattleEnd(1)
else
BattleLogic.Event:DispatchEvent(BattleEventName.BattleOrderChange, BattleLogic.CurOrder + 1)
BattleLogic.StartOrder()
end
end
-- 检测帧事件技能命中伤害计算buff生成
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
-- 检测buff
BattleLogic.BuffMgr:Update()
---
-- 检测死亡
if RoleManager.CheckDead() then -- 单独用一帧执行死亡
return
end
-- 检测复活
if RoleManager.CheckRelive() then -- 单独用一帧执行复活
return
end
-- 没有技能释放时再检测轮转
if SkillManager.IsSkillEmpty() then
-- 检测轮转
BattleLogic.CheckTurnRound()
end
2020-05-09 13:31:21 +08:00
-- 技能
SkillManager.Update()
--如果有英雄有可以复活的技能,先执行技能逻辑,最后判断死亡人数 by:王振兴
-- 检测角色状态
RoleManager.Update()
-- 检测灵兽状态
MonsterManager.Update()
2020-05-09 13:31:21 +08:00
end
-- 战斗结束
function BattleLogic.BattleEnd(result)
2020-05-25 19:16:23 +08:00
--
BattleLogic.Event:DispatchEvent(BattleEventName.BeforeBattleEnd, result)
--
2020-05-09 13:31:21 +08:00
BattleLogic.IsEnd = true
BattleLogic.Result = result
BattleLogic.Event:DispatchEvent(BattleEventName.BattleEnd, result)
if hardStageId and hardStageId~=0 then
--获取精英副本 星级信息
local hardStageConfig=ConfigManager.GetConfigData(ConfigName.HardStage,hardStageId)
if hardStageConfig then
if hardStageConfig.ConditionValue then
for i = 1, #hardStageConfig.ConditionValue do
local harConfig = ConfigManager.GetConfigData(ConfigName.HardStageCondition,hardStageConfig.ConditionValue[i])
local v1 = HardStageCondition.CheckCondition(harConfig.ConditionType,harConfig.ConditionValue)
table.insert(levelStarRecord,hardStageConfig.ConditionValue[i])
table.insert(levelStarRecord,v1)
end
end
end
end
-- 打印结果
BattleLogic.LogResult(result)
2020-06-18 20:39:29 +08:00
-- 战斗日志写入
if not BattleLogic.GetIsDebug() then
BattleLogManager.WriteLogToFile()
2020-06-18 20:39:29 +08:00
end
HardStageEventManager.ClearEvent()
2020-05-09 13:31:21 +08:00
end
-- 打印战斗结果
function BattleLogic.LogResult(result)
local allHeroDamage, allEnemyDamage = BattleLogic.GetAllDamage()
local heroHP = {0, 0, 0, 0, 0, 0}
local arr = RoleManager.Query(function (r) return r.camp == 0 end, true)
for i=1, #arr do
local pos = arr[i].position
heroHP[pos] = arr[i]:GetRoleData(RoleDataName.Hp)
end
local enemyHP = {0, 0, 0, 0, 0, 0}
local arr = RoleManager.Query(function (r) return r.camp == 1 end, true)
for i=1, #arr do
local pos = arr[i].position
enemyHP[pos] = arr[i]:GetRoleData(RoleDataName.Hp)
end
BattleLogManager.Log(
"Battle Over!!!!!!!",
"result", result,
"allHeroDamage", allHeroDamage,
"allEnemyDamage", allEnemyDamage,
"duration", BattleLogic.CurFrame() / BattleLogic.GameFrameRate,
"heroHP", BattleLogManager.PrintBattleTable(heroHP),
"enemyHP", BattleLogManager.PrintBattleTable(enemyHP)
)
end
2020-05-09 13:31:21 +08:00
--
function BattleLogic.Clear()
-- 清空角色
RoleManager.Clear()
-- 清空事件
while tbActionList.size > 0 do
actionPool:Put(tbActionList.buffer[tbActionList.size])
tbActionList:Remove(tbActionList.size)
end
2020-06-23 18:36:24 +08:00
end