using Snxxz.UI; using TableConfig; using UnityEngine; public abstract class GActorNpcFight : GActorFight, IOtherSelectable { protected GameObject m_Model { get; private set; } protected Animator m_Animator { get; private set; } private SFXController m_Shadow; protected DialogueBubble m_DialogAppear; protected DialogueBubble m_DialogTiming; protected float m_LastTalkTime; public NPCConfig NpcConfig { get; private set; } private SFXController m_AppearEffect; private bool m_LoadDefaultRes = false; /// /// 上一次记录不能被攻击旋转的时间 /// protected float m_LastCantAtkedTime; private Vector3 m_BornPos; public virtual Vector3 BornPos { get { return m_BornPos; } set { m_BornPos = value; } } public override int NextAction { get { if (!m_Animator) { return -1; } return m_Animator.GetInteger(GAStaticDefine.Param_Action); } set { if (m_Animator) { if (m_Animator.parameterCount > 0) { m_Animator.SetInteger(GAStaticDefine.Param_Action, value); } } } } public void Init(uint serverInstID, uint clientInstID, uint npcID, E_ActorGroup group, GameNetPackBasic package) { m_LoadDefaultRes = false; NpcConfig = Config.Instance.Get((int)npcID); if (NpcConfig == null) { // 报错 return; } ActorType = GameObjType.gotNPC; // 初始化表现层 GameObject _prefab = InstanceResourcesLoader.LoadNpcPrefab(NpcConfig.NPCID); if (_prefab == null) { if (this is GA_Pet) { _prefab = InstanceResourcesLoader.LoadDefaultPet(); } else { _prefab = InstanceResourcesLoader.LoadDefaultFightNPC(); } if (_prefab) { m_LoadDefaultRes = true; } } if (_prefab) { if (PreFightMission.Instance.IsFinished()) { GAMgr.Instance.AddNeedDestroyPrefab(_prefab); } if (m_LoadDefaultRes) { if (this is GA_Pet) { m_Model = GameObjectPoolManager.Instance.RequestDefaultPet(); } else { m_Model = GameObjectPoolManager.Instance.RequestDefaultFightNpc(); } } else { m_Model = GameObjectPoolManager.Instance.RequestNpcGameObject(NpcConfig.NPCID); } if (m_Model) { SkinnedMeshRenderer _renderer = m_Model.GetComponentInChildren(); if (_renderer) { _renderer.gameObject.layer = LayerUtility.Monster; m_Material = _renderer.material; } m_Animator = m_Model.GetComponent(); if (!m_Animator) { if (m_Model.transform.childCount > 0) { m_Animator = m_Model.transform.GetChild(0).GetComponent(); } } if (m_Animator) { m_Animator.enabled = true; if (m_Animator.parameterCount > 0) { m_Animator.SetInteger(GAStaticDefine.Param_ActorInstID, (int)clientInstID); } IdleImmediate(); } SetupBindNode(m_Model.transform); } } // 执行父类的初始化 Init(serverInstID, clientInstID, group, package); if (m_Model) { m_Model.transform.SetParent(m_Root.transform); m_Model.transform.localPosition = Vector3.zero; m_Model.transform.localRotation = Quaternion.identity; bool _playEffect = true; uint _parentSID = ActorInfo.ownerSID; if (_parentSID != PlayerDatas.Instance.PlayerId) { GA_Player _player = GAMgr.Instance.GetBySID(_parentSID) as GA_Player; if (_player != null) { _playEffect = _player.ShowOrHide; } } if (_playEffect) { if (NpcConfig.NPCEffect != 0) { m_AppearEffect = SFXPlayUtility.Instance.PlayBattleEffect(NpcConfig.NPCEffect, this); EffectConfig _effectConfig = Config.Instance.Get(NpcConfig.NPCEffect); if (_effectConfig != null) { SoundPlayer.Instance.PlayAudio(m_AudioSource, _effectConfig.audio); } } } } Root.gameObject.layer = LayerUtility.Monster; if (CanBeSelected()) { CapsuleCollider _collider = Root.AddMissingComponent(); _collider.center = new Vector3(0, NpcConfig.ModleHeight * .5f, 0); _collider.radius = NpcConfig.ModelRadius; _collider.height = NpcConfig.ModleHeight; } // 影子不依赖于表现层 RequestShadow(); if (NpcConfig.ModeProportion != 1) { Root.localScale = Vector3.one * NpcConfig.ModeProportion; } RequestDialogueBubble(); GAStaticDefine.NPCLocation _npcLocation; if (GAStaticDefine.TryGetMapNPCLocation(NpcConfig.NPCID, out _npcLocation)) { if (_npcLocation.face != 0) { Rotation = MathUtility.GetClientRotationFromAngle(_npcLocation.face); } else { Rotation = Quaternion.Euler(0, Random.Range(0, 360), 0); } } else { Rotation = Quaternion.Euler(0, Random.Range(0, 360), 0); } OnAfterInit(); } protected override void OnUnit() { StatusMgr.Instance.ReleaseActor(ServerInstID); if (!ShowOrHide) { m_Model.transform.localPosition = Vector3.zero; m_Model.transform.localRotation = Quaternion.identity; if (MP_Name != m_Model.transform) { MP_Name.SetParent(m_Model.transform); } if (MP_Hit != m_Model.transform) { MP_Hit.SetParent(m_Model.transform); } if (MP_Stun != m_Model.transform) { MP_Stun.SetParent(m_Model.transform); } } if (m_LoadDefaultRes) { GameObjectPoolManager.Instance.ReleaseDefaultFightNPC(m_Model); } else { GameObject _prefab = InstanceResourcesLoader.LoadNpc(NpcConfig.NPCID); GameObjectPoolManager.Instance.ReleaseGameObject(_prefab, m_Model); } m_Model = null; if (m_Animator) { NextAction = 0; m_Animator.enabled = false; m_Animator = null; } ReleaseShadow(); ReleaseName(); ReleaseLifeBar(); ReleaseDialogueBubble(); if (m_AppearEffect) { SFXPlayUtility.Instance.Release(m_AppearEffect); m_AppearEffect = null; } base.OnUnit(); } public override void Destroy() { } public sealed override void SetAnimatorSpeed(float speed) { if (m_Animator) { m_Animator.speed = speed; //if (this is GA_NpcSummonFight) //{ // Debug.LogFormat("设置了动画速度: {0}", speed); //} } } public sealed override void Play(int stateNameHash, float normalizeTime = 0) { if (m_Animator) { if (m_Animator.HasState(0, stateNameHash)) { m_Animator.Play(stateNameHash, 0, normalizeTime); } } } public override void Idle() { NextAction = GAStaticDefine.Act_Idle; } public override void IdleImmediate() { if (m_Animator) { Idle(); if (m_Animator.HasState(0, GAStaticDefine.State_IdleHash)) { m_Animator.Play(GAStaticDefine.State_IdleHash); } //Debug.LogFormat("调用了 {0} 的立即站立", ServerInstID); } } public override void Run() { NextAction = GAStaticDefine.Act_Run; } public override void RunImmediate() { if (m_Animator) { Run(); m_Animator.Play(GAStaticDefine.State_RunHash); } } public override bool IsIdle() { if (m_Animator) { AnimatorStateInfo _stateInfo = m_Animator.GetCurrentAnimatorStateInfo(0); return _stateInfo.shortNameHash == GAStaticDefine.State_IdleHash; } return false; } public override bool IsRun() { if (m_Animator) { AnimatorStateInfo _stateInfo = m_Animator.GetCurrentAnimatorStateInfo(0); return _stateInfo.shortNameHash == GAStaticDefine.State_RunHash; } return false; } public override bool IsHurt() { if (m_Animator) { AnimatorStateInfo _stateInfo = m_Animator.GetCurrentAnimatorStateInfo(0); return _stateInfo.shortNameHash == GAStaticDefine.State_HurtHash; } return false; } public sealed override bool IsStun() { if (m_Animator) { AnimatorStateInfo _stateInfo = m_Animator.GetCurrentAnimatorStateInfo(0); return _stateInfo.shortNameHash == GAStaticDefine.State_StunHash; } return false; } public sealed override void Hurt() { if (m_Animator == null) { return; } if (NextAction == GAStaticDefine.Act_Dead || NextAction == GAStaticDefine.Act_Warn) { return; } m_Animator.Play(GAStaticDefine.State_HurtHash); } public sealed override void HurtDown() { if (m_Animator == null) { return; } if (m_Animator.GetInteger(GAStaticDefine.Param_Action) == GAStaticDefine.Act_Dead || m_Animator.GetInteger(GAStaticDefine.Param_Action) == GAStaticDefine.Act_Warn) { return; } m_Animator.Play(GAStaticDefine.State_HurtDown1Hash); } public override void Die() { if (m_Animator == null) { ReleaseShadow(); StatusMgr.Instance.ReleaseActor(ServerInstID); GAMgr.Instance.Release(this); return; } if (NextAction == GAStaticDefine.Act_Dead) { return; } if (OnDie != null) { OnDie(); } ReleaseDialogueBubble(); if (PlayerDatas.Instance.hero.LockTarget == this) { PlayerDatas.Instance.hero.LockTarget = null; } if (PlayerDatas.Instance.hero.SelectTarget == this) { PlayerDatas.Instance.hero.SelectTarget = null; } ReleaseShadow(); StatusMgr.Instance.ReleaseActor(ServerInstID); NextAction = GAStaticDefine.Act_Dead; Play(GAStaticDefine.State_DeadHash); Dead_4 _dead = m_Animator.GetBehaviour(); if (_dead) { _dead.killServerInstID = KillerServerInstID; _dead.killerPos = KillerPos; } if (this is GA_NpcClientFightBoss || this is GA_NpcFightBoss) { if (m_AudioSource) { if (NpcConfig.Sounds != null) { if (NpcConfig.Sounds.Length > 2) { SoundPlayer.Instance.PlayAudio(m_AudioSource, NpcConfig.Sounds[2]); } } } } #if UNITY_EDITOR string _content = string.Format("调用了 SID: {0}, CID: {1} 的Die方法 ", ServerInstID, ClientInstID); RuntimeLogUtility.AddLog_Red(_content, ServerInstID); #endif } public sealed override void RequestShadow() { ReleaseShadow(); m_Shadow = SFXPlayUtility.Instance.PlayBattleEffect(999999, m_Root); m_Shadow.duration = 0; m_Shadow.transform.localScale = new Vector3((NpcConfig.ModelRadius * 2) / Root.transform.localScale.x, 1, (NpcConfig.ModelRadius * 2) / Root.transform.localScale.z); } public sealed override void ReleaseShadow() { if (m_Shadow) { SFXPlayUtility.Instance.Release(m_Shadow); m_Shadow = null; } } public sealed override bool HasState(int stateHash) { if (m_Animator) { return m_Animator.HasState(0, stateHash); } return false; } public abstract void RequestDialogueBubble(); protected abstract void UpdateTimeDialogueBubble(); public void ReleaseDialogueBubble() { if (m_DialogAppear != null) { NPCDialogueBubble.Recyle(m_DialogAppear); m_DialogAppear = null; } if (m_DialogTiming != null) { NPCDialogueBubble.Recyle(m_DialogTiming); m_DialogTiming = null; } } public override abstract void RequestName(); public override abstract void RequestLifeBar(); public abstract bool CanBeSelected(); public abstract void OnSelect(); public abstract void OnUnSelect(); public abstract void OnClick(); protected virtual void OnAfterInit() { } /// /// 显示或者隐藏表现层 /// /// 显示: true, 隐藏: false public sealed override void ShowOrHideModel(bool showOrHide) { if (ShowOrHide == showOrHide) { return; } if (showOrHide) { if (m_Model) { m_Model.transform.localPosition = Vector3.zero; m_Model.transform.localRotation = Quaternion.identity; GA_Hero _hero = PlayerDatas.Instance.hero; if (_hero != null && _hero.SelectTarget == this) { RequestLifeBar(); } if (MP_Name != m_Model.transform) { MP_Name.SetParent(m_Model.transform); } if (MP_Hit != m_Model.transform) { MP_Hit.SetParent(m_Model.transform); } if (MP_Stun != m_Model.transform) { MP_Stun.SetParent(m_Model.transform); } } RequestShadow(); } else { if (MP_Name != m_Model.transform) { MP_Name.SetParent(Root); } if (MP_Hit != m_Model.transform) { MP_Hit.SetParent(Root); } if (MP_Stun != m_Model.transform) { MP_Stun.SetParent(Root); } if (m_Model) { m_Model.transform.localPosition = Constants.Special_Hide_Position; } ReleaseShadow(); } ShowOrHide = showOrHide; } public void CastSkill(int skillID) { Vector3 _dir = (PlayerDatas.Instance.hero.Pos - Pos).normalized; _dir.y = 0; Forward = _dir; Skill _skill = SkillMgr.Get(skillID); if (_skill.IsValid() == false) { return; } SkillMgr.CastSkill(ServerInstID, skillID); if (_skill.skillInfo.config.CastTime != 0) { Warn_300 _warn300 = m_Animator.GetBehaviour(); if (_warn300) { _warn300.nextSkillID = _skill.id; } m_Animator.speed = 2 / (_skill.skillInfo.config.CastTime * Constants.F_GAMMA); NextAction = 300; m_Animator.Play(GAStaticDefine.State_WarnHash); int _type; int _effectID = -1; SFXController _sfxController = null; WarnEffectController _warnEffectController = null; if (_skill.skillInfo.config.WarnInfo > 99) { _type = _skill.skillInfo.config.WarnInfo / 1000000; _effectID = _skill.skillInfo.config.WarnInfo % 1000000; } else { _type = _skill.skillInfo.config.WarnInfo; } if (_effectID != -1) { _sfxController = SFXPlayUtility.Instance.Play(_effectID, Pos, Vector3.forward); _warnEffectController = _sfxController.GetComponent(); _warnEffectController.Init(10009, _skill.skillInfo.config.CastTime, _skill.skillInfo.config.CastTime); if (_type == 100 || _type == 310) { _warnEffectController.CalculateScale(E_HitTestType.Sector, 1, _skill.skillInfo.config.AtkDist); } else if (_type > 200 && _type < 300) { _warnEffectController.transform.position = Pos; float width = _type % 10; float length = (_type % 100) / 10; SkillHelper.EffectValue _effectValue; if (_skill.skillInfo.effectValue.TryGetValue(2100, out _effectValue)) { length = _effectValue.value1 * .5f; } _dir = MathUtility.ForwardXZ(PlayerDatas.Instance.hero.Pos, Pos); if (_dir == Vector3.zero) { _dir = Forward; } _skill.mainTarget = PlayerDatas.Instance.hero; Vector3 _sourcePos = Pos; _sourcePos.y = 0; Vector3 _targetPos = Pos + Forward * (length * .5f); _targetPos.y = 0; UnityEngine.AI.NavMeshHit _navMeshHit; if (UnityEngine.AI.NavMesh.Raycast(_sourcePos, _targetPos, out _navMeshHit, -1)) { _targetPos = _navMeshHit.position; } _skill.targetPosition = _targetPos; //_skill.targetPosition.y = Pos.y; _warnEffectController.transform.forward = _dir; _warnEffectController.CalculateScale(E_HitTestType.Rect, width, length); } } _skill.SkillPreparing = true; SkillMgr.DoingPrepareSkill = true; } else { if (_skill.skillInfo.config.Skillactmark != 0) { NextAction = _skill.skillInfo.config.Skillactmark; SkillMgr.CastSkill(ServerInstID, skillID); uint hurtValue = 0; byte attackType = 0; AttackHandler.CalculateDamage(this, PlayerDatas.Instance.hero, _skill, 0, ref hurtValue, ref attackType); AttackHandler.HurtObjs _hurtObject = new AttackHandler.HurtObjs { AttackType = attackType, clientInstID = PlayerDatas.Instance.hero.ClientInstID, CurHP = PlayerDatas.Instance.hero.ActorInfo.Hp - hurtValue, CurHPEx = 0, HurtHP = hurtValue, ObjID = PlayerDatas.Instance.hero.ServerInstID, ObjType = (byte)GameObjType.gotPlayer }; _skill.hurtClientList.Add(_hurtObject); } } } public void StartCantAtkedRotate() { m_LastCantAtkedTime = Time.time; } }