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;
}
}