Files
Main/Assets/Code/Logic/_Required/Entity/Character/Pet/LocalPet.cs

415 lines
16 KiB
C#
Raw Normal View History

2025-01-25 04:38:09 +08:00
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
}
}