using System; using System.Collections.Generic; using UnityEngine; using DG.Tweening; namespace BF { public class BattleManager : ManagerBase { public BattlePool PoolHelper { get; private set; } private bool battleStart = false; public bool UpdateEnabled { get; private set; } public GameObject BattleRoot { get; private set; } private Vector2 vector2A = Vector2.zero; private Vector2 vector2B = Vector2.zero; private BattleControlHero MainHero; private Camera uiCamera; private Camera battleCamera; private GameObject numberRoot; private RectTransform hpBarRootTransform; private RectTransform skillToastRootTransform; public List AtkUnitsList = new List(); public List DefUnitsList = new List(); public bool IsAutoUpdateNumberRootPosition = false; private Action luaOnPlayFxFunc; private Action luaOnWarningHeroNumChangedFunc; private Action luaOnWarningNumChangedFunc; private HashSet effectHeroWarningSet = new HashSet(); // 包含了玩家的所有预警 private HashSet effectWarningSet = new HashSet(); // 场上显示的预警 private HashSet skillToastSet = new HashSet(); #region override static BattleManager instance; public static BattleManager Create() { BFLog.LogAssert(instance == null, "This method only allows BFMain to call once"); instance = new BattleManager(); return instance; } BattleManager() { } public override void Init() { base.Init(); PoolHelper = new BattlePool(); } public override void Destroy() { base.Destroy(); instance = null; } public override void Update() { base.Update(); if(!UpdateEnabled) { return; } } public override void SetMono(MonoBehaviour mono) { base.SetMono(mono); } #endregion public void InitBattle(Transform sceneNode, Camera uiCamera, Camera battleCamera) { if (ReferenceEquals(BattleRoot, null)) { BattleRoot = new GameObject(BattleConst.BATTLE_ROOT_NAME); } BattleRoot.transform.SetParent(sceneNode, false); PoolHelper.SetSceneNode(BattleRoot.transform); PoolHelper.Init(); this.uiCamera = uiCamera; this.battleCamera = battleCamera; BattleConfigure.BattleCenterPosX = 0.0f; } public void SetMainHero(BattleControlHero mainHero) { MainHero = mainHero; } public void StartFight() { battleStart = true; UpdateEnabled = true; } public void EndFight() { battleStart = false; UpdateEnabled = false; } public void PauseFight() { UpdateEnabled = false; PoolHelper.Pause(); BattleHelper.Pause(); } public void ResumeFight() { UpdateEnabled = true; PoolHelper.Resume(); BattleHelper.Resume(); } public void SetShadow(GameObject shadow) { PoolHelper.SetShadow(shadow); } public void SetHpBar(GameObject hpBarRoot, GameObject hpAtk, GameObject hpDef) { hpBarRootTransform = hpBarRoot.transform as RectTransform; PoolHelper.SetHpBar(hpAtk, hpDef, hpBarRoot.transform); } public void SetSkillToast(GameObject skillToastRoot, GameObject skillToast) { skillToastRootTransform = skillToastRoot.transform as RectTransform; PoolHelper.SetSkillToast(skillToast, skillToastRoot.transform); } public void ShowNormalSkillToast(string iconName, string str, float x, float y, float z, float addY) { var skillToast = PoolHelper.GetSkillToast(); skillToast.transform.SetAsLastSibling(); skillToast.transform.localScale = new Vector3(1.0f, 1.0f, 1.0f); skillToast.ShowNormalSkillToast(iconName, str); var screenPosition = battleCamera.WorldToScreenPoint(new Vector3(x, y, z)); Vector2 lp; RectTransformUtility.ScreenPointToLocalPointInRectangle(this.skillToastRootTransform.transform as RectTransform, new Vector2(screenPosition.x, screenPosition.y), uiCamera, out lp); var rectTransform = skillToast.transform as RectTransform; rectTransform.anchoredPosition = new Vector2(lp.x, lp.y + addY); skillToastSet.Add(skillToast); } public void ShowLegacySkillToast(string qltName, string iconName, string str, float x, float y, float z, float addY) { var skillToast = PoolHelper.GetSkillToast(); skillToast.transform.SetAsLastSibling(); skillToast.transform.localScale = new Vector3(1.0f, 1.0f, 1.0f); skillToast.ShowLegacySkillToast(qltName, iconName, str); var screenPosition = battleCamera.WorldToScreenPoint(new Vector3(x, y, z)); Vector2 lp; RectTransformUtility.ScreenPointToLocalPointInRectangle(this.skillToastRootTransform.transform as RectTransform, new Vector2(screenPosition.x, screenPosition.y), uiCamera, out lp); var rectTransform = skillToast.transform as RectTransform; rectTransform.anchoredPosition = new Vector2(lp.x, lp.y + addY); skillToastSet.Add(skillToast); } public void RemoveSkillToastSet(BattleSkillToast skillToast) { skillToastSet.Remove(skillToast); } public void SetEffectTextParent(GameObject numberRoot, GameObject effectText, GameObject effectTextRed, GameObject effectTextGreen, GameObject effectTextYellow) { this.numberRoot = numberRoot; PoolHelper.SetEffectText(effectText, effectTextRed, effectTextGreen, effectTextYellow, numberRoot.transform); IsAutoUpdateNumberRootPosition = true; } public void ShowEffectNumber(int colorType, int effectType, string effectNumber, float x, float y, float z, float addY) { var effectText = PoolHelper.GetEffectText(colorType); effectText.transform.localScale = new Vector3(1.0f, 1.0f, 1.0f); effectText.ShowEffectNumber(effectType, effectNumber); var screenPosition = battleCamera.WorldToScreenPoint(new Vector3(x, y, z)); Vector2 lp; RectTransformUtility.ScreenPointToLocalPointInRectangle(this.numberRoot.transform as RectTransform, new Vector2(screenPosition.x, screenPosition.y), uiCamera, out lp); var rectTransform = effectText.transform as RectTransform; rectTransform.anchoredPosition = new Vector2(lp.x, lp.y + addY); } public void UpdateEffectTextRootNode() { if (IsAutoUpdateNumberRootPosition) { numberRoot.transform.localPosition = new Vector3(-BattleConfigure.BattleCenterPosX * BattleConfigure.WorldToScreenWidth, 0.0f, 0.0f); } } public void UpdateUIPosition(Vector3 worldPosition, float addY, RectTransform uiTransform) { var screenPosition = battleCamera.WorldToScreenPoint(worldPosition); Vector2 lp; RectTransformUtility.ScreenPointToLocalPointInRectangle(hpBarRootTransform, new Vector2(screenPosition.x, screenPosition.y), uiCamera, out lp); uiTransform.anchoredPosition = new Vector2(lp.x, lp.y + addY); } public void AddLuaOnPlayFxFunc(Action luaFunc) { luaOnPlayFxFunc = luaFunc; } public void PlayFx(int fxId, int direction, float x, float z) { luaOnPlayFxFunc?.Invoke(fxId, direction, x, z); } public void AddLuaOnWarningHeroNumChangedFunc(Action luaFunc) { luaOnWarningHeroNumChangedFunc = luaFunc; } public void WarningHeroNumChanged(int changedNum, int totalNum) { luaOnWarningHeroNumChangedFunc?.Invoke(changedNum, totalNum); } public void AddEffectHeroWarning(int uniqueId) { var success = effectHeroWarningSet.Add(uniqueId); if (success) { WarningHeroNumChanged(1, GetEffectHeroWarningCount()); } } public void RemoveEffectHeroWarning(int uniqueId) { var success = effectHeroWarningSet.Remove(uniqueId); if (success) { WarningHeroNumChanged(-1, GetEffectHeroWarningCount()); } } public int GetEffectHeroWarningCount() { return effectHeroWarningSet.Count; } public void AddLuaOnWarningNumChangedFunc(Action luaFunc) { luaOnWarningNumChangedFunc = luaFunc; } public void WarningNumChanged(int changedNum, int totalNum) { luaOnWarningNumChangedFunc?.Invoke(changedNum, totalNum); } public void AddEffectWarning(int uniqueId) { var success = effectWarningSet.Add(uniqueId); if (success) { WarningNumChanged(1, GetEffectWarningCount()); } } public void RemoveEffectWarning(int uniqueId) { var success = effectWarningSet.Remove(uniqueId); if (success) { WarningNumChanged(-1, GetEffectWarningCount()); } } public int GetEffectWarningCount() { return effectWarningSet.Count; } public void AddToAtkUnitsList(BattleControlUnit unit) { AtkUnitsList.Add(unit); } public void RemoveFromAtkUnitsList(BattleControlUnit unit) { AtkUnitsList.Remove(unit); } public void AddToDefUnitsList(BattleControlUnit unit) { DefUnitsList.Add(unit); } public void RemoveFromDefUnitsList(BattleControlUnit unit) { DefUnitsList.Remove(unit); } public List GetUnitsList(int side) { if (side == BattleConst.SIDE_ATK) { return DefUnitsList; } else { return AtkUnitsList; } } public int GetDefUnitsCount() { return DefUnitsList.Count; } public BattleControlUnit GetNearestUnit(int side) { BattleControlUnit unit = null; if (side == BattleConst.SIDE_ATK) { var countDef = DefUnitsList.Count; if(countDef <= 0) { return null; } var position = MainHero.transform.position; vector2A.Set(position.x, position.z); float minDis = float.MaxValue; for(int j = 0; j < countDef; j++) { var objB = DefUnitsList[j]; if (!objB.IsCollisionEnabled) { continue; } vector2B.Set(objB.transform.position.x, objB.transform.position.z); var dis = (vector2B - vector2A).sqrMagnitude; if (dis < minDis) { minDis = dis; unit = objB; } } } else { return MainHero; } return unit; } public void GetNearestDefUnit(float x, float z, out BattleControlUnit leftUnit, out BattleControlUnit rightUnit) { leftUnit = null; rightUnit = null; var count = DefUnitsList.Count; if (count <= 0) { return; } float leftMinX = float.MaxValue; float rightMinX = float.MaxValue; float leftDisZ = 0.0f; float rightDisZ = 0.0f; for (int i = 0; i < count; i++) { var defUnit = DefUnitsList[i]; var defX = defUnit.transform.position.x; if (defX >= x) { var diffX = defX - x; if (Mathf.Abs(diffX - rightMinX) < 0.000001f) { var newDisZ = Mathf.Abs(defUnit.transform.position.z - z); if (newDisZ < rightDisZ) { rightMinX = diffX; rightDisZ = newDisZ; rightUnit = defUnit; } } else if (diffX < rightMinX) { rightMinX = diffX; rightDisZ = Mathf.Abs(defUnit.transform.position.z - z); rightUnit = defUnit; } } else { var diffX = x - defX; if (Mathf.Abs(diffX - leftMinX) < 0.000001f) { var newDisZ = Mathf.Abs(defUnit.transform.position.z - z); if (newDisZ < leftDisZ) { leftMinX = diffX; leftDisZ = newDisZ; leftUnit = defUnit; } } else if (diffX < leftMinX) { leftMinX = diffX; leftDisZ = Mathf.Abs(defUnit.transform.position.z - z); leftUnit = defUnit; } } } } public BattleControlUnit GetNearestDefUnitOnCurrDirection(float x, float z, int direction) { BattleControlUnit unit = null; var countDef = DefUnitsList.Count; if(countDef <= 0) { return null; } vector2A.Set(x, z); float minDis = float.MaxValue; if (direction == 1) // 找右边的 { for(int j = 0; j < countDef; j++) { var objB = DefUnitsList[j]; if (objB.transform.position.x >= x) { vector2B.Set(objB.transform.position.x, objB.transform.position.z); var dis = (vector2B - vector2A).sqrMagnitude; if (dis < minDis) { minDis = dis; unit = objB; } } } } else // 找左边的 { for(int j = 0; j < countDef; j++) { var objB = DefUnitsList[j]; if (objB.transform.position.x <= x) { vector2B.Set(objB.transform.position.x, objB.transform.position.z); var dis = (vector2B - vector2A).sqrMagnitude; if (dis < minDis) { minDis = dis; unit = objB; } } } } return unit; } public void Clear() { battleStart = false; UpdateEnabled = false; AtkUnitsList.Clear(); DefUnitsList.Clear(); PoolHelper.Clear(); MainHero = null; luaOnPlayFxFunc = null; luaOnWarningHeroNumChangedFunc = null; effectHeroWarningSet.Clear(); effectWarningSet.Clear(); skillToastSet.Clear(); if (!ReferenceEquals(BattleRoot, null)) { GameObject.Destroy(BattleRoot); BattleRoot = null; } } } }