520 lines
18 KiB
C#
520 lines
18 KiB
C#
/*
|
|
* FILE: EC_HPWorkFly.cs
|
|
*
|
|
* DESCRIPTION: Host player work classes for flying, flash move, and passive movement
|
|
*
|
|
* CONVERTED FROM: EC_HPWorkFly.cpp/EC_HPWorkFly.h
|
|
*
|
|
* CREATED BY: Duyuxin, 2004/11/23
|
|
*
|
|
* Copyright (c) 2004 Archosaur Studio, All Rights Reserved.
|
|
*/
|
|
|
|
using UnityEngine;
|
|
using CSNetwork.GPDataType;
|
|
using BrewMonster.Scripts.Skills;
|
|
using BrewMonster;
|
|
|
|
namespace BrewMonster.Scripts
|
|
{
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Class CECHPWorkFly
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
public class CECHPWorkFly : CECHPWork
|
|
{
|
|
// Constants
|
|
private const uint FLY_PREPARE = 420;
|
|
private const uint FLY_LAUNCH = 1400;
|
|
private const float LAUNCH_HEIGHT = 2.0f;
|
|
private const float LAUNCH_VELOCITY = LAUNCH_HEIGHT * 1000.0f / FLY_PREPARE;
|
|
|
|
// Attributes
|
|
public uint m_dwLaunchTime;
|
|
public bool m_bContinueFly;
|
|
|
|
protected A3DVECTOR3 m_vDestPos; // 目的地停止位置 / Destination stop position
|
|
protected bool m_bAddSpeed; // 添加一个垂直速度 / Add a vertical speed
|
|
|
|
// Constructor and Destructor
|
|
public CECHPWorkFly(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_FLYOFF, pWorkMan)
|
|
{
|
|
m_dwMask = Work_mask.MASK_FLYOFF;
|
|
m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_MOVETOPOS;
|
|
|
|
Reset();
|
|
}
|
|
|
|
// Reset work
|
|
public override void Reset()
|
|
{
|
|
base.Reset();
|
|
|
|
m_dwLaunchTime = 0;
|
|
m_bAddSpeed = true;
|
|
m_bContinueFly = false;
|
|
}
|
|
|
|
// Copy work data
|
|
public override bool CopyData(CECHPWork pWork)
|
|
{
|
|
if (!base.CopyData(pWork))
|
|
return false;
|
|
|
|
CECHPWorkFly pSrc = (CECHPWorkFly)pWork;
|
|
|
|
m_vDestPos = pSrc.m_vDestPos;
|
|
m_dwLaunchTime = pSrc.m_dwLaunchTime;
|
|
m_bContinueFly = pSrc.m_bContinueFly;
|
|
m_bAddSpeed = pSrc.m_bAddSpeed;
|
|
|
|
return true;
|
|
}
|
|
|
|
// Work is cancel
|
|
public override void Cancel()
|
|
{
|
|
m_pHost.m_CDRInfo.vAbsVelocity.Clear();
|
|
m_pHost.m_CDRInfo.fYVel = 0.0f;
|
|
base.Cancel();
|
|
}
|
|
|
|
// This work is do player moving?
|
|
public override bool IsMoving()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// On first tick
|
|
protected override void OnFirstTick()
|
|
{
|
|
m_pHost.m_iMoveEnv = (int)CECPlayer.Move_environment.MOVEENV_AIR;
|
|
m_pHost.m_iMoveMode = (int)MoveMode.MOVE_MOVE;
|
|
|
|
m_pHost.m_vVelocity.Clear();
|
|
m_pHost.m_vAccel.Clear();
|
|
m_pHost.ResetJump();
|
|
|
|
m_vDestPos = m_pHost.GetPos();
|
|
m_vDestPos.y += LAUNCH_HEIGHT;
|
|
|
|
// for test: solving the pull down problem, by sxw 2009-09-03
|
|
m_bAddSpeed = false;
|
|
if (m_pHost.m_GndInfo.fGndHei > m_pHost.m_GndInfo.fWaterHei)
|
|
{
|
|
if (m_pHost.GetPos().y - m_pHost.m_GndInfo.fGndHei < 0.2f)
|
|
m_bAddSpeed = true;
|
|
}
|
|
else
|
|
m_bAddSpeed = true;
|
|
|
|
m_pHost.ShowWing(true);
|
|
|
|
if (m_pHost.GetWingType() == enumWingType.WINGTYPE_WING)
|
|
m_pHost.PlayAction((int)PLAYER_ACTION_TYPE.ACT_TAKEOFF);
|
|
else
|
|
{
|
|
m_pHost.PlayAction((int)PLAYER_ACTION_TYPE.ACT_TAKEOFF_SWORD);
|
|
}
|
|
}
|
|
|
|
// Tick routine
|
|
public override bool Tick(float dwDeltaTime)
|
|
{
|
|
base.Tick(dwDeltaTime);
|
|
m_dwLaunchTime += (uint)(dwDeltaTime * 1000.0f);
|
|
|
|
if (m_dwLaunchTime < FLY_PREPARE)
|
|
{
|
|
if (m_bContinueFly)
|
|
return true;
|
|
else
|
|
{
|
|
float fDeltaTime = dwDeltaTime;
|
|
float fVerSpeed = m_bAddSpeed ? LAUNCH_VELOCITY : 0.0f;
|
|
m_bAddSpeed = false;
|
|
A3DVECTOR3 vCurPos = m_pHost.m_MoveCtrl.GroundMove(new A3DVECTOR3 (0), 0.0f, fDeltaTime, fVerSpeed, 0.0f);
|
|
m_pHost.SetPos(EC_Utility.ToVector3(vCurPos));
|
|
}
|
|
}
|
|
else if (m_dwLaunchTime < FLY_LAUNCH && !m_bContinueFly)
|
|
return true;
|
|
else
|
|
{
|
|
m_bFinished = true;
|
|
A3DVECTOR3 vCurPos = m_pHost.GetPos();
|
|
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), 0, (int)GPMoveMode.GP_MOVE_AIR | (int)GPMoveMode.GP_MOVE_RUN);
|
|
|
|
// TODO: Implement GetWingType and wing action constants when wing system is ready
|
|
m_pHost.PlayAction(
|
|
m_pHost.GetWingType() == enumWingType.WINGTYPE_WING ? (int)PLAYER_ACTION_TYPE.ACT_HANGINAIR : (int)PLAYER_ACTION_TYPE.ACT_HANGINAIR_SWORD,
|
|
true,
|
|
300);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Class CECHPWorkFMove
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
public class CECHPWorkFMove : CECHPWork
|
|
{
|
|
// Attributes
|
|
protected A3DVECTOR3 m_vDestPos; // 目的地位置 / Destination position
|
|
protected A3DVECTOR3 m_vMoveDir; // 移动方向 / Move direction
|
|
protected float m_fSpeed; // 移动速度 / Move speed
|
|
protected float m_fDist; // 距离 / Distance
|
|
protected float m_fDistCnt; // 距离计数器 / Distance counter
|
|
protected int m_iFMoveSkillID; // Flash move skill id
|
|
|
|
// Constructor and Destructor
|
|
public CECHPWorkFMove(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_FLASHMOVE, pWorkMan)
|
|
{
|
|
m_dwMask = Work_mask.MASK_FLYOFF;
|
|
m_dwTransMask = Work_mask.MASK_STAND;
|
|
|
|
Reset();
|
|
}
|
|
|
|
// Reset work
|
|
public override void Reset()
|
|
{
|
|
base.Reset();
|
|
|
|
m_fSpeed = 0.0f;
|
|
m_fDist = 0.0f;
|
|
m_fDistCnt = 0.0f;
|
|
m_iFMoveSkillID = 0;
|
|
}
|
|
|
|
// Copy work data
|
|
public override bool CopyData(CECHPWork pWork)
|
|
{
|
|
if (!base.CopyData(pWork))
|
|
return false;
|
|
|
|
CECHPWorkFMove pSrc = (CECHPWorkFMove)pWork;
|
|
|
|
m_vDestPos = pSrc.m_vDestPos;
|
|
m_fSpeed = pSrc.m_fSpeed;
|
|
m_fDist = pSrc.m_fDist;
|
|
m_fDistCnt = pSrc.m_fDistCnt;
|
|
m_vMoveDir = pSrc.m_vMoveDir;
|
|
m_iFMoveSkillID = pSrc.m_iFMoveSkillID;
|
|
return true;
|
|
}
|
|
|
|
// This work is do player moving?
|
|
public override bool IsMoving()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Prepare to move
|
|
public void PrepareMove(A3DVECTOR3 vDestPos, float fMoveTime, int iFMoveSkillID = 0)
|
|
{
|
|
// ASSERT(fMoveTime > 0.0f);
|
|
fMoveTime = Mathf.Max(fMoveTime, 0.001f * 50);
|
|
|
|
m_vDestPos = vDestPos;
|
|
m_fDistCnt = 0.0f;
|
|
m_vMoveDir = vDestPos - m_pHost.GetPos();
|
|
m_fDist = m_vMoveDir.Magnitude();
|
|
m_vMoveDir.Normalize();
|
|
m_fSpeed = m_fDist / fMoveTime;
|
|
m_iFMoveSkillID = iFMoveSkillID;
|
|
}
|
|
|
|
// On first tick
|
|
protected override void OnFirstTick()
|
|
{
|
|
A3DVECTOR3 newPos = m_pHost.GetPos() + new A3DVECTOR3(0.0f, 0.7f, 0.0f);
|
|
m_pHost.SetPos(EC_Utility.ToVector3(newPos));
|
|
m_pHost.m_MoveCtrl.SetHostLastPos(newPos);
|
|
|
|
if (m_iFMoveSkillID > 0)
|
|
{
|
|
int reffake = 0;
|
|
// TODO: Verify PlayAttackEffect signature when implemented
|
|
m_pHost.PlayAttackEffect(m_pHost.GetSelectedTarget(), m_iFMoveSkillID, 0, -2, 0, 0, ref reffake );
|
|
}
|
|
else
|
|
{
|
|
m_pHost.PlayAction((int)PLAYER_ACTION_TYPE.ACT_JUMP_START, true, 0);
|
|
m_pHost.PlayAction((int)PLAYER_ACTION_TYPE.ACT_JUMP_LOOP, false, 0, true);
|
|
}
|
|
|
|
// Motion blur effect (if needed, can be implemented later)
|
|
// CECFullGlowRender* pGlow = g_pGame->GetGameRun()->GetFullGlowRender();
|
|
// if (pGlow && pGlow->IsGlowOn())
|
|
// pGlow->SetMotionBlur(0.8f, 0.8f, 1);
|
|
}
|
|
|
|
// Tick routine
|
|
public override bool Tick(float dwDeltaTime)
|
|
{
|
|
base.Tick(dwDeltaTime);
|
|
float fMoveDelta = m_fSpeed * dwDeltaTime;
|
|
A3DVECTOR3 vCurPos = m_pHost.GetPos();
|
|
|
|
if (m_fDistCnt + fMoveDelta >= m_fDist)
|
|
{
|
|
fMoveDelta = m_fDist - m_fDistCnt;
|
|
m_fDistCnt = m_fDist;
|
|
|
|
m_pHost.SetPos(EC_Utility.ToVector3(m_vDestPos));
|
|
m_pHost.m_MoveCtrl.Reset();
|
|
m_pHost.m_MoveCtrl.SetHostLastPos(m_vDestPos);
|
|
m_pHost.m_MoveCtrl.SetLastSevPos(m_vDestPos);
|
|
|
|
if (!m_pHost.m_CDRInfo.vTPNormal.IsZero())
|
|
m_pHost.SetGroundNormal(m_pHost.m_CDRInfo.vTPNormal);
|
|
|
|
// Motion blur effect (if needed, can be implemented later)
|
|
// CECFullGlowRender* pGlow = g_pGame->GetGameRun()->GetFullGlowRender();
|
|
// if (pGlow && pGlow->IsGlowOn())
|
|
// pGlow->SetMotionBlur(0.8f, 0.0f, 3000);
|
|
|
|
// Finish work
|
|
Finish();
|
|
}
|
|
else
|
|
{
|
|
m_fDistCnt += fMoveDelta;
|
|
|
|
vCurPos += m_vMoveDir * fMoveDelta;
|
|
m_pHost.SetPos(EC_Utility.ToVector3(vCurPos));
|
|
m_pHost.m_MoveCtrl.SetHostLastPos(vCurPos);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Finish work
|
|
protected void Finish()
|
|
{
|
|
m_bFinished = true;
|
|
|
|
CECComboSkill pcs = m_pHost.m_pComboSkill;
|
|
if (pcs != null && !pcs.IsStop())
|
|
pcs.Continue(false);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Class CECHPWorkPassiveMove
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
public class CECHPWorkPassiveMove : CECHPWork
|
|
{
|
|
// Passive move type
|
|
public static class PassiveMoveType
|
|
{
|
|
public const int PASSIVE_DIRECT = 0; // cmd_player_teleport mode == 0
|
|
public const int PASSIVE_PULL = 1; // cmd_player_teleport mode == 1
|
|
public const int PASSIVE_KNOCKBACK = 2; // cmd_player_knockback
|
|
}
|
|
|
|
// Attributes
|
|
protected A3DVECTOR3 m_vStartPos; // 起始位置,传送开始时起始位置 / Start position when teleport begins
|
|
protected A3DVECTOR3 m_vDestPos; // 目标位置,传送后结果 / Destination position, result after teleport
|
|
protected A3DVECTOR3 m_vMoveDir; // 移动方向 / Move direction
|
|
protected float m_fSpeed; // 移动速度 / Move speed
|
|
protected int m_nMoveTime; // 移动所需总时间(ms) / Total time required for movement (ms)
|
|
protected int m_nMoveTimeCnt; // 累积的移动时间(ms) / Accumulated movement time (ms)
|
|
protected int m_nWaitTime; // 移动完成后,进行服务器同步等待的时间(ms) / Wait time for server sync after movement (ms)
|
|
protected int m_nWaitTimeCnt; // 累积的同步等待时间(ms) / Accumulated sync wait time (ms)
|
|
|
|
// Constructor and Destructor
|
|
public CECHPWorkPassiveMove(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_PASSIVEMOVE, pWorkMan)
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
// Reset work
|
|
public override void Reset()
|
|
{
|
|
base.Reset();
|
|
|
|
m_fSpeed = 0.0f;
|
|
m_nMoveTime = 0;
|
|
m_nMoveTimeCnt = 0;
|
|
m_nWaitTime = 0;
|
|
m_nWaitTimeCnt = 0;
|
|
}
|
|
|
|
// Copy work data
|
|
public override bool CopyData(CECHPWork pWork)
|
|
{
|
|
if (!base.CopyData(pWork))
|
|
return false;
|
|
|
|
CECHPWorkPassiveMove pSrc = (CECHPWorkPassiveMove)pWork;
|
|
|
|
m_vStartPos = pSrc.m_vStartPos;
|
|
m_vDestPos = pSrc.m_vDestPos;
|
|
m_vMoveDir = pSrc.m_vMoveDir;
|
|
m_fSpeed = pSrc.m_fSpeed;
|
|
m_nMoveTime = pSrc.m_nMoveTime;
|
|
m_nMoveTimeCnt = pSrc.m_nMoveTimeCnt;
|
|
m_nWaitTime = pSrc.m_nWaitTime;
|
|
m_nWaitTimeCnt = pSrc.m_nWaitTimeCnt;
|
|
return true;
|
|
}
|
|
|
|
// This work is do player moving?
|
|
public override bool IsMoving()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Prepare to move
|
|
public void PrepareMove(A3DVECTOR3 vDestPos, int nMoveTime)
|
|
{
|
|
// ASSERT(nMoveTime > 0);
|
|
nMoveTime = Mathf.Max(nMoveTime, 50);
|
|
A3DVECTOR3 vCurPos = m_pHost.GetPos();
|
|
|
|
m_vStartPos = vCurPos;
|
|
m_vDestPos = vDestPos;
|
|
m_vMoveDir = vDestPos - vCurPos;
|
|
|
|
// 移动速度保持不变(与等待时间无关),因此为等待时间长,则移动速度变大 / Movement speed remains constant (independent of wait time), so longer wait time means faster movement speed
|
|
float fDist = m_vMoveDir.Magnitude();
|
|
m_vMoveDir.Normalize();
|
|
m_fSpeed = fDist / (nMoveTime * 0.001f);
|
|
|
|
// 计算移动时间、等待时间、移动位置 / Calculate movement time, wait time, movement position
|
|
m_nMoveTime = nMoveTime;
|
|
m_nWaitTime = nMoveTime - m_nMoveTime;
|
|
m_nWaitTimeCnt = 0;
|
|
m_nMoveTimeCnt = 0;
|
|
}
|
|
|
|
// On first tick
|
|
protected override void OnFirstTick()
|
|
{
|
|
m_pHost.PlayAction((int)PLAYER_ACTION_TYPE.ACT_STRIKEBACK, true, 0);
|
|
|
|
// Motion blur effect (if needed, can be implemented later)
|
|
// CECFullGlowRender* pGlow = g_pGame->GetGameRun()->GetFullGlowRender();
|
|
// if (pGlow && pGlow->IsGlowOn())
|
|
// pGlow->SetMotionBlur(0.8f, 0.8f, 1);
|
|
}
|
|
|
|
// Helper function: Calculate no brush collide position
|
|
// 计算非冲突位置 / Calculate non-collision position
|
|
private bool CalculateNoBrushCollidePos(int nMaxTryTimes, float fStep, float fMaxMove, bool bDownward,
|
|
A3DVECTOR3 vCurPos, A3DVECTOR3 vExt, out A3DVECTOR3 vPos)
|
|
{
|
|
// nMaxTryTimes: 尝试发出射线次数 / Max try times for raycasting
|
|
// fStep: 每次尝试向垂直方向上下移动(起始为向下) / Each attempt moves vertically up or down (initially down)
|
|
// fMaxMove: 尝试发出射线距离(起始为向下) / Max distance for raycasting (initially down)
|
|
// bDownward: 是否向下移动 / Whether to move downward
|
|
// vCurPos: 起始参考位置 / Starting reference position
|
|
// vExt: 包围盒大小 / Bounding box size
|
|
// vPos: 返回的非冲突位置(返回值为 true 有效) / Returned non-collision position (valid if return value is true)
|
|
|
|
vPos = vCurPos;
|
|
bool bOK = false;
|
|
|
|
// For now, simplified collision detection
|
|
// TODO: Implement proper brush collision detection with raycasting
|
|
// This would require access to world terrain and collision systems
|
|
|
|
return bOK;
|
|
}
|
|
|
|
// Tick routine
|
|
public override bool Tick(float dwDeltaTime)
|
|
{
|
|
base.Tick(dwDeltaTime);
|
|
|
|
int dwDeltaTimeMs = (int)(dwDeltaTime * 1000.0f);
|
|
|
|
// 计算本次的移动时间、等待时间 / Calculate movement time and wait time for this tick
|
|
int nMoveTime = dwDeltaTimeMs;
|
|
int nWaitTime = 0;
|
|
if (nMoveTime + m_nMoveTimeCnt > m_nMoveTime)
|
|
{
|
|
nMoveTime = m_nMoveTime - m_nMoveTimeCnt;
|
|
nWaitTime = dwDeltaTimeMs - nMoveTime;
|
|
if (nWaitTime + m_nWaitTimeCnt > m_nWaitTime)
|
|
nWaitTime = m_nWaitTime - m_nWaitTimeCnt;
|
|
}
|
|
|
|
if (nMoveTime > 0)
|
|
{
|
|
// 需要移动 / Need to move
|
|
|
|
// 计算移动后的距离 / Calculate distance after movement
|
|
float fMoveDelta = m_fSpeed * (m_nMoveTimeCnt + nMoveTime) * 0.001f;
|
|
A3DVECTOR3 vCurPos = m_vStartPos;
|
|
vCurPos += m_vMoveDir * fMoveDelta;
|
|
|
|
// 根据地形的高度调整高度,保证在地面之上 / Adjust height based on terrain to ensure above ground
|
|
// TODO: Implement proper terrain height query
|
|
// float terrainHeight = g_pGame->GetGameRun()->GetWorld()->GetTerrainHeight(vCurPos);
|
|
// vCurPos.y = Mathf.Max(vCurPos.y, terrainHeight);
|
|
|
|
A3DVECTOR3 vExt = m_pHost.m_CDRInfo.vExtent;
|
|
A3DVECTOR3 vStart = vCurPos + new A3DVECTOR3(0,1,0) * vExt.y;
|
|
|
|
// 检查当前位置是否与刷子冲突 / Check if current position collides with brush
|
|
// TODO: Implement proper collision detection
|
|
// For now, just set the position directly
|
|
|
|
// 记录新位置 / Record new position
|
|
m_pHost.SetPos(EC_Utility.ToVector3(vCurPos));
|
|
m_pHost.m_MoveCtrl.SetHostLastPos(vCurPos);
|
|
|
|
// 记录时间 / Record time
|
|
m_nMoveTimeCnt += nMoveTime;
|
|
}
|
|
|
|
if (nWaitTime > 0)
|
|
{
|
|
// 需要等待,与服务器同步 / Need to wait, sync with server
|
|
m_nWaitTimeCnt += nWaitTime;
|
|
}
|
|
|
|
if (m_nMoveTimeCnt >= m_nMoveTime &&
|
|
m_nWaitTimeCnt >= m_nWaitTime)
|
|
{
|
|
// 工作完成 / Work finished
|
|
|
|
A3DVECTOR3 vCurPos = m_pHost.GetPos();
|
|
|
|
m_pHost.m_MoveCtrl.Reset();
|
|
m_pHost.m_MoveCtrl.SetHostLastPos(vCurPos);
|
|
m_pHost.m_MoveCtrl.SetLastSevPos(vCurPos);
|
|
|
|
// Motion blur effect (if needed, can be implemented later)
|
|
// CECFullGlowRender* pGlow = g_pGame->GetGameRun()->GetFullGlowRender();
|
|
// if (pGlow && pGlow->IsGlowOn())
|
|
// pGlow->SetMotionBlur(0.8f, 0.0f, 3000);
|
|
|
|
Finish();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Finish work
|
|
protected void Finish()
|
|
{
|
|
m_bFinished = true;
|
|
}
|
|
}
|
|
}
|
|
|