1220 lines
35 KiB
C#
1220 lines
35 KiB
C#
using Thousandto.Plugins.Common.UniScene;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
|
||
using System.Text;
|
||
//#define DEBUG_LOG
|
||
using UnityEngine;
|
||
using System.IO;
|
||
using Thousandto.Core.Framework;
|
||
using Thousandto.Core.Asset;
|
||
using Thousandto.Core.Base;
|
||
using Thousandto.Core.RootSystem;
|
||
|
||
using Thousandto.Cfg.Data;
|
||
using Thousandto.Code.Center;
|
||
|
||
using Thousandto.Plugins.Common;
|
||
using Thousandto.Code.Global;
|
||
using Thousandto.Core.Support;
|
||
|
||
using PathEditor.Proxy.Plugin;
|
||
using Thousandto.Plugins.PathGrid;
|
||
using Thousandto.Code.Logic.LocalPlayerBT;
|
||
|
||
namespace Thousandto.Code.Logic
|
||
{
|
||
/// <summary>
|
||
/// 角色类
|
||
/// </summary>
|
||
public class Character : Entity
|
||
{
|
||
#region members
|
||
//角色所在场景
|
||
private GameScene _sceneEx = null;
|
||
//模型信息
|
||
private FSkinModel _roleSkin = null;
|
||
//属性模块
|
||
protected BaseProperty _propMoudle = null;
|
||
//
|
||
protected SkillManager _skillManager = null;
|
||
|
||
//死亡信息
|
||
private CharacterDeadInfo _deadDetail = null;
|
||
//状态数据
|
||
protected StateManager _stateManager = null;
|
||
//受击效果计时器,每隔1秒才会执行一次受击特效,闪烁,震动的效果
|
||
protected float _hitEffectTimer = 0.0f;
|
||
protected const float HitEffectTime = 1f;
|
||
|
||
//战斗状态
|
||
private bool _fightState = false;
|
||
//是否显示HUD
|
||
private bool _isShowHUD = false;
|
||
|
||
//是否被屏蔽模型
|
||
protected bool _isShowModel = true;
|
||
#endregion
|
||
|
||
#region //属性接口
|
||
|
||
//主角的战斗状态由服务器处理,其他玩家的战斗状态由客户端模拟计算
|
||
public bool FightState
|
||
{
|
||
get { return _fightState || GameCenter.MapLogicSwitch.HoldFighting; }
|
||
set
|
||
{
|
||
if (_fightState != value)
|
||
{
|
||
_fightState = value;
|
||
OnFightStateChangated(_fightState);
|
||
}
|
||
}
|
||
}
|
||
|
||
public SkillManager skillManager
|
||
{
|
||
get
|
||
{
|
||
return _skillManager;
|
||
}
|
||
}
|
||
|
||
public new GameScene Scene
|
||
{
|
||
get
|
||
{
|
||
if (_sceneEx == null)
|
||
{
|
||
_sceneEx = base.Scene as GameScene;
|
||
}
|
||
return _sceneEx;
|
||
}
|
||
set
|
||
{
|
||
_sceneEx = value;
|
||
base.Scene = value;
|
||
}
|
||
|
||
}
|
||
|
||
//属性模块
|
||
public BaseProperty PropMoudle
|
||
{
|
||
get
|
||
{
|
||
return _propMoudle;
|
||
}
|
||
}
|
||
|
||
public float AnimSpeedScale
|
||
{
|
||
get
|
||
{
|
||
return 1.0f / BodyScale;
|
||
}
|
||
}
|
||
|
||
public virtual float MoveSpeed
|
||
{
|
||
get
|
||
{
|
||
return PropMoudle.MoveSpeed / 100.0f;
|
||
}
|
||
}
|
||
public float AttackSpeed
|
||
{
|
||
get
|
||
{
|
||
return PropMoudle.AttackSpeed / 100.0f;
|
||
}
|
||
}
|
||
|
||
public new FSkinModel Skin
|
||
{
|
||
get
|
||
{
|
||
if (_roleSkin == null)
|
||
{
|
||
_roleSkin = base.Skin as FSkinModel;
|
||
}
|
||
return _roleSkin;
|
||
}
|
||
set
|
||
{
|
||
base.Skin = value;
|
||
_roleSkin = value;
|
||
}
|
||
}
|
||
|
||
//等级
|
||
public int Level
|
||
{
|
||
get
|
||
{
|
||
return (int)PropMoudle.Level;
|
||
}
|
||
}
|
||
//vip等级
|
||
public int VipLevel
|
||
{
|
||
get
|
||
{
|
||
return (int)PropMoudle.VipLevel;
|
||
}
|
||
set
|
||
{
|
||
PropMoudle.VipLevel = (uint)value;
|
||
}
|
||
}
|
||
//vip经验
|
||
public ulong VipExp
|
||
{
|
||
get
|
||
{
|
||
return PropMoudle.VipExp;
|
||
}
|
||
set
|
||
{
|
||
PropMoudle.VipExp = value;
|
||
}
|
||
}
|
||
//当前血量
|
||
public virtual ulong CurHP
|
||
{
|
||
get
|
||
{
|
||
return PropMoudle.CurHP;
|
||
}
|
||
set
|
||
{
|
||
if (PropMoudle.CurHP != value)
|
||
{
|
||
PropMoudle.CurHP = value;
|
||
}
|
||
}
|
||
}
|
||
//最大血量
|
||
public ulong MaxHP
|
||
{
|
||
get
|
||
{
|
||
return (ulong)PropMoudle.MaxHP;
|
||
}
|
||
}
|
||
//血量百分比
|
||
public virtual float HpPercent
|
||
{
|
||
get
|
||
{
|
||
if (IsDead())
|
||
return 0;
|
||
return PropMoudle.HpPercent;
|
||
}
|
||
}
|
||
|
||
//名称
|
||
public String Name
|
||
{
|
||
get
|
||
{
|
||
return PropMoudle.Name;
|
||
}
|
||
}
|
||
|
||
public CharacterDeadInfo DeadDetail
|
||
{
|
||
get
|
||
{
|
||
return _deadDetail;
|
||
}
|
||
set
|
||
{
|
||
_deadDetail = value;
|
||
}
|
||
}
|
||
|
||
public bool InSafeTile
|
||
{
|
||
get
|
||
{
|
||
if (Scene != null && Scene.navigator != null)
|
||
{
|
||
if (Scene.navigator.GetCellType(Position2d) == PathGridType.Safe)
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public bool InBlockTile
|
||
{
|
||
get
|
||
{
|
||
return IsBlocked(Position2d);
|
||
}
|
||
}
|
||
|
||
public StateManager StateManager
|
||
{
|
||
get
|
||
{
|
||
return _stateManager;
|
||
}
|
||
}
|
||
|
||
//是否能被选中
|
||
public virtual bool CanBeSelect
|
||
{
|
||
get
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
|
||
//是否显示选中框
|
||
public virtual bool CanShowSelectUI
|
||
{
|
||
get
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
|
||
//是否显示HUD
|
||
public bool IsShowHUD
|
||
{
|
||
get
|
||
{
|
||
return _isShowHUD;
|
||
}
|
||
}
|
||
|
||
public virtual bool IsShowModel
|
||
{
|
||
get
|
||
{
|
||
return _isShowModel;
|
||
}
|
||
set
|
||
{
|
||
_isShowModel = value;
|
||
if (_isShowModel != Skin.IsActive())
|
||
{
|
||
Skin.SetActive(_isShowModel);
|
||
}
|
||
}
|
||
}
|
||
//是否正在打坐
|
||
public bool IsSitDown
|
||
{
|
||
get
|
||
{
|
||
return Fsm.CurrentState != null && Fsm.CurrentState.StateID == EntityStateID.SitDown;
|
||
}
|
||
}
|
||
//是否正在出生
|
||
public virtual bool IsBorning
|
||
{
|
||
get
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region//初始化和卸载 -- 重写父类函数
|
||
|
||
//创建FSM之前的处理
|
||
protected override bool OnSetupFSMBefore()
|
||
{
|
||
_skillManager = new SkillManager(this);
|
||
_stateManager = new StateManager();
|
||
_stateManager.Initialize(this);
|
||
|
||
ResetDirection();
|
||
|
||
return base.OnSetupFSMBefore();
|
||
}
|
||
|
||
//设置FSM
|
||
protected override bool OnSetupFSM()
|
||
{
|
||
Fsm = new EntityFSM(this);
|
||
Fsm.AddState(new Idle());
|
||
Fsm.AddState(new PathMove());
|
||
Fsm.AddState(new Dead());
|
||
Fsm.AddState(new Collect());
|
||
Fsm.SetDefaultStateId(EntityStateID.Idle);
|
||
Fsm.Init(this);
|
||
return true;
|
||
}
|
||
|
||
//初始化完成
|
||
protected override bool OnInitializeAfter(EntityInitInfo baseInfo)
|
||
{
|
||
RefreshSkinQuality();
|
||
return base.OnInitializeAfter(baseInfo);
|
||
}
|
||
|
||
//卸载之前
|
||
protected override void OnUninitializeBefore()
|
||
{
|
||
base.Scene = null;
|
||
_sceneEx = null;
|
||
GameCenter.BuffSystem.OnCharacterReleased(ID);
|
||
if (_propMoudle != null)
|
||
{
|
||
_propMoudle.Uninitialize();
|
||
}
|
||
ItemDropEffectSystem.Remove(ID);
|
||
GameCenter.WarningFiledManager.RemoveFiled(this);
|
||
base.OnUninitializeBefore();
|
||
|
||
if (_skillManager != null)
|
||
{
|
||
_skillManager.Clear();
|
||
_skillManager = null;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region//心跳更新处理
|
||
//重载更新
|
||
protected override void OnUpdate(float elapsedTime)
|
||
{
|
||
base.OnUpdate(elapsedTime);
|
||
_skillManager.Update(elapsedTime);
|
||
UpdateDeadMsg(elapsedTime);
|
||
UpdateHitEffectTime(elapsedTime);
|
||
//UpdateAnimRate();
|
||
}
|
||
|
||
//更新死亡信息--为了防止死亡效果执行不成功
|
||
protected void UpdateDeadMsg(float dt)
|
||
{
|
||
if (_deadDetail != null && !_deadDetail.IsDid)
|
||
{
|
||
_deadDetail.TimeCounter -= dt;
|
||
if (_deadDetail.TimeCounter <= 0.0f)
|
||
{
|
||
if (Fsm.TryTransTo(EntityStateID.Dead))
|
||
{
|
||
_deadDetail.IsDid = true;
|
||
}
|
||
else
|
||
{
|
||
_deadDetail.TimeCounter = 3f;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//更新被击效果
|
||
protected void UpdateHitEffectTime(float dt)
|
||
{
|
||
if (_hitEffectTimer >= 0)
|
||
_hitEffectTimer -= dt;
|
||
}
|
||
|
||
//更新动作刷新频率
|
||
protected void UpdateAnimRate()
|
||
{
|
||
if (IsLocalPlayer())
|
||
return;
|
||
//10帧刷新一次
|
||
if (Time.frameCount % 5 != 0)
|
||
return;
|
||
var cPos = Scene.SceneCamera.transform.position;
|
||
var sqrDis = Vector3.SqrMagnitude(cPos - Position);
|
||
if (sqrDis <= 900f)
|
||
{
|
||
AnimUpdateRate = 1;
|
||
}
|
||
else if (sqrDis <= 1600f)
|
||
{
|
||
AnimUpdateRate = 3;
|
||
}
|
||
else if (sqrDis <= 2500f)
|
||
{
|
||
AnimUpdateRate = 5;
|
||
}
|
||
else
|
||
{
|
||
AnimUpdateRate = 20;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region //HUD的隐藏和显示
|
||
//载入头顶面板
|
||
public void ShowHUD(bool pushEvent = true)
|
||
{
|
||
_isShowHUD = true;
|
||
if (pushEvent)
|
||
{
|
||
GameCenter.PushFixEvent(LogicEventDefine.EID_UIHUD_ADDHUD, this);
|
||
}
|
||
}
|
||
//删除头顶面板
|
||
public void HideHUD()
|
||
{
|
||
_isShowHUD = false;
|
||
GameCenter.PushFixEvent(LogicEventDefine.EID_UIHUD_REMOVEEHUD, this);
|
||
}
|
||
#endregion
|
||
|
||
#region//判断当前角色处于那种状态 ,是否死亡,是否移动,是否被击等...
|
||
//判断是否死亡
|
||
public virtual bool IsDead()
|
||
{
|
||
if (_deadDetail != null)
|
||
{
|
||
return true;
|
||
}
|
||
|
||
if (IsXState(EntityStateID.Dead))
|
||
{
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
//判断当前是否处于某个状态
|
||
public virtual bool IsXState(EntityStateID state)
|
||
{
|
||
bool retval = false;
|
||
if (Fsm != null)
|
||
{
|
||
retval = Fsm.CurrentState.StateID == state;
|
||
}
|
||
return retval;
|
||
}
|
||
|
||
//判断是否正在移动中
|
||
public virtual bool IsMoving()
|
||
{
|
||
if (IsXState(EntityStateID.DirMove) || IsXState(EntityStateID.PathMove))
|
||
{
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
//判断当前是否正在被击状态
|
||
public virtual bool IsBeHitAway()
|
||
{
|
||
if (IsXState(EntityStateID.BeHitBack) || IsXState(EntityStateID.BeHitFly) || IsXState(EntityStateID.BeHitGrab))
|
||
return true;
|
||
return false;
|
||
}
|
||
#endregion
|
||
|
||
#region//激活转移到某个状态,休闲,被击,移动等...
|
||
|
||
//停止活动,也是休闲状态
|
||
public bool Stop_Action(bool sendStopMove = true)
|
||
{
|
||
if (!IsXState(EntityStateID.Idle))
|
||
{
|
||
return Action_Idle(sendStopMove);
|
||
}
|
||
return false;
|
||
}
|
||
|
||
//强制停止活动,适用于切换地图
|
||
public void ForcedStop_Action()
|
||
{
|
||
IdleData data = StateDateCache.Get<IdleData>(EntityStateID.Idle);
|
||
data.SendStopMoveMsg = false;
|
||
Fsm.TransTo(EntityStateID.Idle, data);
|
||
}
|
||
|
||
//休闲状态
|
||
public bool Action_Idle(bool sendStopMove = true)
|
||
{
|
||
if (!IsTransAble(EntityStateID.Idle))
|
||
return false;
|
||
IdleData data = StateDateCache.Get<IdleData>(EntityStateID.Idle);
|
||
data.SendStopMoveMsg = sendStopMove;
|
||
bool ret = Fsm.TryTransTo(EntityStateID.Idle, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
//普通被击状态
|
||
public bool Action_BeHit(Character attacker, float time, bool canDoDead, string hitAniName)
|
||
{
|
||
if (!IsTransAble(EntityStateID.BeHit))
|
||
return false;
|
||
skillManager.Clear();
|
||
BeHitData data = StateDateCache.Get<BeHitData>(EntityStateID.BeHit);
|
||
data.Time = time;
|
||
data.CanDodead = canDoDead;
|
||
data.Attacker = attacker;
|
||
data.AniName = hitAniName;
|
||
bool ret = Fsm.TryTransTo(EntityStateID.BeHit, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
//被击退的状态
|
||
public bool Action_BeHitBack(Character attacker, Vector2 targetPos, AnimationCurve timecurve, float time, bool canDoDead, string hitAniName)
|
||
{
|
||
if (!IsTransAble(EntityStateID.BeHitBack))
|
||
return false;
|
||
skillManager.Clear();
|
||
BeHitBackData data = StateDateCache.Get<BeHitBackData>(EntityStateID.BeHitBack);
|
||
data.TargetPos = targetPos;
|
||
data.Time = time;
|
||
data.TimeCurve = timecurve;
|
||
data.CanDodead = canDoDead;
|
||
data.Attacker = attacker;
|
||
data.AniName = hitAniName;
|
||
bool ret = Fsm.TryTransTo(EntityStateID.BeHitBack, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
//被击飞的状态
|
||
public bool Action_BeHitFly(Character attacker, Vector2 targetPos, AnimationCurve heightcurve, AnimationCurve timecurve, float flyTime, float lieTime, bool canDoDead)
|
||
{
|
||
if (!IsTransAble(EntityStateID.BeHitFly))
|
||
return false;
|
||
skillManager.Clear();
|
||
BeHitFlyData data = StateDateCache.Get<BeHitFlyData>(EntityStateID.BeHitFly);
|
||
data.TargetPos = targetPos;
|
||
data.HeightCurve = heightcurve;
|
||
data.TimeCurve = timecurve;
|
||
data.FlyTime = flyTime;
|
||
data.LieTime = lieTime;
|
||
data.CanDodead = canDoDead;
|
||
data.Attacker = attacker;
|
||
bool ret = Fsm.TryTransTo(EntityStateID.BeHitFly, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
//被抓的状态
|
||
public bool Action_BeHitGrab(Vector2 targetPos, AnimationCurve timecurve, float time, bool canDoDead)
|
||
{
|
||
if (!IsTransAble(EntityStateID.BeHitGrab))
|
||
return false;
|
||
skillManager.Clear();
|
||
BeHitGrabData data = StateDateCache.Get<BeHitGrabData>(EntityStateID.BeHitGrab);
|
||
data.TargetPos = targetPos;
|
||
data.Time = time;
|
||
data.TimeCurve = timecurve;
|
||
data.CanDodead = canDoDead;
|
||
bool ret = Fsm.TryTransTo(EntityStateID.BeHitGrab, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
//移动到某个方向
|
||
public bool Action_DirMove(Vector2 dir)
|
||
{
|
||
if (!IsTransAble(EntityStateID.DirMove))
|
||
return false;
|
||
|
||
DirMoveData data = StateDateCache.Get<DirMoveData>(EntityStateID.DirMove);
|
||
data.MoveDir = dir.normalized;
|
||
bool ret = Fsm.TryTransTo(EntityStateID.DirMove, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
//移动到目的--一个以目的点为中心的的圆圈
|
||
public bool Action_MoveTo(Vector3 target, float targetRadius, bool sitDown = false)
|
||
{
|
||
Vector3 dummy = target;
|
||
return Action_MoveTo(target, targetRadius, ref dummy, sitDown);
|
||
}
|
||
|
||
//移动到目的点
|
||
public bool Action_MoveTo(Vector3 target, bool sitDown = false)
|
||
{
|
||
Vector3 dummy = target;
|
||
return Action_MoveTo(target, 0, ref dummy, sitDown);
|
||
}
|
||
|
||
//移动到目的--一个以目的点为中心的的圆圈
|
||
public bool Action_MoveTo(Vector3 target, float targetRadius, ref Vector3 modTarget, bool sitDown = false)
|
||
{
|
||
if (!IsTransAble(EntityStateID.PathMove))
|
||
return false;
|
||
|
||
List<Vector2> outPath = null;
|
||
outPath = PathGridSystem.instance.SearchTargetPath(ModelTransform.position, target, targetRadius);
|
||
|
||
if (outPath != null && outPath.Count >= 2)
|
||
{
|
||
PathMoveData data = StateDateCache.Get<PathMoveData>(EntityStateID.PathMove);
|
||
data.Path = outPath;
|
||
data.EndSitDown = sitDown;
|
||
|
||
bool ret = Fsm.TryTransTo(EntityStateID.PathMove, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
else
|
||
{
|
||
if (outPath == null)
|
||
{
|
||
//GameCenter.MsgPromptSystem.ShowPrompt("无法自动寻路,请手动前往");
|
||
}
|
||
else
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
//移动到目的--路径点
|
||
public bool Action_MoveTo(List<Vector2> targetList)
|
||
{
|
||
if (!IsTransAble(EntityStateID.PathMove))
|
||
return false;
|
||
|
||
if (targetList != null && targetList.Count >= 2)
|
||
{
|
||
PathMoveData data = StateDateCache.Get<PathMoveData>(EntityStateID.PathMove);
|
||
data.Path = targetList;
|
||
|
||
bool ret = Fsm.TryTransTo(EntityStateID.PathMove, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
//起跳
|
||
public bool Action_Jump(Vector2 targetPos, float height)
|
||
{
|
||
if (!IsTransAble(EntityStateID.Jump))
|
||
return false;
|
||
|
||
JumpData data = StateDateCache.Get<JumpData>(EntityStateID.Jump);
|
||
data.TargetPos = targetPos;
|
||
data.JumpHeight = height;
|
||
bool ret = Fsm.TryTransTo(EntityStateID.Jump, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
//采集
|
||
public bool Action_Collect(ulong collectID)
|
||
{
|
||
if (!IsTransAble(EntityStateID.Collect))
|
||
return false;
|
||
|
||
CollectData data = StateDateCache.Get<CollectData>(EntityStateID.Collect);
|
||
data.TargetID = collectID;
|
||
bool ret = Fsm.TryTransTo(EntityStateID.Collect, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
//起飞
|
||
public bool Action_MountFlyUp()
|
||
{
|
||
if (!IsTransAble(EntityStateID.MountFlyUp))
|
||
return false;
|
||
|
||
FlyUpData data = StateDateCache.Get<FlyUpData>(EntityStateID.MountFlyUp);
|
||
bool ret = Fsm.TryTransTo(EntityStateID.MountFlyUp, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
//落地
|
||
public bool Action_MountFlyDown(Vector2 targetPos)
|
||
{
|
||
if (!IsTransAble(EntityStateID.MountFlyDown))
|
||
return false;
|
||
|
||
FlyDownData data = StateDateCache.Get<FlyDownData>(EntityStateID.MountFlyDown);
|
||
data.TargetPos = targetPos;
|
||
bool ret = Fsm.TryTransTo(EntityStateID.MountFlyDown, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
//飞行传送
|
||
public bool Action_FlyTeleport(int dataId)
|
||
{
|
||
var cfgData = FlyTeleportDataManager.Find(dataId);
|
||
if (!IsTransAble(EntityStateID.FlyTeleport) || cfgData == null)
|
||
return false;
|
||
|
||
skillManager.Clear();
|
||
FlyTeleportData data = StateDateCache.Get<FlyTeleportData>(EntityStateID.FlyTeleport);
|
||
data.CfgData = cfgData;
|
||
bool ret = Fsm.TryTransTo(EntityStateID.FlyTeleport, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
//翻滚闪避
|
||
public bool Action_RollDodge(Vector2 targetPos)
|
||
{
|
||
if (!IsTransAble(EntityStateID.RollDodge))
|
||
return false;
|
||
|
||
RollDodgeData data = StateDateCache.Get<RollDodgeData>(EntityStateID.RollDodge);
|
||
data.TargetPos = targetPos;
|
||
bool ret = Fsm.TryTransTo(EntityStateID.RollDodge, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
//任务转圈
|
||
public bool Action_TaskBarAround(int iconId)
|
||
{
|
||
if (!IsTransAble(EntityStateID.Collect))
|
||
return false;
|
||
|
||
TaskBarAroundData data = StateDateCache.Get<TaskBarAroundData>(EntityStateID.TaskBarAround);
|
||
data.IconId = iconId;
|
||
bool ret = Fsm.TryTransTo(EntityStateID.TaskBarAround, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
//技能移动
|
||
public bool Action_SkillMove(PlaySelfMoveEventInfo eventInfo, Vector2 stratPos, Vector2 targetPos)
|
||
{
|
||
if (!IsTransAble(EntityStateID.SkillMove))
|
||
return false;
|
||
var data = StateDateCache.Get<SkillMoveData>(EntityStateID.SkillMove);
|
||
data.Info = eventInfo;
|
||
data.StartPos = stratPos;
|
||
data.TargetPos = targetPos;
|
||
bool ret = Fsm.TryTransTo(EntityStateID.SkillMove, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
public bool Action_SitDown(bool isRefresh = false)
|
||
{
|
||
if (!IsTransAble(EntityStateID.SitDown))
|
||
return false;
|
||
|
||
SitDownData data = StateDateCache.Get<SitDownData>(EntityStateID.SitDown);
|
||
data.IsRefreshPlayer = isRefresh;
|
||
bool ret = Fsm.TryTransTo(EntityStateID.SitDown, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
public bool Action_ChuanDaoSitDown()
|
||
{
|
||
if (!IsTransAble(EntityStateID.ChuanDaoSitDown))
|
||
return false;
|
||
ChuanDaoSitDownData data = StateDateCache.Get<ChuanDaoSitDownData>(EntityStateID.ChuanDaoSitDown);
|
||
bool ret = Fsm.TryTransTo(EntityStateID.ChuanDaoSitDown, data);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
//进入地图
|
||
public bool Action_EnterMap()
|
||
{
|
||
if (!IsTransAble(EntityStateID.EnterMap))
|
||
return false;
|
||
bool ret = Fsm.TryTransTo(EntityStateID.EnterMap, null);
|
||
if (ret)
|
||
{
|
||
Fsm.Update(0);
|
||
}
|
||
return ret;
|
||
}
|
||
#endregion
|
||
|
||
#region//其他公共接口
|
||
//获取伤害数字跳起的位置
|
||
public Vector3 GetDamageNumberPos()
|
||
{
|
||
//if (!Skin.IsActive())
|
||
//{
|
||
// var pos = Position;
|
||
// pos.y += 1.5f;
|
||
// return pos;
|
||
//}
|
||
//if (ModelTransform != null)
|
||
//{
|
||
// Vector3 ret = ModelTransform.position;
|
||
// if (Skin.GetHeight() > 0)
|
||
// {
|
||
// ret.y += Skin.GetHeight() / 2f;
|
||
// return ret;
|
||
// }
|
||
//}
|
||
return Position + Vector3.up * 1.5f;
|
||
}
|
||
|
||
//获取模型顶部的位置,根据角色控制器的高度来决定
|
||
public Vector3 GetModelTopPos()
|
||
{
|
||
if (!_roleSkin.IsActive())
|
||
{
|
||
var pos = Position;
|
||
pos.y += 1.5f;
|
||
return pos;
|
||
}
|
||
if (_roleSkin.RealTransform != null)
|
||
{
|
||
Vector3 ret = _roleSkin.RealTransform.position;
|
||
var h = _roleSkin.GetHeight();
|
||
if (h > 0)
|
||
{
|
||
ret.y += h + 0.1f;
|
||
}
|
||
return ret;
|
||
}
|
||
return Vector3.zero;
|
||
}
|
||
|
||
//获取模型中间的位置,根据角色控制器的高度来决定
|
||
public Vector3 GetModelCenterPos()
|
||
{
|
||
if (!_roleSkin.IsActive())
|
||
{
|
||
var pos = Position;
|
||
pos.y += 0.75f;
|
||
return pos;
|
||
}
|
||
if (_roleSkin.RealTransform != null)
|
||
{
|
||
Vector3 ret = _roleSkin.RealTransform.position;
|
||
var h = _roleSkin.GetHeight();
|
||
if (h > 0)
|
||
{
|
||
ret.y += h / 2.0f;
|
||
}
|
||
return ret;
|
||
}
|
||
return Vector3.zero;
|
||
}
|
||
|
||
//获取身体模型顶部位置
|
||
public Vector3 GetBodyModelTopPos()
|
||
{
|
||
if (!_roleSkin.IsActive())
|
||
{
|
||
var pos = Position;
|
||
pos.y += 1.5f;
|
||
return pos;
|
||
}
|
||
var body = _roleSkin.GetSkinPart(FSkinPartCode.Body);
|
||
if (body != null && body.RealTransform != null)
|
||
{
|
||
var pos = body.RealTransform.position;
|
||
var h = body.GetHeight();
|
||
if (_roleSkin.SkinPartIsValid(FSkinPartCode.Mount))
|
||
{
|
||
pos.y += (h / 2f) + 0.1f;
|
||
}
|
||
else
|
||
{
|
||
pos.y += h + 0.1f;
|
||
}
|
||
return pos;
|
||
}
|
||
return GetModelTopPos();
|
||
}
|
||
|
||
//获取身体模型中间的位置
|
||
public Vector3 GetBodyModelCenterPos()
|
||
{
|
||
if (!_roleSkin.IsActive())
|
||
{
|
||
var pos = Position;
|
||
pos.y += 0.75f;
|
||
return pos;
|
||
}
|
||
var body = _roleSkin.GetSkinPart(FSkinPartCode.Body);
|
||
if (body != null && body.RealTransform != null)
|
||
{
|
||
var pos = body.RealTransform.position;
|
||
if (!_roleSkin.SkinPartIsValid(FSkinPartCode.Mount))
|
||
{
|
||
pos.y += body.GetHeight() / 2f;
|
||
}
|
||
return pos;
|
||
}
|
||
return GetModelTopPos();
|
||
}
|
||
|
||
//初始化角色开始姿势
|
||
public void InitStartPose(float startX, float startZ, float endX, float endZ)
|
||
{
|
||
InitStartPose(new Vector2(startX, startZ), new Vector2(endX, endZ));
|
||
}
|
||
//初始化角色开始姿势
|
||
public void InitStartPose(float startX, float startZ, ref List<Vector2> pathList)
|
||
{
|
||
RayCastToGroundXOZ(new Vector2(startX, startZ));
|
||
if (pathList != null && pathList.Count >= 2)
|
||
{
|
||
Action_MoveTo(pathList);
|
||
}
|
||
}
|
||
//初始化角色开始姿势
|
||
public void InitStartPose(Vector2 start, Vector2 end)
|
||
{
|
||
RayCastToGroundXOZ(start);
|
||
if (end.x != 0 && end.y != 0)
|
||
{
|
||
Action_MoveTo(new Vector3(end.x, 0, end.y));
|
||
}
|
||
}
|
||
|
||
//刷新skin品质
|
||
public void RefreshSkinQuality()
|
||
{
|
||
if (IsLocalPlayer())
|
||
{
|
||
var setCode = GameCenter.GameSetting.GetSetting(GameSettingKeyCode.LocalBonesCount);
|
||
switch (setCode)
|
||
{
|
||
case 2:
|
||
SkinQuality = SkinQuality.Bone2;
|
||
break;
|
||
case 4:
|
||
SkinQuality = SkinQuality.Bone4;
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
var setCode = GameCenter.GameSetting.GetSetting(GameSettingKeyCode.OtherBonesCount);
|
||
switch (setCode)
|
||
{
|
||
case 1:
|
||
SkinQuality = SkinQuality.Bone1;
|
||
break;
|
||
case 2:
|
||
SkinQuality = SkinQuality.Bone2;
|
||
break;
|
||
case 4:
|
||
SkinQuality = SkinQuality.Bone4;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region//重写父类的一些处理 ---- 播放动作等
|
||
//播放
|
||
protected override bool OnPlayAnim(string anim, AnimationPartType partType = AnimationPartType.AllBody, WrapMode wrapMode = WrapMode.Default, bool isCrossFade = true, float crossFadeTime = 0.2f, float speed = 1f, float normalizedTime = 0.0f)
|
||
{
|
||
return Skin.PlayAnim(anim, partType, wrapMode, isCrossFade, crossFadeTime, speed, normalizedTime);
|
||
}
|
||
#endregion
|
||
|
||
#region//一些普通方法 和 一些需要被回调的处理 --虚函数, 子类可以继承重写
|
||
//是否是主角
|
||
public virtual bool IsLocalPlayer()
|
||
{
|
||
return false;
|
||
}
|
||
//是否是主角宠物
|
||
public virtual bool IsLocalPet()
|
||
{
|
||
return false;
|
||
}
|
||
//是否是主角法宝
|
||
public virtual bool IsLocalFaBao()
|
||
{
|
||
return false;
|
||
}
|
||
//是否是主角飞剑
|
||
public virtual bool IsLocalFlySword()
|
||
{
|
||
return false;
|
||
}
|
||
//是否是主角仙娃
|
||
public virtual bool IsLocalMarryChild()
|
||
{
|
||
return false;
|
||
}
|
||
|
||
//死亡后的回调
|
||
public virtual void OnDead()
|
||
{
|
||
_skillManager.Clear();
|
||
//死亡删除警示圈
|
||
GameCenter.WarningFiledManager.RemoveFiled(this);
|
||
}
|
||
#endregion
|
||
|
||
#region 异常状态
|
||
public virtual void OnAddState(RoleState type)
|
||
{
|
||
}
|
||
public virtual void OnRemoveState(RoleState type)
|
||
{
|
||
}
|
||
#endregion
|
||
|
||
#region 战斗状态
|
||
public virtual void OnFightStateChangated(bool state)
|
||
{
|
||
|
||
}
|
||
#endregion
|
||
|
||
#region 受击处理
|
||
public void BeAttackedResponse(Character attacker, HitEffectInfo hitInfo, MSG_Fight.HitEffectInfo msgInfo)
|
||
{
|
||
var targetPos = new Vector2(msgInfo.posx, msgInfo.posy);
|
||
var hitType = CombatUtil.ConvertToHitType(msgInfo.effect);
|
||
GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_HUD_POPUP_DAMAGE, msgInfo, attacker);
|
||
if (hitInfo.HitVfx > 0 && !GameCenter.GameSetting.IsEnabled(GameSettingKeyCode.TPVFXSkill))
|
||
{
|
||
var setCode = GameCenter.GameSetting.GetSetting(GameSettingKeyCode.HitVfx);
|
||
if (setCode > 0 || attacker.IsLocalPlayer())
|
||
{
|
||
//控制每个被击位置只有一个特效
|
||
var vfx = Skin.PlayVFX(ModelTypeCode.SkillVFX, hitInfo.HitVfx, hitInfo.HitSlot, FSkinPartCode.Body, true, 1f, true, false, null, false, true);
|
||
if (vfx != null)
|
||
{
|
||
vfx.LiftTime = 3f;
|
||
}
|
||
}
|
||
}
|
||
switch (hitType)
|
||
{
|
||
case SkillHitType.None:
|
||
{
|
||
if (DeadDetail != null)
|
||
{
|
||
DeadDetail.TimeCounter = 0f;
|
||
}
|
||
}
|
||
break;
|
||
case SkillHitType.HitStiff:
|
||
{
|
||
Action_BeHit(attacker, hitInfo.HitEffectTime, true, hitInfo.HitAnim);
|
||
}
|
||
break;
|
||
case SkillHitType.HitBack:
|
||
{
|
||
Action_BeHitBack(attacker, targetPos, hitInfo.HitTimeCurve, hitInfo.HitEffectTime, true, hitInfo.HitAnim);
|
||
}
|
||
break;
|
||
case SkillHitType.HitFly:
|
||
{
|
||
Action_BeHitFly(attacker, targetPos, hitInfo.HitFlyHeightCurve, hitInfo.HitTimeCurve, hitInfo.FlyTime, hitInfo.LieTime, true);
|
||
}
|
||
break;
|
||
case SkillHitType.HitGrab:
|
||
{
|
||
Action_BeHitGrab(targetPos, hitInfo.HitTimeCurve, hitInfo.HitEffectTime, true);
|
||
}
|
||
break;
|
||
}
|
||
OnBeAttackedResponse(attacker, hitInfo, hitType, msgInfo);
|
||
}
|
||
|
||
public virtual void OnBeAttackedResponse(Character attacker, HitEffectInfo hitInfo, SkillHitType hitType, MSG_Fight.HitEffectInfo msgInfo)
|
||
{
|
||
if (hitType != SkillHitType.None)
|
||
{
|
||
//被控制删除警示圈
|
||
GameCenter.WarningFiledManager.RemoveFiled(this);
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region //阻挡判定
|
||
public virtual bool IsBlocked(Vector2 position)
|
||
{
|
||
return Scene.navigator.IsBlocked(ref position);
|
||
}
|
||
|
||
public virtual bool IsBlocked(Vector3 position)
|
||
{
|
||
return Scene.navigator.IsBlocked(ref position);
|
||
}
|
||
|
||
public virtual bool IsBlocked(ref Vector2 position)
|
||
{
|
||
return Scene.navigator.IsBlocked(ref position);
|
||
}
|
||
|
||
public virtual bool IsBlocked(ref Vector3 position)
|
||
{
|
||
return Scene.navigator.IsBlocked(ref position);
|
||
}
|
||
#endregion
|
||
|
||
#region//可视状态改变
|
||
protected void OnActiveChanged(bool b)
|
||
{
|
||
if (b)
|
||
{
|
||
GameCenter.BuffSystem.ReAddAllBuffVfx(this);
|
||
}
|
||
else
|
||
{
|
||
GameCenter.BuffSystem.RemoveAllBuffVfx(this);
|
||
}
|
||
}
|
||
#endregion
|
||
}
|
||
}
|