using System.Collections.Generic; using UnityEngine; using System; using LitJson; using DG.Tweening; public class BattleField { public BattleObjMgr battleObjMgr; public BattleEffectMgr battleEffectMgr; public BattleTweenMgr battleTweenMgr; public RecordPlayer recordPlayer; public IOperationAgent operationAgent; public int round = 0; public string guid = string.Empty;//等于string.Empty的时候代表是StoryBattleField 是主线副本 public int MapID = 0; public int FuncLineID = 0; public float speedRatio = 1.1f; public JsonData extendData; public bool IsBattleFinish { get; protected set; } private bool m_IsPause = false; public bool IsPause { get { return m_IsPause; } set { m_IsPause = value; if (m_IsPause) { PauseGame(); } else { ResumeGame(); } OnBattlePause?.Invoke(m_IsPause); } } public BattleRootNode battleRootNode; private BattleMode battleMode; public event Action ChangeBattleModeEvent; public Action OnBattlePause; protected List redTeamList = null; protected List blueTeamList = null; protected int redTeamIndex = 0; protected int blueTeamIndex = 0; public BattleField(string _guid) { guid = _guid; GameObject go = ResManager.Instance.LoadAsset("Battle/Prefabs", "BattleRootNode"); GameObject battleRootNodeGO = GameObject.Instantiate(go); battleRootNode = battleRootNodeGO.GetComponent(); battleRootNodeGO.name = this.GetType().Name; battleObjMgr = new BattleObjMgr(); battleEffectMgr = new BattleEffectMgr(); battleTweenMgr = new BattleTweenMgr(); recordPlayer = new RecordPlayer(); } public virtual void Init(int _MapID, int _FuncLineID, JsonData _extendData, List _redTeamList, List _blueTeamList) { MapID = _MapID; redTeamList = _redTeamList; blueTeamList = _blueTeamList; FuncLineID = _FuncLineID; extendData = _extendData; redTeamIndex = 0; blueTeamIndex = 0; battleEffectMgr.Init(this); battleTweenMgr.Init(this); recordPlayer.Init(this); if (blueTeamList == null) { battleObjMgr.Init(this, redTeamList[redTeamIndex], null); HaveRest(); } else { battleObjMgr.Init(this, redTeamList[redTeamIndex], blueTeamList[blueTeamIndex]); } battleRootNode.SetBackground(ResManager.Instance.LoadAsset("Texture/FullScreenBg", "mainui_img_277")); SetBattleStartState(); SetSpeedRatio(speedRatio); SetRootNodePosition(); } public void SetSpeedRatio(float ratio) { speedRatio = ratio; battleObjMgr.SetSpeedRatio(ratio); recordPlayer.SetSpeedRatio(ratio); battleEffectMgr.SetSpeedRatio(ratio); battleTweenMgr.SetSpeedRatio(ratio); } protected virtual void SetBattleStartState() { foreach (var obj in battleObjMgr.allBattleObjDict.Values) { obj.layerMgr.SetFront(); } battleRootNode.skillMaskNode.SetActive(false); } // 在Run之前要设置完毕 要创建Agent public void SetBattleMode(BattleMode _battleMode) { battleMode = _battleMode; CreateAgent(); ChangeBattleModeEvent?.Invoke(battleMode); } public BattleMode GetBattleMode() { return battleMode; } public virtual void Release() { battleObjMgr.Release(); battleEffectMgr.Release(); battleTweenMgr.Release(); recordPlayer.Release(); } public virtual void Run() { if (IsPause) return; if (IsRoundReachLimit()) { return; } if (recordPlayer == null || battleObjMgr == null) return; recordPlayer.Run(); battleObjMgr.Run(); if (operationAgent == null) { Debug.LogError("you should SetBattleMode before Run"); return; } operationAgent.Run(); } protected virtual void CreateAgent() { // Hand,//手动战斗 // Auto,//自动战斗 // Record,//战报 switch (battleMode) { case BattleMode.Hand: operationAgent = new HandModeOperationAgent(this); break; case BattleMode.Auto: operationAgent = new AutoModeOperationAgent(this); break; case BattleMode.Record: operationAgent = new RecordModeOperationAgent(this); break; case BattleMode.Stop: operationAgent = new StopModeOperationAgent(this); break; default: operationAgent = new HandModeOperationAgent(this); break; } } public virtual void AutoSetBattleMode() { // 除了主线都是战报 主线的内容在StoryBattleField里 SetBattleMode(BattleMode.Record); } public virtual void PlayRecord(RecordAction recordAction) { recordPlayer.PlayRecord(recordAction); } public virtual void PlayRecord(List recordList) { recordPlayer.PlayRecord(recordList); } public virtual void ResumeGame() { battleObjMgr.ResumeGame(); recordPlayer.ResumeGame(); battleEffectMgr.ResumeGame(); battleTweenMgr.ResumeGame(); } public virtual void PauseGame() { // 怎么通知界面暂停了呢? battleObjMgr.PauseGame(); recordPlayer.PauseGame(); battleEffectMgr.PauseGame(); battleTweenMgr.PauseGame(); } public virtual void TurnFightState(int TurnNum, int State, uint FuncLineID, JsonData extendData) { round = TurnNum; } public virtual void OnTurnFightObjAction(int turnNum, int ObjID) { } public virtual void OnTurnFightState(int turnNum, int State, int FuncLineID, JsonData turnFightStateData) { // 切换回合 // 是每个战斗开始/每个回合的第一个战斗包 // MapID = MapID // MapID; // 自定义地图ID,可用于绑定战斗地图场景功能(如主线关卡、主线boss、爬塔、竞技场等) // FuncLineID; // MapID对应的扩展值,如具体某个关卡等 章节*10000+关卡编号*100+第x波,如第一章,第10关卡的boss值 = 11001 // State; // 0-起始状态标记;1-准备完毕;2-战斗中;3-战斗结束;4-结算奖励;5-结束状态标记 // TurnNum; // 当前轮次 // Len; // Msg; //size = Len + if (State == 4) { //已经结束并结算 OnBattleEnd(turnFightStateData); return; } // 做表现 if (turnNum == 1) { if (State == 2) { Debug.Log("战斗开始"); } } else { Debug.Log("战斗回合 : " + turnNum + ",状态 " + State); } DistributeNextPackage(); // 做一个Action 通知UI翻下牌子 然后结束Action // TurnFightStateAction turnFightStateAction = new TurnFightStateAction(this, turnNum, State, FuncLineID, extendData); // recordPlayer.PlayRecord(turnFightStateAction); } public void ObjInfoRefresh(H0418_tagObjInfoRefresh _refreshInfo) { BattleObject battleObj = battleObjMgr.GetBattleObject((int)_refreshInfo.ObjID); if (null != battleObj) { battleObj.OnObjInfoRefresh(_refreshInfo); } } public void ObjPropertyRefreshView(HB418_tagSCObjPropertyRefreshView vNetData) { } public virtual void OnObjsDead(List deadPackList) { if (deadPackList.Count > 0) { DeathRecordAction recordAction = new DeathRecordAction(this, deadPackList); recordPlayer.ImmediatelyPlay(recordAction); } } public virtual void Destroy() { ForceFinish(); // 销毁全部内容 BattleManager.Instance.DestroyBattleField(this); } public void NPCDisappear(uint[] ObjIDArr) { // 让npc消失 battleObjMgr.DestroyObjIds(ObjIDArr); } public RectTransform GetTeamNode(BattleCamp battleCamp) { if (battleCamp == BattleCamp.Red) { return battleRootNode.redTeamNode; } else { return battleRootNode.blueTeamNode; } } public RectTransform GetTeamNode(BattleCamp battleCamp, BattleObject target) { int index = target.teamHero.positionNum; return GetTeamNode(battleCamp, index); } public RectTransform GetTeamNode(BattleCamp battleCamp, SkillConfig skillConfig) { int index = skillConfig.CastIndexNum - 1; // 技能配置的index是从1开始的,所以要减1 return GetTeamNode(battleCamp, index); } public RectTransform GetTeamNode(BattleCamp battleCamp, int index) { if (index < 0 || index >= battleRootNode.redTeamNodeList.Count) { Debug.LogError($"GetTeamNode: Index {index} is out of range for {battleCamp} camp."); return null; } if (battleCamp == BattleCamp.Red) { return battleRootNode.redTeamNodeList[index].transform as RectTransform; } else { return battleRootNode.blueTeamNodeList[index].transform as RectTransform; } } public bool IsRoundReachLimit() { // return round > xxx; return false; } public void UpdateCanvas(Canvas canvas) { foreach (var obj in battleObjMgr.allBattleObjDict.Values) { obj.layerMgr.UpdateLayer(); } // RendererAdjuster[] adjusters = battleRootNode.GetComponentsInChildren(true); // if (null != adjusters) // { // foreach (var adjuster in adjusters) // { // adjuster.SetParentCanvas(canvas); // } // } } public void StartBattle(Action onMoveComplete) { List blueTeam = battleObjMgr.GetBattleObjList(BattleCamp.Blue); Tween tween = null; foreach (var obj in blueTeam) { obj.heroGo.SetActive(true); obj.motionBase.PlayAnimation(MotionName.run, true); RectTransform trans = obj.heroRectTrans; trans.anchoredPosition = new Vector2(-800, 0); tween = trans.DOAnchorPos(Vector2.zero, 1f).SetEase(Ease.Linear); battleTweenMgr.OnPlayTween(tween); } tween.onComplete = () => { foreach (var obj in blueTeam) { obj.motionBase.PlayAnimation(MotionName.idle, true); } // 播放战斗开始的特效 // var efplayer = battleEffectMgr.PlayEffect(0, BattleConst.BattleStartEffectID, battleRootNode.transform); // efplayer.onDestroy += a => onMoveComplete(); onMoveComplete?.Invoke(); }; } public void OnObjReborn(HB423_tagMCTurnFightObjReborn vNetData) { // 处理复活逻辑 BattleObject battleObj = battleObjMgr.GetBattleObject((int)vNetData.ObjID); if (battleObj != null) { battleObj.OnReborn(vNetData); } else { Debug.LogError($"BattleObject with ID {vNetData.ObjID} not found for reborn."); } } //各个战场没有场景概念,且可以共存,同时存在战场和结算的情况 //内部结算需要处理的逻辑,不含UI protected virtual void OnSettlement(JsonData turnFightStateData) { } //UI结算后回调需要处理的逻辑 public virtual void WhaleFall() { Destroy(); } public virtual void OnBattleEnd(JsonData turnFightStateData) { BattleEndAction battleEndAction = new BattleEndAction(this, turnFightStateData, () => { BattleDebug.LogError(turnFightStateData.ToJson()); // 战场自身的结束逻辑,不含结算等外部逻辑 OnSettlement(turnFightStateData); int winFaction = (int)turnFightStateData["winFaction"]; //获胜阵营: 一般为1或者2,当玩家发起的战斗时,如果获胜阵营不等于1代表玩家失败了 if (winFaction == 1) { Debug.LogError(guid + " : 战斗胜利"); // 战斗胜利 } else { // 战斗失败 Debug.LogError(guid + " : 战斗失败"); } IsBattleFinish = true; //提供外部 胜利等奖励显示 if (guid != "") EventBroadcast.Instance.Broadcast(EventName.BATTLE_END, guid, turnFightStateData); }); recordPlayer.PlayRecord(battleEndAction); } public virtual void HaveRest() { // 休息状态 battleEffectMgr.HaveRest(); battleTweenMgr.HaveRest(); recordPlayer.HaveRest(); battleObjMgr.HaveRest(BattleCamp.Red); battleObjMgr.DestroyTeam(BattleCamp.Blue); SetBattleMode(BattleMode.Stop); } public bool IsBattleEnd() { return IsBattleFinish; } public virtual void DistributeNextPackage() { } public void OnRefreshBuff(HB428_tagSCBuffRefresh vNetData) { BattleObject battleObj = battleObjMgr.GetBattleObject((int)vNetData.ObjID); if (null != battleObj) { battleObj.buffMgr.RefreshBuff(vNetData); } else { Debug.LogError($"BattleObject with ID {vNetData.ObjID} not found for buff refresh."); } } protected virtual void SetRootNodePosition() { battleRootNode.imgBackground.rectTransform.anchoredPosition = battleRootNode.bgPos2.anchoredPosition; battleRootNode.battleNode.anchoredPosition = battleRootNode.battleNodePos2.anchoredPosition; } public void ForceFinish() { recordPlayer.HaveRest(); } }