DragonNest/Server/DNGameServer/DnVehicleActor.cpp
Cussrro 47f7895977 Revert "修复编码问题"
This reverts commit 9e69c01767.
2024-12-21 10:04:04 +08:00

614 lines
No EOL
19 KiB
C++

#include "stdafx.h"
#include <mmsystem.h>
#include "TaskManager.h"
#include "DNGameDataManager.h"
#include "DnWorld.h"
#include "navigationmesh.h"
#include "DnVehicleActor.h"
#include "DnActorClassDefine.h"
#include "DnMovableChecker.h"
#include "DnJumpableChecker.h"
#include "DnGroundMovableChecker.h"
#include "DnStateBlow.h"
#include "MAWalkMovement.h"
#include "DnGameTask.h"
#include "DNUserSession.h"
CDnVehicleActor::CDnVehicleActor( CMultiRoom *pRoom, int nClassID )
: CDnActor( pRoom, nClassID )
{
CDnActionBase::Initialize( this );
CDnVehicleState::Initialize(nClassID);
m_bAttachToPlayer = false;
m_hMyActor.Identity();
for(int i=0;i<2;i++)
m_hSimpleParts[i].Identity();
m_cMovePushKeyFlag = 0;
m_dwHairColor = 0;
// 스핵관련
m_dwSyncDatumTick = 0;
m_vLastValidPos = EtVector3( 0.f, 0.f, 0.f );
#ifdef PRE_ADD_VEHICLE_ACTION_STRING
m_strVehicleActionString = "Vehicle_"; // As Default
#endif
SetHP(10); // 탈것의 체력은 현재 따로 테이블이나 데이터를 적용하지않고있습니다. 맞게되면 바로 내리게됩니다.
SetMaxHP(10);
}
CDnVehicleActor::~CDnVehicleActor()
{
for(int i=0;i<2;i++)
SAFE_RELEASE_SPTR( m_hSimpleParts[i] );
}
void CDnVehicleActor::ProcessDie( LOCAL_TIME LocalTime, float fDelta )
{
if( !IsDie() ) return;
if(GetMyPlayerActor())
{
CDnPlayerActor *pPlayerActor = static_cast<CDnPlayerActor*>(GetMyPlayerActor().GetPointer());
if(pPlayerActor->IsVehicleMode())
pPlayerActor->ForceUnRideVehicle();
// 탈것은 자체소멸이아닌 캐릭터 입장에서 내리는것으로 합니다.
// 패킷을보내고 UnrideVehicle이 호출되고난이후에 , SetDestroy가 되는형태입니다.
}
// m_fDieDelta -= fDelta; // 일단 다이델타 쓰는경우가 없기때문에 스킵해줍니다.
// if( m_fDieDelta <= 0.f ) {
// SetDestroy();
// return;
// }
}
MAMovementBase* CDnVehicleActor::CreateMovement()
{
MAMovementBase* pMovement = new IBoostPoolMAWalkMovement();
return pMovement;
}
bool CDnVehicleActor::Initialize()
{
CDnActor::Initialize();
if( m_hObject ) {
m_hObject->SetCollisionGroup( COLLISION_GROUP_DYNAMIC( 1 ) );
m_hObject->SetTargetCollisionGroup( COLLISION_GROUP_STATIC( 1 ) | COLLISION_GROUP_DYNAMIC( 2 ) | COLLISION_GROUP_DYNAMIC( 3 ) ); // 충돌 그룹을 일단 플레이어 엑터와 동일한 수준으로 설정 해 놓음.*/
}
// SetPartsColor(m_hSimpleParts[Hair]->GetObjectHandle(),"g_CustomColor",EtInterface::textcolor::SILVER); // 헤어 칼라를 설정해줍니다. - 아직 정보 없음 -
// SetPartsColor(m_hObject,"g_MaterialAmbient",EtInterface::textcolor::SILVER);
// g_MaterialAmbient
// g_MaterialDiffuse 탈것 몸통에 적용되는 값 !
return true;
}
void CDnVehicleActor::EquipItem(TItem tInfo)
{
TVehiclePartsData *pVehicleParts = g_pDataManager->GetVehiclePartsData(tInfo.nItemID);
if (!pVehicleParts) return;
if((pVehicleParts->nVehiclePartsType != Vehicle::Slot::Saddle) && (pVehicleParts->nVehiclePartsType != Vehicle::Slot::Hair))
return;
if(m_hSimpleParts[pVehicleParts->nVehiclePartsType-1])
{
SAFE_RELEASE_SPTR( m_hSimpleParts[pVehicleParts->nVehiclePartsType-1] );
m_hSimpleParts[pVehicleParts->nVehiclePartsType-1] = CDnSimpleParts::CreateParts( GetRoom(), tInfo.nItemID, pVehicleParts->strSkinName.c_str(), m_szAniFileName.c_str() );
// 아이템 정보 설정 //
m_hSimpleParts[pVehicleParts->nVehiclePartsType-1]->InitializeItem(tInfo.nItemID,0,tInfo.cOption,0,tInfo.cPotential,tInfo.cSealCount,tInfo.bSoulbound);
m_hSimpleParts[pVehicleParts->nVehiclePartsType-1]->SetSerialID(tInfo.nSerial);
//////////////////////
if(pVehicleParts->nVehiclePartsType-1 == Vehicle::Parts::Hair)
ChangeHairColor(m_dwHairColor);
}
else if(m_hSimpleParts[pVehicleParts->nVehiclePartsType-1] == NULL)
{
m_hSimpleParts[pVehicleParts->nVehiclePartsType-1] = CDnSimpleParts::CreateParts( GetRoom(), tInfo.nItemID, pVehicleParts->strSkinName.c_str(), m_szAniFileName.c_str() );
m_hSimpleParts[pVehicleParts->nVehiclePartsType-1]->InitializeItem(tInfo.nItemID,0);
// 아이템 정보 설정 //
m_hSimpleParts[pVehicleParts->nVehiclePartsType-1]->InitializeItem(tInfo.nItemID,0,tInfo.cOption,0,tInfo.cPotential,tInfo.cSealCount,tInfo.bSoulbound);
m_hSimpleParts[pVehicleParts->nVehiclePartsType-1]->SetSerialID(tInfo.nSerial);
//////////////////////
if(pVehicleParts->nVehiclePartsType-1 == Vehicle::Parts::Hair)
ChangeHairColor(m_dwHairColor);
}
}
void CDnVehicleActor::UnEquipItem(int nSlot)
{
TVehiclePartsData *pVehicleParts = g_pDataManager->GetVehiclePartsData(nSlot);
if (!pVehicleParts) return;
if((pVehicleParts->nVehiclePartsType != Vehicle::Slot::Saddle) && (pVehicleParts->nVehiclePartsType != Vehicle::Slot::Hair))
return;
if(m_hSimpleParts[pVehicleParts->nVehiclePartsType-1])
{
m_hSimpleParts[pVehicleParts->nVehiclePartsType-1]->FreeObject();
}
else
{
OutputDebug("탈것 장착템이 없는데 벗으려고 합니다");
}
}
void CDnVehicleActor::SetDefaultParts()
{
TVehicleData *pVehicle = g_pDataManager->GetVehicleData(m_nItemID);
if (!Vehicle) return;
// 기본 파츠는 아이템 아이디에 대한 정보 밖에없습니다. //
TItem tItem;
memset(&tItem, 0, sizeof(tItem));
tItem.nItemID = pVehicle->nDefaultParts1;
EquipItem(tItem);
tItem.nItemID = pVehicle->nDefaultParts2;
EquipItem(tItem);
}
void CDnVehicleActor::ChangeHairColor(DWORD dwColor)
{
if(!m_hSimpleParts[Vehicle::Parts::Hair])
return;
if(dwColor !=0 )
m_dwHairColor = dwColor;
}
void CDnVehicleActor::SetDefaultHairColor()
{
int nVehicleDefaultColor = g_pDataManager->GetItemTypeParam1(m_nItemID);
ChangeHairColor(nVehicleDefaultColor);
if(m_dwHairColor == 0)
m_dwHairColor = nVehicleDefaultColor;
}
void CDnVehicleActor::Process(LOCAL_TIME LocalTime, float fDelta )
{
CDnActor::Process( LocalTime, fDelta );//
PreProcess( LocalTime, fDelta);//
if( 0 < GetCantXZMoveSEReferenceCount() )
m_vAniDistance.x = m_vAniDistance.z = 0.0f;
m_pMovement->Process( LocalTime, fDelta );
MASingleBody::Process( m_Cross, LocalTime, fDelta );//
// 게임서버의 SetParents 효과
if(m_hMyActor && !m_hMyActor->IsDestroy())
m_hMyActor->SetPosition(*GetPosition());
}
void CDnVehicleActor::OnSignal( SignalTypeEnum Type, void *pPtr, LOCAL_TIME LocalTime, LOCAL_TIME SignalStartTime, LOCAL_TIME SignalEndTime, int nSignalIndex )
{
switch( Type ) {
case STE_Projectile:
return;
case STE_Jump:
{
JumpStruct *pStruct = (JumpStruct *)pPtr;
EtVector2 vVec( 0.f, 0.f );
// 애니메이션 키 까지 이동 불가일때는 방향키 먹지 않도록 처리한다.
if( 0 == GetCantXZMoveSEReferenceCount() )
{
if( !pStruct->bIgnoreJumpDir) {
if( m_cMovePushKeyFlag & 0x01 ) vVec.x -= 1.f;
if( m_cMovePushKeyFlag & 0x02 ) vVec.x += 1.f;
if( m_cMovePushKeyFlag & 0x04 ) vVec.y += 1.f;
if( m_cMovePushKeyFlag & 0x08 ) vVec.y -= 1.f;
EtVec2Normalize( &vVec, &vVec );
}
}
if( pStruct->bResetPrevVelocity ) {
SetVelocityY( 0.f );
SetResistanceY( 0.f );
}
Jump( pStruct->fJumpVelocity , vVec );
SetResistanceY( pStruct->fJumpResistance );
}
return;
}
CDnActor::OnSignal( Type, pPtr, LocalTime, SignalStartTime, SignalEndTime, nSignalIndex );
}
void CDnVehicleActor::CmdMove( EtVector3 &vPos, const char *szActionName, int nLoopCount, float fBlendFrame )
{
MovePos( vPos, false );
SetActionQueue( szActionName, nLoopCount, fBlendFrame );
}
void CDnVehicleActor::CmdStop( const char *szActionName, int nLoopCount, float fBlendFrame, float fStartFrame, bool bResetStop )
{
MAMovementBase *pMovement = GetMovement();
if( !pMovement ) return;
pMovement->ResetMove();
SetActionQueue( szActionName, nLoopCount, fBlendFrame, fStartFrame );
}
void CDnVehicleActor::CmdAction( const char *szActionName, int nLoopCount, float fBlendFrame, bool bCheckOverlapAction,
bool bFromStateBlow/* = false*/, bool bSkillChain/* = false*/ )
{
CDnActor::CmdAction( szActionName, nLoopCount, fBlendFrame, bCheckOverlapAction, bFromStateBlow, bSkillChain );
}
void CDnVehicleActor::OnDrop( float fCurVelocity )
{
if( IsAir() ) {
if( !IsHit() ) {
char szStr[64];
sprintf_s( szStr, "%s_Landing", GetCurrentAction() );
if( IsExistAction( szStr ) )
{
SetActionQueue( szStr, 0, 0.f, 0.f, true, false );
}
else {// 만약에 없을경우에 하늘에서 병신짓하구있어서 넣어놉니다. 일단은 마춰서 넣어주는거임
if( GetVelocity()->y != 0.f )
SetActionQueue( "Stand", 0, 0.f, 0.f, true, false );
}
SetMovable( false );
}
}
}
void CDnVehicleActor::OnFall( float fCurVelocity )
{
if( ( IsStay() || IsMove() ) && !IsFloorCollision() ) {
// 움직여지는 각도도 체크해서 계단등을 내려올때 떨어져보이는것 보정해보아요.
EtVector3 vDir = *GetPosition() - *GetPrevPosition();
EtVec3Normalize( &vDir, &vDir );
float fDot = EtVec3Dot( &EtVector3( 0.f, 1.f, 0.f ), &vDir );
float fAngle = EtToDegree( EtAcos( fDot ) );
if( fCurVelocity < -4.f && fAngle > 155.f ) {
ActionElementStruct *pStruct = GetElement( "Jump" );
if( pStruct ) {
SetActionQueue( "Jump", 0, 10.f, (float)pStruct->dwLength / 3.5f );
SetMovable( false );
}
}
}
}
int CDnVehicleActor::GetMoveSpeed()
{
int nMoveSpeed = CDnActor::GetMoveSpeed();
if( CDnWorld::IsActive(GetRoom()) && ( CDnWorld::GetInstance(GetRoom()).GetMapType() == EWorldEnum::MapTypeVillage || CDnWorld::GetInstance(GetRoom()).GetMapType() == EWorldEnum::MapTypeWorldMap ) )
nMoveSpeed += GetSafeZoneMoveSpeed();
if( m_cMovePushKeyFlag & 0x08 ) nMoveSpeed = 200;
return nMoveSpeed;
}
bool CDnVehicleActor::SetActionQueue( const char *szActionName, int nLoopCount, float fBlendFrame, float fStartFrame, bool bCheck, bool bCheckStateEffect )
{
std::string VehicleAction;
std::string szCurAction = szActionName;
#ifdef PRE_ADD_VEHICLE_ACTION_STRING
VehicleAction = GetVehicleActionString() + szCurAction;
#else
VehicleAction = "Vehicle_" + szCurAction;
#endif
if(m_hMyActor && !m_hMyActor->IsDestroy() )
m_hMyActor->SetActionQueue(VehicleAction.c_str(),nLoopCount,fBlendFrame,fStartFrame,bCheck,bCheckStateEffect); // 플레이어의 액션을 말액션을 기준으로 맞추어 줍니다.
return CDnActor::SetActionQueue( szActionName , nLoopCount, fBlendFrame, fStartFrame, bCheck, bCheckStateEffect );
}
void CDnVehicleActor::OnDispatchMessage( CDNUserSession *pSession, DWORD dwActorProtocol, BYTE *pPacket )
{
switch( dwActorProtocol ) {
case eActor::CS_CMDMOVE:
{
CPacketCompressStream Stream( pPacket, 128 );
int nActionIndex;
int nMoveSpeed;
EtVector3 vPos, vXVec;
EtVector2 vZVec, vLook;
char cFlag;
DWORD dwGap;
Stream.Read( &dwGap, sizeof(DWORD) );
Stream.Read( &nActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT );
Stream.Read( &vPos, sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
Stream.Read( &vZVec, sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
Stream.Read( &vLook, sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
Stream.Read( &cFlag, sizeof(char) );
Stream.Read( &nMoveSpeed, sizeof(int) );
Look( vZVec, false );
EtVec3Cross( &vXVec, &EtVector3( 0.f, 1.f, 0.f ), &EtVec2toVec3( vZVec ) );
SetMoveVectorX( vXVec );
SetMoveVectorZ( EtVec2toVec3( vZVec ) );
SetMagnetPosition( vPos );
m_cMovePushKeyFlag = cFlag;
float fXSpeed = 0.f, fZSpeed = 0.f;
if( cFlag & 0x01 ) fXSpeed = -100000.f;
if( cFlag & 0x02 ) fXSpeed = 100000.f;
if( cFlag & 0x04 ) fZSpeed = 100000.f;
if( cFlag & 0x08 ) fZSpeed = -100000.f;
vPos += ( vXVec * fXSpeed );
vPos += ( EtVec2toVec3( vZVec ) * fZSpeed );
ActionElementStruct *pStruct = m_hMyActor->GetElement( nActionIndex ); // !중요! 플레이어 액터의 인덱스로 검출해야합니다
if( pStruct == NULL ) break;
CmdMove( vPos, pStruct->szName.c_str(), -1, 8.f );
}
break;
case eActor::CS_CMDSTOP:
{
CPacketCompressStream Stream( pPacket, 128 );
EtVector3 vPos;
bool bResetStop;
DWORD dwGap;
Stream.Read( &dwGap, sizeof(DWORD) );
Stream.Read( &vPos, sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
Stream.Read( &bResetStop, sizeof(bool) );
std::string szActionName = GetCurrentAction();
if( EtVec2Length( &( EtVector2( vPos.x, vPos.z ) - EtVector2( GetPosition()->x, GetPosition()->z ) ) ) > 100.f ) {
if( GetState() != ActorStateEnum::Move ) szActionName = "Move_Front";
}
if(strstr(GetCurrentAction(),"Stand") == NULL)
{
CmdStop("Stand",-1,6.f);
}
}
break;
case eActor::CS_CMDACTION:
{
CPacketCompressStream Stream( pPacket, 128 );
int nActionIndex, nLoopCount;
float fBlendFrame;
EtVector3 vPos, vXVec;
EtVector2 vLook, vZVec;
DWORD dwGap;
bool bFromStateBlow = false;
Stream.Read( &nActionIndex, sizeof(int), CPacketCompressStream::INTEGER_SHORT );
Stream.Read( &dwGap, sizeof(DWORD) );
Stream.Read( &nLoopCount, sizeof(int), CPacketCompressStream::INTEGER_CHAR );
Stream.Read( &fBlendFrame, sizeof(float), CPacketCompressStream::FLOAT_SHORT, 10.f );
Stream.Read( &vPos, sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
Stream.Read( &vZVec, sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
Stream.Read( &vLook, sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
Stream.Read( &m_cMovePushKeyFlag, sizeof(char) );
Stream.Read( &bFromStateBlow, sizeof(bool) );
EtVec3Cross( &vXVec, &EtVector3( 0.f, 1.f, 0.f ), &EtVec2toVec3( vZVec ) );
m_pMovement->ResetMove();
SetMoveVectorX( vXVec );
SetMoveVectorZ( EtVec2toVec3( vZVec ) );
Look( vLook, true );
SetMagnetPosition( vPos );
ActionElementStruct *pStruct = GetElement( nActionIndex );
if( pStruct == NULL ) break;
#ifdef PRE_ADD_VEHICLE_SPECIAL_ACTION
if( CheckSpecialAction( pStruct->szName.c_str() ) == false )
{
if( m_hMyActor )
{
CDnPlayerActor *pPlayerActor = static_cast<CDnPlayerActor*>(m_hMyActor.GetPointer());
pPlayerActor->ReportInvalidAction();
}
break;
}
#endif
CmdAction( pStruct->szName.c_str(), nLoopCount, fBlendFrame, false );
}
break;
case eActor::CS_CMDLOOK:
{
CPacketCompressStream Stream( pPacket, 128 );
EtVector2 vLook, vZVec;
EtVector3 vXVec;
Stream.Read( &vZVec, sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
Stream.Read( &vLook, sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
CmdLook( vLook );
EtVec3Cross( &vXVec, &EtVector3( 0.f, 1.f, 0.f ), &EtVec2toVec3( vZVec ) );
SetMoveVectorX( vXVec );
SetMoveVectorZ( EtVec2toVec3( vZVec ) );
}
break;
case eActor::CS_POSREV:
{
CPacketCompressStream Stream( pPacket, 128 );
EtVector3 vPos;
bool bMove;
DWORD dwGap;
Stream.Read( &vPos, sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
Stream.Read( &dwGap, sizeof(DWORD) );
Stream.Read( &bMove, sizeof(bool) );
SetMagnetPosition( vPos );
if( bMove ) {
EtVector3 vXVec;
EtVector2 vZVec;
Stream.Read( &vZVec, sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
EtVec3Cross( &vXVec, &EtVector3( 0.f, 1.f, 0.f ), &EtVec2toVec3( vZVec ) );
SetMoveVectorX( vXVec );
SetMoveVectorZ( EtVec2toVec3( vZVec ) );
if( EtVec3LengthSq( m_pMovement->GetMovePos() ) > 0.f ) {
float fXSpeed = 0.f, fZSpeed = 0.f;
if( m_cMovePushKeyFlag & 0x01 ) fXSpeed = -100000.f;
if( m_cMovePushKeyFlag & 0x02 ) fXSpeed = 100000.f;
if( m_cMovePushKeyFlag & 0x04 ) fZSpeed = 100000.f;
if( m_cMovePushKeyFlag & 0x08 ) fZSpeed = -100000.f;
vPos += ( vXVec * fXSpeed );
vPos += ( EtVec2toVec3( vZVec ) * fZSpeed );
MovePos( vPos, false );
}
}
OutputDebug( "PosRev\n" );
}
break;
case eActor::CS_VIEWSYNC:
{
CPacketCompressStream Stream( pPacket, 128 );
EtVector3 vPos, vXVec;
EtVector2 vZVec, vLook;
DWORD dwGap;
Stream.Read( &dwGap, sizeof(DWORD) );
Stream.Read( &vPos, sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
Stream.Read( &vZVec, sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
Stream.Read( &vLook, sizeof(EtVector2), CPacketCompressStream::VECTOR2_SHORT );
Look( vLook, true );
EtVec3Cross( &vXVec, &EtVector3( 0.f, 1.f, 0.f ), &EtVec2toVec3( vZVec ) );
SetMoveVectorX( vXVec );
SetMoveVectorZ( EtVec2toVec3( vZVec ) );
SetMagnetPosition( vPos );
OutputDebug( "ViewSync\n" );
}
break;
case eActor::CS_ONDROP:
{
CPacketCompressStream Stream( pPacket, 128 );
EtVector3 vPos;
DWORD dwGap;
Stream.Read( &vPos, sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
Stream.Read( &dwGap, sizeof(DWORD) );
SetMagnetPosition( vPos );
SetJumpMovement( EtVector2( 0.f, 0.f ) );
}
break;
case eActor::CS_CMDESCAPE:
{
CPacketCompressStream Stream( pPacket, 32 );
EtVector3 vPos;
Stream.Read( &vPos, sizeof(EtVector3), CPacketCompressStream::VECTOR3_BIT );
SetPosition( vPos );
SetPrevPosition( vPos );
SetActionQueue( "Stand" );
CmdWarp( vPos, EtVec3toVec2( *GetMoveVectorZ() ) );
}
break;
}
}
int CDnVehicleActor::CmdAddStateEffect( const CDnSkill::SkillInfo* pParentSkill, STATE_BLOW::emBLOW_INDEX emBlowIndex, int nDurationTime, const char *szParam, bool bOnPlayerInit/* = false */, bool bCheckCanBegin/* = true*/ , bool bEternity )
{
int iID = CDnActor::CmdAddStateEffect( pParentSkill, emBlowIndex, nDurationTime, szParam, bOnPlayerInit, bCheckCanBegin , bEternity );
if( -1 == iID )
return -1;
DnBlowHandle hAddedBlow = m_pStateBlow->GetStateBlowFromID( iID );
const CPacketCompressStream* pPacket = hAddedBlow->GetPacketStream( szParam, bOnPlayerInit );
Send( eActor::SC_CMDADDSTATEEFFECT, const_cast<CPacketCompressStream*>(pPacket) );
return iID;
}
void CDnVehicleActor::SendRemoveStateEffect( STATE_BLOW::emBLOW_INDEX emBlowIndex )
{
BYTE pBuffer[32];
CPacketCompressStream Stream( pBuffer, 32 );
Stream.Write( &emBlowIndex, sizeof(STATE_BLOW::emBLOW_INDEX) );
Send( eActor::SC_CMDREMOVESTATEEFFECT, &Stream );
}
void CDnVehicleActor::SetMagnetPosition( EtVector3 &vPos )
{
EtVector2 vMagnet;
float fHeightDiff = vPos.y - GetMatEx()->m_vPosition.y;
vMagnet.x = vPos.x - GetMatEx()->m_vPosition.x;
vMagnet.y = vPos.z - GetMatEx()->m_vPosition.z;
float fAberraionLength = EtVec2Length( &vMagnet );
if( ( fAberraionLength > 1.f && fAberraionLength < 300.f ) && fHeightDiff < 300.f ) {
SetMagnetLength( fAberraionLength );
EtVec2Normalize( &vMagnet, &vMagnet );
SetMagnetDir( vMagnet );
}
else {
SetPosition( vPos );
}
}
#ifdef PRE_ADD_VEHICLE_SPECIAL_ACTION
bool CDnVehicleActor::CheckSpecialAction( const char *szAction )
{
if( !m_hMyActor )
return false;
CDnPlayerActor *pPlayerActor = static_cast<CDnPlayerActor*>(m_hMyActor.GetPointer());
int nCurrentMapID = 0;
CDnGameTask *pGameTask = (CDnGameTask *)CTaskManager::GetInstance(GetRoom()).GetTask( "GameTask" );
if( pGameTask )
nCurrentMapID = pGameTask->GetMapTableID();
else
nCurrentMapID = pPlayerActor->GetUserSession()->GetMapIndex();
bool bEnableSpecialAction = false; // g_pDataManager->IsVehicleSpecialActionMode(nCurrentMapID);
if( bEnableSpecialAction == false )
{
if( strstr( szAction, "Special_" ) )
return false;
}
return true;
}
#endif