415 lines
16 KiB
C#
415 lines
16 KiB
C#
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
|
||
}
|
||
}
|