Files
Sun1602/Client/GameClient/State/StateKeyboardJump2.cpp
T
2022-10-26 12:25:11 +08:00

2070 lines
54 KiB
C++

//------------------------------------------------------------------------------
// StateKeyboardMove.cpp
// (C) 2005 Webzen Sunstudio
//------------------------------------------------------------------------------
#include "SunClientPrecompiledHeader.h"
#ifdef _NA_20120220_JUMP_RENEWAL
#include "statebase.h"
#include "statemove.h"
#include "./statekeyboardjump.h"
#include "Hero.h"
#include "Player.h"
#include "Map.h"
#include "ObjectManager.h"
#include "Camera.h"
#include "GameFunc.h"
#include "NumericValues.h"
#include "GlobalFunc.h"
#include "InterfaceManager.h"
#include "GameFramework.h"
#include "SceneBase.h"
#include "RidingInfoParser.h"
#include "Rider.h"
#include "KBMoveCheckManagerInClient.h"
#include "BattleScene.h"
#define HEIGHT 2.8F
#define AVERAGE_DISTANCE 6.3f;
#define MAX_JUMP_TIME 1000
#define STUN_HEIGHT 8.0F
static float s_fMaxUpper = -40.0f; // 수직 낙하시의 제한치
static float s_fJumpUpperForce = 11.0f; // 점프 초기 속도 (수직)
static float s_fJumpMoveForce = 11.7f; // 점프 초기 속도 (수평)
static float s_fDownGravity = 20.0f; // 수직 속도에 적용할 중력치
static float s_fMoveGravity = 7.0f; // 수평이동 속도에 적용할 중력치
static float s_fMoveableMinDistance = 0.25f; // 낙하중 지면에서 수평이동을 가능하게할 최소한의 거리 - 착지모션에 미끄러지듯 이동하지 않기위해
static float s_fJumpEffectHeight = 0.5f;
static float s_fRateForTick1 = 1.0f; // 시간당 중력치 차감 비율 (수평)
static float s_fRateForTick2 = 1.0f; // 시간당 중력치 차감 비율 (수직)
//------------------------------------------------------------------------------
/**
*/
StateKeyboardJump::StateKeyboardJump(void)
{
}
//------------------------------------------------------------------------------
/**
*/
StateKeyboardJump::~StateKeyboardJump(void)
{
}
//------------------------------------------------------------------------------
/**
*/
BOOL StateKeyboardJump::CanTransite(Object* pOwner, DWORD CurTime, StateBase* pToTransiteState)
{
return TRUE;
}
BOOL StateKeyboardJump::CheckJumpTile(WzVector vSrc, WzVector vDest)
{
if(!g_pPathExplorer || !g_pMap)
return FALSE;
g_pPathExplorer->Stop();
// 대상 Tile 얻기
int iDestTileFocussing = g_pSunTerrain->x_pPathFinder->GetTileToStand( vDest, NULL, -1.f, 100.0f );
if( iDestTileFocussing < 0 )
{
return FALSE;
}
if(SCENE_TYPE_DOMINATION == GameFramework::GetCurScene())
{
WzRay ray;
ray.m_wvOrigin = vDest;
ray.m_wvOrigin.z += 1.0f;
ray.m_wvDirection.x = 0.0f;
ray.m_wvDirection.y = 0.0f;
ray.m_wvDirection.z = -1.0f;
int iTile = g_pSunTerrain->PickPathTile(&ray);
if(0 > iTile)
return FALSE;
}
int iSrcTileFocussing = g_pSunTerrain->x_pPathFinder->GetTileToStand( vSrc, NULL, -1.f, 100.0f );
if( iSrcTileFocussing < 0 )
{
return FALSE;
}
WORD Src_tile_attribute = g_pMap->GetWorldBase()->x_pPathFinder->GetAttribute(iSrcTileFocussing);
WORD dest_tile_attribute = g_pMap->GetWorldBase()->x_pPathFinder->GetAttribute(iDestTileFocussing);
#if WZENGINEVER >= 270
if ((Src_tile_attribute & PTA_JUMP_CONTROL_A) &&
(dest_tile_attribute & PTA_JUMP_CONTROL_B))
{
return FALSE;
}
if ((Src_tile_attribute & PTA_JUMP_CONTROL_B) &&
(dest_tile_attribute & PTA_JUMP_CONTROL_A))
{
return FALSE;
}
#endif //WZENGINEVER >= 270
if ((Src_tile_attribute & PTA_PLAYER_JUMP_TILE) &&
(dest_tile_attribute & PTA_PLAYER_JUMP_TILE))
{
return TRUE;
}
return FALSE;
}
BOOL StateKeyboardJump::TestMoveablePosition( const WzVector& StartPosition, WzVector& TargetPosition )
{
WzVector vStart = StartPosition;
g_pPathExplorer->Stop();
if( g_pSunTerrain->PathExp_Reset(g_pPathExplorer, &vStart, -1) == FALSE )
{
return FALSE;
}
WzVector vOldPosition = g_pPathExplorer->GetPos();
WzVector vDirection = TargetPosition - StartPosition;
g_pSunTerrain->PathExp_Thrust( g_pPathExplorer, &vDirection, PTA_NO_WALK );
g_pSunTerrain->PathExp_Progress( g_pPathExplorer, 1000000, NULL );
if( vOldPosition != g_pPathExplorer->GetPos() )
{
// 새 위치
TargetPosition = g_pPathExplorer->GetPos();
return TRUE;
}
return FALSE;
}
//------------------------------------------------------------------------------
bool StateKeyboardJump::GetJumpDestPosByDirection(OUT WzVector& dest_pos, WzVector& scr_pos, WzVector& direction, float player_height, float min_dist, float max_dist)
{
if (max_dist < min_dist)
{
max_dist = min_dist;
}
//최대 10회까지만 찾는다
for (int i = 0; i < 5; ++i)
//for (int i = 4; i >= 0; --i)
{
float gab = min_dist + ((max_dist - min_dist) / 5.0f * i);
WzRay ray;
ray.m_wvOrigin = scr_pos + (direction * gab);
ray.m_wvOrigin.z += player_height;
ray.m_wvDirection.x = 0.0f;
ray.m_wvDirection.y = 0.0f;
ray.m_wvDirection.z = -1.0f;
bool is_find = true;
float fT;
if (g_pSunTerrain->PickTerrainMesh(&ray, &fT ,TRUE, TMGO_NO_COLLISION) < 0)
{
ray.m_wvOrigin.z += player_height;
ray.m_wvDirection.x = 0.0f;
ray.m_wvDirection.y = 0.0f;
ray.m_wvDirection.z = 1.0f;
if(g_pSunTerrain->PickTerrainMesh(&ray, &fT , FALSE,TMGO_NO_COLLISION) < 0)
{
is_find = false;
}
}
if (is_find)
{
dest_pos = ray.m_wvOrigin + ray.m_wvDirection * fT;
if (abs(dest_pos.z - scr_pos.z) < CGeneralGameParam::Instance()->wings_down_jump_height())
{
g_pPathExplorer->Stop();
g_pSunTerrain->PathExp_Reset(g_pPathExplorer, &dest_pos, -1);
WzVector backup_pos = g_pHero->m_JumpData.m_vJumpTargetPosition;
g_pHero->m_JumpData.m_vJumpTargetPosition = dest_pos;
WzVector result;
if( FindEnablePathPosition( g_pHero->m_JumpData.m_vJumpStartPosition, g_pHero->m_JumpData.m_vJumpTargetPosition, result ) == TRUE )
{
g_pHero->m_vTargetPosition = result;
int tile_no = g_pPathExplorer->GetTile();
if ((tile_no >= 0) &&
((g_pSunTerrain->x_pPathFinder->GetAttribute(tile_no) & PTA_NO_WALK) == false))
{
g_pHero->m_JumpData.m_vJumpTargetPosition = dest_pos;
return true;
}
}
g_pHero->m_JumpData.m_vJumpTargetPosition = backup_pos;
}
}
}
return false;
}
//------------------------------------------------------------------------------
BOOL StateKeyboardJump::GetJumpDirection(OUT WzVector& direction, int flag, WzVector& foward)
{
SetVector( &direction, 0.0f, 0.0f, 0.0f);
WzVector vRight, vLeft;
vRight.x = foward.y; // sin(a - 90) = -cos(a) = vFoward.y;
vRight.y = -foward.x; // -cos(a - 90) = -sin(a) = -vFoward.y;
vRight.z = 0.0f;
vLeft.x = -foward.y; // sin(a + 90) = cos(a) = -vFoward.y;
vLeft.y = foward.x; // -cos(a + 90) = sin(a) = vFoward.x;
vLeft.z = 0.0f;
if (flag & KEYBOARDMOVE_RIGHTSTEP)
{
direction = direction + vRight;
// -45도
if (flag & KEYBOARDMOVE_FOWARD)
{
direction+=foward;
}
else if (flag & KEYBOARDMOVE_BACKWARD)
{
direction-=foward;
}
else
{
}
}
else if (flag & KEYBOARDMOVE_LEFTSTEP)
{
direction = direction + vLeft;
// 45도
if (flag & KEYBOARDMOVE_FOWARD)
{
direction+=foward;
}
else if (flag & KEYBOARDMOVE_BACKWARD)
{
direction-=foward;
}
else
{
}
}
else if (flag & KEYBOARDMOVE_FOWARD)
{
direction = direction + foward;
}
else if (flag & KEYBOARDMOVE_BACKWARD)
{
direction = direction - foward;
}
else if (flag & KEYBOARDMOVE_LEFTTURN)
{
}
else if (flag & KEYBOARDMOVE_RIGHTTURN)
{
}
else
{
}
if( direction.x == 0.0f && direction.y == 0.0f && direction.z == 0.0f )
{
return FALSE;
}
VectorNormalize( &direction, &direction );
return TRUE;
}
void CatmulRom( WzVector& Out, const WzVector& P1, const WzVector& P2, const WzVector& P3, const WzVector& P4, float s )
{
float s2 = s*s;
float s3 = s2*s;
Out.x = 0.5f * (( 2.0f * P2.x ) +
( -P1.x + P3.x ) * s +
( 2.0f * P1.x - 5.0f * P2.x + 4.0f * P3.x - P4.x ) * s2 +
( -P1.x + 3.0f * P2.x - 3.0f * P3.x + P4.x ) * s3 );
Out.y = 0.5f * (( 2.0f * P2.y ) +
( -P1.y + P3.y ) * s +
( 2.0f * P1.y - 5.0f * P2.y + 4.0f * P3.y - P4.y ) * s2 +
( -P1.y + 3.0f * P2.y - 3.0f * P3.y + P4.y ) * s3 );
Out.z = 0.5f * (( 2.0f * P2.z ) +
( -P1.z + P3.z ) * s +
( 2.0f * P1.z - 5.0f * P2.z + 4.0f * P3.z - P4.z ) * s2 +
( -P1.z + 3.0f * P2.z - 3.0f * P3.z + P4.z ) * s3 );
};
bool StateKeyboardJump::MovePositionOnSimulatedPosition( Player* pPlayer, float fTick, WzVector& Position, const WzVector& Direction, float& fMoveForce, float& fUpperForce )
{
const std::vector<WzVector>& simulated_position_array = pPlayer->m_JumpData.m_JumpPositionArray;
//pPlayer->m_fJumpTick += fTick;
if( simulated_position_array.size() < 2 )
{
return false;
}
float current_tick = pPlayer->m_JumpData.m_fJumpTick;
float tick_per_frame = 1.0f / 30.0f;
size_t frame_index = (size_t)(current_tick / tick_per_frame);
float rate = (current_tick - (tick_per_frame*(float)frame_index) ) / tick_per_frame;
WzVector p1,p2,p3,p4;
if( frame_index > 0 && frame_index < simulated_position_array.size() -2 )
{
p1 = simulated_position_array[frame_index-1];
p2 = simulated_position_array[frame_index];
p3 = simulated_position_array[frame_index+1];
p4 = simulated_position_array[frame_index+2];
}
else if( frame_index == 0 && frame_index < simulated_position_array.size() -2 )
{
//p1 = simulated_position_array[frame_index];
p2 = simulated_position_array[frame_index];
p3 = simulated_position_array[frame_index+1];
p4 = simulated_position_array[frame_index+2];
WzVector d = p3-p2;
p1 = p2 - d;
}
else if( frame_index > 0 && frame_index < simulated_position_array.size() -1 )
{
p1 = simulated_position_array[frame_index-1];
p2 = simulated_position_array[frame_index];
p3 = simulated_position_array[frame_index+1];
//p4 = simulated_position_array[frame_index+1];
WzVector d = p3-p2;
p4 = p3 + d;
}
else
{
return false;
}
CatmulRom( Position, p1, p2, p3, p4, rate );
// 1. 수평이동할 위치를 먼저 구한다
if( fMoveForce > 0.0f )
{
float fDelta = fMoveForce * fTick * s_fRateForTick1;
WzVector vDelta = Direction * fDelta;
fMoveForce -= s_fMoveGravity * fTick;
fMoveForce = max( fMoveForce, 0.0f );
}
// 3. 수직 이동
float fDelta = fUpperForce * fTick * s_fRateForTick2;
fUpperForce -= s_fDownGravity * fTick; // 1초에 s_fDownGravity 감소
fUpperForce = max( fUpperForce, s_fMaxUpper );
return true;
}
void StateKeyboardJump::MovePositionOnJump( const WzVector& Direction, float fTick, WzVector& Position, float& fMoveForce, float& fUpperForce )
{
// 1. 수평이동할 위치를 먼저 구한다
if( fMoveForce > 0.0f )
{
float fDelta = fMoveForce * fTick;
WzVector vDelta = Direction * fDelta;
Position.x += vDelta.x;
Position.y += vDelta.y;
fMoveForce -= s_fMoveGravity * fTick;
fMoveForce = max( fMoveForce, 0.0f );
}
// 3. 수직 이동
float fDelta = fUpperForce * fTick * s_fRateForTick2;
Position.z += fDelta;
fUpperForce -= s_fDownGravity * fTick; // 1초에 s_fDownGravity 감소
fUpperForce = max( fUpperForce, s_fMaxUpper );
}
BOOL StateKeyboardJump::SimulateJump( const WzVector& StartPosition, const WzVector& Direction, OUT WzVector& ResultPosition, OUT std::vector<WzVector>& SimulatedPositionArray )
{
// 점프의 목적지, 시작위치, 방향을 설정 (목적지는 수평점프 거리에 피킹한 위치 )
float fCurrentTick = 0.0f;
float fMoveForce = s_fJumpMoveForce;
float fUpperForce = s_fJumpUpperForce;
WzVector vTestPosition = StartPosition;
WzVector LastStandablePosition = StartPosition;
WzVector vLastPosition;
// 20프레임단위로 가상으로 점프를 시뮬레이션해서
// 최종 목적지의 수평상의 위치를 구한다.
SimulatedPositionArray.clear();
SimulatedPositionArray.push_back(StartPosition);
float fMoveTick = 1.0f / 30; // 30프레임으로 테스트
while( true )
{
vLastPosition = vTestPosition;
MovePositionOnJump( Direction, fMoveTick, vTestPosition, fMoveForce, fUpperForce );
fCurrentTick += fMoveTick;
// 오브젝트에 부딧치면 수평이동은 중지
if( TestObjectCollision( vLastPosition, vTestPosition ) == TRUE )
{
break;
}
// 착지가 가능한 위치인가
WzVector vTemp = vTestPosition;
if( fUpperForce < 0.0f )
{
vTemp.z = vLastPosition.z;
}
if( TestMoveableTerrainPosition( StartPosition, vTemp ) == TRUE )
{
LastStandablePosition = vTemp;
// 다운중이고, 지면의 위치와 0.5이내라면 착지로 간주
float fDistanceToLand = vTestPosition.z - vTemp.z;
if( fUpperForce < 0.0f && fDistanceToLand < s_fMoveableMinDistance )
{
break;
}
}
if( fMoveForce <= 0.0f )
{
break;
}
SimulatedPositionArray.push_back( vTestPosition );
}
ResultPosition = LastStandablePosition;
return ResultPosition != StartPosition;
}
// 목표 위치가 길찾기엔진상의 유효한 위치인지 확인
BOOL StateKeyboardJump::TestEnablePathPosition( const WzVector& TestPosition )
{
WzVector vVisible = TestPosition;
g_pPathExplorer->Stop();
g_pSunTerrain->PathExp_Reset(g_pPathExplorer, &vVisible, -1);
if( g_pPathExplorer->GetTile() < 0 )
return FALSE;
if( g_pPathExplorer->GetVisiblePos().z - TestPosition.z > 1.0f )
return FALSE;
return TRUE;
}
BOOL StateKeyboardJump::SendJumpPacket()
{
//Todo;hero에 포지션 세팅 할것
if (g_pHero)
{
#ifdef _NA000000_SPEED_HACK_PREVENTION_SUPPORT
if ((g_pHero->PacketNak.is_recv_nak == false) && (BattleScene::IsWaitEnterSync() == FALSE))
{
ulong next_serial_key = 0;
if (KBMoveCheckManagerInClient::Instance()->IssueNextSerial(&next_serial_key) == true)
{
MSG_CG_SYNC_JUMP_SYN Packet;
Packet.m_wvDestPos = g_pHero->GetPosition();
Packet.m_iDir = g_pHero->m_JumpData.m_JumpFlag.GetMoveFlag();
Packet.issued_serial = next_serial_key;
Packet.client_test_result = \
nsSync::MemoryHackMonitor::Instance()->GetNextClientTestSerial();
g_pHero->SendPacket(&Packet,sizeof(Packet));
}
else
{
WRITELOG(eLOG_LEVEL_ERR, c_wOUTPUT_LOG_SYSCHAT, "KBMoveCheckManagerInClient::Instance()->IssueNextSerial(&next_serial_key) == false");
}
}
#else
MSG_CG_SYNC_JUMP_SYN Packet;
Packet.m_byCategory = CG_SYNC;
Packet.m_byProtocol = CG_SYNC_JUMP_SYN;
//서버로 네비게이션 메쉬 좌표를 보낸다.
Packet.m_wvDestPos = g_pHero->GetPosition();
Packet.m_iDir = g_pHero->m_JumpData.m_JumpFlag.GetMoveFlag();
g_pHero->SendPacket(&Packet,sizeof(Packet));
#endif //_NA000000_SPEED_HACK_PREVENTION_SUPPORT
}
return TRUE;
}
BOOL StateKeyboardJump::SendStopPacket()
{
//Todo;hero에 포지션 세팅 할것
if (g_pHero)
{
#ifdef _NA000000_SPEED_HACK_PREVENTION_SUPPORT
if ((g_pHero->PacketNak.is_recv_nak == false) && (BattleScene::IsWaitEnterSync() == FALSE))
{
ulong next_serial_key = 0;
if (KBMoveCheckManagerInClient::Instance()->IssueNextSerial(&next_serial_key) == true)
{
MSG_CG_SYNC_JUMP_STOP_SYN Packet;
Packet.issued_serial = next_serial_key;
Packet.client_test_result = \
nsSync::MemoryHackMonitor::Instance()->GetNextClientTestSerial();
Packet.m_wvDestPos = g_pHero->GetPosition();
g_pHero->SendPacket(&Packet,sizeof(Packet));
}
}
#else
MSG_CG_SYNC_JUMP_STOP_SYN Packet;
Packet.m_byCategory = CG_SYNC;
Packet.m_byProtocol = CG_SYNC_JUMP_STOP_SYN;
Packet.m_wvDestPos = g_pHero->GetPosition();
g_pHero->SendPacket(&Packet,sizeof(Packet));
#endif //_NA000000_SPEED_HACK_PREVENTION_SUPPORT
}
return TRUE;
}
// 길찾기 매쉬상의 유효한 위치를 구한다.
BOOL StateKeyboardJump::FindEnablePathPosition( const WzVector& StartPosition, const WzVector& TargetPosition, OUT WzVector& ResultPosition )
{
WzVector TestPosition;
float fRate = 1.0f;
//최대 10회까지만 찾는다
for(int i=0;i<10;i++)
{
TestPosition = StartPosition * (1.0f - fRate) + TargetPosition * fRate;
// 길찾기 매쉬의 속성설정에 양쪽 모두 점프가 가능한경우에는 유효한 위치
if( CheckJumpTile( StartPosition, TestPosition ) )
{
g_pPathExplorer->Stop();
g_pSunTerrain->PathExp_Reset(g_pPathExplorer, &TestPosition, -1);
WzVector vPos = g_pPathExplorer->GetVisiblePos();
if( vPos.z - g_pHero->GetVisiblePos().z <= g_pHero->GetJumpHeight() )
{
ResultPosition = vPos;
return TRUE;
}
}
fRate -= 0.1f;
}
g_pPathExplorer->Stop();
// 길찾기 타일의 속성을 직접 검사후 이동가능한 위치면 유효하도록 적용하지만
// 특정 씬에서는 너무 멀리 돌아가야하는 위치라면 유효하지 않도록 적용
// 대상 Tile 얻기
int TargetTileIndex = g_pSunTerrain->x_pPathFinder->GetTileToStand( TargetPosition, NULL, -1.0f, 100.0f );
if( TargetTileIndex < 0 )
{
return FALSE;
}
if (g_pMap->GetWorldBase()->x_pPathFinder->GetAttribute(TargetTileIndex) & (PTA_NO_WALK))
{
return FALSE;
}
if(GameFramework::GetCurrentScene())
{
SCENE_TYPE type = GameFramework::GetCurrentScene()->GetType();
switch(type)
{
case SCENE_TYPE_MISSION:
if( GameFunc::IsMove( StartPosition, TargetPosition, TRUE, 200 ) )
{
ResultPosition = TargetPosition;
return TRUE;
}
break;
case SCENE_TYPE_DOMINATION:
if( GameFunc::IsMove( StartPosition, TargetPosition, TRUE, 20 ) )
{
ResultPosition = TargetPosition;
return TRUE;
}
break;
case SCENE_TYPE_CHUNTING:
if( GameFunc::IsMove( StartPosition, TargetPosition, TRUE, 1000 ) )
{
ResultPosition = TargetPosition;
return TRUE;
}
break;
default:
ResultPosition = TargetPosition;
return TRUE;
}
}
return FALSE;
}
BOOL StateKeyboardJump::TestObjectCollision( const WzVector& TestPosition )
{
// 캐릭터의 BV를 써야하지만 일단 대충 구로 하자
WzBoundingVolume BoundingVolume;
BoundingVolume.m_eBvType = BVT_SPHERE;
BoundingVolume.m_BvSphere.m_wvCenter = TestPosition;
BoundingVolume.m_BvSphere.m_fRadius = 0.3f;
// 나무
if( g_pMap->IntersectTree( &BoundingVolume ) == TRUE )
{
return TRUE;
}
// 오브젝트
if( g_pMap->IntersectMapObject( &BoundingVolume ) == TRUE )
{
return TRUE;
}
return FALSE;
}
// StartPosition에서 TargetPosition 까지 오브젝트의 BV과 충돌되는가
BOOL StateKeyboardJump::TestObjectCollision( const WzVector& StartPosition, const WzVector& TargetPosition )
{
if( TestObjectCollision( TargetPosition ) == TRUE )
{
return TRUE;
}
if( StartPosition == TargetPosition )
{
return FALSE;
}
WzVector vDistance = TargetPosition - StartPosition;
float fDistance = VectorLength(&vDistance);
WzRay ray;
ray.m_wvDirection = TargetPosition - StartPosition;
ray.m_wvOrigin = StartPosition;
ray.m_wvOrigin.z += 0.2f;
VectorNormalize(&ray.m_wvDirection,&ray.m_wvDirection);
// 지형
float fT;
int Index = g_pSunTerrain->PickTerrainMesh( &ray, &fT, FALSE, TMGO_NO_COLLISION );
if( Index >= 0 && fT <= fDistance )
{
return TRUE;
}
int PathTileIndex = g_pSunTerrain->x_pPathFinder->PickPathTile(&ray, &fT, TRUE );
if( PathTileIndex >= 0 && fT < fDistance )
{
// 속성체크
WORD TileAttrib = g_pSunTerrain->x_pPathFinder->GetAttribute(PathTileIndex);
if( TileAttrib & PTA_NO_WALK )
{
return TRUE;
}
if( TileAttrib & PTA_PLAYER_FALLDOWN_TILE )
{
return TRUE;
}
}
ray.m_wvOrigin = StartPosition;
ray.m_wvOrigin.z += 0.8f;
PathTileIndex = g_pSunTerrain->x_pPathFinder->PickPathTile(&ray, &fT, TRUE );
if( PathTileIndex >= 0 && fT < fDistance )
{
// 속성체크
WORD TileAttrib = g_pSunTerrain->x_pPathFinder->GetAttribute(PathTileIndex);
if( TileAttrib & PTA_NO_WALK )
{
return TRUE;
}
if( TileAttrib & PTA_PLAYER_FALLDOWN_TILE )
{
return TRUE;
}
}
return FALSE;
}
BOOL StateKeyboardJump::CheckRidingState(Player *pPlayer)
{
if (pPlayer &&
pPlayer->is_riding_jump())
{
if (pPlayer->IsRiding() == FALSE)
{
//상태전이시켜준다:라이딩상태에서 점프중 라이딩이 풀렸을때
pPlayer->set_is_riding_jump(false);
pPlayer->SetAnimation(pPlayer->GetCurrentJumpKeepAnimation(),TRUE);
pPlayer->m_JumpData.m_bJumpStart=TRUE;
}
}
else
{
if (pPlayer->IsRiding())
{
return TRUE;
}
}
return FALSE;
}
STATECHANGE::TYPE StateKeyboardJump::OnStart(Object* pOwner, DWORD CurTime)
{
#ifdef _DEBUG
Character* pChr = (Character*)pOwner;
// 키보드 이동은 플레이어만의 특권!
assert(pChr->IsKindOfObject(PLAYER_OBJECT));
#endif
Player* pPlayer = (Player*)pOwner;
#ifdef _NA_000000_20120410_SPEEDHACK
if (pPlayer == g_pHero)
{
g_pHero->move_speed_ = 7.0f * SPEED_MULTIPLIER;
}
else
{
pPlayer->SetMoveSpeed( 7.0f * SPEED_MULTIPLIER);
}
#else
pPlayer->SetMoveSpeed( 7.0f * SPEED_MULTIPLIER);
#endif //_NA_000000_20120410_SPEEDHACK
pPlayer->m_JumpData.m_bJumpStun = FALSE;
pPlayer->m_JumpData.m_hStunEffect = INVALID_HANDLE_VALUE;
pPlayer->m_JumpData.m_bJumpEndEffect = FALSE;
pPlayer->SetFreeMove(TRUE);
if( pPlayer->IsTransForm() )//변신은 준비 동작 없음
pPlayer->m_JumpData.m_bJumpStart = TRUE;
else
pPlayer->m_JumpData.m_bJumpStart = FALSE;
pPlayer->m_JumpData.m_fJumpEndFrame = 0.0f;
pPlayer->m_JumpData.m_fJumpUpperForce = s_fJumpUpperForce;
pPlayer->m_JumpData.m_fJumpMoveForce = s_fJumpUpperForce;
pPlayer->m_JumpData.m_fJumpDistanceToLand = 1.0f;
pPlayer->m_JumpData.m_bCreateJumpEndEffect = FALSE;
pPlayer->m_JumpData.m_JumpTime = 0;
WzVector vDummy;
vDummy.x = 0.0f;
vDummy.y = 0.0f;
vDummy.z = 0.0f;
pPlayer->SetOldKeyboardDirection( &vDummy );
pPlayer->SetHeight( 0.0f );
pPlayer->m_fTurnAccelerate = 0.0f;
pPlayer->StopBlendAnimation();
//m_OffsetHeight = 3.0f;
pPlayer->set_is_riding_jump(false);
if (pPlayer->IsRiding())
{
pPlayer->set_is_riding_jump(true);
pPlayer->SetKeyBoardJumpFlag(TRUE);
}
// 애니메이션을 점프 시작으로 설정
pPlayer->SetPlayerAnimation( pPlayer->GetCurrentJumpStartAnimation(), eANI_JUMP_START, FALSE);
if( pPlayer == g_pHero)
{
//Thrust 이동의 경우 못가는데서 점프하는 경우가 있다.
g_pHero->SetKeyboardMovePacketSendDuration(0);
g_pHero->SetKeyboardMovePacketSendTime(0);
g_pHero->SetVisibleAngleModifer(0.0f);
g_pHero->m_JumpData.m_CharacterDirection = g_pHero->GetDirection();
if ((g_pHero->is_spread_wings() == true) ||
((g_pHero->rider() != NULL) && (g_pHero->rider()->is_spread() == true)))
{
//! 위치가 계산되어 있다.
}
else
{
if( g_pMap )
{
// 이동상태에로 방향을 구함
WzVector vDirection;
if ( GetJumpDirection(vDirection, g_pHero->m_JumpData.m_JumpFlag.GetMoveFlag(), g_pHero->m_JumpData.m_CharacterDirection ) == TRUE )
{
// 점프의 목적지, 시작위치, 방향을 설정 (목적지는 수평점프 거리에 피킹한 위치 )
WzVector vTargetPosition;
SimulateJump( g_pHero->GetVisiblePos(), vDirection, vTargetPosition, g_pHero->m_JumpData.m_JumpPositionArray );
// 설정
g_pHero->m_JumpData.m_vJumpStartPosition = g_pHero->GetVisiblePos();
g_pHero->m_JumpData.m_vJumpTargetPosition = vTargetPosition;
g_pHero->m_JumpData.m_vJumpDirection = vDirection;
}
else
{
// 제자리 점프
g_pHero->m_JumpData.m_vJumpStartPosition = g_pHero->GetVisiblePos();
g_pHero->m_JumpData.m_vJumpTargetPosition = g_pHero->GetVisiblePos();
g_pHero->m_JumpData.m_vJumpDirection = vDirection;
g_pHero->m_JumpData.m_fJumpMoveForce = 0.0f;
}
#ifdef _DEBUG
// TargetPosition을 확인하기 위해
g_pEffectManager->CreateEffect(StrToWzID("A023"), g_pHero->m_JumpData.m_vJumpTargetPosition );
#endif
}
}
SendJumpPacket();
}
else
{
GetJumpDirection( pPlayer->m_JumpData.m_vJumpDirection, pPlayer->m_JumpData.m_JumpFlag.GetMoveFlag(), pPlayer->GetDirection() );
}
//시간 계산
WzVector vDistance = pPlayer->m_JumpData.m_vJumpTargetPosition - pPlayer->m_JumpData.m_vJumpStartPosition;
float fDistance = VectorLength(&vDistance);
//타락한 사원에서 속성 검사 해서 속성이 검출 될 경우 z값을 -10정도 더 내려 준다
int iTileFocussing = g_pSunTerrain->x_pPathFinder->GetTileToStand(pPlayer->m_JumpData.m_vJumpTargetPosition, NULL, -1.0f, 100.0f);
if (iTileFocussing >= 0)
{
if (g_pSunTerrain->x_pPathFinder->GetAttribute( iTileFocussing ) & PTA_PLAYER_FALLDOWN_TILE)
{
pPlayer->m_JumpData.m_vJumpTargetPosition.z -= 50.0f;
}
}
int iMoveFlag = pPlayer->m_JumpData.m_JumpFlag.GetMoveFlag();
if (iMoveFlag & KEYBOARDMOVE_RIGHTSTEP)
{
// -45도
if (iMoveFlag & KEYBOARDMOVE_FOWARD)
{
pPlayer->SetVisibleAngleModifer(-(WZ_PI / 4.0f));
}
if (iMoveFlag & KEYBOARDMOVE_BACKWARD)
{
pPlayer->SetVisibleAngleModifer((WZ_PI / 4.0f));
}
}
else if (iMoveFlag & KEYBOARDMOVE_LEFTSTEP)
{
// 45도
if (iMoveFlag & KEYBOARDMOVE_FOWARD)
{
pPlayer->SetVisibleAngleModifer((WZ_PI / 4.0f));
}
if (iMoveFlag & KEYBOARDMOVE_BACKWARD)
{
pPlayer->SetVisibleAngleModifer(-(WZ_PI / 4.0f));
}
}
// 높이가 높으면 스턴? -_-
float fH = pPlayer->m_JumpData.m_vJumpStartPosition.z - pPlayer->m_JumpData.m_vJumpTargetPosition.z;
if( fH > STUN_HEIGHT )
{
pPlayer->m_JumpData.m_bJumpStun = TRUE;
// 높이가 높을 수록 경직시간은 길게한다
float fTime = 50;
fTime*=(fH-STUN_HEIGHT);
pPlayer->m_JumpData.m_JumpStunTime = (int)fTime;
}
else
{
pPlayer->m_JumpData.m_bJumpStun = FALSE;
pPlayer->m_JumpData.m_JumpStunTime = 0;
}
return STATECHANGE::SUCCESS;
}
BOOL StateKeyboardJump::TestMoveableTerrainPosition( const WzVector& vStartPosition, WzVector& vTargetPosition )
{
// 현재 위치가 이동가능한 타일인가
static float s_fTemp = 0.01f;
WzRay ray;
ray.m_wvOrigin = vTargetPosition;
ray.m_wvOrigin.z += s_fTemp;
ray.m_wvDirection.x = 0.0f;
ray.m_wvDirection.y = 0.0f;
ray.m_wvDirection.z = -1.0f;
float fT;
int iCurrentTerrainMesh = -1;
iCurrentTerrainMesh = g_pSunTerrain->PickTerrainMesh( &ray, &fT, TRUE, TMGO_NO_COLLISION );
if( iCurrentTerrainMesh >= 0 )
{
vTargetPosition = ray.m_wvOrigin + ray.m_wvDirection * fT;
}
else if( iCurrentTerrainMesh < 0 && SCENE_TYPE_DOMINATION == GameFramework::GetCurScene() )
{
int iTile = g_pSunTerrain->PickPathTile(&ray, &fT);
if( iTile >= 0 )
{
vTargetPosition = ray.m_wvOrigin + ray.m_wvDirection * fT;
}
else
{
return FALSE;
}
}
else
{
return FALSE;
}
// 길찾기 타일 얻기
int iSrcTileFocussing = g_pSunTerrain->x_pPathFinder->GetTileToStand(vStartPosition, NULL, -1.f, 100.0f );
int iTileFocussing = g_pSunTerrain->x_pPathFinder->GetTileToStand(vTargetPosition, NULL, -1.0f, 100.0f);
if (iTileFocussing < 0 || iSrcTileFocussing < 0)
{
return FALSE;
}
// 속성체크
WORD TargetTileAttrib = g_pSunTerrain->x_pPathFinder->GetAttribute(iTileFocussing);
WORD SourceTileAttrib = g_pSunTerrain->x_pPathFinder->GetAttribute(iSrcTileFocussing);
#if WZENGINEVER >= 270
if ((SourceTileAttrib & PTA_JUMP_CONTROL_A) &&
(TargetTileAttrib & PTA_JUMP_CONTROL_B))
{
return FALSE;
}
if ((SourceTileAttrib & PTA_JUMP_CONTROL_B) &&
(TargetTileAttrib & PTA_JUMP_CONTROL_A))
{
return FALSE;
}
#endif //WZENGINEVER >= 270
if ((SourceTileAttrib & PTA_PLAYER_JUMP_TILE) &&
(TargetTileAttrib & PTA_PLAYER_JUMP_TILE))
{
return TRUE;
}
if( TargetTileAttrib & PTA_NO_WALK )
{
return FALSE;
}
if( TargetTileAttrib & PTA_PLAYER_FALLDOWN_TILE )
{
return FALSE;
}
if( SceneBase* current_scene = GameFramework::GetCurrentScene())
{
int maxNode = 0;
switch(current_scene->GetType())
{
case SCENE_TYPE_MISSION: maxNode = 200; break;
case SCENE_TYPE_DOMINATION: maxNode = 20; break;
case SCENE_TYPE_CHUNTING: maxNode = 1000; break;
}
if( maxNode )
return GameFunc::IsMove(vStartPosition, vTargetPosition,TRUE,maxNode);
else
return TRUE;
}
return FALSE;
}
BOOL StateKeyboardJump::IsInCource( WzVector P1, WzVector P2, WzVector T )
{
P1.z = P2.z = T.z;
P2 = P2 - P1;
T = T - P1;
return VectorLength(&T) <= VectorLength( &P2 );
}
BOOL StateKeyboardJump::CalcJumpMoving( Player* pPlayer, const WzVector& CurrentPosition, DWORD dwTick )
{
// 1. 지형과의 거리를 구한다
float fDistanceToLand = pPlayer->m_JumpData.m_fJumpDistanceToLand;
float fLandHeight = CurrentPosition.z - fDistanceToLand;
if( pPlayer->m_JumpData.m_fJumpUpperForce < 0.0f && fDistanceToLand <= 0.0f )
{
return FALSE;
}
// 2. 점프중에는 별다른 충돌검사를 하지 않고, TargetPosition까지 그냥 날아간다
float fMoveTick = (float)dwTick * 0.001f;
WzVector ResultPosition = CurrentPosition;
pPlayer->m_JumpData.m_fJumpTick += fMoveTick;
if( MovePositionOnSimulatedPosition( pPlayer, fMoveTick, ResultPosition, pPlayer->m_JumpData.m_vJumpDirection, pPlayer->m_JumpData.m_fJumpMoveForce, pPlayer->m_JumpData.m_fJumpUpperForce ) == false )
MovePositionOnJump( pPlayer->m_JumpData.m_vJumpDirection, fMoveTick, ResultPosition, pPlayer->m_JumpData.m_fJumpMoveForce, pPlayer->m_JumpData.m_fJumpUpperForce );
WzVector vTargetPosition = ResultPosition;
BOOL bCanMove = TRUE;
// 4. 이동이 좌표인가
if( TestObjectCollision( CurrentPosition, vTargetPosition ) == TRUE )
{
bCanMove = FALSE;
}
WzVector vTemp = vTargetPosition;
if( pPlayer->m_JumpData.m_fJumpUpperForce < 0.0f )
{
vTemp.z = CurrentPosition.z;
}
if( TestMoveableTerrainPosition( pPlayer->m_JumpData.m_vJumpStartPosition, vTemp ) == TRUE )
{
vTargetPosition = vTemp;
}
else
{
bCanMove = FALSE;
}
if( bCanMove == TRUE )
{
// 착지가능한 위치라면, 지형과의 거리와 지형의 높이 갱신
fDistanceToLand = ResultPosition.z - vTargetPosition.z;
fLandHeight = vTargetPosition.z;
}
if( bCanMove == FALSE )
{
// 목표위치에 이미 도달한 경우에는 이동불가능 지역이 있으면 수평이동은 멈춘다
if( IsInCource( pPlayer->m_JumpData.m_vJumpStartPosition, pPlayer->m_JumpData.m_vJumpTargetPosition, vTargetPosition ) == FALSE )
{
// 이전 위치를 사용하고, 더이상 수평이동은 하지않음
ResultPosition.x = CurrentPosition.x;
ResultPosition.y = CurrentPosition.y;
pPlayer->m_JumpData.m_fJumpMoveForce = 0.0f;
}
// 공중에 떠있다면 이전 마지막 수치를 그대로 사용
fDistanceToLand = ResultPosition.z - fLandHeight;
}
// 땅속으로 파고들지 않도록
if( fDistanceToLand < 0.0f )
{
pPlayer->m_JumpData.m_fJumpDistanceToLand = 0.0f;
ResultPosition.z = fLandHeight;
}
else
{
//ResultPosition.z = vTargetPosition.z;
pPlayer->m_JumpData.m_fJumpDistanceToLand = fDistanceToLand;
}
//
if( pPlayer->m_JumpData.m_fJumpUpperForce < 0.0f && pPlayer->m_JumpData.m_fJumpDistanceToLand < s_fMoveableMinDistance )
{
ResultPosition.x = CurrentPosition.x;
ResultPosition.y = CurrentPosition.y;
pPlayer->m_JumpData.m_fJumpMoveForce = 0.0f;
}
// 5. 오브젝트에 적용
pPlayer->SetVisiblePos( ResultPosition );
pPlayer->GetBasePart()->SetPosition( ResultPosition );
pPlayer->SetFreeMove(TRUE);
pPlayer->GetBasePart()->SetPosition(pPlayer->GetVisiblePos());
pPlayer->UpdateOctree(TRUE);
return TRUE;
}
STATEPROCESS::TYPE StateKeyboardJump::OnProcess(Object* pOwner, DWORD CurTime,DWORD dwTick)
{
Player* pPlayer = (Player*)pOwner;
// 회전 관련 액셀 값을 세팅 한다.
if(pPlayer == g_pHero)
{
CalculateTurnAccelerate(dwTick);
}
int iMoveFlag = pPlayer->m_JumpData.m_JumpFlag.GetMoveFlag();
pPlayer->m_JumpData.m_JumpTime += dwTick;
if(pPlayer->m_JumpData.m_bJumpStart == FALSE)
{
pPlayer->m_JumpData.m_JumpTime = 1;
}
if(pPlayer->m_JumpData.m_hStunEffect != INVALID_HANDLE_VALUE)
{
if( CEffectBody *pBody= g_pEffectManager->GetEffectPtrHandle(pPlayer->m_JumpData.m_hStunEffect) )
{
WzVector vPos;
vPos = pPlayer->GetHeadBonePos();
vPos.z+=0.1f;
WzVector vRot;
vRot.x = 0.0f;
vRot.y = 0.0f;
vRot.z = 0.0f;
WzVector vScale;
vScale.x=1.0f;
vScale.y=1.0f;
vScale.z=1.0f;
pBody->SetResultMatrix(vPos,vRot,vScale);
}
}
WzVector CurrentPosition = pPlayer->GetVisiblePos();
// 이동
CalcJumpMoving( pPlayer, CurrentPosition, dwTick );
float fDistanceToLand = pPlayer->m_JumpData.m_fJumpDistanceToLand;
if(pPlayer->m_JumpData.m_bJumpStun )
{
if( fDistanceToLand <= s_fJumpEffectHeight )
{
if( pPlayer->m_JumpData.m_fJumpUpperForce < 0.0f && pPlayer->m_JumpData.m_bCreateJumpEndEffect == FALSE )
{
pPlayer->m_JumpData.m_bCreateJumpEndEffect = TRUE;
OnFootStep(pPlayer);
SendStopPacket();
}
pPlayer->m_JumpData.m_fJumpEndFrame = 0;
}
}
else
{
if( pPlayer->m_JumpData.m_fJumpUpperForce < 0.0f && fDistanceToLand <= s_fJumpEffectHeight )
{
if(!pPlayer->m_JumpData.m_bCreateJumpEndEffect)
{
pPlayer->m_JumpData.m_bCreateJumpEndEffect = TRUE;
OnFootStep(pPlayer);
SendStopPacket();
}
pPlayer->m_JumpData.m_fJumpEndFrame=0;
}
}
//점프중 라이딩상태 변경(소환.해제)이 일어났을경우 OnProcess를 끝낸다
if(CheckRidingState(pPlayer))
{
return STATEPROCESS::END;
}
if(pPlayer->IsPolymorph() )
{
return STATEPROCESS::END;
}
// 애니메이션 이펙트 처리
char szAniCode[5];
ZeroMemory(szAniCode,sizeof(szAniCode));
WzIDToString(szAniCode,pPlayer->GetCurrentAnimation());
szAniCode[1]='0';
WzID wzCurrentAnimationID=StrToWzID(szAniCode);
ZeroMemory(szAniCode,sizeof(szAniCode));
WzIDToString(szAniCode,pPlayer->GetCurrentJumpStartAnimation());
szAniCode[1]='0';
WzID wzJumpStartAnimationID=StrToWzID(szAniCode);
ZeroMemory(szAniCode,sizeof(szAniCode));
WzIDToString(szAniCode,pPlayer->GetCurrentJumpKeepAnimation());
szAniCode[1]='0';
WzID wzJumpKeepAnimationID=StrToWzID(szAniCode);
ZeroMemory(szAniCode,sizeof(szAniCode));
WzIDToString(szAniCode,pPlayer->GetCurrentJumpEndAnimation());
szAniCode[1]='0';
WzID wzJumpEndAnimationID=StrToWzID(szAniCode);
ZeroMemory(szAniCode,sizeof(szAniCode));
WzIDToString(szAniCode,pPlayer->GetCurrentJumpLandAnimation());
szAniCode[1]='0';
WzID wzJumpLandAnimationID=StrToWzID(szAniCode);
ZeroMemory(szAniCode,sizeof(szAniCode));
WzIDToString(szAniCode,pPlayer->GetCurrentJumpStunEndAnimation());
szAniCode[1]='0';
WzID wzJumpStunAnimationEndID=StrToWzID(szAniCode);
ZeroMemory(szAniCode,sizeof(szAniCode));
WzIDToString(szAniCode,pPlayer->GetCurrentJumpStunAnimation());
szAniCode[1]='0';
WzID wzJumpStunAnimationID=StrToWzID(szAniCode);
ZeroMemory(szAniCode,sizeof(szAniCode));
WzIDToString(szAniCode,pPlayer->GetCurrentJumpStunKeepAnimation());
szAniCode[1]='0';
WzID wzJumpStunKeepAnimationID=StrToWzID(szAniCode);
WzEvent event;
float fRet = 0.0f;
if(wzCurrentAnimationID == wzJumpStartAnimationID)//점프시작
{
pPlayer->ProcessInterpolation(dwTick);
fRet=pPlayer->ProcessAnimation(dwTick,&event);
// 이벤트가 잡힐때까지 못움직인다.
if( pPlayer->m_JumpData.m_bJumpStart == FALSE )
{
if (event.m_iNumCustom)
{
for (int a = 0; a < event.m_iNumCustom; a++)
{
// 타격점에 오른쪽치기인지 왼쪽치기인지 결정한다.
switch(event.m_Custom[a].m_iaParam3[0])
{
// 1번 event는 공격 타이밍
case 1:
{
if (event.m_Custom[a].m_iaParam3[1] == 1)
{
pPlayer->m_JumpData.m_bJumpStart = TRUE;
}
}
break;
}
}
}
}
// 적절한 타이밍이 지난 후 애니메이션 변경
if (fRet >= 100.0f)
{
pPlayer->SetPlayerAnimation(pPlayer->GetCurrentJumpKeepAnimation(),eANI_JUMP_LOOP,TRUE);
pPlayer->ProcessAnimation(0);
}
}
else if(wzCurrentAnimationID==wzJumpKeepAnimationID)
{
//pPlayer->SetAnimation(pPlayer->GetCurrentJumpKeepAnimation(),TRUE);
pPlayer->SetPlayerAnimation(pPlayer->GetCurrentJumpKeepAnimation(),eANI_JUMP_LOOP,TRUE);
pPlayer->ProcessInterpolation(dwTick);
pPlayer->ProcessAnimation(dwTick,&event);
// 낙하중 모션블러 적용
if ( pPlayer->m_JumpData.m_bJumpStun == TRUE && pPlayer->m_JumpData.m_fJumpUpperForce <= s_fMaxUpper )
{
SetMotionBlur(pPlayer, true);
}
static float s_Distance = 2.0f;
// 떨어지고 있는중이고, 거리가 2 이하인 경우
if( fDistanceToLand <= s_Distance && pPlayer->m_JumpData.m_fJumpUpperForce < 0.0f )
{
//SetMotionBlur(pPlayer, false);
if(pPlayer->m_JumpData.m_bJumpStun == TRUE && pPlayer->IsDead() == FALSE )
{
pPlayer->SetPlayerAnimation(pPlayer->GetCurrentJumpStunAnimation(),eANI_HJUMP_END,FALSE);
}
else
{
pPlayer->SetPlayerAnimation(pPlayer->GetCurrentJumpEndAnimation(),eANI_JUMP_END,FALSE);
}
}
}
else if(wzCurrentAnimationID==wzJumpEndAnimationID)
{
if(pPlayer->GetVisiblePos().z - pPlayer->m_JumpData.m_fJumpTargetHeight<=0.8f)
{
pPlayer->m_JumpData.m_fJumpEndFrame = 0;
}
if (pPlayer->m_JumpData.m_fJumpEndFrame )
{
pPlayer->SetCurrentFrame(pPlayer->m_JumpData.m_fJumpEndFrame );
pPlayer->ProcessInterpolation(dwTick);
pPlayer->ProcessAnimation(0,&event);
}
else
{
pPlayer->ProcessInterpolation(dwTick);
fRet=pPlayer->ProcessAnimation(dwTick,&event);
if (event.m_iNumCustom)
{
for (int a = 0; a < event.m_iNumCustom; a++)
{
switch(event.m_Custom[a].m_iaParam3[0])
{
case 1:
{
if (event.m_Custom[a].m_iaParam3[1] == 1)
{
pPlayer->m_JumpData.m_fJumpEndFrame = pPlayer->GetCurrentFrame();
}
}
break;
}
}
}
}
if( fDistanceToLand <= 0.0f &&
iMoveFlag &&
( pPlayer->CheckMoveFlag(KEYBOARDMOVE_FOWARD)||
pPlayer->CheckMoveFlag(KEYBOARDMOVE_BACKWARD)||
pPlayer->CheckMoveFlag(KEYBOARDMOVE_RIGHTSTEP)||
pPlayer->CheckMoveFlag(KEYBOARDMOVE_LEFTSTEP)||
pPlayer->IsDead()
)
)
{
return STATEPROCESS::END;
}
float s_tRet = 100.0f;
//if (pPlayer->GetVisiblePos().z == pPlayer->m_fJumpTargetHeight )
if ( fDistanceToLand <= 0.0f && fRet == s_tRet )
{
return STATEPROCESS::END;
}
}
else if(wzCurrentAnimationID==wzJumpStunAnimationID)
{
pPlayer->ProcessInterpolation(dwTick);
fRet = pPlayer->ProcessAnimation(dwTick,&event);
if( fRet == 100.0f )
{
pPlayer->SetPlayerAnimation(pPlayer->GetCurrentJumpStunKeepAnimation(),eANI_HJUMP_END_LOOP,FALSE);
pPlayer->ProcessAnimation(0);
}
}
else if(wzCurrentAnimationID==wzJumpStunKeepAnimationID)
{
pPlayer->m_JumpData.m_JumpStunTime -= dwTick;
pPlayer->m_JumpData.m_JumpStunTime = max(0,pPlayer->m_JumpData.m_JumpStunTime);
pPlayer->m_JumpData.m_JumpStunTime = min(1000,pPlayer->m_JumpData.m_JumpStunTime);
pPlayer->ProcessInterpolation(dwTick);
fRet = pPlayer->ProcessAnimation(dwTick,&event);
if( fDistanceToLand <= 0.0f && fRet == 100.0f )
{
if(pPlayer->m_JumpData.m_hStunEffect != INVALID_HANDLE_VALUE )
g_pEffectManager->RemoveEffectPtr(pPlayer->m_JumpData.m_hStunEffect);
//pPlayer->SetAnimation(pPlayer->GetCurrentJumpStunEndAnimation(),FALSE);
pPlayer->SetPlayerAnimation(pPlayer->GetCurrentJumpStunEndAnimation(), eANI_HJUMP_GETUP, FALSE);
}
}
else if(wzCurrentAnimationID==wzJumpStunAnimationEndID)//Todo;IDLE 상태에서 처리 해야 한다.
{
pPlayer->ProcessInterpolation(dwTick);
fRet = pPlayer->ProcessAnimation(dwTick,&event);
if( fRet == 100.0f )
{
return STATEPROCESS::END;
}
}
else
{
pPlayer->ProcessInterpolation(dwTick);
fRet=pPlayer->ProcessAnimation(dwTick,&event);
}
return STATEPROCESS::HOLD;
}
STATECHANGE::TYPE StateKeyboardJump::OnEnd(Object* pOwner, DWORD CurTime)
{
WzVector vDummy;
vDummy.x = 0.0f;
vDummy.y = 0.0f;
vDummy.z = 0.0f;
Player* pPlayer = (Player*)pOwner;
g_pPathExplorer->Stop();
//Todo:잘못된 타일일때 오류 처리 할것.
if(g_pSunTerrain->PathExp_Reset(g_pPathExplorer, &pPlayer->GetVisiblePos(), -1))
{
WzVector vPos=g_pPathExplorer->GetPos();
pPlayer->SetPosition(vPos);
pPlayer->SetVisiblePos(g_pPathExplorer->GetVisiblePos());
pPlayer->GetBasePart()->SetPosition(g_pPathExplorer->GetVisiblePos());
}
pPlayer->m_JumpData.m_bJumpStun = FALSE;
pPlayer->m_JumpData.m_JumpFlag.Reset();
pPlayer->SetKeyBoardJumpFlag(FALSE);
//타락한 사원에서 떨어져 죽을땐 하면 안됨
int iTileFocussing = g_pSunTerrain->x_pPathFinder->GetTileToStand(pPlayer->m_JumpData.m_vJumpTargetPosition, NULL, -1.0f, 100.0f);
if (iTileFocussing >= 0)
{
if (!(g_pSunTerrain->x_pPathFinder->GetAttribute(iTileFocussing) & PTA_PLAYER_FALLDOWN_TILE))
{
pPlayer->SetFreeMove(FALSE);
pPlayer->SetHeight(0.0f);
}
}
#ifdef _NA_000000_20120410_SPEEDHACK
if (pPlayer == g_pHero)
{
g_pHero->move_speed_ = GetBaseMoveSpeedAsState(CMS_RUN);
}
else
{
pPlayer->SetMoveSpeed(GetBaseMoveSpeedAsState(CMS_RUN));
}
#else
pPlayer->SetMoveSpeed(GetBaseMoveSpeedAsState(CMS_RUN));
#endif //_NA_000000_20120410_SPEEDHACK
if (pPlayer->m_JumpData.m_hStunEffect != INVALID_HANDLE_VALUE)
{
g_pEffectManager->RemoveEffectPtr( pPlayer->m_JumpData.m_hStunEffect );
}
SetMotionBlur(pOwner, false);
return STATECHANGE::SUCCESS;
}
void StateKeyboardJump::SetMotionBlur(Object* object, bool flag)
{
if (object != g_pHero)
{
return;
}
if (flag)
{
g_pSunRenderer->x_pManagerPostEffect->TurnOnPostEffect( PET_MOTION_BLUR );
}
else
{
g_pSunRenderer->x_pManagerPostEffect->TurnOffPostEffect( PET_MOTION_BLUR );
}
}
void StateKeyboardJump::OnFootStep(Object* pOwner)
{
Player* pPlayer = (Player*)pOwner;
if(pPlayer->IsObserverMode())
{
return;
}
pPlayer->SetKeyBoardJumpFlag(FALSE);
pPlayer->SetPosition(pPlayer->GetVisiblePos());
CEffectBody *pBody=NULL;
WzVector vPos = pPlayer->GetVisiblePos();
WzVector vPos2;
WzVector vPos3;
vPos3=vPos2=vPos;
float fRand=float( rand()%3);
fRand/=10.0f;
float fRand2=float( rand()%4);
if(fRand2==0)
{
vPos3.x+=fRand;
vPos3.y+=fRand;
vPos2.x+=fRand;
vPos2.y+=fRand;
}
else if(fRand2==1)
{
vPos3.x-=fRand;
vPos3.y-=fRand;
vPos2.x-=fRand;
vPos2.y-=fRand;
}
else if(fRand2==2)
{
vPos3.x-=fRand;
vPos3.y-=fRand;
vPos2.x+=fRand;
vPos2.y+=fRand;
}
else
{
vPos3.x+=fRand;
vPos3.y+=fRand;
vPos2.x-=fRand;
vPos2.y-=fRand;
}
Player *pChr=(Player *)pOwner;
assert(pChr->IsKindOfObject(PLAYER_OBJECT));
if(g_pHero==pChr)
{
pChr->Player::OnFootStep(TRUE);
}
if( pChr->m_JumpData.m_bJumpStun )
{
WzVector vRet;
vRet = pPlayer->GetHeadBonePos();
vRet.z+=0.1f;
}
HANDLE handle;
// 지형속성에 따라 이펙트를 뿌려준다
switch(pChr->GetTerrainAttribute())
{
default:
case eTERRAIN_ATTRIBUTE_DIRT:
{
handle=GlobalFunc::CreateEffectBeUpToOption(StrToWzID("A000"),vPos,pChr->GetObjectKey());
pBody = g_pEffectManager->GetEffectPtrHandle(handle);
if(pBody)
{
WzVector vRot;
vRot.x = 0.0f;
vRot.y = 0.0f;
vRot.z = 0.0f;
WzVector vScale;
vScale.x = float( rand()%20);
vScale.y = float( rand()%20);
vScale.z = float( rand()%20);
vScale.x/=10.0f;
vScale.y/=10.0f;
vScale.z/=10.0f;
vScale.x=max(vScale.x,1.0f);
vScale.y=max(vScale.y,1.0f);
vScale.z=max(vScale.y,1.0f);
pBody->SetResultMatrix(vPos,vRot,vScale);
}
handle=GlobalFunc::CreateEffectBeUpToOption(StrToWzID("A000"),vPos2,pChr->GetObjectKey());
CEffectBody *pBody = g_pEffectManager->GetEffectPtrHandle(handle);
if(pBody)
{
WzVector vRot;
vRot.x = 0.0f;
vRot.y = 0.0f;
vRot.z = 0.0f;
WzVector vScale;
vScale.x = float( rand()%20);
vScale.y = float( rand()%20);
vScale.z = float( rand()%20);
vScale.x/=10.0f;
vScale.y/=10.0f;
vScale.z/=10.0f;
vScale.x=max(vScale.x,1.0f);
vScale.y=max(vScale.y,1.0f);
vScale.z=max(vScale.y,1.0f);
pBody->SetResultMatrix(vPos2,vRot,vScale);
}
handle=GlobalFunc::CreateEffectBeUpToOption(StrToWzID("A000"),vPos3,pChr->GetObjectKey());
pBody = g_pEffectManager->GetEffectPtrHandle(handle);
if(pBody)
{
WzVector vRot;
vRot.x = 0.0f;
vRot.y = 0.0f;
vRot.z = 0.0f;
WzVector vScale;
vScale.x = float( rand()%20);
vScale.y = float( rand()%20);
vScale.z = float( rand()%20);
vScale.x/=10.0f;
vScale.y/=10.0f;
vScale.z/=10.0f;
vScale.x=max(vScale.x,1.0f);
vScale.y=max(vScale.y,1.0f);
vScale.z=max(vScale.y,1.0f);
pBody->SetResultMatrix(vPos3,vRot,vScale);
}
}
break;
case eTERRAIN_ATTRIBUTE_GRASS:
{
handle=GlobalFunc::CreateEffectBeUpToOption(StrToWzID("A042"),vPos,pChr->GetObjectKey());
pBody = g_pEffectManager->GetEffectPtrHandle(handle);
if(pBody)
{
WzVector vRot;
vRot.x = 0.0f;
vRot.y = 0.0f;
vRot.z = 0.0f;
WzVector vScale;
vScale.x = float( rand()%20);
vScale.y = float( rand()%20);
vScale.z = float( rand()%20);
vScale.x/=10.0f;
vScale.y/=10.0f;
vScale.z/=10.0f;
vScale.x=max(vScale.x,1.0f);
vScale.y=max(vScale.y,1.0f);
vScale.z=max(vScale.y,1.0f);
pBody->SetResultMatrix(vPos,vRot,vScale);
}
handle=GlobalFunc::CreateEffectBeUpToOption(StrToWzID("A042"),vPos2,pChr->GetObjectKey());
pBody = g_pEffectManager->GetEffectPtrHandle(handle);
if(pBody)
{
WzVector vRot;
vRot.x = 0.0f;
vRot.y = 0.0f;
vRot.z = 0.0f;
WzVector vScale;
vScale.x = float( rand()%20);
vScale.y = float( rand()%20);
vScale.z = float( rand()%20);
vScale.x/=10.0f;
vScale.y/=10.0f;
vScale.z/=10.0f;
vScale.x=max(vScale.x,1.0f);
vScale.y=max(vScale.y,1.0f);
vScale.z=max(vScale.y,1.0f);
pBody->SetResultMatrix(vPos2,vRot,vScale);
}
handle=GlobalFunc::CreateEffectBeUpToOption(StrToWzID("A042"),vPos3,pChr->GetObjectKey());
pBody = g_pEffectManager->GetEffectPtrHandle(handle);
if(pBody)
{
WzVector vRot;
vRot.x = 0.0f;
vRot.y = 0.0f;
vRot.z = 0.0f;
WzVector vScale;
vScale.x = float( rand()%20);
vScale.y = float( rand()%20);
vScale.z = float( rand()%20);
vScale.x/=10.0f;
vScale.y/=10.0f;
vScale.z/=10.0f;
vScale.x=max(vScale.x,1.0f);
vScale.y=max(vScale.y,1.0f);
vScale.z=max(vScale.y,1.0f);
pBody->SetResultMatrix(vPos3,vRot,vScale);
}
}
break;
case eTERRAIN_ATTRIBUTE_WATER:
{
vPos.z+=0.5f;
vPos2.z+=0.5f;
vPos3.z+=0.5f;
handle = GlobalFunc::CreateEffectBeUpToOption(StrToWzID("I695"),
pChr->GetWaterTerrainPos(),
pChr->GetObjectKey());
}
break;
case eTERRAIN_ATTRIBUTE_SNOW:
{
handle=GlobalFunc::CreateEffectBeUpToOption(StrToWzID("A003"),vPos,pChr->GetObjectKey());
pBody = g_pEffectManager->GetEffectPtrHandle(handle);
if(pBody)
{
WzVector vRot;
vRot.x = 0.0f;
vRot.y = 0.0f;
vRot.z = 0.0f;
WzVector vScale;
vScale.x = float( rand()%20);
vScale.y = float( rand()%20);
vScale.z = float( rand()%20);
vScale.x/=10.0f;
vScale.y/=10.0f;
vScale.z/=10.0f;
vScale.x=max(vScale.x,1.0f);
vScale.y=max(vScale.y,1.0f);
vScale.z=max(vScale.y,1.0f);
pBody->SetResultMatrix(vPos,vRot,vScale);
}
handle=GlobalFunc::CreateEffectBeUpToOption(StrToWzID("A003"),vPos2,pChr->GetObjectKey());
pBody = g_pEffectManager->GetEffectPtrHandle(handle);
if(pBody)
{
WzVector vRot;
vRot.x = 0.0f;
vRot.y = 0.0f;
vRot.z = 0.0f;
WzVector vScale;
vScale.x = float( rand()%20);
vScale.y = float( rand()%20);
vScale.z = float( rand()%20);
vScale.x/=10.0f;
vScale.y/=10.0f;
vScale.z/=10.0f;
vScale.x=max(vScale.x,1.0f);
vScale.y=max(vScale.y,1.0f);
vScale.z=max(vScale.y,1.0f);
pBody->SetResultMatrix(vPos2,vRot,vScale);
}
handle=GlobalFunc::CreateEffectBeUpToOption(StrToWzID("A003"),vPos3,pChr->GetObjectKey());
pBody = g_pEffectManager->GetEffectPtrHandle(handle);
if(pBody)
{
WzVector vRot;
vRot.x = 0.0f;
vRot.y = 0.0f;
vRot.z = 0.0f;
WzVector vScale;
vScale.x = float( rand()%20);
vScale.y = float( rand()%20);
vScale.z = float( rand()%20);
vScale.x/=10.0f;
vScale.y/=10.0f;
vScale.z/=10.0f;
vScale.x=max(vScale.x,1.0f);
vScale.y=max(vScale.y,1.0f);
vScale.z=max(vScale.y,1.0f);
pBody->SetResultMatrix(vPos3,vRot,vScale);
}
}
break;
case eTERRAIN_ATTRIBUTE_DESERT:
{
handle=GlobalFunc::CreateEffectBeUpToOption(StrToWzID("A001"),vPos,pChr->GetObjectKey());
pBody = g_pEffectManager->GetEffectPtrHandle(handle);
if(pBody)
{
WzVector vRot;
vRot.x = 0.0f;
vRot.y = 0.0f;
vRot.z = 0.0f;
WzVector vScale;
vScale.x = float( rand()%20);
vScale.y = float( rand()%20);
vScale.z = float( rand()%20);
vScale.x/=10.0f;
vScale.y/=10.0f;
vScale.z/=10.0f;
vScale.x=max(vScale.x,1.0f);
vScale.y=max(vScale.y,1.0f);
vScale.z=max(vScale.y,1.0f);
pBody->SetResultMatrix(vPos,vRot,vScale);
}
handle=GlobalFunc::CreateEffectBeUpToOption(StrToWzID("A001"),vPos2,pChr->GetObjectKey());
pBody = g_pEffectManager->GetEffectPtrHandle(handle);
if(pBody)
{
WzVector vRot;
vRot.x = 0.0f;
vRot.y = 0.0f;
vRot.z = 0.0f;
WzVector vScale;
vScale.x = float( rand()%20);
vScale.y = float( rand()%20);
vScale.z = float( rand()%20);
vScale.x/=10.0f;
vScale.y/=10.0f;
vScale.z/=10.0f;
vScale.x=max(vScale.x,1.0f);
vScale.y=max(vScale.y,1.0f);
vScale.z=max(vScale.y,1.0f);
pBody->SetResultMatrix(vPos2,vRot,vScale);
}
handle=GlobalFunc::CreateEffectBeUpToOption(StrToWzID("A001"),vPos3,pChr->GetObjectKey());
pBody = g_pEffectManager->GetEffectPtrHandle(handle);
if(pBody)
{
WzVector vRot;
vRot.x = 0.0f;
vRot.y = 0.0f;
vRot.z = 0.0f;
WzVector vScale;
vScale.x = float( rand()%20);
vScale.y = float( rand()%20);
vScale.z = float( rand()%20);
vScale.x/=10.0f;
vScale.y/=10.0f;
vScale.z/=10.0f;
vScale.x=max(vScale.x,1.0f);
vScale.y=max(vScale.y,1.0f);
vScale.z=max(vScale.y,1.0f);
pBody->SetResultMatrix(vPos3,vRot,vScale);
}
}
break;
}
}
void StateKeyboardJump::CalculateTurnAccelerate(DWORD dwTick)
{
const float l_fSpeedAccelerator = 0.002f;
float fTurnSpeed = 0.0f;
float fMaxTurnSpeed = 0.04f;
int oldturnflag = g_pHero->GetOldMoveFlag() & (KEYBOARDMOVE_LEFTTURN | KEYBOARDMOVE_RIGHTTURN);
int newturnflag = g_pHero->GetMoveFlag() & (KEYBOARDMOVE_LEFTTURN | KEYBOARDMOVE_RIGHTTURN);
if (oldturnflag == newturnflag && newturnflag)
{
if (newturnflag & KEYBOARDMOVE_LEFTTURN)
{
g_pHero->m_fTurnAccelerate += l_fSpeedAccelerator;
}
else
{
g_pHero->m_fTurnAccelerate -= l_fSpeedAccelerator;
}
}
else
{
g_pHero->m_fTurnAccelerate *= 0.7f;
if (fabs(g_pHero->m_fTurnAccelerate) <= (l_fSpeedAccelerator * 0.1f))
{
g_pHero->m_fTurnAccelerate = 0.0f;
}
}
if (g_pHero->GetMoveFlag() & (KEYBOARDMOVE_LEFTTURN | KEYBOARDMOVE_RIGHTTURN))
{
if (g_pHero->GetMoveFlag() & KEYBOARDMOVE_LEFTTURN)
{
g_pHero->m_fTurnAccelerate = l_fSpeedAccelerator;
}
else
{
g_pHero->m_fTurnAccelerate = -l_fSpeedAccelerator;
}
}
else
{
g_pHero->m_fTurnAccelerate = 0.0f;
}
fTurnSpeed += g_pHero->m_fTurnAccelerate;
if (fTurnSpeed >= fMaxTurnSpeed)
{
fTurnSpeed = fMaxTurnSpeed;
}
else if (fTurnSpeed <= -fMaxTurnSpeed)
{
fTurnSpeed = -fMaxTurnSpeed;
}
if (fabs(fTurnSpeed) > 0.0f)
{
g_pHero->Rotate(fTurnSpeed * dwTick,TRUE);
}
}
#endif