using System.Collections.Generic; using Thousandto.Cfg.Data; using Thousandto.Code.Center; using Thousandto.Code.Global; using Thousandto.Core.Asset; using UnityEngine; namespace Thousandto.Code.Logic { //主角宠物 public class LocalPet : Pet { #region//私有变量 private AIState _aiState = AIState.Count; private Vector2 _moveTarget2D = Vector2.zero; private DeclareSkill _skillCfg = null; private float _sqrUseDis = 0f; private float _useDis = 0f; //技能CD private float _skillCDTimer = 0f; //当前选择的目标Id private ulong _curSelectedTargetId = 0; //助战宠物id列表 private List<ulong> _assistPetList = new List<ulong>(); //载入助战宠物等待帧数 private int _assistLoadWairFrame = 0; #endregion #region//继承基类 protected override bool OnInitializeAfter(EntityInitInfo baseInfo) { _assistLoadWairFrame = 10; GameCenter.RegFixEventHandle(LogicEventDefine.EID_EVENT_REFRESH_ASSIST_PET, OnAssistPetChanged); return base.OnInitializeAfter(baseInfo); } protected override void OnUninitializeBefore() { UnLoadAssistPet(); base.OnUninitializeBefore(); GameCenter.UnRegFixEventHandle(LogicEventDefine.EID_EVENT_REFRESH_ASSIST_PET, OnAssistPetChanged); } protected override void OnUpdate(float elapsedTime) { if (_skillCDTimer > 0f) { _skillCDTimer -= elapsedTime; } UpdateState(); if(_assistLoadWairFrame > 0) { --_assistLoadWairFrame; if(_assistLoadWairFrame <= 0) { LoadAssistPet(); } } base.OnUpdate(elapsedTime); } public override bool IsLocalPet() { return true; } #endregion #region//私有函数 private bool CheckSkill() { if (_skillCfg != null && _sqrUseDis > 0f) { return true; } _skillCfg = DeclareSkill.Get(PropMoudle.Cfg.Baseskill); if (_skillCfg == null) { return false; } var visCfg = GameCenter.SkillVisualManager.Find(_skillCfg.VisualDef); if (visCfg == null) { _skillCfg = null; return false; } _useDis = CombatUtil.GetSkillFindPathDis(visCfg); _sqrUseDis = _useDis * _useDis; return true; } private bool CanMove() { if (skillManager.IsSkillUseing()) return false; return true; } private void ChangeState(AIState state) { if (_aiState == state) return; OnStateLeave(_aiState); _aiState = state; OnStateEnter(_aiState); } private void UpdateState() { switch (_aiState) { case AIState.Idle: { var lp = GameCenter.GameSceneSystem.GetLocalPlayer(); if (lp != null) { if (!lp.IsDead() && lp.FightState && lp.GetCurSelectedTarget() != null && CheckSkill()) { //主角正在战斗状态 ChangeState(AIState.Fight); } else if (Vector2.SqrMagnitude(Position2d - lp.Position2d) < 1f && CanMove()) { //距离太近,走远一点 var dir = -lp.GetFacingDirection2d(); _moveTarget2D = lp.Position2d + dir.normalized * 2; ChangeState(AIState.Follow); break; } else if (Vector2.SqrMagnitude(Position2d - lp.Position2d) > 9f && CanMove()) { //距离太远,走近一点 var dir = -lp.GetFacingDirection2d(); _moveTarget2D = lp.Position2d + dir.normalized * 2; ChangeState(AIState.Follow); } } } break; case AIState.Follow: { var lp = GameCenter.GameSceneSystem.GetLocalPlayer(); if (lp != null) { if (Vector2.SqrMagnitude(Position2d - lp.Position2d) > 400f) { Stop_Action(false); var dir = -lp.GetFacingDirection2d(); var targetPos = lp.Position2d + dir.normalized * 2; if (Scene.navigator.IsBlocked(targetPos)) { RayCastToGroundXOZ(lp.Position2d); } else { RayCastToGroundXOZ(targetPos); } //与玩家的距离超过了20米,直接瞬移 NetHandler.SendMessage_PetJumpBlock(Position2d.x, Position2d.y); } else if (!lp.IsDead() && lp.FightState && lp.GetCurSelectedTarget() != null && CheckSkill()) { //主角正在战斗状态 ChangeState(AIState.Fight); } else if (CanMove()) { if (!IsMoving()) { if (Vector2.SqrMagnitude(Position2d - lp.Position2d) > 9f) { //距离太远,走近一点 var dir = -lp.GetFacingDirection2d(); _moveTarget2D = lp.Position2d + dir.normalized * 2; Action_MoveTo(new Vector3(_moveTarget2D.x, 0f, _moveTarget2D.y), 0.5f); } else { ChangeState(AIState.Idle); } } else { //如果快到目标点了计算是否继续移动,主要为了防止宠物行走卡顿 var moveState = Fsm.CurrentState as PathMove; if (moveState != null) { if (Vector2.SqrMagnitude(Position2d - moveState.CurPathTarget) <= 1f && Vector2.SqrMagnitude(Position2d - lp.Position2d) > 9f) { //距离太远,走近一点 var dir = -lp.GetFacingDirection2d(); _moveTarget2D = lp.Position2d + dir.normalized * 2; Action_MoveTo(new Vector3(_moveTarget2D.x, 0f, _moveTarget2D.y), 0.5f); } } } } } } break; case AIState.Fight: { var lp = GameCenter.GameSceneSystem.GetLocalPlayer(); if (lp != null) { if (!lp.FightState || lp.IsDead()) { ChangeState(AIState.Idle); } else if (!skillManager.IsSkillUseing()) { //查找主目标 var target = lp.GetCurSelectedTarget(); if (target != null && CombatUtil.CanAttackTarget(lp, target, false)) { SetCurSelectedTargetId(target.ID); //判断是否在技能范围内 if (Vector2.SqrMagnitude(Position2d - target.Position2d) > _sqrUseDis) { //不在范围 if (!IsMoving() && CanMove()) { Action_MoveTo(target.Position, _useDis * 0.9f); } } else { if (!IsMoving()) { if (_skillCDTimer <= 0f) { //使用技能 skillManager.LocalPetUseSkill(_skillCfg); _skillCDTimer = _skillCfg.Cd / 1000f; } } else if (!target.IsMoving()) { //如果目标没有移动了,停止移动 Stop_Action(true); } } } else if (Vector2.SqrMagnitude(Position2d - lp.Position2d) > 9f && CanMove() && !IsMoving()) { //跟随一下 var dir = -lp.GetFacingDirection2d(); _moveTarget2D = lp.Position2d + dir.normalized * 2; Action_MoveTo(new Vector3(_moveTarget2D.x, 0f, _moveTarget2D.y), 0.5f); } } } } break; case AIState.Count: { ChangeState(AIState.Idle); } break; } } private void OnStateEnter(AIState state) { switch (state) { case AIState.Idle: { } break; case AIState.Follow: { Action_MoveTo(new Vector3(_moveTarget2D.x, 0f, _moveTarget2D.y), 0.5f); } break; case AIState.Fight: { } break; } } private void OnStateLeave(AIState state) { switch (state) { case AIState.Idle: { } break; case AIState.Follow: { } break; case AIState.Fight: { } break; case AIState.Count: { } break; } } #endregion #region//目标选择 //获取当前目标 public Character GetCurSelectedTarget() { if (_curSelectedTargetId == 0 || Scene == null) { return null; } Character target = Scene.Find<Character>(_curSelectedTargetId); return target; } //设置当前目标, //当id==0是表示取消选择目标,id!=0但是没有找到目标的情况下不做任何操作 public bool SetCurSelectedTargetId(ulong id, bool isAuto = true) { if (id == 0) { _curSelectedTargetId = 0; return true; } else { Character newTarget = Scene.Find<Character>(id); //重复选择 if (id == _curSelectedTargetId || Scene == null) { return true; } if (newTarget != null && !newTarget.IsDead() && newTarget.CanBeSelect) { _curSelectedTargetId = id; return true; } } return false; } public void UpdateTarget() { //如果当前有选择的目标ID但是查找不到目标对象,丢失目标 if (_curSelectedTargetId > 0) { Character target = GetCurSelectedTarget(); if (target == null || target.IsDead() || !target.CanBeSelect) { SetCurSelectedTargetId(0); } } } #endregion #region//助战宠物 //助战宠物列表改变 private void OnAssistPetChanged(object obj, object sender) { LoadAssistPet(); } //排序 private int AssistRank(DeclarePet left, DeclarePet right) { return left.FllowRank.CompareTo(right.FllowRank); } //载入助战宠物 public void LoadAssistPet() { UnLoadAssistPet(); var idList = GameCenter.LuaSystem.Adaptor.GetAssistPetList(); if (idList == null) return; var cfgList = new List<DeclarePet>(); for(int i = 0; i < idList.Length; ++i) { cfgList.Add(DeclarePet.Get((int)idList[i])); } cfgList.Sort(AssistRank); Entity fllowEntity = this; for(int i = 0; i < cfgList.Count; ++i) { var petInfo = new AssistPetInitInfo(cfgList[i], fllowEntity); GameCenter.GameSceneSystem.RefreshAssistPet(petInfo); var newPet = GameCenter.GameSceneSystem.FindEntity<Entity>(petInfo.ID); if(newPet != null) { fllowEntity = newPet; _assistPetList.Add(petInfo.ID); } } } //协助助战宠物 public void UnLoadAssistPet() { for(int i = 0; i < _assistPetList.Count; ++i) { GameCenter.GameSceneSystem.RemoveRemoteEntity(_assistPetList[i]); } _assistPetList.Clear(); } #endregion #region//私有类 private enum AIState { Idle, Follow, Fight, Count, } #endregion } }