Files
test/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs
T
2026-04-09 16:14:01 +07:00

1412 lines
58 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.
// Enable IntelligentRoute AutoPF integration (ported from original PW client).
// 启用智能寻路 AutoPF 集成(从原版完美客户端移植)。
#define ENABLE_CEC_INTELLIGENT_ROUTE
using CSNetwork.GPDataType;
using System;
using System.Collections.Generic;
using UnityEngine;
using BrewMonster.Managers;
using Types = BrewMonster.Scripts.CECHPWorkMove.DestTypes;
using BrewMonster.Network;
namespace BrewMonster.Scripts
{
public class CECHPWorkMove : CECHPWork
{
public static class DestTypes
{
public const int DEST_2D = 0,
DEST_3D = 1,
DEST_DIR = 2,
DEST_PUSH = 3,
DEST_STANDJUMP = 4,
DEST_AUTOPF = 5; // Movement type
}
const float A3D_PI = 3.1415926535f;
static float DEG2RAD(float deg) => ((deg) * A3D_PI / 180.0f);
static float pitch_ang_wing => DEG2RAD(45.0f);
static float pitch_ang_fly_sword => DEG2RAD(25.0f);
static float lean_max_ang => DEG2RAD(45.0f);
static float ang_vel_fly => 1.0f / DEG2RAD(60.0f);
static float ang_vel_swim => 1.0f / DEG2RAD(180.0f);
static float pitch_co_wing => pitch_ang_wing / A3D_PI;
static float pitch_co_fly_sword => pitch_ang_fly_sword / A3D_PI;
const float sidle_co = .5f;
static float sidle_co_r => 1.0f - sidle_co;
static float push_pitch_vel_wing => pitch_ang_wing / 0.5f;
static float push_pitch_vel_fly_sword => pitch_ang_fly_sword / 0.5f;
private const uint MoveInputMask = 0x0F; // MD_FORWARD | MD_RIGHT | MD_BACK | MD_LEFT
protected A3DVECTOR3 m_vMoveDest; // Move destination position or direction
protected int m_iDestType; // Destination type
protected bool m_bHaveDest; // true, have destination
protected bool m_bMeetSlide; // true, meet slide
protected A3DVECTOR3 m_vCurDir; // Current move direction
protected bool m_bReadyCancel; // true, ready to cancel
protected bool m_bGliding; // glide
protected float m_fGlideTime;
protected float m_fGlideSpan;
protected float m_fGlideAng;
protected float m_fGlideVel; // glide angular vel
protected float m_fGlidePitch; // glide pitch angle
protected float m_fCurPitch;
protected float m_fPushPitch;
protected float m_fPushLean;
protected A3DVECTOR3 vDir = new A3DVECTOR3();
protected bool m_bUseAutoMoveDialog; // Auto move
protected float m_fAutoHeight; // Height of auto moving destination
protected bool m_bAutoLand; // Auto land when arrive at destination
protected bool m_bAutoFly; // Auto fly
protected bool m_bReachedHeight;// Player reached specified height
protected bool m_bAutoFlyPending; // Mark whether a fly command had been executed
protected int m_iNPCTempleId;
protected int m_iTaskId;
protected bool m_bSwitchTo2D;
protected bool m_bResetAutoPF;
public CECHPWorkMove(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_MOVETOPOS, pWorkMan)
{
m_dwMask = Work_mask.MASK_MOVETOPOS;
m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_TRACEOBJECT | Work_mask.MASK_FOLLOW;
Reset();
}
public CECHPWorkMove(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID, pWorkMan)
{
}
// Set destination position or direction
public void SetDestination(int iDestType, A3DVECTOR3 vMoveDest)
{
m_iDestType = iDestType;
m_vMoveDest = vMoveDest;
m_bHaveDest = true;
m_bGliding = false;
//m_pHost.SetAdjustOrient(false); // 2014-9-10 ı CECHPWorkMove ʱ򶼻ô˺ʱͨ SetDestDirAndUp öijʧЧ
// ַΪɡӽͷźϰס'A''D'ƶסţʩƫĿƶγԣ
//Ϣ
m_iTaskId = 0;
m_iNPCTempleId = 0;
ResetUseAutoPF();
if (iDestType == Types.DEST_DIR)
{
m_vCurDir = vMoveDest;
if (m_bUseAutoMoveDialog)
{
m_bUseAutoMoveDialog = false;
m_bAutoLand = false;
m_fAutoHeight = -1.0f;
m_bAutoFly = false;
m_bReachedHeight = true;
m_bAutoFlyPending = false;
}
}
else if (iDestType == Types.DEST_2D || iDestType == Types.DEST_3D)
{
m_vCurDir = vMoveDest - new A3DVECTOR3(m_pHost.transform.position.x, m_pHost.transform.position.y, m_pHost.transform.position.z);
m_vCurDir.y = 0.0f;
m_vCurDir.Normalize();
}
else if (IsAutoPF())
{
m_vCurDir = CECIntelligentRoute.Instance().GetCurDest() - m_pHost.GetPos();
m_vCurDir.y = 0.0f;
m_vCurDir.Normalize();
if (m_bUseAutoMoveDialog)
{
// ˴ m_bUseAutoMoveDialog SetUseAutoMoveDialog ˵
m_bUseAutoMoveDialog = false;
m_bAutoLand = false;
m_fAutoHeight = -1.0f;
m_bAutoFly = false;
m_bReachedHeight = true;
m_bAutoFlyPending = false;
}
}
// TO DO: fix later
//if (m_pHost.m_pMoveTargetGFX)
//{
// if (iDestType != DEST_PUSH)
// m_pHost.m_pMoveTargetGFX.Stop();
//}
}
void ResetUseAutoPF()
{
m_bResetAutoPF = true;
}
// Tick routine
public override bool Tick(float dwDeltaTime)
{
UpdateResetUseAutoPF();
if (m_bSwitchTo2D)
{
SwitchToDest2D();
m_bSwitchTo2D = false;
return true;
}
#if ENABLE_CEC_INTELLIGENT_ROUTE
if (IsAutoPF())
{
if (global::BrewMonster.Scripts.CECIntelligentRoute.Instance().IsIdle())
{
// C++: AutoPF not ready yet, wait next tick.
// C++:自动寻路未就绪,等待下一帧。
return true;
}
if (m_pHost.IsFlying())
{
// C++: if flying, reset and switch back to DEST_2D.
// C++:飞行状态下重置并切回 DEST_2D。
global::BrewMonster.Scripts.CECIntelligentRoute.Instance().ResetSearch();
m_bSwitchTo2D = true;
return true;
}
}
#endif
base.Tick(dwDeltaTime);
// Draw red line showing the path the player has to move
// 绘制红色线条显示玩家需要移动的路径
if (m_bHaveDest)
{
A3DVECTOR3 curPos = m_pHost.GetPos();
Vector3 vCurPos = new Vector3(curPos.x, curPos.y, curPos.z);
#if ENABLE_CEC_INTELLIGENT_ROUTE
if (IsAutoPF() && global::BrewMonster.Scripts.CECIntelligentRoute.Instance().IsMoveOn())
{
// Draw AutoPF path in red
// 绘制 AutoPF 路径(红色)
List<Vector3> path = global::BrewMonster.Scripts.CECIntelligentRoute.Instance().GetFullPath();
if (path != null && path.Count > 1)
{
// Draw lines connecting all path nodes (red)
// 绘制连接所有路径节点的线(红色)
for (int i = 0; i < path.Count - 1; i++)
{
Vector3 from = path[i];
Vector3 to = path[i + 1];
Debug.DrawLine(from, to, Color.red, 0.1f, false);
}
// Draw line from current position to first path node (red)
// 绘制从当前位置到第一个路径节点的线(红色)
if (path.Count > 0)
{
Debug.DrawLine(vCurPos, path[0], Color.red, 0.1f, false);
}
}
}
else
#endif
{
// Draw straight line to destination (red)
// 绘制到目的地的直线(红色)
Vector3 vDest = new Vector3(m_vMoveDest.x, m_vMoveDest.y, m_vMoveDest.z);
Debug.DrawLine(vCurPos, vDest, Color.red, 0.1f, false);
}
}
if (m_pHost.IsRooting())
return true;
if (m_bUseAutoMoveDialog)
{
if (m_pHost.IsFlying())
{
m_bAutoFly = false;
m_bAutoFlyPending = false;
}
if (m_bAutoFly && !m_bAutoFlyPending && !m_pHost.IsFlying())
{
if (m_pHost.CmdFly(true))
{
m_bAutoFly = false;
m_bAutoFlyPending = true;
}
}
}
else
{
// Make sure 'Win_AutoPlay' dialog doesn't show up
/* CECGameUIMan pGameUI = g_pGame.GetGameRun().GetUIManager().GetInGameUIMan();
pGameUI.AutoMoveShowDialog(false);*/
}
// 如果目标是任务 NPC(模板ID),当接近时切换到 WorkTrace(对话/交互)。
// English: If destination is a task NPC (template id), handoff to WorkTrace (talk/interact) when close.
if ((m_vMoveDest - m_pHost.GetPos()).MagnitudeH() <= 5.0f)
{
if (m_iNPCTempleId != 0)
{
// Find live NPC in scene by template id.
// 按模板ID在场景中查找活体 NPC。
CECNPC pNPC = EC_ManMessageMono.Instance != null
? EC_ManMessageMono.Instance.CECNPCMan.FindNPCByTemplateID(m_iNPCTempleId)
: null;
if (pNPC != null && m_pHost.SelectTarget(pNPC.GetNPCID()))
{
CECHPWorkTrace pWork = m_pWorkMan.CreateNPCTraceWork(pNPC, m_iTaskId);
if (pWork != null)
{
// Prevent auto land before switching.
// 防止在切换前自动降落。
m_bAutoLand = false;
Finish();
m_pWorkMan.SetPostTickCommand(new CECHPWorkPostTickRunWorkCommand(pWork, true));
return true;
}
}
}
}
//m_pHost.SetGroundInfoClient();
float fDeltaTime = dwDeltaTime;
if (m_pHost.m_iMoveEnv == (int)MoveEnvironment.MOVEENV_GROUND ||
m_pHost.m_iMoveEnv == (int)MoveEnvironment.MOVEENV_WATER && m_pHost.IsJumping() && (m_pHost.m_CDRInfo.vAbsVelocity.y > 0 || m_pHost.m_CDRInfo.fYVel > 0))
{
// Play appropriate actions
if (!m_pHost.IsJumping() && !m_pHost.IsPlayingAction((int)PLAYER_ACTION_TYPE.ACT_TRICK_RUN) &&
m_pHost.m_iMoveMode != (int)MoveMode.MOVE_SLIDE && !m_bMeetSlide)
{
int iAction = m_pHost.GetMoveStandAction(true);
m_pHost.PlayAction(iAction, false);
}
Tick_Walk(fDeltaTime);
}
else // (m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_AIR || m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_WATER)
{
m_pHost.ResetJump();
// Play appropriate actions
if (!m_bGliding)
{
int iAction = m_pHost.GetMoveStandAction(true);
m_pHost.PlayAction(iAction, false);
}
Tick_FlySwim(fDeltaTime);
}
return true;
}
// Reset work
public override void Reset()
{
base.Reset();
m_iDestType = DestTypes.DEST_2D;
m_bHaveDest = false;
m_bMeetSlide = false;
m_bReadyCancel = false;
m_bGliding = false;
m_fGlideTime = 0;
m_fCurPitch = 0;
m_fPushPitch = 0;
m_fPushLean = 0;
m_bUseAutoMoveDialog = false;
m_fAutoHeight = -1.0f;
m_bAutoLand = false;
m_bAutoFly = false;
m_bReachedHeight = true;
m_bAutoFlyPending = false;
m_iNPCTempleId = 0;
m_iTaskId = 0;
m_bSwitchTo2D = false;
m_bResetAutoPF = false;
}
// Work is cancel
public override void Cancel()
{
//if (m_pHost.m_pMoveTargetGFX)
// m_pHost.m_pMoveTargetGFX.Stop();
//A3DVECTOR3 vDir = m_pHost.GetDir();
//vDir.y = 0;
//vDir.Normalize();
//if (!vDir.IsZero())
//{
// m_pHost.StopModelMove(vDir, g_vAxisY, 0);
//}
ClearResetUseAutoPF();
//if (CECIntelligentRoute::Instance().IsUsageMove())
//{
// if (!CECIntelligentRoute::Instance().IsIdle())
// {
// CECIntelligentRoute::Instance().ResetSearch();
// m_bSwitchTo2D = true; // Æô¶¯·ÉÐÐÖжϺó»Ö¸´Ê±¡¢ÐèÒªÇл»µ½ DEST_2D ģʽ
// }
//}
base.Cancel();
//AP_ActionEvent(AP_EVENT_MOVEFINISHED);
}
// This work is do player moving ?
public override bool IsMoving() { return true; }
// Copy work data
public override bool CopyData(CECHPWork pWork)
{
if (!base.CopyData(pWork))
return false;
CECHPWorkMove pSrc = pWork as CECHPWorkMove;
m_iDestType = pSrc.m_iDestType;
m_bHaveDest = pSrc.m_bHaveDest;
m_bMeetSlide = pSrc.m_bMeetSlide;
m_bReadyCancel = pSrc.m_bReadyCancel;
m_bGliding = pSrc.m_bGliding;
m_fGlideTime = pSrc.m_fGlideTime;
m_fGlideSpan = pSrc.m_fGlideSpan;
m_fGlideAng = pSrc.m_fGlideAng;
m_fGlideVel = pSrc.m_fGlideVel;
m_fGlidePitch = pSrc.m_fGlidePitch;
m_fCurPitch = pSrc.m_fCurPitch;
m_fPushPitch = pSrc.m_fPushPitch;
m_fPushLean = pSrc.m_fPushLean;
m_iDestType = pSrc.m_iDestType;
m_vMoveDest = pSrc.m_vMoveDest;
m_vCurDir = pSrc.m_vCurDir;
m_bUseAutoMoveDialog = pSrc.m_bUseAutoMoveDialog;
m_fAutoHeight = pSrc.m_fAutoHeight;
m_bAutoLand = pSrc.m_bAutoLand;
m_bAutoFly = pSrc.m_bAutoFly;
m_bReachedHeight = pSrc.m_bReachedHeight;
m_bAutoFlyPending = pSrc.m_bAutoFlyPending;
m_iNPCTempleId = pSrc.m_iNPCTempleId;
m_iTaskId = pSrc.m_iTaskId;
m_bSwitchTo2D = pSrc.m_bSwitchTo2D;
m_bResetAutoPF = pSrc.m_bResetAutoPF;
return true;
}
// Play move target effect
public void PlayMoveTargetGFX(A3DVECTOR3 vPos, A3DVECTOR3 vNormal)
{
}
// User press cancel button
public void PressCancel() { m_bReadyCancel = true; }
public void SetUseAutoMoveDialog(bool bUseAutoMoveDialog)
{
}
public bool GetUseAutoMoveDialog() { return m_bUseAutoMoveDialog; }
public bool GetAutoMove()
{
return true;
}
void SetAutoLand(bool bAutoLand) { m_bAutoLand = bAutoLand; }
bool GetAutoLand() { return m_bAutoLand; }
void SetAutoHeight(float fHeight) { m_fAutoHeight = fHeight; m_bAutoFly = true; m_bReachedHeight = false; }
float GetAutoHeight() { return m_fAutoHeight; }
bool IsAutoFly() { return m_bAutoFly; }
bool IsAutoPF() { return m_iDestType == Types.DEST_AUTOPF; }
// Finish work
public void Finish()
{
m_bFinished = true;
Cancel();
// Close 'Win_AutoPlay' dialog if it exists
//CECGameUIMan* pGameUI = g_pGame.GetGameRun().GetUIManager().GetInGameUIMan();
//pGameUI.AutoMoveShowDialog(false);
if (m_bUseAutoMoveDialog)
{
if (m_bAutoLand)
{
m_bAutoLand = false;
if (EC_Game.GetGameRun().GetHostPlayer().IsFlying())
EC_Game.GetGameRun().GetHostPlayer().CmdFly(false);
}
m_bUseAutoMoveDialog = false;
m_fAutoHeight = -1.0f;
m_bAutoFly = false;
m_bReachedHeight = true;
}
//׷
m_iNPCTempleId = 0;
m_iTaskId = 0;
}
public void SetTaskNPCInfo(int tid, int taskid)
{
m_iNPCTempleId = tid;
m_iTaskId = taskid;
}
void SwitchToDest2D()
{
int tid, taskid;
tid = m_iNPCTempleId;
taskid = m_iTaskId;
//CECGameUIMan* pGameUI = g_pGame.GetGameRun().GetUIManager().GetInGameUIMan();
//pGameUI.SetAutoMoveShowDialogTarget((int)m_vMoveDest.x, (int)m_vMoveDest.z);
SetDestination(CECHPWorkMove.DestTypes.DEST_2D, m_vMoveDest);
SetTaskNPCInfo(tid, taskid);
SetUseAutoMoveDialog(true);
}
// On first tick
protected override void OnFirstTick()
{
m_pHost.m_iMoveMode = Move_Mode.MOVE_MOVE;
//PlayMoveTargetGFX();
if (m_pHost.m_iMoveEnv != CECPlayer.Move_environment.MOVEENV_AIR)
m_pHost.ShowWing(false);
if (!m_pHost.IsJumping())
{
int iAction = m_pHost.GetMoveStandAction(true);
m_pHost.PlayAction(iAction, false);
}
}
// Tick routine of walking on ground
protected bool Tick_Walk(float fDeltaTime)
{
A3DVECTOR3 vCurPos = m_pHost.GetPos();
ref CDR_INFO cdr = ref m_pHost.m_CDRInfo;
if (m_pHost.m_iMoveMode == (int)MoveMode.MOVE_SLIDE)
{
m_pHost.PlayAction((int)PLAYER_ACTION_TYPE.ACT_JUMP_LOOP, false);
A3DVECTOR3 vDir;
if (m_iDestType == DestTypes.DEST_DIR)
{
vDir = m_vCurDir;
}
else if (m_iDestType == DestTypes.DEST_PUSH)
{
vDir = GetCurrentModelDir();
}
#if ENABLE_CEC_INTELLIGENT_ROUTE
else if (IsAutoPF())
{
vDir = global::BrewMonster.Scripts.CECIntelligentRoute.Instance().GetCurDest() - vCurPos;
vDir.y = 0.0f;
vDir.Normalize();
}
#endif
else
{
vDir = m_vMoveDest - vCurPos;
vDir.y = 0.0f;
vDir.Normalize();
}
float fMaxSpeedV = 0.0f;
m_bMeetSlide = m_pHost.m_MoveCtrl.MeetSlope(vDir, fMaxSpeedV);
cdr.fYVel = EC_Utility.a_ClampFloor(cdr.fYVel, -fMaxSpeedV);
if (m_pHost.m_GndInfo.bOnGround)
m_vCurDir = vDir;
vCurPos = m_pHost.m_MoveCtrl.GroundMove(m_vCurDir, m_pHost.GetGroundSpeed(), fDeltaTime);
if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3)
{
m_pHost.m_MoveCtrl.SetSlideLock(true);
cdr.fYVel = 0.0f;
Finish();
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), m_pHost.GetGroundSpeed(), (int)GPMoveMode.GP_MOVE_SLIDE);
}
else
{
m_pHost.SetPos(EC_Utility.ToVector3(vCurPos));
#if ENABLE_CEC_INTELLIGENT_ROUTE
if (IsAutoPF() && global::BrewMonster.Scripts.CECIntelligentRoute.Instance().IsMoveOn())
global::BrewMonster.Scripts.CECIntelligentRoute.Instance().OnPlayerPosChange(vCurPos);
#endif
#if SHOW_AUTOMOVE_FOOTPRINTS
if (IsAutoPF() || m_iDestType == DestTypes.DEST_2D)
g_AutoPFFollowPoints.Add(vCurPos);
#endif
m_pHost.m_MoveCtrl.SendMoveCmd(
vCurPos,
2,
GPDataTypeHelper.g_vOrigin,
(cdr.vAbsVelocity),
(int)GPMoveMode.GP_MOVE_SLIDE);
}
}
else if (!m_bMeetSlide)
{
float fSpeed = m_pHost.GetGroundSpeed();
int iMoveMode = m_pHost.m_bWalkRun ? (int)GPMoveMode.GP_MOVE_RUN : (int)GPMoveMode.GP_MOVE_WALK;
if (m_pHost.IsJumping())
iMoveMode = (int)GPMoveMode.GP_MOVE_JUMP;
else if (!m_pHost.m_GndInfo.bOnGround)
iMoveMode = (int)GPMoveMode.GP_MOVE_FALL;
if (m_bReadyCancel && m_pHost.m_GndInfo.bOnGround)
{
Finish();
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), fSpeed, iMoveMode);
return true;
}
if ((GetMoveRelDirMask() & (uint)((CECHostPlayer.MOVE_DIR.MD_LEFT | CECHostPlayer.MOVE_DIR.MD_RIGHT | CECHostPlayer.MOVE_DIR.MD_FORWARD | CECHostPlayer.MOVE_DIR.MD_BACK))) != 0)
m_iDestType = DestTypes.DEST_PUSH;
if (m_iDestType == DestTypes.DEST_2D)
{
float fDist;
if (m_pHost.m_GndInfo.bOnGround)
{
m_vCurDir = m_vMoveDest - vCurPos;
m_vCurDir.y = 0.0f;
fDist = m_vCurDir.Normalize();
}
else
{
fDist = (m_vMoveDest - vCurPos).MagnitudeH();
}
vCurPos = m_pHost.m_MoveCtrl.GroundMove(m_vCurDir, fSpeed, fDeltaTime, m_pHost.m_fVertSpeed);
UpdateFacingFromDelta(vCurPos);
if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3)
{
cdr.fYVel = 0.0f;
Finish();
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), fSpeed, iMoveMode);
}
else if (cdr.vTPNormal != new A3DVECTOR3(0))
{
A3DVECTOR3 vMoveDelta = vCurPos - m_pHost.GetPos();
vMoveDelta.y = 0.0f;
float fMoveDist = vMoveDelta.Normalize();
if (fMoveDist >= fDist)
{
Finish();
m_bUseAutoMoveDialog = false;
m_pHost.SetPos(EC_Utility.ToVector3(vCurPos));
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), fSpeed, iMoveMode);
}
else
{
m_pHost.SetPos(EC_Utility.ToVector3(vCurPos));
m_pHost.m_MoveCtrl.SendMoveCmd(
vCurPos,
0,
m_vMoveDest,
(cdr.vAbsVelocity),
iMoveMode);
}
#if SHOW_AUTOMOVE_FOOTPRINTS
g_AutoPFFollowPoints.Add(vCurPos);
#endif
}
else
{
#if SHOW_AUTOMOVE_FOOTPRINTS
g_AutoPFFollowPoints.Add(vCurPos);
#endif
m_pHost.SetPos(EC_Utility.ToVector3(vCurPos));
m_pHost.m_MoveCtrl.SendMoveCmd(
vCurPos,
1,
m_vMoveDest,
(cdr.vAbsVelocity),
iMoveMode);
}
}
else if (m_iDestType == DestTypes.DEST_DIR)
{
vCurPos = m_pHost.m_MoveCtrl.GroundMove(m_vCurDir, fSpeed -0.5f, fDeltaTime, m_pHost.m_fVertSpeed);
UpdateFacingFromDelta(vCurPos);
m_pHost.SetPos(EC_Utility.ToVector3(vCurPos));
if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3)
{
cdr.fYVel = 0.0f;
Finish();
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), fSpeed, iMoveMode);
}
else if (m_pHost.m_GndInfo.bOnGround)
{
m_pHost.m_MoveCtrl.SendMoveCmd(
vCurPos,
2,
GPDataTypeHelper.g_vOrigin,
(cdr.vAbsVelocity),
iMoveMode);
}
else
{
m_pHost.m_MoveCtrl.SendMoveCmd(
vCurPos,
1,
m_vMoveDest,
(cdr.vAbsVelocity),
iMoveMode);
}
}
else if (m_iDestType == DestTypes.DEST_STANDJUMP)
{
if (!m_pHost.IsJumping())
{
Finish();
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), fSpeed, iMoveMode);
}
else
{
vCurPos = m_pHost.m_MoveCtrl.GroundMove(GPDataTypeHelper.g_vOrigin, 0.0f, fDeltaTime, m_pHost.m_fVertSpeed);
m_pHost.SetPos(EC_Utility.ToVector3(vCurPos));
if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3)
{
m_pHost.ResetJump();
Finish();
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), fSpeed, iMoveMode);
}
else
{
m_pHost.m_MoveCtrl.SendMoveCmd(
vCurPos,
0,
m_vMoveDest,
(cdr.vAbsVelocity),
iMoveMode);
}
}
}
else if (m_iDestType == DestTypes.DEST_PUSH)
{
Vector3 vMoveDir = Vector3.zero;//EC_Utility.ToVector3(GPDataTypeHelper.g_vOrigin);
fSpeed = m_pHost.GetGroundSpeed();
bool bFinish = false;
if (m_pHost.GetPushDir(ref vMoveDir, (uint)(CECHostPlayer.MOVE_DIR.MD_FORWARD | CECHostPlayer.MOVE_DIR.MD_BACK | CECHostPlayer.MOVE_DIR.MD_LEFT | CECHostPlayer.MOVE_DIR.MD_RIGHT), fDeltaTime))
{
if (vMoveDir != Vector3.zero)
{
m_pHost.SetRotationHP(vMoveDir);
}
vCurPos = m_pHost.m_MoveCtrl.GroundMove(EC_Utility.ToA3DVECTOR3(vMoveDir), fSpeed, fDeltaTime, m_pHost.m_fVertSpeed);
m_pHost.SetPos(EC_Utility.ToVector3(vCurPos));
}
else
{
if (!m_bUseAutoMoveDialog)
bFinish = true;
else
m_iDestType = DestTypes.DEST_2D;
}
if (bFinish || m_pHost.m_MoveCtrl.MoveBlocked() >= 3)
{
if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3)
{
cdr.fYVel = 0.0f;
}
Finish();
m_pHost.m_vVelocity.Clear();
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), fSpeed, iMoveMode);
}
else
{
m_pHost.m_vVelocity = EC_Utility.ToA3DVECTOR3(vMoveDir) * fSpeed;
m_pHost.m_MoveCtrl.SendMoveCmd(
vCurPos,
2,
GPDataTypeHelper.g_vOrigin,
m_pHost.m_vVelocity,
iMoveMode);
}
}
//else if (m_iDestType == DestTypes.DEST_PUSH)
//{
// m_iDestType = DestTypes.DEST_2D;
//}
#if ENABLE_CEC_INTELLIGENT_ROUTE
else if (IsAutoPF())
{
float fDist = 0.0f;
A3DVECTOR3 vCurDest = global::BrewMonster.Scripts.CECIntelligentRoute.Instance().GetCurDest();
if (m_pHost.m_GndInfo.bOnGround)
{
m_vCurDir = vCurDest - vCurPos;
m_vCurDir.y = 0.0f;
fDist = m_vCurDir.Normalize();
}
else
{
fDist = (vCurDest - vCurPos).MagnitudeH();
}
vCurPos = m_pHost.m_MoveCtrl.GroundMove(m_vCurDir, fSpeed, fDeltaTime, m_pHost.m_fVertSpeed);
if (!m_vCurDir.IsZero())
{
//m_pHost.StartModelMove(m_vCurDir, GPDataTypeHelper.g_vAxisY, 100);
//m_pHost.ChangeModelTargetDirAndUp(m_vCurDir, GPDataTypeHelper.g_vAxisY);
UpdateFacingFromDelta(vCurPos);
}
if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3)
{
cdr.fYVel = 0.0f;
Finish();
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), fSpeed, iMoveMode);
}
else
{
m_pHost.SetPos(EC_Utility.ToVector3(vCurPos));
global::BrewMonster.Scripts.CECIntelligentRoute.Instance().OnPlayerPosChange(vCurPos);
if (global::BrewMonster.Scripts.CECIntelligentRoute.Instance().IsPathFinished())
{
Finish();
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), fSpeed, iMoveMode);
}
else
{
// NOTE: Use Vector3 overload to avoid signature mismatch across ports.
// 注意:使用 Vector3 重载以避免移植过程中签名不匹配。
m_pHost.m_MoveCtrl.SendMoveCmd(
EC_Utility.ToVector3(vCurPos),
EC_Utility.ToVector3(cdr.vAbsVelocity),
iMoveMode,
false);
}
}
}
#else
else if (IsAutoPF())
{
m_bSwitchTo2D = true;
}
#endif
}
else
{
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), m_pHost.GetGroundSpeed(), (int)GPMoveMode.GP_MOVE_SLIDE);
Finish();
}
return true;
}
// Tick routine of flying or swimming
protected bool Tick_FlySwim(float fDeltaTime)
{
A3DVECTOR3 vCurPos = m_pHost.GetPos();
int iMoveMode = (m_pHost.m_iMoveEnv == (int)MoveEnvironment.MOVEENV_AIR) ? (int)GPMoveMode.GP_MOVE_AIR : (int)GPMoveMode.GP_MOVE_WATER;
float na, fMaxSpeed;
bool bInAir;
//Debug.LogError("Tick_FlySwim m_pHost.m_dwMoveRelDir = " + m_pHost.m_dwMoveRelDir);
if (m_pHost.m_iMoveEnv == (int)MoveEnvironment.MOVEENV_AIR)
{
bInAir = true;
na = CECHostMove.EC_NACCE_AIR;
fMaxSpeed = m_pHost.GetFlySpeed();
}
else
{
bInAir = false;
na = CECHostMove.EC_NACCE_WATER;
fMaxSpeed = m_pHost.GetSwimSpeedSev();
}
if (m_bReadyCancel || m_bMeetSlide)
{
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), fMaxSpeed, iMoveMode | (int)GPMoveMode.GP_MOVE_RUN);
Finish();
return true;
}
// for auto move
if (m_bUseAutoMoveDialog && m_fAutoHeight > 0.0f && m_iDestType != DestTypes.DEST_PUSH)
{
if (m_pHost.m_dwMoveRelDir == 0)
{
if ((int)(vCurPos.y / 10.0f) == (int)m_fAutoHeight)
{
if (!m_bReachedHeight)
{
m_pHost.m_vVelocity.y = 0.0f;
m_pHost.m_dwMoveRelDir &= ~((uint)(CECHostPlayer.MOVE_DIR.MD_ABSUP | CECHostPlayer.MOVE_DIR.MD_ABSDOWN));
m_bReachedHeight = true;
}
}
else
{
if (!m_bReachedHeight)
{
if (vCurPos.y < m_fAutoHeight * 10.0f)
{
m_pHost.m_dwMoveRelDir &= ~((uint)(CECHostPlayer.MOVE_DIR.MD_ABSDOWN));
m_pHost.m_dwMoveRelDir |= ((uint)CECHostPlayer.MOVE_DIR.MD_ABSUP);
}
else if (vCurPos.y > m_fAutoHeight * 10.0f)
{
m_pHost.m_dwMoveRelDir &= ~((uint)(CECHostPlayer.MOVE_DIR.MD_ABSUP));
m_pHost.m_dwMoveRelDir |= (uint)CECHostPlayer.MOVE_DIR.MD_ABSDOWN;
}
}
else // Auto adjust height, so we should refresh move height
{
m_fAutoHeight = vCurPos.y / 10.0f;
}
}
}
else // Player manually set auto move height
{
m_bReachedHeight = true;
m_fAutoHeight = vCurPos.y / 10.0f;
}
}
if ((m_pHost.m_dwMoveRelDir & (uint)(CECHostPlayer.MOVE_DIR.MD_LEFT | CECHostPlayer.MOVE_DIR.MD_RIGHT | CECHostPlayer.MOVE_DIR.MD_FORWARD | CECHostPlayer.MOVE_DIR.MD_BACK)) != 0)
m_iDestType = DestTypes.DEST_PUSH;
ON_AIR_CDR_INFO cdr = m_pHost.m_AirCDRInfo;
if (m_iDestType == DestTypes.DEST_DIR)
{
Vector3 vPushDir = Vector3.zero;
m_pHost.GetPushDir(ref vPushDir, (uint)CECHostPlayer.MOVE_DIR.MD_ALL, 0);
vPushDir.x = vPushDir.z = 0.0f;
float fSpeed1H = m_pHost.m_vVelocity.MagnitudeH();
float fSpeed1V = m_pHost.m_vVelocity.y;
A3DVECTOR3 vMoveDirH = m_vMoveDest;
float pa = CECHostMove.EC_PUSH_ACCE;
float fSpeed2H = fSpeed1H + (pa + na) * fDeltaTime;
if (Math.Abs(pa - 0) < float.Epsilon && fSpeed2H < 0.0f)
fSpeed2H = 0.0f; // Only resistance couldn't generate negative speed
else if (fSpeed2H > fMaxSpeed)
fSpeed2H = fMaxSpeed;
Glide(5.0f, vMoveDirH, fDeltaTime, bInAir);
vMoveDirH = m_pHost.GetModelMoveDir();
vMoveDirH.y = 0;
vMoveDirH.Normalize();
// Vertical speed
float fSpeed2V = CalcFlySwimVertSpeed(fSpeed1V, vPushDir.y, CECHostMove.EC_PUSH_ACCE, fDeltaTime);
A3DVECTOR3 vVel2 = vMoveDirH * fSpeed2H + GPDataTypeHelper.g_vAxisY * fSpeed2V;
// Air/water move
vCurPos = m_pHost.m_MoveCtrl.AirWaterMove(vVel2, fDeltaTime, bInAir);
m_pHost.SetPos(EC_Utility.ToVector3(vCurPos));
m_pHost.m_vVelocity = vVel2;
if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3)
{
Finish();
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), fMaxSpeed, iMoveMode | (int)GPMoveMode.GP_MOVE_RUN);
}
else
m_pHost.m_MoveCtrl.SendMoveCmd(vCurPos, 0, m_vMoveDest, vVel2, iMoveMode | (int)GPMoveMode.GP_MOVE_RUN);
}
else if (m_iDestType == DestTypes.DEST_2D)
{
Vector3 vPushDir = Vector3.zero;
m_pHost.GetPushDir(ref vPushDir, (uint)CECHostPlayer.MOVE_DIR.MD_ALL, 0f);
vPushDir.x = vPushDir.z = 0.0f;
float fSpeed1H = m_pHost.m_vVelocity.MagnitudeH();
float fSpeed1V = m_pHost.m_vVelocity.y;
A3DVECTOR3 vMoveDirH = m_vMoveDest - vCurPos;
vMoveDirH.y = 0.0f;
float fDistH = vMoveDirH.Normalize();
float pa = 0.0f;
// Calculate the distance to reduce velocity to 0
float s = -0.5f * fSpeed1H * fSpeed1H / na;
if (fDistH > s - 0.01f)
pa = CECHostMove.EC_PUSH_ACCE;
float fSpeed2H = fSpeed1H + (pa + na) * fDeltaTime;
if (Math.Abs(pa - 0f) < float.Epsilon && fSpeed2H < 0.0f)
fSpeed2H = 0.0f; // Only resistance couldn't generate negative speed
else if (fSpeed2H > fMaxSpeed)
fSpeed2H = fMaxSpeed;
Glide(fDistH / fMaxSpeed, vMoveDirH, fDeltaTime, bInAir);
vMoveDirH = m_pHost.GetModelMoveDir();
vMoveDirH.y = 0;
vMoveDirH.Normalize();
// Vertical speed
float fSpeed2V = CalcFlySwimVertSpeed(fSpeed1V, vPushDir.y, CECHostMove.EC_PUSH_ACCE, fDeltaTime);
A3DVECTOR3 vVel2 = vMoveDirH * fSpeed2H + GPDataTypeHelper.g_vAxisY * fSpeed2V;
// Air/water move
vCurPos = m_pHost.m_MoveCtrl.AirWaterMove(vVel2, fDeltaTime, bInAir);
if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3)
{
vVel2.Clear();
Finish();
}
else
{
// Reached destination ?
A3DVECTOR3 vMoveDelta = vCurPos - m_pHost.GetPos();
vMoveDelta.y = 0.0f;
float fMoveDistH = vMoveDelta.Normalize();
if (fMoveDistH >= fDistH)
{
vVel2.x = vVel2.z = 0.0f;
if (Math.Abs(vVel2.y - 0f) < float.Epsilon)
{
Finish();
}
else
{
if (m_bUseAutoMoveDialog)
{
Finish();
vVel2.y = 0.0f;
}
m_iDestType = DestTypes.DEST_PUSH;
}
}
}
m_pHost.SetPos(EC_Utility.ToVector3(vCurPos));
m_pHost.m_vVelocity = vVel2;
if (m_bFinished)
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), vVel2.Magnitude(), iMoveMode | (int)GPMoveMode.GP_MOVE_RUN);
else
m_pHost.m_MoveCtrl.SendMoveCmd(vCurPos, 0, m_vMoveDest, vVel2, iMoveMode | (int)GPMoveMode.GP_MOVE_RUN);
}
else if (m_iDestType == DestTypes.DEST_3D)
{
float fSpeed1 = m_pHost.m_vVelocity.Magnitude();
A3DVECTOR3 vMoveDir = m_vMoveDest - vCurPos;
float fDist = vMoveDir.Normalize();
float pa = 0.0f;
// Calculate the distance to reduce velocity to 0
float s = -0.5f * fSpeed1 * fSpeed1 / na;
if (fDist > s - 0.01f)
pa = CECHostMove.EC_PUSH_ACCE;
float fSpeed2 = fSpeed1 + (pa + na) * fDeltaTime;
if (Math.Abs(pa - 0f) < float.Epsilon && fSpeed2 < 0.0f)
fSpeed2 = 0.0f; // Only resistance couldn't generate negative speed
AAssist.a_Clamp(ref fSpeed2, -fMaxSpeed, fMaxSpeed);
Vector3 vMoveDirH = new Vector3(vMoveDir.x, 0.0f, vMoveDir.z);
if (vMoveDirH != Vector3.zero)
{
//m_pHost.StartModelMove(vMoveDirH, g_vAxisY, 100);
//m_pHost.ChangeModelTargetDirAndUp(vMoveDirH, g_vAxisY);
m_pHost.SetRotationHP(vMoveDirH);
}
// Air/water move
// A3DVECTOR3 vVel1 = vMoveDir * fSpeed1;
A3DVECTOR3 vVel2 = vMoveDir * fSpeed2;
vCurPos = m_pHost.m_MoveCtrl.AirWaterMove(vMoveDir, fSpeed2, fDeltaTime, bInAir, false);
if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3)
{
vVel2.Clear();
Finish();
}
else
{
// Reached destination ?
A3DVECTOR3 vMoveDelta = vCurPos - m_pHost.GetPos();
float fMoveDist = vMoveDelta.Normalize();
if (fMoveDist >= fDist)
{
vVel2.Clear();
Finish();
m_bUseAutoMoveDialog = false;
}
}
m_pHost.SetPos(EC_Utility.ToVector3(vCurPos));
m_pHost.m_vVelocity = vVel2;
if (m_bFinished)
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), fMaxSpeed, iMoveMode | (int)GPMoveMode.GP_MOVE_RUN);
else
m_pHost.m_MoveCtrl.SendMoveCmd(vCurPos, 1, m_vMoveDest, vVel2, iMoveMode | (int)GPMoveMode.GP_MOVE_RUN);
}
else if (m_iDestType == DestTypes.DEST_PUSH)
{
Vector3 vPushDir = Vector3.zero;
bool bPush = m_pHost.GetPushDir(ref vPushDir, (uint)(CECHostPlayer.MOVE_DIR.MD_FORWARD | CECHostPlayer.MOVE_DIR.MD_BACK | CECHostPlayer.MOVE_DIR.MD_LEFT | CECHostPlayer.MOVE_DIR.MD_RIGHT), fDeltaTime);
if (!bPush)
{
//vPushDir = m_pHost.GetCameraCoord().GetDir();
vPushDir.y = 0;
vPushDir.Normalize();
}
int nPitchDir = 0;
if ((m_pHost.m_dwMoveRelDir & (int)(CECHostPlayer.MOVE_DIR.MD_LEFT | CECHostPlayer.MOVE_DIR.MD_RIGHT)) == 0)
{
A3DVECTOR3 vOldDir = m_pHost.GetModelMoveDir();
vOldDir.y = 0;
vOldDir.Normalize();
A3DVECTOR3 vNewDir = EC_Utility.ToA3DVECTOR3(vPushDir);
vNewDir.y = 0;
vNewDir.Normalize();
float fAngle = A3DVECTOR3.DotProduct(vOldDir, vNewDir);
if (fAngle < 1.0f - 1e-4)
{
A3DVECTOR3 vUp_fAngle = A3DVECTOR3.CrossProduct(vOldDir, vNewDir);
if (vUp_fAngle.y > 0) nPitchDir = 1;
else nPitchDir = -1;
if ((m_pHost.m_dwMoveRelDir & (uint)CECHostPlayer.MOVE_DIR.MD_BACK) != 0)
nPitchDir = -nPitchDir;
}
}
if (m_pHost.m_dwMoveRelDir != 0)
{
if ((m_pHost.m_dwMoveRelDir & ~(uint)(CECHostPlayer.MOVE_DIR.MD_ABSDOWN | CECHostPlayer.MOVE_DIR.MD_ABSUP)) != 0)
{
float fPitchDelta = (/*m_pHost.UsingWing()*/m_pHost.GetWingType() == enumWingType.WINGTYPE_WING ? push_pitch_vel_wing : push_pitch_vel_fly_sword) * fDeltaTime;
if ((m_pHost.m_dwMoveRelDir & (uint)CECHostPlayer.MOVE_DIR.MD_LEFT) != 0 || nPitchDir == -1)
{
if ((m_pHost.m_dwMoveRelDir & (uint)CECHostPlayer.MOVE_DIR.MD_BACK) != 0)
m_fPushPitch -= fPitchDelta;
else
m_fPushPitch += fPitchDelta;
}
else if ((m_pHost.m_dwMoveRelDir & (uint)CECHostPlayer.MOVE_DIR.MD_RIGHT) != 0 || nPitchDir == 1)
{
if ((m_pHost.m_dwMoveRelDir & (uint)CECHostPlayer.MOVE_DIR.MD_BACK) != 0)
m_fPushPitch += fPitchDelta;
else
m_fPushPitch -= fPitchDelta;
}
else if (m_fPushPitch > fPitchDelta)
m_fPushPitch -= fPitchDelta;
else if (m_fPushPitch < -fPitchDelta)
m_fPushPitch += fPitchDelta;
else
m_fPushPitch = 0;
// TO DO: fix after
//A3DVECTOR3 vRight = m_pHost.GetCameraCoord().GetRight();
//float fLean = -Math.Asin(m_pHost.GetCameraCoord().GetDir().y);
//AAssist.a_Clamp(ref fLean, -lean_max_ang, lean_max_ang);
//if (Math.Abs(fLean) > DEG2RAD(3.0f))
//{
// vPushDir = a3d_RotatePosAroundAxis(vPushDir, vRight, fLean);
// vUp = a3d_RotatePosAroundAxis(g_vAxisY, vRight, fLean);
//}
//else
// vUp = EC_Utility.ToVector3(GPDataTypeHelper.g_vAxisY);
//float pitch_ang = /*m_pHost.UsingWing()*/ m_pHost.GetWingType() == enumWingType.WINGTYPE_WING ? pitch_ang_wing : pitch_ang_fly_sword;
//AAssist.a_Clamp(ref m_fPushPitch, -pitch_ang, pitch_ang);
//if (Math.Abs(m_fPushPitch) > DEG2RAD(4.0f))
// vUp = a3d_RotatePosAroundAxis(vUp, vPushDir, m_fPushPitch);
//m_pHost.StartModelMove(vPushDir, vUp, 0);
if (vPushDir != Vector3.zero)
{
m_pHost.SetRotationHPWithTime(vPushDir, 0.1f);
}
}
// if (bPush)
if (bPush || (m_pHost.m_dwMoveRelDir & (uint)(CECHostPlayer.MOVE_DIR.MD_ABSDOWN | CECHostPlayer.MOVE_DIR.MD_ABSUP)) != 0)
{
// float pa = bPush ? EC_PUSH_ACCE : 0.0f;
float pa = CECHostMove.EC_PUSH_ACCE;
float na1 = m_pHost.m_iMoveEnv == (int)MoveEnvironment.MOVEENV_AIR ? CECHostMove.EC_NACCE_AIR : CECHostMove.EC_NACCE_WATER;
float fAccel = pa + na1;
float fSpeed1 = m_pHost.m_vVelocity.Magnitude();
float fSpeed2 = fSpeed1 + fAccel * fDeltaTime;
AAssist.a_Clamp(ref fSpeed2, 0.0f, fMaxSpeed);
// Air/water move
Vector3 vVelDir = Vector3.zero;
if (bPush)
vVelDir = vPushDir;
if ((m_pHost.m_dwMoveRelDir & (uint)CECHostPlayer.MOVE_DIR.MD_ABSDOWN) != 0)
{
vVelDir += -EC_Utility.ToVector3(GPDataTypeHelper.g_vAxisY);
vVelDir.Normalize();
}
else if ((m_pHost.m_dwMoveRelDir & (uint)CECHostPlayer.MOVE_DIR.MD_ABSUP) != 0)
{
vVelDir += EC_Utility.ToVector3(GPDataTypeHelper.g_vAxisY);
vVelDir.Normalize();
}
// A3DVECTOR3 vVel = vPushDir * fSpeed2;
Vector3 vVel = vVelDir * fSpeed2;
vCurPos = m_pHost.m_MoveCtrl.AirWaterMove(EC_Utility.ToA3DVECTOR3(vVel), fDeltaTime, bInAir);
if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3)
{
Finish();
m_pHost.m_vVelocity.Clear();
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), fMaxSpeed, iMoveMode | (int)GPMoveMode.GP_MOVE_RUN);
}
else
{
m_pHost.SetPos(EC_Utility.ToVector3(vCurPos));
if (m_bUseAutoMoveDialog)
{
m_fAutoHeight = vCurPos.y / 10.0f;
}
m_pHost.m_vVelocity = EC_Utility.ToA3DVECTOR3(vVel);
m_pHost.m_MoveCtrl.SendMoveCmd(vCurPos, 2, GPDataTypeHelper.g_vOrigin, EC_Utility.ToA3DVECTOR3(vVel), iMoveMode | (int)GPMoveMode.GP_MOVE_RUN);
}
}
}
else
{
if (!m_bUseAutoMoveDialog)
Finish();
else
m_iDestType = DestTypes.DEST_2D;
m_fPushPitch = 0;
m_pHost.m_vVelocity.Clear();
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), fMaxSpeed, iMoveMode | (int)GPMoveMode.GP_MOVE_RUN);
}
}
else if (m_iDestType == DestTypes.DEST_STANDJUMP)
{
// If host player fly off when jumping up, code will go here. In the
// case, just stop move work is well.
Finish();
}
else if (IsAutoPF())
{
CECIntelligentRoute.Instance().ResetSearch();
m_bSwitchTo2D = true;
}
return true;
}
// Start gliding
protected void Glide(float fMoveTime, A3DVECTOR3 vMoveDirH, float fDeltaTime, bool bFly)
{
}
// Calculate vertical speed when fly or swim
protected float CalcFlySwimVertSpeed(float fSpeed1, float fPushDir, float fPushAccel, float fDeltaTime)
{
float pa = Math.Abs(fPushDir - 0.0f) > float.Epsilon ? fPushAccel : 0.0f;
float na = 0.0f, fMaxSpeed;
if (m_pHost.m_iMoveEnv == CECPlayer.Move_environment.MOVEENV_AIR)
{
na = CECHostMove.EC_NACCE_AIR;
fMaxSpeed = m_pHost.GetFlySpeed();
}
else
{
na = CECHostMove.EC_NACCE_WATER;
fMaxSpeed = m_pHost.GetSwimSpeedSev();
}
// When player free fall into water, fSpeed1 may be >= fMaxSpeed
if (Math.Abs(fSpeed1) > fMaxSpeed)
{
na *= 2.0f;
if (fPushDir * fSpeed1 > 0.0f)
pa = 0.0f;
}
// Vertical accelerate
float fAccel = 0.0f;
if (fPushDir > 0.0f)
fAccel = pa + na;
else if (fPushDir < 0.0f)
fAccel = -(pa + na);
else if (fSpeed1 > 0.0f)
fAccel = na;
else if (fSpeed1 < 0.0f)
fAccel = -na;
// Vertical speed
float fSpeed2 = fSpeed1 + fAccel * fDeltaTime;
if (Math.Abs(pa - 0.0f) < float.Epsilon && fSpeed2 * fSpeed1 < 0.0f)
fSpeed2 = 0.0f;
// If accelerate and speed on same direction, limit speed
if (fAccel * fSpeed2 > 0.0f)
AAssist.a_Clamp(ref fSpeed2, -fMaxSpeed, fMaxSpeed);
return fSpeed2;
}
protected void ClearResetUseAutoPF()
{
m_bResetAutoPF = false;
}
protected void UpdateResetUseAutoPF()
{
if (!m_bResetAutoPF)
{
return;
}
#if ENABLE_CEC_INTELLIGENT_ROUTE
global::BrewMonster.Scripts.CECIntelligentRoute.Instance().SetUsage(global::BrewMonster.Scripts.CECIntelligentRoute.Usage.enumUsageWorkMove);
global::BrewMonster.Scripts.CECIntelligentRoute.Instance().ResetSearch();
if (IsAutoPF())
{
bool bSwitchTo2D = true;
while (true)
{
if (m_pHost.IsFlying())
{
if (CECUIManager.Instance != null)
{
// string message = $"Please deactive the fly mode to start the path finding.";
// CECUIManager.Instance.ShowMessageBox(
// "Fly Mode", // 飞行模式
// message, // 消息
// BrewMonster.MessageBoxType.YesButton
// );
// Finish();
//return;
}
break;
}
// Brush test is not fully ported yet; pass null for now (static movemap only).
// BrushTest 暂未完整移植;当前先传 null(仅静态 movemap)。
var ret = global::BrewMonster.Scripts.CECIntelligentRoute.Instance().Search(
m_pHost.GetPos(),
m_vMoveDest,
null);
if (ret == CECIntelligentRoute.SearchResult.enumSearchNoPath)
{
// Calculate map coordinates from world coordinates
// 从世界坐标计算地图坐标
// Map coord formula: (world / 10) + offset (X: +400, Z: +550)
// 地图坐标公式:(世界坐标 / 10) + 偏移量 (X: +400, Z: +550)
int mapX = Mathf.RoundToInt(m_vMoveDest.x / 10.0f) + 400;
int mapY = Mathf.RoundToInt(m_vMoveDest.y / 10.0f);
int mapZ = Mathf.RoundToInt(m_vMoveDest.z / 10.0f) + 550;
// Show popup notification to player that path cannot be found
// 显示弹窗通知玩家无法找到路径
if (CECUIManager.Instance != null)
{
// string message = $"Cannot find path to target position.\nPlease move manually to target location.\n\nMap Coordinates: ({mapX}, {mapZ}, ↑{mapY})";
// string messageCN = $"无法找到到目标位置的路径。\n请手动移动到目标位置。\n\n地图坐标: ({mapX}, {mapZ}, ↑{mapY})";
//
// // CECUIManager.Instance.ShowMessageBox(
// // "Path Not Found", // 路径未找到
// // message, // English message with map coordinates
// // BrewMonster.MessageBoxType.YesButton
// // );
// CECUIManager.Instance.ShowMessageBoxYes("Path Not Found", message, null, null);
}
else
{
Debug.LogWarning($"[CECIntelligentRoute] Cannot find path to target position. Map Coordinates: ({mapX}, {mapZ}, ↑{mapY}). Please move manually.");
}
Finish();
break;
}
else if (ret != CECIntelligentRoute.SearchResult.enumSearchSuccess)
{
break;
}
bSwitchTo2D = false;
break;
}
if (bSwitchTo2D)
{
m_bSwitchTo2D = true;
}
}
#endif
ClearResetUseAutoPF();
}
protected virtual uint GetMoveRelDirMask()
{
// TODO: hook up CECHostPlayer move-direction flags when available.
return m_pHost.m_dwMoveRelDir;
}
private void UpdateFacingFromDelta(A3DVECTOR3 nextPos)
{
A3DVECTOR3 prevPos = m_pHost.GetPos();
Vector3 delta = EC_Utility.ToVector3(nextPos - prevPos);
delta.y = 0.0f;
if (delta.sqrMagnitude > 1e-6f)
{
delta.Normalize();
m_pHost.SetDirAndUp(delta, Vector3.up);
}
}
private A3DVECTOR3 GetCurrentModelDir()
{
Vector3 forward = m_pHost != null ? m_pHost.transform.forward : Vector3.forward;
return new A3DVECTOR3(forward.x, forward.y, forward.z);
}
}
}