Files
Main/Assets/Code/Logic/_Required/Entity/Character/Pet/LocalPet.cs
2025-01-25 04:38:09 +08:00

415 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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