using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; using DG.Tweening.Core; using DG.Tweening.Plugins.Options; using Spine.Unity; using UnityEngine.UI; using System.Linq; public enum BattleCamp { Red, Blue } public enum BattleState { None = 0, Stunned = 1 << 0, Poisoned = 1 << 1, Bleeding = 1 << 2, Silenced = 1 << 3, Frozen = 1 << 4, Burned = 1 << 5 } public class BattleObject { public BattleField battleField; public BattleObjectBuffMgr buffMgr; public int ObjID { get; set; } public BattleCamp Camp { get; protected set; } public TeamHero teamHero { get; protected set; } // public BuffMgr buffMgr; public MotionBase motionBase; public GameObject heroGo { get; private set; } protected Action onDeathAnimationComplete; protected Renderer[] renderers; public Transform effectNode; public BattleObject(BattleField _battleField) { battleField = _battleField; } public virtual void Init(GameObject _heroGo, TeamHero _teamHero, BattleCamp _camp) { heroGo = _heroGo; teamHero = _teamHero; Camp = _camp; motionBase = new MotionBase(); motionBase.Init(heroGo.GetComponentInChildren(true)); motionBase.onAnimationComplete += OnAnimationComplete; buffMgr = new BattleObjectBuffMgr(); buffMgr.Init(this); renderers = heroGo.GetComponentsInChildren(true); } public virtual void Run() { motionBase.Run(); } public virtual void Pause() { motionBase.Pause(); } public virtual void Resume() { motionBase.Resume(); } public virtual void Destroy() { if (heroGo != null) { GameObject.DestroyImmediate(heroGo); heroGo = null; } motionBase.Release(); motionBase = null; teamHero = null; ObjID = 0; motionBase.onAnimationComplete -= OnAnimationComplete; } public void OnObjInfoRefresh(H0418_tagObjInfoRefresh _refreshInfo) { switch ((PlayerDataType)_refreshInfo.RefreshType) { case PlayerDataType.HP: teamHero.curHp = GeneralDefine.GetFactValue(_refreshInfo.Value, _refreshInfo.ValueEx); break; case PlayerDataType.MaxHP: teamHero.maxHp = GeneralDefine.GetFactValue(_refreshInfo.Value, _refreshInfo.ValueEx); break; case PlayerDataType.XP: teamHero.rage = (int)GeneralDefine.GetFactValue(_refreshInfo.Value, _refreshInfo.ValueEx); break; default: Debug.LogError("BattleObject.ObjInfoRefresh 出现意外类型 " + _refreshInfo.RefreshType.ToString()); break; } } // 眩晕 public bool IsStunned() { return teamHero.isStunned; } // 冰冻 public bool IsFrozen() { return teamHero.isFrozen; } // 石化 public bool IsStoned() { return teamHero.isStoned; } // 被沉默 public bool IsSlient() { return teamHero.isSlient; } // 被缴械 public bool IsDisarmed() { return teamHero.isDisarmed; } // 是否无敌 public bool IsInvincable() { return teamHero.isInvinceble; } // 是否死亡 public bool IsDead() { return teamHero.isDead; } // 是否被控住了 public bool IsCrowdControlled() { return IsStunned() || IsStoned() || IsFrozen(); } public virtual bool IsCanCastSkill() { // 被控住 if (IsCrowdControlled()) { return false; } // 被沉默 if (IsSlient()) { return false; } // 看看怒气是否达到释放要求 return teamHero.rage >= 100; } public virtual bool IsCanNormalAttack() { // 被控住 if (IsCrowdControlled()) { return false; } // 缴械 if (IsDisarmed()) { return false; } return true; } public virtual void Hurt(List damageValues, int attackType) { PopDamage(teamHero.curHp, damageValues, attackType); motionBase.PlayAnimation(MotionName.hit, false); // 计算伤害 long totalDamage = 0; foreach (var damage in damageValues) { totalDamage += damage; } // 扣血 teamHero.curHp -= totalDamage; } // 闪避开始 public virtual void OnDodgeBegin() { float pingpongTime = 0.2f; RectTransform rectTrans = heroGo.GetComponent(); var tween = rectTrans.DOAnchorPos(new Vector3(-50, 50, 0), pingpongTime) .SetEase(Ease.OutCubic); battleField.battleTweenMgr.OnPlayTween(tween); } // 闪避结束 public virtual void OnDodgeEnd() { float pingpongTime = 0.2f; RectTransform rectTrans = heroGo.GetComponent(); var tween = rectTrans.DOAnchorPos(Vector3.zero, pingpongTime) .SetEase(Ease.OutCubic); battleField.battleTweenMgr.OnPlayTween(tween); } public virtual void OnDeath(Action _onDeathAnimationComplete) { onDeathAnimationComplete = _onDeathAnimationComplete; motionBase.PlayAnimation(MotionName.dead, false); } protected virtual void OnAnimationComplete(MotionName motionName) { if (motionName == MotionName.dead) { OnDeadAnimationComplete(); onDeathAnimationComplete?.Invoke(); onDeathAnimationComplete = null; } } protected virtual void OnDeadAnimationComplete() { // 或许看看溶解特效? YYL TODO heroGo.SetActive(false); } // 伤害还要看 是否闪避 暴击 and so on 需要有一个DamageType 服务器应该会给 protected virtual void PopDamage(long curHp, List damageValues, int attackType) { // 其实应该通知出去给UI界面解耦 让UI界面自己来显示的 YYL TODO // 播放伤害数字 // 这里可以实现一个伤害数字的弹出效果 // 比如使用一个UI组件来显示伤害数字 foreach (var damage in damageValues) { Debug.Log($"Damage: {damage}"); } EventBroadcast.Instance.Broadcast(EventName.BATTLE_DAMAGE_TAKEN, battleField.guid, this, damageValues); } public RectTransform GetAliasTeamNode() { return battleField.GetTeamNode(Camp); } public RectTransform GetEnemyTeamNode() { return battleField.GetTeamNode(Camp == BattleCamp.Red ? BattleCamp.Blue : BattleCamp.Red); } public BattleCamp GetEnemyCamp() { return Camp == BattleCamp.Red ? BattleCamp.Blue : BattleCamp.Red; } public void HaveRest() { // YYL TODO // 休息状态 // 多一个zzz的一个特效 } #if UNITY_EDITOR_STOP_USING public void EditorRevive() { teamHero.curHp = 100; heroGo.SetActive(true); motionBase.PlayAnimation(MotionName.idle, true); } public List TryAttack(BattleObject obj, SkillConfig skillConfig) { List damageList = new List(); int totalDamage = 100; int damage1 = (int)((float)totalDamage * 0.3f); int damage2 = (int)((float)totalDamage * 0.25f); int damage3 = totalDamage - damage1 - damage2; damageList.Add(damage1); damageList.Add(damage2); damageList.Add(damage3); return damageList; } #endif }