946 lines
24 KiB
C++
946 lines
24 KiB
C++
#include "stdafx.h"
|
|
#include ".\SGameLocalPlayer.h"
|
|
|
|
#include "GameDefine.h"
|
|
#include "KSeqAvatarEx.h"
|
|
|
|
#include "SGameAniType.h"
|
|
#include "SAvatarProperty.h"
|
|
#include "SAvatarStateMachine.h"
|
|
#include "SSkillDB.h"
|
|
#include "SGameMessage.h"
|
|
//#include "SGameMessageUI.h"
|
|
#include "SSKillStageType.h"
|
|
|
|
#include <toolkit/XStringUtil.h>
|
|
#include "SChatType.h"
|
|
#include "SStringDB.h"
|
|
#include "SMotionDB.h"
|
|
#include "SGameWorld.h"
|
|
|
|
#include ".\SGameLocalCreature.h"
|
|
|
|
#include "SDebug_Util.h"
|
|
#include "Arena\\ArenaJoinSituationChecker.h"
|
|
#include "SGameSystem.h"
|
|
extern SGameSystem * g_pCurrentGameSystem;
|
|
|
|
#include "SUISysMsgDefine.h"
|
|
AR_TIME SGameLocalPlayer::CREATURE_MOUNT_COOLTIME = 200;
|
|
|
|
void SGameLocalPlayer::sKMoveTargetList::add(K3DVector const& pos)
|
|
{
|
|
if (m_list.size() >= sKMoveTargetList::MAX_LIST_NUM)
|
|
m_list.erase(m_list.begin());
|
|
m_list.push_back(pos);
|
|
}
|
|
|
|
bool SGameLocalPlayer::sKMoveTargetList::is(K3DVector const& pos) const
|
|
{
|
|
std::vector<K3DVector>::const_iterator it = std::find(m_list.begin(), m_list.end(), pos);
|
|
if (it != m_list.end())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool SGameLocalPlayer::sKMoveTargetList::erase(K3DVector const& pos)
|
|
{
|
|
std::vector<K3DVector>::iterator it = std::find(m_list.begin(), m_list.end(), pos);
|
|
if (it != m_list.end())
|
|
{
|
|
m_list.erase( it );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
SGameLocalPlayer::SGameLocalPlayer() : SGamePlayer()
|
|
, m_bDeadDialog( false )
|
|
, m_bDeadMsgInDeathMatch( false )
|
|
, m_bSendResurrecMsgInDeathMatch( false )
|
|
, m_bDeadMsgInDeathMatchTime( 0 )
|
|
, m_bDeadMsgInDeathMatchTime2( 0 )
|
|
, m_dwUpdateTime( 0 ) //서버 업데이트 시간
|
|
, m_dwDeadDialogTime( 0 )
|
|
, m_nPrevHP( 1 )
|
|
, m_pWayPointList( NULL )
|
|
, m_nWayPointSize( 0 )
|
|
, m_nCurrentWayPoint( -1 )
|
|
, m_nTotalLak( 0 )
|
|
, m_nTotalBonusLak( 0 )
|
|
, m_nAbsorbLak( 0 )
|
|
, m_nBonusLakType( 0 ) // sonador 3.10.2 PC 방 혜택 관련 라크 획득 시스템 메시지 변경
|
|
, m_nBonusLakPercentage( 0 ) //
|
|
, m_nPKModeState( PK_MODE_OFF )
|
|
, m_instanceArenaStatus(IAS_NORMAL)
|
|
, m_pPending_poslist(NULL)
|
|
, m_nPending_handle( 0 )
|
|
{
|
|
m_pStateVM = new SLocalPlayerStateMachine;
|
|
m_pStateVM->SetReceiver( this );
|
|
|
|
m_pLocalPlayer = this;
|
|
m_bFootsteps = true;
|
|
m_bLocal = true;
|
|
m_creatureMountedTime = 0;
|
|
|
|
if (m_pPending_poslist==NULL)
|
|
{ m_pPending_poslist = new ArPosition[PENDINGSIZE];
|
|
}
|
|
m_dwActivateSkillTime = timeGetTime();
|
|
}
|
|
|
|
SGameLocalPlayer::~SGameLocalPlayer()
|
|
{
|
|
if( m_pStateVM ) m_pStateVM->SetReceiver( NULL );
|
|
|
|
if ( m_pPending_poslist )
|
|
delete []m_pPending_poslist;
|
|
}
|
|
|
|
void SGameLocalPlayer::OnInput( class SGameInput * pInput )
|
|
{
|
|
if( !m_pStateVM ) return;
|
|
m_pStateVM->OnInput( pInput );
|
|
}
|
|
|
|
void SGameLocalPlayer::NPlayAnimation( int nType , int nAniType, float fPlayRate )
|
|
{
|
|
/* if( nType == 11 )
|
|
{
|
|
assert(0);
|
|
}
|
|
_oprint( "로컬 NPlayAnimation : %d\n", nType );*/
|
|
if ((m_nNewCurAniType==ANI_WALK || m_nNewCurAniType==ANI_RUN) && (nType>=ANI_FIRE_MAGIC01 && nType<=ANI_FIRE_MAGIC05)) return;
|
|
assert( nType && "Local::NPlayAnimation Ani value is abnormal." );
|
|
|
|
SGamePlayer::NPlayAnimation( nType , nAniType, fPlayRate );
|
|
}
|
|
|
|
bool SGameLocalPlayer::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount )
|
|
{
|
|
return SGameAvatarEx::Render( uRenderBitVector, ppViewportList, nViewportCount );
|
|
}
|
|
|
|
bool SGameLocalPlayer::Process( DWORD dwTime, unsigned long uProcessBitVector )
|
|
{
|
|
if( m_bRefreshInven )
|
|
{
|
|
m_bRefreshInven = false;
|
|
|
|
//인벤토리에 셋팅
|
|
SIMSG_UI_MAINPLAYER_INFO msg;
|
|
msg.pSeqForm = GetSeqForm();
|
|
msg.pCobName = GetCobFileName();
|
|
msg.handle = GetArID();
|
|
msg.bRefresh = true;
|
|
|
|
msg.pAniName = GetMotionSetDB().GetAni( GetObjType(), ANI_DEFAULT01, GetRace(), GetSex(), m_nAniClass );
|
|
if( msg.pAniName )
|
|
{
|
|
CStringUtil::GetStrKey( msg.pAniName, '_', m_strTempAniKey );
|
|
msg.pAniName = m_strTempAniKey.c_str();
|
|
}
|
|
|
|
SendGameMsg( &msg );
|
|
}
|
|
|
|
// { TODO : 죽었을때 다이얼로그 처리
|
|
if( /*m_nPrevHP &&*/ IsDead() )
|
|
{
|
|
/*int x = GetPosition()->x;
|
|
int y = GetPosition()->y;
|
|
|
|
//데스매치중이다.
|
|
if(
|
|
( x >= 193536 && x <= 201600
|
|
&& y >= 104832 && y <= 112896)
|
|
|| ( x >= 201600 && x <= 209664
|
|
&& y >= 104832 && y <= 112896)
|
|
|
|
|| ( x >= 193536 && x <= 201600
|
|
&& y >= 96768 && y <= 104832)
|
|
|| ( x >= 201600 && x <= 209664
|
|
&& y >= 96768 && y <= 104832)
|
|
|
|
|| ( x >= 193536 && x <= 201600
|
|
&& y >= 88704 && y <= 96768)
|
|
|| ( x >= 201600 && x <= 209664
|
|
&& y >= 88704 && y <= 96768)
|
|
|
|
|| ( x >= 193536 && x <= 201600
|
|
&& y >= 80640 && y <= 88704)
|
|
|| ( x >= 201600 && x <= 209664
|
|
&& y >= 80640 && y <= 88704)
|
|
) // 데스매치*/
|
|
|
|
#ifndef _EQUATION
|
|
if(IsInDeathMatch())
|
|
{
|
|
//10초후에 부활한다고 한다.
|
|
if (!m_bDeadMsgInDeathMatch)
|
|
{
|
|
m_bDeadMsgInDeathMatch = true;
|
|
m_bSendResurrecMsgInDeathMatch = false;
|
|
m_bDeadMsgInDeathMatchTime = dwTime;
|
|
m_bDeadMsgInDeathMatchTime2 = dwTime;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if( !m_bDeadDialog )
|
|
{
|
|
m_bDeadDialog = true;
|
|
// AziaMafia Temps pour Rez
|
|
m_dwDeadDialogTime = GetSafeTickCount() + 100; //5000 : Une boîte de dialogue apparaît disant qu'il est mort après 5 secondes
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifndef _EQUATION
|
|
if(m_bDeadMsgInDeathMatch && !IsDead() )
|
|
{
|
|
m_bDeadMsgInDeathMatch = false;
|
|
m_bSendResurrecMsgInDeathMatch = false;
|
|
}
|
|
#endif
|
|
|
|
if( m_bDeadDialog && !IsDead() )
|
|
{
|
|
// 다이얼로그 닫자
|
|
m_bDeadDialog = false;
|
|
m_dwDeadDialogTime = 0;
|
|
SendGameMsg( &SMSG_SEND_DATA( "close_all_message_box" ) );
|
|
SendGameMsg( &SMSG_SEND_DATA( "close_rebirth_message_box" ) );
|
|
SendGameMsg( &SMSG_SEND_DATA( "close_rebirth_PVP_message_box" ) );
|
|
}
|
|
}
|
|
// }
|
|
|
|
// m_nPrevHP = GetHP();
|
|
#ifndef _EQUATION
|
|
if( m_bDeadMsgInDeathMatch )
|
|
{
|
|
if( dwTime - m_bDeadMsgInDeathMatchTime > 11000 )
|
|
{
|
|
if( !m_bSendResurrecMsgInDeathMatch )
|
|
{
|
|
//서버에 메시지 전송 하고 이제 대기한다.
|
|
m_bSendResurrecMsgInDeathMatch = true;
|
|
SendGameMsg( &SMSG_RESURRECTION( 0,0,false, true) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//부활메시지를 뿌린다.
|
|
if( dwTime - m_bDeadMsgInDeathMatchTime2 > 1000)
|
|
{
|
|
int ttt = 10 - (DWORD)((m_bDeadMsgInDeathMatchTime2 - m_bDeadMsgInDeathMatchTime)/1000);
|
|
if(ttt >= 0)
|
|
{
|
|
m_bDeadMsgInDeathMatchTime2 += 1000;
|
|
|
|
std::string strRemain = GetStringDB().GetString( 9202 );
|
|
XStringUtil::Replace( strRemain, "#@time@#", CStringUtil::StringFormat( "%d", ttt ));
|
|
|
|
SMSG_CHATTING chatmsg;
|
|
chatmsg.handle = 0;
|
|
chatmsg.nChatType = CHAT_NOTICE;
|
|
chatmsg.szSender = "@NOTICE";//"notice";
|
|
chatmsg.strText = strRemain;
|
|
chatmsg.nNoticeOnly = 0;
|
|
SendGameMsg( &chatmsg );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
// AziaMafia Instant Rez ?
|
|
//if( IsDead() && m_dwDeadDialogTime && m_dwDeadDialogTime < GetSafeTickCount() )
|
|
if (IsDead() && m_dwDeadDialogTime && m_dwDeadDialogTime < GetSafeTickCount())
|
|
{
|
|
m_dwDeadDialogTime = 0;
|
|
SendGameMsg( &SMSG_SEND_DATA( "close_all_message_box" ) );
|
|
|
|
int nStringID = 809; //전투 불능 상태입니다. <br> 마을로 귀환하시려면 확인 버튼을 누르세요.
|
|
int nCurrentLocation = GetCurrentLocation();
|
|
if( nCurrentLocation == PLAYER_IN_DUNGEON_SIEGE || nCurrentLocation == PLAYER_IN_DUNGEON_RAID )
|
|
nStringID = 822; //전투 불능 상태입니다. <br> 확인 버튼을 누르면 부활지점에서 부활합니다.
|
|
else if( nCurrentLocation == PLAYER_IN_MATCH )
|
|
nStringID = 963; //전투 불능 상태입니다.<br>확인 버튼을 누르면 경험치 소모 없이 제자리에서 부활합니다.
|
|
else if (PLAYER_IN_ARENA == nCurrentLocation)
|
|
nStringID = 2480;
|
|
|
|
if( GetStateFlag() & FLAG_STATE::FLAG_STATE_RESURRECTION )
|
|
{
|
|
StateInfoEx* pStateInfo = GetStateDBInfo( STATE_TYPE::STATE_RESURRECTION );
|
|
if( pStateInfo )
|
|
SendGameMsg( &SIMSG_REQ_OPEN_MSGBOX( SIMSG_REQ_OPEN_MSGBOX::MSGBOX_DEAD, GetArID(), false, S(nStringID), true, GetStringDB().GetString( pStateInfo->name_id ) ) );
|
|
else
|
|
SendGameMsg( &SIMSG_REQ_OPEN_MSGBOX( SIMSG_REQ_OPEN_MSGBOX::MSGBOX_DEAD, GetArID(), false, S(nStringID) ) );
|
|
}
|
|
else
|
|
SendGameMsg( &SIMSG_REQ_OPEN_MSGBOX( SIMSG_REQ_OPEN_MSGBOX::MSGBOX_DEAD, 0, false, S(nStringID) ) );
|
|
|
|
/// 2012.05.21 - prodongi
|
|
checkValidArenaJoinSituationAtDead();
|
|
}
|
|
|
|
SGamePlayer::Process( dwTime, uProcessBitVector );
|
|
|
|
if( m_pStateVM )
|
|
{
|
|
m_pStateVM->Process( m_dwTime );
|
|
}
|
|
|
|
if( m_dwUpdateTime == 0 )
|
|
{
|
|
m_dwUpdateTime = m_dwTime;
|
|
}
|
|
else
|
|
{
|
|
if( (m_dwTime - m_dwUpdateTime)>=UPDATE_TIME )
|
|
{
|
|
int cur = GetArTime();;
|
|
static int last = 0;
|
|
|
|
if (cur>last+400 || cur<last)
|
|
{
|
|
m_dwUpdateTime = m_dwTime;
|
|
//서버에 메세지 보냄
|
|
TS_CS_UPDATE msg;
|
|
|
|
msg.handle = GetArID();
|
|
msg.ar_time = cur;
|
|
time_t nowtime;
|
|
time(&nowtime);
|
|
msg.rtc = nowtime;
|
|
SendMsg( &msg );
|
|
last = cur;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if( m_pWayPointList && m_nWayPointSize > 0 )
|
|
CheckWayPoint();
|
|
|
|
return true;
|
|
}
|
|
|
|
void SGameLocalPlayer::SetAttackMode()
|
|
{
|
|
if( !(GetStatus() & TS_ENTER::PlayerInfo::FLAG_BATTLE_MODE) )
|
|
{
|
|
ReqBattle(); //서버에 상태 바뀜 전송
|
|
}
|
|
}
|
|
|
|
void SGameLocalPlayer::CheckPrevState()
|
|
{
|
|
if( m_pStateVM == NULL ) return;
|
|
|
|
TS_ATTACK_REQUEST msg;
|
|
msg.handle = GetArID();
|
|
msg.target_handle = m_pStateVM->GetAttackTarget();
|
|
SendMsg( &msg );
|
|
}
|
|
|
|
void SGameLocalPlayer::ReqTakeItem( AR_HANDLE handle )
|
|
{
|
|
TS_CS_TAKE_ITEM msg;
|
|
msg.item_handle = handle;
|
|
msg.taker_handle = GetArID(); // sonador #2.1.2.4.3 팻 조작 UI 연동
|
|
|
|
SendMsg( &msg );
|
|
}
|
|
|
|
void SGameLocalPlayer::ReqMove( AR_HANDLE handle, const ArPosition & target, bool bSpeedSync, bool bChase )
|
|
{
|
|
//TODO : 이 곳에서 검사를 하면, 문제가 생겨서 일단 제거. 상태 머신 안으로 들어가야 할 듯 하다.
|
|
//전에 요청한 위치보다 FREQ_MOVE_LIMIT 만큼은 커야 한다.
|
|
//float fLen = K3DVectorGetLength( K3DVector(m_vTargetPos.x, m_vTargetPos.y, 0.f), K3DVector(target.x, target.y, 0.f) );
|
|
//if( fLen < FREQ_MOVE_LIMIT )
|
|
//{
|
|
// return;
|
|
//}
|
|
|
|
//사용 중인 스킬이 있어서 이동 불가
|
|
if( !IsUseSkill_complete() )
|
|
return;
|
|
|
|
if( IsUsingSkill() )
|
|
return;
|
|
|
|
//뭔가를 하는중인가?
|
|
if( IsIng() )
|
|
return;
|
|
|
|
m_vTargetPos.x = target.x;
|
|
m_vTargetPos.y = target.y;
|
|
WORD wTile=0;
|
|
GetHeight( m_vTargetPos.x, m_vTargetPos.y, m_vTargetPos.z,wTile );
|
|
|
|
//SetMoveTargetPos( m_vTargetPos.x, m_vTargetPos.y, m_vTargetPos.z, bChase );
|
|
|
|
int nDetourSize = GetAllDetourPointSize();
|
|
//if( nDetourSize > 1 )
|
|
//{
|
|
// SGameObject::ReqMove( handle, target, GetAllDetourPoint(), nDetourSize, bSpeedSync );
|
|
ReqGameObjectMove( handle, target, GetAllDetourPoint(), nDetourSize, bSpeedSync );
|
|
//
|
|
// }
|
|
//else
|
|
//if ( nDetourSize == 1 )
|
|
//{
|
|
// ReqGameObjectMove( handle, target, GetAllDetourPoint(), 1, bSpeedSync );
|
|
//}
|
|
//else
|
|
//{ SGameObject::ReqMove( handle, target, &target, 1, bSpeedSync );
|
|
//}
|
|
|
|
|
|
|
|
DeleteReqPoint();
|
|
|
|
SGameLocalCreature::SetIdleProcess( true );
|
|
|
|
stopKMove();
|
|
|
|
// _oprint( "Local ReqMove : %d %f %f %f\n", nDetourSize, target.x, target.y, target.z );
|
|
}
|
|
|
|
void SGameLocalPlayer::reqKMove(AR_HANDLE handle, const K3DVector & target, bool bSpeedSync, bool bChase )
|
|
{
|
|
|
|
// AziaMafia FixSkill
|
|
/*if( !IsUseSkill_complete() )
|
|
return;
|
|
|
|
if( IsUsingSkill() )
|
|
return;
|
|
|
|
//뭔가를 하는중인가?
|
|
if( IsIng() )
|
|
return;
|
|
|
|
AziaMafia FixSkill end
|
|
*/
|
|
|
|
m_vTargetPos.x = target.x;
|
|
m_vTargetPos.y = target.y;
|
|
WORD wTile=0;
|
|
GetHeight( m_vTargetPos.x, m_vTargetPos.y, m_vTargetPos.z,wTile );
|
|
|
|
ArPosition _target;
|
|
_target.x = target.x;
|
|
_target.y = target.y;
|
|
_target.z = target.z;
|
|
ReqGameObjectMove( handle, _target, &_target, 1, bSpeedSync );
|
|
|
|
SGameLocalCreature::SetIdleProcess( true );
|
|
}
|
|
static DWORD dwLastMoveTime = timeGetTime();
|
|
void SGameLocalPlayer::ReqGameObjectMove( AR_HANDLE handle, const ArPosition & target, const ArPosition * poslist, int count, bool bSpeedSync )
|
|
{
|
|
//static int pending_handle = 0;
|
|
static int pending_count = 0;
|
|
static ArPosition pending_target = ArPosition(0,0);
|
|
//static ArPosition *pending_poslist = NULL;
|
|
|
|
|
|
//static ArPosition last_req_pos = ArPosition(0,0);
|
|
unsigned int cur_tick = timeGetTime();
|
|
if (cur_tick - m_dwActivateSkillTime < 1000 ) return;
|
|
|
|
|
|
|
|
if (target.x == 0 && target.y==0)
|
|
{
|
|
if ( m_nPending_handle && cur_tick - dwLastMoveTime > 200 && ( cur_tick - m_dwActivateSkillTime > 2000 ) )
|
|
{
|
|
SGameObject::ReqMove( m_nPending_handle, pending_target, m_pPending_poslist, pending_count, true );
|
|
dwLastMoveTime = cur_tick;
|
|
m_nPending_handle = 0;
|
|
pending_count = 0;
|
|
} else
|
|
{
|
|
SGameWorld* pGameWorld = dynamicCast<SGameWorld*>(g_pCurrentGameSystem->GetGame());
|
|
if( pGameWorld==0) return;
|
|
|
|
if (pGameWorld->GetGameManager()->IsShowLoadingWnd() )
|
|
{ dwLastMoveTime = cur_tick;
|
|
resetPending_poslist();
|
|
pending_count = 0;
|
|
return;
|
|
}
|
|
|
|
if (IsMoving()==0) return;
|
|
if (cur_tick - dwLastMoveTime < 1000 ) return;
|
|
dwLastMoveTime = cur_tick;
|
|
|
|
int ts = GetAllDetourPointSize();
|
|
if (ts<=0)
|
|
return;
|
|
int step = GetDetourStep();
|
|
|
|
if (step==0 || step==ts)
|
|
{ step>0 ? step=step-1 : step=0 ;
|
|
int currentX, currentY;
|
|
currentX = GetPosition()->x;
|
|
currentY = GetPosition()->y;
|
|
int xd = currentX - m_pPending_poslist[step].x;
|
|
int yd = currentY - m_pPending_poslist[step].y;
|
|
int dis = (xd*xd) + (yd*yd);
|
|
if ( dis >= 3000000 )
|
|
return;
|
|
SGameObject::ReqMove( GetArID(), pending_target, &m_pPending_poslist[step], 1, true );
|
|
}
|
|
|
|
}
|
|
return;
|
|
}
|
|
// Timer Process End
|
|
|
|
// Input Porcess Start
|
|
if (count>=PENDINGSIZE) return;
|
|
|
|
if( count >= 1 )
|
|
{
|
|
|
|
if ( ( cur_tick - dwLastMoveTime > 200 || count>1 ) )
|
|
{
|
|
dwLastMoveTime = cur_tick;
|
|
SGameObject::ReqMove( handle, target, poslist, count, bSpeedSync );
|
|
m_nPending_handle = 0;
|
|
pending_target.x = (int)target.x;
|
|
pending_target.y = (int)target.y;
|
|
pending_count = count;
|
|
for (int i=0;i<count;i++)
|
|
{ m_pPending_poslist[i]= poslist[i];
|
|
}
|
|
} else
|
|
{
|
|
m_nPending_handle = handle;
|
|
pending_target.x = (int)target.x;
|
|
pending_target.y = (int)target.y;
|
|
pending_count = count;
|
|
for (int i=0;i<count;i++)
|
|
{ m_pPending_poslist[i]= poslist[i];
|
|
}
|
|
}
|
|
} else
|
|
{
|
|
ArPosition current;
|
|
current.x = GetPosition()->x;
|
|
current.y = GetPosition()->y;
|
|
current.z = GetPosition()->z;
|
|
//pending_count = 0;
|
|
dwLastMoveTime = cur_tick;
|
|
resetPending_poslist();
|
|
SGameObject::ReqMove( handle, current, ¤t, 1, bSpeedSync );
|
|
//SGameObject::ReqMove( handle, target, &target, 1, bSpeedSync );
|
|
//pending_handle = 0;
|
|
//pending_target = target;
|
|
//pending_count = 0;
|
|
}
|
|
}
|
|
|
|
void SGameLocalPlayer::setCameraRoll(float angle)
|
|
{
|
|
SGameAvatarEx::setCameraRoll(angle);
|
|
SGameAvatarEx* creature = GetRiderCreatureObject();
|
|
if (creature)
|
|
{
|
|
creature->setCameraRoll(angle);
|
|
}
|
|
}
|
|
|
|
void SGameLocalPlayer::addKMoveTargetList(K3DVector const& targetPos)
|
|
{
|
|
m_kmoveTargetList.add(targetPos);
|
|
}
|
|
|
|
bool SGameLocalPlayer::isKMoveTargetList(std::vector<ArPosition> const& targetPosList) const
|
|
{
|
|
if (targetPosList.empty())
|
|
return false;
|
|
ArPosition pos = targetPosList.back();
|
|
return m_kmoveTargetList.is(K3DVector(pos.x, pos.y, 0.0f));
|
|
}
|
|
|
|
void SGameLocalPlayer::eraseKMoveTargetList(std::vector<ArPosition> const& targetPosList)
|
|
{
|
|
if (targetPosList.empty())
|
|
return;
|
|
ArPosition pos = targetPosList.back();
|
|
m_kmoveTargetList.erase(K3DVector(pos.x, pos.y, 0.0f));
|
|
}
|
|
|
|
void SGameLocalPlayer::clearMoveTargetList()
|
|
{
|
|
m_kmoveTargetList.clear();
|
|
}
|
|
|
|
|
|
void SGameLocalPlayer::ReqAttack( AR_HANDLE target ) // target == 0 공격 중지 요청
|
|
{
|
|
assert( target && "ReqAttack : Target ID Invalid!!!" );
|
|
|
|
if( m_pArObject && !m_pArObject->FinishedReqRegionUpdate() )
|
|
return;
|
|
|
|
|
|
//#ifndef NDEBUG
|
|
// SGameObject * pTarget = GetGameObject( target );
|
|
// if( pTarget )
|
|
// {
|
|
// float fDistance;
|
|
// K3DVector tpos = *pTarget->GetPosition();
|
|
// K3DVector spos = *GetPosition();
|
|
// fDistance = K3DVectorGetLength( tpos, spos ); //전체 거리
|
|
//
|
|
// _oprint( "[s크기 : %f %f], [t크기 %f %f]\n", GetSize()/2.f, GetScale(), pTarget->GetSize()/2.f, pTarget->GetScale() );
|
|
// _oprint( "[사거리 : %f], [거리 %f], <tpos %f %f %f >, <spos %f %f %f > \n", GetAttackRange(), fDistance, tpos.x, tpos.y, tpos.z, spos.x, spos.y, spos.z );
|
|
// }
|
|
//#endif
|
|
// _oprint( "[ReqAttack : %u]\n", target );
|
|
|
|
//if( target == 0 )
|
|
//{
|
|
// int a = 2;
|
|
// a = 3;
|
|
//}
|
|
|
|
|
|
// AziaMafia Mafia Fix Skill
|
|
/*
|
|
if( !IsUseSkill_complete() )
|
|
return;
|
|
|
|
if( IsUsingSkill() )
|
|
return;
|
|
*/
|
|
|
|
//뭔가를 하는중인가?
|
|
if( IsIng() ) return;
|
|
|
|
// TODO : 우선 임시로 막아 두자
|
|
if( IsMount() || IsMountMode() ) return;
|
|
|
|
TS_ATTACK_REQUEST msg;
|
|
msg.handle = GetArID();
|
|
msg.target_handle = target;
|
|
SendMsg( &msg );
|
|
}
|
|
|
|
void SGameLocalPlayer::ReqCast( AR_HANDLE target, int nSkillID, int nSkillLv, K3DVector const& targetPos )
|
|
{
|
|
// _oprint( "====>스킬 요청 %d %d\n", nSkillID, nSkillLv );
|
|
|
|
//TODO : 사용 중인 스킬의 모션이 있는가 판별.
|
|
//_SKILL_FX* pSkillFX = GetSkillStageDB().GetSkillStageData( info.nSkillID );
|
|
//if( !pSkillFX )
|
|
//{
|
|
// return;
|
|
//}
|
|
//if( pSkillFX->nCasting_Type_Id != 1 )
|
|
//{
|
|
// pSkillFX->nCasting_Start_Motion_Id;
|
|
//}
|
|
|
|
if( !IsUseSkill_complete() )
|
|
return;
|
|
|
|
if( IsUsingSkill() )
|
|
{
|
|
if( IsAttackingByBow() == false )
|
|
return;
|
|
}
|
|
|
|
//뭔가를 하는중인가?
|
|
if( IsIng() )
|
|
return;
|
|
|
|
_SKILL_FX* pSkillFX = GetSkillStageDB().GetSkillStageData( nSkillID );
|
|
if( !pSkillFX )
|
|
{
|
|
assert(0 && "스킬 ID 확인 : 스킬 유형이 없다!!!" );
|
|
return;
|
|
}
|
|
|
|
if( pSkillFX->szType == 0 || pSkillFX->szDeal_Damage == 1 ) //전투 기술이면 또는 해로운 기술 이면, 전투 모드로 전환
|
|
SetAttackMode();
|
|
|
|
|
|
SkillBaseEx* pSkill = GetSkillDB().GetSkillData(nSkillID);
|
|
SGameAvatarEx* pLocal = g_pCurrentGameSystem->GetLocalPlayer();
|
|
if (pSkill && pLocal)
|
|
{ if (pSkill->cost_energy_per_skl == 1)
|
|
{ nSkillLv = pLocal->m_nEnergy;//
|
|
}
|
|
}
|
|
|
|
|
|
TS_CS_SKILL msg;
|
|
msg.caster = GetArID();
|
|
msg.skill_id = nSkillID;
|
|
msg.target = target;
|
|
msg.skill_level= nSkillLv;
|
|
msg.x = targetPos.x;
|
|
msg.y = targetPos.y;
|
|
msg.z = targetPos.z;
|
|
|
|
SendMsg( &msg );
|
|
|
|
//사용 여부를 인터페이스에 알리자~
|
|
}
|
|
static DWORD dwCancelLastTime = GetSafeTickCount();
|
|
void SGameLocalPlayer::ReqCancelAction()
|
|
{
|
|
// _oprint( "SGameLocalPlayer::ReqCancelAction()\n" );
|
|
|
|
if ( GetSafeTickCount() - dwCancelLastTime > 200 )
|
|
{
|
|
// _oprint( "SGameLocalPlayer::ReqCancelAction()\n" );
|
|
TS_CS_CANCEL_ACTION msg;
|
|
msg.handle = GetArID();
|
|
SendMsg( &msg );
|
|
dwCancelLastTime = GetSafeTickCount();
|
|
}
|
|
}
|
|
void SGameLocalPlayer::ReqThrow( AR_HANDLE target, AR_HANDLE itemhandle )
|
|
{
|
|
//던지는게 가능한 아이템인지 검사는 Input에서 필터링 하는 것이 맞음.
|
|
//TS_CS_USE_ITEM use_msg;
|
|
//use_msg.item_handle = itemhandle;
|
|
//use_msg.target_handle = target;
|
|
//SendMsg( &use_msg );
|
|
}
|
|
void SGameLocalPlayer::ReqSit()
|
|
{
|
|
if( IsMount() && IsMountMode() ) return;
|
|
if( IsIng() ) return;
|
|
|
|
RqChatting( CHAT_NORMAL, m_pProperty->Name, "/sitdown" );
|
|
}
|
|
|
|
void SGameLocalPlayer::ReqStandUp()
|
|
{
|
|
if( IsMount() && IsMountMode() ) return;
|
|
if( IsIng() ) return;
|
|
|
|
RqChatting( CHAT_NORMAL, m_pProperty->Name, "/standup" );
|
|
}
|
|
|
|
void SGameLocalPlayer::ReqNormal()
|
|
{
|
|
if( IsMount() && IsMountMode() ) return;
|
|
if( IsIng() ) return;
|
|
|
|
std::string str;
|
|
XStringUtil::Format(str, "%u", GetArID() );
|
|
RqChatting( CHAT_NORMAL, str.c_str(), "/normal" );
|
|
}
|
|
|
|
void SGameLocalPlayer::ReqBattle()
|
|
{
|
|
if( IsMount() && IsMountMode() ) return;
|
|
if( IsIng() ) return;
|
|
|
|
std::string str;
|
|
XStringUtil::Format(str, "%u", GetArID() );
|
|
RqChatting( CHAT_NORMAL, str.c_str(), "/battle" );
|
|
SGamePlayer::SetAttackMode();
|
|
}
|
|
|
|
void SGameLocalPlayer::ReqMount()
|
|
{
|
|
if( IsIng() ) return;
|
|
|
|
if (!checkCreatureMountCooltime()) return ;
|
|
|
|
RqChatting( CHAT_NORMAL, m_pProperty->Name, "/mount_creature" );
|
|
}
|
|
|
|
void SGameLocalPlayer::ReqUnMount()
|
|
{
|
|
if( IsIng() ) return;
|
|
|
|
if (!checkCreatureMountCooltime()) return ;
|
|
|
|
RqChatting( CHAT_NORMAL, m_pProperty->Name, "/unmount_creature" );
|
|
}
|
|
|
|
void SGameLocalPlayer::ReqEmotion()
|
|
{
|
|
//서버로 보내기
|
|
}
|
|
|
|
void SGameLocalPlayer::ReqUseItem( AR_HANDLE hTargetHandle, AR_HANDLE hItemHandle, int nSkillID, AR_HANDLE hItemUseTargetHandle, const char* lpText )
|
|
{
|
|
_SKILL_FX* pSkillFX = GetSkillStageDB().GetSkillStageData( nSkillID );
|
|
if( pSkillFX )
|
|
{
|
|
//전투 기술이면 또는 해로운 기술 이면, 전투 모드로 전환
|
|
if( pSkillFX->szType == 0 || pSkillFX->szDeal_Damage == 1 )
|
|
SetAttackMode();
|
|
}
|
|
|
|
TS_CS_USE_ITEM msg;
|
|
|
|
msg.target_handle = hTargetHandle;
|
|
|
|
//로그인 되어있고, 시야에 없는 파티원등에게 사용 시
|
|
if( hItemUseTargetHandle > 0 )
|
|
msg.target_handle = hItemUseTargetHandle;
|
|
|
|
msg.item_handle = hItemHandle;
|
|
|
|
assert(32>::strlen(lpText));
|
|
if( 32>::strlen(lpText) )
|
|
::memcpy( msg.szParameter, lpText, ::strlen(lpText) );
|
|
|
|
SendMsg( &msg );
|
|
}
|
|
|
|
void SGameLocalPlayer::SetWayPointList( K3DVector* pWayPointList, int nWayPointSize )
|
|
{
|
|
ClearWayPointList();
|
|
|
|
m_pWayPointList = pWayPointList;
|
|
m_nWayPointSize = nWayPointSize;
|
|
m_nCurrentWayPoint = -1;
|
|
|
|
K3DVector vPos = GetCurPosWithChangeDir();
|
|
float fOldDis = 9999999.0f;
|
|
for( int nCount = 0; nCount < m_nWayPointSize; nCount++ )
|
|
{
|
|
float fDistance = GetDistance( vPos, m_pWayPointList[nCount] );
|
|
if( fDistance < fOldDis )
|
|
{
|
|
fOldDis = fDistance;
|
|
m_nCurrentWayPoint = nCount;
|
|
}
|
|
}
|
|
|
|
//현재 웨이포인트가 마지막인가? 없는 웨이 포인트인가? 웨이 포인트와 플레이어의 거리가 5미터 이내인가?
|
|
if( m_nCurrentWayPoint < m_nWayPointSize && m_nCurrentWayPoint > -1 &&
|
|
fOldDis < (float)GameRule::DEFAULT_UNIT_SIZE * 5 )
|
|
{
|
|
//각도를 구하자
|
|
if( m_nCurrentWayPoint < m_nWayPointSize - 1 ) //다음 위치가 있어야 한다
|
|
{
|
|
K3DVector vVec1 = m_pWayPointList[m_nCurrentWayPoint+1] - m_pWayPointList[m_nCurrentWayPoint];
|
|
K3DVector vVec2 = vPos - m_pWayPointList[m_nCurrentWayPoint];
|
|
|
|
vVec1.Normalize();
|
|
vVec2.Normalize();
|
|
float fAngle = K3DVectorDot( vVec1, vVec2 );
|
|
|
|
//현재 위치로 이동할지 아니면 바로 다음 위치로 이동할지 결정
|
|
if( fAngle > 0 ) m_nCurrentWayPoint++;
|
|
}
|
|
|
|
//길찾기 땜에 잠시 주석처리 하자
|
|
// ReqMove( GetArID(), ArPosition( m_pWayPointList[m_nCurrentWayPoint].x, m_pWayPointList[m_nCurrentWayPoint].y, 0 ), GetAllDetourPoint(), GetDetourSize(), true, true );
|
|
}
|
|
else
|
|
ClearWayPointList();
|
|
}
|
|
|
|
void SGameLocalPlayer::CheckWayPoint()
|
|
{
|
|
if( m_nCurrentWayPoint < m_nWayPointSize )
|
|
{
|
|
float fDistance = GetDistance( GetCurPosWithChangeDir(), m_pWayPointList[m_nCurrentWayPoint] );
|
|
if( fDistance < (float)GameRule::DEFAULT_UNIT_SIZE * 3 )
|
|
{
|
|
if( ++m_nCurrentWayPoint < m_nWayPointSize )
|
|
{
|
|
//길찾기 땜에 잠시 주석처리 하자
|
|
// ReqMove( GetArID(), ArPosition( m_pWayPointList[m_nCurrentWayPoint].x, m_pWayPointList[m_nCurrentWayPoint].y, 0 ), GetAllDetourPoint(), GetDetourSize(), true, true );
|
|
}
|
|
else
|
|
ClearWayPointList();
|
|
}
|
|
}
|
|
else
|
|
ClearWayPointList();
|
|
}
|
|
|
|
void SGameLocalPlayer::ClearWayPointList()
|
|
{
|
|
m_pWayPointList = NULL;
|
|
m_nWayPointSize = 0;
|
|
m_nCurrentWayPoint = -1;
|
|
}
|
|
|
|
void SGameLocalPlayer::SetStatus( unsigned status )
|
|
{
|
|
if( status & TS_ENTER::PlayerInfo::FLAG_PK_ON )
|
|
{
|
|
if( !(GetStatus() & TS_ENTER::PlayerInfo::FLAG_PK_ON) )
|
|
{
|
|
SetPKMode( true );
|
|
SetPKModeState( PK_MODE_ON );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//현재 PKON상태 였다면 OFF로
|
|
if( GetStatus() & TS_ENTER::PlayerInfo::FLAG_PK_ON )
|
|
{
|
|
SetPKMode( false );
|
|
SetPKModeState( PK_MODE_OFF );
|
|
}
|
|
}
|
|
|
|
SGameAvatarEx::SetStatus( status );
|
|
}
|
|
|
|
void SGameLocalPlayer::stopKMove()
|
|
{
|
|
if (m_pMsgHandler)
|
|
m_pMsgHandler->stopKMove();
|
|
}
|
|
|
|
/// 2012.05.21 - prodongi
|
|
void SGameLocalPlayer::checkValidArenaJoinSituationAtDead()
|
|
{
|
|
sArenaJoinSituationCondition situationCondition;
|
|
/// way
|
|
situationCondition.m_notificationWays = cArenaJoinSituationChecker::WAY_NOTIFICATION_WND;
|
|
/// situation
|
|
situationCondition.add(cArenaJoinSituationChecker::SITUATION_ARENA_WAITING, S(2456));
|
|
situationCondition.add(cArenaJoinSituationChecker::SITUATION_ARENA_WAITING_COUNT, S(2456));
|
|
|
|
g_pCurrentGameSystem->isValidArenaJoinSituation(situationCondition);
|
|
}
|
|
|
|
bool SGameLocalPlayer::checkCreatureMountCooltime()
|
|
{
|
|
AR_TIME curTime = GetArTime();
|
|
AR_TIME e = curTime - m_creatureMountedTime;
|
|
if (e < CREATURE_MOUNT_COOLTIME)
|
|
{
|
|
SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_OTHER_ACTION_WAIT ) );
|
|
return false;
|
|
}
|
|
m_creatureMountedTime = curTime;
|
|
return true;
|
|
}
|
|
void SGameLocalPlayer::resetPending_poslist()
|
|
{
|
|
m_nPending_handle = 0;
|
|
if ( m_pPending_poslist )
|
|
memset ( m_pPending_poslist, 0, sizeof(m_pPending_poslist)*PENDINGSIZE );
|
|
} |