Files
2026-06-01 12:46:52 +02:00

5446 lines
150 KiB
C++

#include "stdafx.h"
#include "SGameWorld.h"
#include "SCommandSystem.h"
#include "KDeviceManager.h"
#include "KRenderDeviceDX.h"
#include "SGameObject.h"
#include "SGameMessage.h"
//#include "SGameMessageUI.h"
#include "SGameWork.h"
#include "SGameViewPort.h"
#include "SGameAvatarEx.h"
#include "SGameLocalCreature.h"
#include "SGameLocalPlayer.h"
#include "SGameSkilProp.h"
#include "SGameFieldQuestProp.h"
#include "SGameOtherCreature.h"
#include "SGameOtherPlayer.h"
#include "SGameMob.h"
#include "SGameNpc.h"
#include "SGameItem.h"
#include "SGameSystem.h"
#include "SGameEffect.h"
#include "SGameLocalPet.h" // sonador 10.2.1 팻 시스템 구현
#include "SGameOtherPet.h"
#include "SUISysMsgDefine.h"
#include "K3DCamera.h"
#include "KRenderObjectBone.h"
#include "SActionMgr.h"
#include "STargetMgr.h"
#include "ErrorCode/ErrorCode.h"
#include "SGameOtherEffectMng.h"
#include "SItemDB.h"
#include "SNetMessage.h"
#include "SMonsterDB.h"
#include "SCreatureDB.h"
#include "SNpcResourceDB.h"
#include "STenacityDB.h"
#include "SPetDB.h"
#include "SFieldPropResourceDB.h"
#include "SRenderFlag.h"
#include "SGameOption.h"
#include "SUIDisplayInfo.h"
#include "SSKillStageType.h"
#include "SDebug_Util.h"
#include "SPlayerInfoMgr.h"
#include "SPetMgr.h" // sonador #2.1.2.4.3 팻 조작 UI 연동
// 2010.06.18 - prodongi
#include "SSelectedAvatarInfo.h"
/// 2010.11.10 - prodongi
#include "SGameLobbyDefine.h"
// 2011. 9. 16 - marine
#include "SGameManager.h"
#include "SGameInterface.h"
#include "TerrainMapEngine.h"
//#include "SUIUtil.h"
const float HEAD_DEF_TOP = 27.f;
const float HEAD_DEF = 20.f;
const float HEAD_DEF_HALF = 10.f; //
const float HEAD_ITEM = 5.f;
const float HEAD_PET = 5.f;
const float HEAD_GAP_MOB = 5.f;
const float HEAD_GAP_AVATAR = 2.f;
const float HEAD_GAP_PET = 2.f;
const float HEAD_GAP_ITEM = 1.f;
const float SHADOW_RENDER_MAX_LEN = 125.f; // LocalPlayer로 부터 그림자 그려지는 범위
const DWORD BOOTH_CHECK_INTERVAL = 1000; // 노점 이름 보여줄지 말지 검사하는 주기
const DWORD OBJ_LEAVE_TIME = 60000*3;
extern DWORD g_dwFPS;
//SCommandSystem::m_fAvatarVisRange = 1000.0f;
#define _WEAPON_FX_
static bool g_bRenderPlayerObj = false;
extern SGameSystem* g_pCurrentGameSystem;
SCommandSystem::SCommandSystem(K3DRenderDeviceDX *pRenderDevice, SGame* pGame)
{
m_pRenderDevice = pRenderDevice;
m_pGame = pGame;
m_dwTime = 0;
m_pPrevBoothProcTime = 0;
m_fAvatarVisRange = 5000.0f;
m_bDestroy = false;
m_hMouseOverItem = 0;
m_bCircleShadowEnable = false;
m_dwLocalCreaturePrcessTime = 0;
m_dwCheckTime = 0;
setIsTaming(false); /// 2011.01.20 - prodongi
Init();
}
SCommandSystem::~SCommandSystem()
{
Destroy();
}
void SCommandSystem::Init()
{
m_pActionMgr = new SGameActionMgr(m_pGame);
m_pOtherEffecMgr = new SGameOtherEffectMng( m_pGame );
m_nCreatureSelect = -1;
m_pTargetMgr = new STargetMgr;
}
void SCommandSystem::Destroy()
{
m_bDestroy = true;
SAFE_DELETE( m_pActionMgr );
SAFE_DELETE( m_pTargetMgr );
SAFE_DELETE( m_pOtherEffecMgr );
SGameAvatarExTag* pAvatarTag = NULL;
bool res = m_hashLeaveList.get_first_value( pAvatarTag );
while ( res )
{
if ( pAvatarTag != NULL )
{
SAFE_DELETE( pAvatarTag->ptr );
SAFE_DELETE( pAvatarTag );
}
res = m_hashLeaveList.get_next_value( pAvatarTag );
}
m_hashLeaveList.clear();
SGameAvatarEx* pGameObject = NULL;
KSortVector< class SGameAvatarEx* >::iterator it = m_svObject.begin();
while ( it != m_svObject.end() )
{
pGameObject = (*it); ++it;
if ( pGameObject != NULL )
{
delete pGameObject;
}
}
m_hashObject.clear();
m_svObject.clear();
m_svPlayerObject.clear();
m_svOtherObject.clear();
m_svRecongnizeMobObject.clear();
m_vLocalCreature.clear(); //포인터만 들어 있다.
m_svReservationObject.clear();
m_svRidingObject.clear();
KSortVector< SGameAvatarEx* >::iterator iter = m_svTransportCreatureObject.begin();
while( iter != m_svTransportCreatureObject.end() )
{
pGameObject = (*iter); ++iter;
if ( pGameObject != NULL )
{
delete pGameObject;
}
}
m_svTransportCreatureObject.clear();
m_hashTransportCreatureObject.clear();
m_hashPendingObjList.clear();
}
void SCommandSystem::PlayerEmotion( AR_HANDLE handel, int nEmotionID )
{
if( handel != 0 )
{
SGameAvatarEx * pPlayer = GetAvatar( handel );
if( pPlayer && pPlayer->GetObjType() == TS_ENTER::GAME_PLAYER )
{
if( pPlayer->IsWorkListEmpty() )
{
SWorkEmotion* pEmotion = new SWorkEmotion( pPlayer, NULL );
if( pEmotion->SetEmotion( nEmotionID ) )
{
pPlayer->AllWorkEnd();
pPlayer->AddWork( pEmotion );
}
}
}
}
else
{
int nPlayerObj = m_svPlayerObject.size();
for( int i(0); nPlayerObj>i; i++ )
{
SGameAvatarEx * pPlayer = m_svPlayerObject[i];
if( pPlayer->GetObjType() != TS_ENTER::GAME_PLAYER ) continue;
if( pPlayer->IsWorkListEmpty() )
{
SWorkEmotion* pEmotion = new SWorkEmotion( pPlayer, NULL );
if( pEmotion->SetEmotion( nEmotionID ) )
{
pPlayer->AllWorkEnd();
pPlayer->AddWork( pEmotion );
}
}
}
}
}
//===================================================================================================
int GetMagicType( int nMagicType )
{
switch( nMagicType )
{
case StateInfo::ET_FIRE: //화속성
return 5076;
case StateInfo::ET_WATER: //수속성
return 5077;
case StateInfo::ET_WIND: //풍속성
return 5078;
case StateInfo::ET_EARTH: //토속성
return 5079;
case StateInfo::ET_LIGHT: //명속성
return 5080;
case StateInfo::ET_DARK: //암속성
return 5081;
}
return 0; //무속성
}
void SCommandSystem::ProcMsgAtStatic( SGameMessage * pGameMsg )
{
if( pGameMsg->nType == IMSG_KEYUP ||
pGameMsg->nType == IMSG_KEYDOWN ||
pGameMsg->nType == IMSG_MOUSEMOVE ||
pGameMsg->nType == IMSG_UI_2DPOS_INFO ||
pGameMsg->nType == IMSG_UI_ETC_INFO ||
pGameMsg->nType == IMSG_UI_MY_DEGREE ||
pGameMsg->nType == IMSG_UI_MINIMAP_INFO ) return;
// _oprint( "!!!!!SCommandSystem::ProcMsgAtStatic : %d\n", pGameMsg->nType );
switch( pGameMsg->nType )
{
case MSG_RESULT :
{
OnMsgResult ( static_cast<SMSG_RESULT*>(pGameMsg) );
break;
}
case MSG_CHATTING :
{
OnMsgChatting ( static_cast<SMSG_CHATTING*>(pGameMsg) );
break;
}
case MSG_MOVE :
{
OnMsgMove ( static_cast<SMSG_MOVE*>(pGameMsg) );
break; //이동
}
case MSG_KMOVE:
{
OnMsgKMove(dynamic_cast<SMSG_KMOVE*>(pGameMsg));
break;
}
case MSG_REGION_ACK :
{
OnMsgRegionAck ( static_cast<SMSG_REGION_ACK*>(pGameMsg) );
break; //영역 요청
}
case MSG_LOGIN :
{
OnMsgLogin ( static_cast<SMSG_LOGIN*>(pGameMsg) );
break; //Login (Local Player)
}
case MSG_HAIR_INFO:
{
OnMsgHairInfo ( static_cast<SMSG_HAIR_INFO*>(pGameMsg) );
break; //Login (Local Player)
}
// 2010.05.19 - prodongi
case MSG_HIDE_EQUIP_INFO:
{
OnMsgHideEquipInfo(static_cast<SMSG_HIDE_EQUIP_INFO*>(pGameMsg));
break;
}
// 꾸미기아이템 보임숨김 개별 정보.
case MSG_HIDE_EQUIP_FLAG:
OnMsgHideEquipFlag(static_cast<SMSG_HIDE_EQUIP_INFO*>(pGameMsg));
break;
case MSG_LEAVE :
{
OnMsgLeave ( static_cast<SMSG_LEAVE*>(pGameMsg) );
break; //Leave (Other Player)
}
case MSG_ENTER :
{
OnMsgEnter ( static_cast<SMSG_ENTER*>(pGameMsg) );
break; //Enter (Other Player)
}
case MSG_ATTACK :
{
OnMsgAttack ( static_cast<SMSG_ATTACK*>(pGameMsg) );
break; //공격
}
case MSG_ATTACK_DOUBLE :
{
OnMsgAttackDouble ( static_cast<SMSG_ATTACK_DOUBLE*>(pGameMsg) );
break;
}
case MSG_CANT_ATTACK :
{
SMSG_CANT_ATTACK* pCantMsg = static_cast<SMSG_CANT_ATTACK*>(pGameMsg);
SGameAvatarEx * pAvatar = NULL;
if( (pAvatar = (SGameAvatarEx*)GetObject( pCantMsg->attacker_handle )) != NULL )
pAvatar->OnNetInput( pGameMsg );
break;
}
case MSG_UNSUMMON :
{
SMSG_UNSUMMON* pUnsummonMsg = static_cast<SMSG_UNSUMMON*>(pGameMsg);
SGameAvatarEx* pAvatar = (SGameAvatarEx*)GetObject( pUnsummonMsg->summon_handle );
if( pAvatar && pAvatar->GetObjType() == TS_ENTER::GAME_SUMMON )
{
int nMagicType = GetCreatureDB().GetMagicType( pAvatar->GetContentID() );
nMagicType = GetMagicType( nMagicType );
OnAddOtherEffect( SGameOtherEffectMng::FX_UN_SUMMONING_CREATURE, &OtherFxData( 0, pUnsummonMsg->summon_handle, 5067 ) );
pAvatar->SetReservation(true); //삭제 보류시키고
// 내가 소환한 소환수이면 소환수 삭제해준다
m_pGame->DelSummon( pUnsummonMsg->summon_handle );
}
}
break;
case MSG_UNSUMMON_PET: // sonador 10.2.1 팻 시스템 구현
{
SMSG_UNSUMMON_PET* pUnsummonPetMsg = static_cast< SMSG_UNSUMMON_PET* >( pGameMsg );
SGameAvatarEx* pAvatar = static_cast< SGameAvatarEx* >( GetObject( pUnsummonPetMsg->pet_handle ) );
if( pAvatar && pAvatar->GetObjType() == TS_ENTER::GAME_PET )
{
// 아바타 삭제 보류
OnAddOtherEffect( SGameOtherEffectMng::FX_UN_SUMMONING_CREATURE, &OtherFxData( 0, pUnsummonPetMsg->pet_handle, 5067 ) );
pAvatar->SetReservation( true );
m_pGame->RemovePet( pUnsummonPetMsg->pet_handle );
// sonador #2.3.1.45
// 팻이 가시 거리보다 멀어졌을 때(deactivated 상태)
// 서버에서 TS_LEAVE 메시지가 오지 않기 때문에
// 클라이언트에서 임의로 leave 처리를 한다.
if( !pAvatar->IsActivated() )
{
SMSG_LEAVE leaveMsg;
leaveMsg.handle = pUnsummonPetMsg->pet_handle;
ProcMsgAtStatic( &leaveMsg );
}
}
}
break;
case MSG_CHANGE_NAME :
{
SMSG_CHANGE_NAME * pChangeName = static_cast< SMSG_CHANGE_NAME* >( pGameMsg );
DATA_PET* pPetData = m_pGame->IsLocalPet( pChangeName->handle );
if( pPetData )
{
strcpy_s( pPetData->name, pChangeName->m_name.c_str() );
}
SGameAvatarEx * pAvatar = GetAvatar( pChangeName->handle );
if( pAvatar )
{
pAvatar->SetName( pChangeName->m_name.c_str() );
pChangeName->status = pAvatar->GetStatus();
}
}
break;
case MSG_SUMMON_EVOLUTION :
{
SMSG_SUMMON_EVOLUTION* pSummonEvolution = static_cast<SMSG_SUMMON_EVOLUTION*>(pGameMsg);
m_pGame->EvolutionSummon( pSummonEvolution );
SGameAvatarEx* pAvatar = (SGameAvatarEx*)GetObject( pSummonEvolution->summon_handle );
if( pAvatar && pAvatar->GetObjType() == TS_ENTER::GAME_SUMMON )
{
int nMagicType = GetCreatureDB().GetMagicType( pAvatar->GetContentID() );
nMagicType = GetMagicType( nMagicType );
OnAddOtherEffect( SGameOtherEffectMng::FX_CREATURE_EVOLUTION, &OtherFxData( 0, pSummonEvolution->summon_handle, 5067 ) );
}
break;
}
case MSG_MOUNT_SUMMON :
{
OnMsgMount( static_cast<SMSG_MOUNT_SUMMON*>(pGameMsg) );
break;
}
case MSG_UNMOUNT_SUMMON :
{
OnMsgUnMount( static_cast<SMSG_UNMOUNT_SUMMON*>(pGameMsg) );
break;
}
case MSG_USE_ITEM_RESULT:
{
OnMsgItemResult( static_cast<SMSG_USE_ITEM_RESULT*>(pGameMsg) );
break;
}
case MSG_SKILL_EVENT :
{
OnMsgSkillEvent ( static_cast<SMSG_SKILL_EVENT*>(pGameMsg) );
break; //Skill
}
case MSG_ADDED_SKILL_LIST:
{
break; //Skill List
}
case MSG_SKILL_LIST :
{
break; //Skill List
}
//타이밍 맞추기 곤란한다.
//case MSG_SKILL_EFFECT :
// {
// OnMsgSkillEffect( static_cast<SMSG_SKILL_EFFECT*>(pGameMsg) );
// break; //Skill Effect
// }
case MSG_TAMING_INFO:
{
OnTamingInfo( static_cast<SMSG_TAMING_INFO*>(pGameMsg) );
break;
}
case MSG_CMD_RESULT :
{
OnMsgCmd ( static_cast<SMSG_CMD_RESULT*>(pGameMsg) );
break; //Cmd
}
case MSG_ITEM_TAKE_RESULT :
{
OnMsgTakeResult( static_cast<SMSG_ITEM_TAKE*>(pGameMsg) );
break; //인벤에 넣기
}
case MSG_ITEM_DROP_RESULT :
{
OnMsgDropResult( static_cast<SMSG_ITEM_DROP*>(pGameMsg) );
break; //인벤에서 삭제
}
case MSG_ITEM_DROP_INFO :
{
OnMsgDropInfo ( static_cast<SMSG_ITEM_DROP_INFO*>(pGameMsg));
break;
}
case MSG_ITEM_WEAR :
{
OnMsgWearInfo ( static_cast<SMSG_ITEM_WEAR*>(pGameMsg) );
break; //아이템 변경
}
case MSG_ITEM_INVEN :
{
OnMsgInventory ( static_cast<SMSG_ITEM_INVEN*>(pGameMsg) );
break; //인벤 정보
}
case MSG_ITEM_DESTROY :
{
break; //Item Destroy
}
case MSG_TAKE_ITEM_RESULT :
{
OnMsgTakeItemResult( static_cast<SMSG_TAKE_ITEM_RESULT*>(pGameMsg) );
break;
}
case MSG_UPDATE_ITEM_COUNT:
{
break; //Item Count Update
}
case MSG_MIX_RESULT:
{
SMSG_MIX_RESULT* pMixResultMsg = static_cast< SMSG_MIX_RESULT* >( pGameMsg );
SGameAvatarEx* pLocalPlayer = GetLocalPlayer();
if( pLocalPlayer == NULL ) return;
FX_DATA fx_data;
fx_data.attack = pLocalPlayer->GetArID();
fx_data.owner = pLocalPlayer->GetArID();
fx_data.target = pLocalPlayer->GetArID();
fx_data.fPlayRate = 1.f;
fx_data.nEffPos = EFFECT_POS_TOP;
fx_data.nPlayID = 1;
if( pMixResultMsg->count > 0 ) //성공
{
fx_data.nFX_ID = 18016;
}
else //실패
{
fx_data.nFX_ID = 18017;
}
m_pGame->AddEffect( &fx_data );
}
break;
case MSG_BOOTH_NAME :
{
OnMsgBoothName( static_cast< SMSG_BOOTH_NAME* >( pGameMsg ) );
break;
}
case MSG_BOOTH_CLOSED :
{
OnMsgBoothClosed( static_cast< SMSG_BOOTH_CLOSED * >( pGameMsg ) );
break;
}
case MSG_TRADE :
{
SMSG_TRADE* pTradeMsg = static_cast<SMSG_TRADE*>(pGameMsg);
SGameAvatarEx * pPlayer = GetAvatar( pTradeMsg->target_player );
if( pPlayer )
pTradeMsg->target_Name = pPlayer->GetName();
break; //Trade
}
case MSG_STATE :
{
OnMsgState( static_cast<SMSG_STATE*>(pGameMsg) );
break; //상태 이상 시간
}
case MSG_PROPERTY :
{
OnMsgProperty( static_cast<SMSG_PROPERTY*>(pGameMsg) );
break; //각종 상태
}
case MSG_HPMP :
{
OnMsgHPMP( static_cast<SMSG_HPMP*>(pGameMsg) );
break; //HPMP 동시에
}
case MSG_EXP_UPDATE :
{
OnMsgExpUpdate( static_cast<SMSG_EXP_UPDATE*>(pGameMsg) );
break;
}
case MSG_MARKET :
{
break; //Market
}
case MSG_NPC_DIALOG :
{
break; //NPC Dialog
}
case MSG_LEVEL_UPDATE :
{
OnMsgLevelUpdate( static_cast<SMSG_LEVEL_UPDATE*>(pGameMsg) );
break;
}
case CMSG_WARP :
{
OnMsgWarp ( static_cast<SCMSG_WARP*>(pGameMsg) );
break; //Warp
}
case MSG_STATUS_CHANGE :
{
OnMsgStatusChange( static_cast<SMSG_STATUS_CHANGE*>(pGameMsg) );
break; //Warp
}
case MSG_REGEN_HPMP :
{
OnMsgRegenHPMP( static_cast<SMSG_REGEN_HPMP*>(pGameMsg));
break;
}
case IMSG_REQ_OPEN_MSGBOX:
{
SIMSG_REQ_OPEN_MSGBOX* pReqOpenMsg = static_cast<SIMSG_REQ_OPEN_MSGBOX*>(pGameMsg);
//Msg 박스 호출 될 경우, 로컬 플레이어의 죽는 상자를 표시 플래그를 꺼준다.
if( pReqOpenMsg->m_MsgBoxID != SIMSG_REQ_OPEN_MSGBOX::MSGBOX_DEAD )
{
if( GetLocalPlayer() && GetLocalPlayer()->IsDead() )
{
SGameLocalPlayer * pPlayer = (SGameLocalPlayer *)GetLocalPlayer();
//사라진 메세지 박스 다시 켜기 위해서
pPlayer->ResetDeadDialog();
}
}
break;
}
case MSG_EMOTION:
{
OnMsgEmotion( static_cast<SMSG_EMOTION*>(pGameMsg) );
break;
}
//연출이 필요한 이펙트 모음
case MSG_GET_CHAOS:
{
OnMsgAddOtherEffect( pGameMsg );
break;
}
case MSG_ENERGY:
{
OnMsgAddForceSphere( static_cast<SMSG_ENERGY*>(pGameMsg) );
break;
}
}
}
//===================================================================================================
//Other Object
SGameAvatarEx * SCommandSystem::GetObject( int nType, K3DVector & pos, float & fDist, int nItemType /*= -1*/, float fLimitDistance )
{
int nSelectIndex = -1;
float fFirstLen = 0.f;
switch( nType )
{
case TS_ENTER::GAME_PLAYER : break;
case TS_ENTER::GAME_NPC : break;
case TS_ENTER::GAME_ITEM :
case TS_ENTER::GAME_MOB :
{
SGameAvatarEx* pFindObject = NULL;
SGameAvatarEx* pGameObject = NULL;
KSortVector< class SGameAvatarEx* >::iterator it = m_svObject.begin();
int i=0;
while ( it != m_svObject.end() )
{
pGameObject = (*it);
if ( pGameObject != NULL && pGameObject->GetObjType() == nType && pGameObject->IsActivated() )
{
if( i == 0 )
{
fFirstLen = GetDistance( pos, *pGameObject->GetPosition() );
pFindObject = pGameObject;
i++;
}
float fLen = GetDistance( pos, *pGameObject->GetPosition() );
if( fFirstLen > fLen )
{
fFirstLen = fLen;
pFindObject = pGameObject;
}
}
++it;
}
if( pFindObject )
{
if( nType == TS_ENTER::GAME_ITEM )
{
if( fFirstLen > fLimitDistance ) return NULL; //먹는 범위 보다 크면, 안 간다.
if( nItemType != -1 )
{
if( nItemType != GetItemDB().GetUseType( pFindObject->GetContentID() ) ) return NULL;
}
}
else if( nType == TS_ENTER::GAME_MOB )
{
if( fFirstLen > 30 * GameRule::DEFAULT_UNIT_SIZE ) return NULL; //10m 보다 크면, 안 간다. // AziaMafia LoadMap 30
}
fDist = fFirstLen;
return pFindObject;
}
return NULL;
}
break;
case TS_ENTER::GAME_SUMMON : break;
case TS_ENTER::GAME_SKILL_PROP : break;
}
return NULL;
}
//===================================================================================================
// 펫 아이템 줍기 기능용 특수 함수 -
void SCommandSystem::GetItemObjects_For_PetAutoGather( const K3DVector& center, float fLimitRange, std::vector<SGameAvatarEx*>& vecResult, const K3DVector& dist_pos, std::vector<float>& vecDist, int nMaxCount )
{
int nSelectIndex = -1;
float fFirstLen = 0.f;
vecResult.clear();
vecDist.clear();
SGameAvatarEx* pFindObject = NULL;
SGameAvatarEx* pGameObject = NULL;
KSortVector< class SGameAvatarEx* >::iterator it = m_svObject.begin();
int i=0;
while ( it != m_svObject.end() )
{
pGameObject = (*it);
if ( pGameObject != NULL && pGameObject->GetObjType() == TS_ENTER::GAME_ITEM && pGameObject->IsActivated() )
{
float fLen = GetDistance( center, *pGameObject->GetPosition() );
SGameAvatarEx* pFindObject = pGameObject;
if( fLen < fLimitRange )
{
vecResult.push_back(pFindObject);
vecDist.push_back( GetDistance( dist_pos, *pGameObject->GetPosition() ) );
if( vecResult.size() >= nMaxCount )
break;
}
}
++it;
}
}
SGameAvatarEx* SCommandSystem::GetObjectFromLeaveList( AR_HANDLE arHandle )
{
SGameAvatarExTag* pAvatarExTag = NULL;
if( m_hashLeaveList.lookup( arHandle, pAvatarExTag ) )
{
SGameAvatarEx* pAvatar = NULL;
if( pAvatarExTag )
{
if( pAvatarExTag->bNotUse ) //사용 할수 없다면
{
return NULL;
}
pAvatar = pAvatarExTag->ptr;
if( pAvatar )
{
pAvatar->Activate();
pAvatar->ReInitialize();
_Object* arObj = &pAvatar->GetArObject();
if( arObj )
{
arObj->bIsActivate = true;
arObj->bIsLeaved = false;
arObj->leaveTime = 0;
}
}
pAvatarExTag->ptr = NULL;
SAFE_DELETE( pAvatarExTag );
}
m_hashLeaveList.erase( arHandle );
return pAvatar;
}
return NULL;
}
SGameAvatarEx * SCommandSystem::GetSelectCreature()
{
if( m_vLocalCreature.empty() ) return NULL;
if( m_nCreatureSelect < 0 || m_nCreatureSelect >= (int)m_vLocalCreature.size() ) return NULL;
return m_vLocalCreature[m_nCreatureSelect];
}
void SCommandSystem::onLeave( AR_HANDLE handle, BOOL bEffect )
{
//Target 초기화~
//for( unsigned int i(0); m_vLocalList.size()>i; i++ )
//{
// m_vLocalList[i]->CheckAttackObject( pPtr->handle );
// m_vLocalList[i]->CheckTargetObject( pPtr->handle );
//}
if( m_hMouseOverItem == handle )
m_hMouseOverItem = 0;
//삭제 보류중인 Object 검사
RemoveReservationObject();
//TargetMgr Leave
m_pTargetMgr->LeaveTarget( handle );
SGameAvatarEx* pAvatar = NULL;
if( m_hashObject.lookup( handle, pAvatar ) )
{
/// 2011.01.20 - prodongi
if (pAvatar->IsLocalPlayer())
setIsTaming(false);
//마스터가 존재 한다면 Ride 정보를 초기화 시킨다
SGameAvatarEx* pMaster = GetAvatar( pAvatar->GetMaster() );
if( pMaster )
{
//같은 핸들이 Leave라면 링크 끊자
if( pMaster->GetCreatureMountHandle() == pAvatar->GetArID() )
pMaster->SetRiderCreatureInfo();
DeleteRidingObject( pAvatar->GetMaster(), pAvatar->GetArID() );
// 2010.08.12 - prodongi
if (pAvatar->GetInnObjType() == TS_ENTER::GAME_SUMMON)
pMaster->SetCreature(handle, false);
if( pMaster->IsLocalPlayer() == true )
UISendStringMessage(m_pGame->GetGameManager(), SIMSG_TOGGLE_UIWINDOW::UIWINDOW_DURABILITY, "refresh_durability");
}
LeaveTransportCreature( pAvatar->GetTransportCreatureHandle() );
pAvatar->Deactivate();
pAvatar->LeaveData();
//삭제 보류 대상인가?
//잦은 이동시 몹안나오는 문제가 있어서 임시로 삭제 2009.12.24. sfreer
/*if ((!pAvatar->IsDead()) && (pAvatar->GetInnObjType() == TS_ENTER::GAME_MOB)) // 몹이고 안 죽었는데도 Leave 메시지가 날아오면
{
pAvatar->Activate(); // 비활성화했던걸 살리고
pAvatar->SetReservation(true);
pAvatar->SetFadeOut(3000); // 3초에 걸쳐 페이드아웃하게 한다. 3초는 하드코딩
}*/
if(!pAvatar->IsReservation())
{
m_hashObject.erase( handle );
m_hashLeaveList.add( handle, new SGameAvatarExTag( pAvatar, GetSafeTickCount() ) );
m_svObject.erase( pAvatar );
if( pAvatar->GetObjType() == TS_ENTER::GAME_PLAYER )
{
m_svPlayerObject.erase( pAvatar );
}
else
{
m_svOtherObject.erase( pAvatar );
{
int idx = m_svRecongnizeMobObject.search_index( pAvatar );
if( idx >= 0)
m_svRecongnizeMobObject.erase( pAvatar );
}
}
}
else
m_svReservationObject.push_back(handle);
m_pGame->DelOwnerEffect( handle );
}
else
{
LeaveTransportCreature( handle );
}
pAvatar = NULL;
if( m_hashPendingObjList.lookup( handle, pAvatar ) )
{
m_hashPendingObjList.erase( handle );
}
}
void SCommandSystem::LeaveTransportCreature( AR_HANDLE hCreature, bool bWithArObj )
{
SGameAvatarEx* pCreature = NULL;
if( m_hashTransportCreatureObject.lookup( hCreature, pCreature ) )
{
pCreature->Deactivate();
pCreature->LeaveData();
m_hashTransportCreatureObject.erase( hCreature );
m_hashLeaveList.add( hCreature, new SGameAvatarExTag( pCreature, GetSafeTickCount() ) );
m_svTransportCreatureObject.erase( pCreature );
if( bWithArObj ) m_pArObject->onLeave( hCreature );
}
pCreature = NULL;
if( m_hashPendingObjList.lookup( hCreature, pCreature ) )
{
m_hashPendingObjList.erase( hCreature );
}
}
void SCommandSystem::ActivateStateEffect()
{
int nObjSize( m_svObject.size() );
for( int i(0); i<nObjSize; ++i )
{
RefreshStateEffect( m_svObject[i] );
}
}
void SCommandSystem::RefreshStateEffect( SGameAvatarEx* pAvatar )
{
if( pAvatar == NULL ) return;
pAvatar->RefreshAllStateEffect();
SGameOption& gameoption = GetGameOption();
std::vector<SStateSlot*> vecStateList;
SStateSlot* pStateSlot(NULL);
pAvatar->GetAllStateList( vecStateList, false );
SMSG_STATE state;
std::vector<SStateSlot*>::iterator iter = vecStateList.begin();
for( ; iter != vecStateList.end(); ++iter )
{
pStateSlot = (*iter);
if( pStateSlot == NULL ) continue;
state.handle = pStateSlot->GetTargetHandle();
state.state_handle = pStateSlot->GetStateHandle();
state.state_code = pStateSlot->GetStateCode();
state.state_level = pStateSlot->GetStateLevel();
state.end_time = pStateSlot->GetEndTime();
StateInfoEx* pStateInfo = GetTenacityDB().GetTenacityData( state.state_code );
if( pStateInfo )
{
switch( pStateInfo->effect_type )
{
case STATE_TYPE::STATE_RIDING:
{
if( pAvatar->GetObjType() == TS_ENTER::GAME_PLAYER )
{
if( state.state_level > 0 )
{
OnUnMount( pStateInfo, pAvatar, true );
OnMount( pStateInfo, pAvatar, false );
}
else if( state.state_level == 0 )
{
OnUnMount( pStateInfo, pAvatar );
}
}
}
break;
}
}
}
vecStateList.clear();
}
void SCommandSystem::RemoveAllReservationObject()
{
std::vector< AR_HANDLE >::iterator iter = m_svReservationObject.begin();
for( ; iter != m_svReservationObject.end(); )
{
SGameAvatarEx* pAvatar = NULL;
if( m_hashObject.lookup( (*iter), pAvatar ) )
{
m_hashObject.erase( (*iter) );
m_hashLeaveList.add( (*iter), new SGameAvatarExTag( pAvatar, GetSafeTickCount() ) );
m_svObject.erase( pAvatar );
if( pAvatar->GetObjType() == TS_ENTER::GAME_PLAYER )
{
m_svPlayerObject.erase( pAvatar );
}
else
{
m_svOtherObject.erase( pAvatar );
{
int idx = m_svRecongnizeMobObject.search_index( pAvatar );
if( idx >= 0)
m_svRecongnizeMobObject.erase( pAvatar );
}
}
iter = m_svReservationObject.erase(iter);
}
else
{
assert( false && "SCommandSystem::RemoveReservationObject ( 들어오면 안되는데... )");
iter = m_svReservationObject.erase(iter);
}
}
}
//삭제 시기 이펙트 종료 되거나 SkillCancel
void SCommandSystem::RemoveReservationObject( bool bCastingCancel )
{
std::vector< AR_HANDLE >::iterator iter = m_svReservationObject.begin();
for( ; iter != m_svReservationObject.end(); )
{
SGameAvatarEx* pAvatar = NULL;
if( m_hashObject.lookup( (*iter), pAvatar ) )
{
//캐스팅 캔슬이 거나 삭제 보류가 해제됐다면 삭제
if( bCastingCancel || !pAvatar->IsReservation() )
{
m_hashObject.erase( (*iter) );
m_hashLeaveList.add( (*iter), new SGameAvatarExTag( pAvatar, GetSafeTickCount() ) );
m_svObject.erase( pAvatar );
if( pAvatar->GetObjType() == TS_ENTER::GAME_PLAYER )
{
m_svPlayerObject.erase( pAvatar );
}
else
{
m_svOtherObject.erase( pAvatar );
{
int idx = m_svRecongnizeMobObject.search_index( pAvatar );
if( idx >= 0)
m_svRecongnizeMobObject.erase( pAvatar );
}
}
iter = m_svReservationObject.erase(iter);
}
else
iter++;
}
else
{
assert( false && "SCommandSystem::RemoveReservationObject ( 들어오면 안되는데... )");
iter = m_svReservationObject.erase(iter);
}
}
}
void SCommandSystem::OnWarp()
{
RemoveAllReservationObject();
SGameAvatarExTag* pAvatarTag = NULL;
bool res = m_hashLeaveList.get_first_value( pAvatarTag );
while ( res )
{
if( pAvatarTag != NULL )
{
pAvatarTag->bNotUse = true;
pAvatarTag->dwTime -= OBJ_LEAVE_TIME;
}
res = m_hashLeaveList.get_next_value( pAvatarTag );
}
m_hashPendingObjList.clear();
//미리 삭제 할수 있으면 삭제 하자
SetArrangeObject();
}
void SCommandSystem::AddRidingObject( AR_HANDLE hMaster, AR_HANDLE hCreature, bool bMount )
{
std::vector< RIDING_INFO >::iterator iter = m_svRidingObject.begin();
for( ; iter != m_svRidingObject.end(); ++iter )
{
if( (*iter).player_handle == hMaster && (*iter).creature_handle == hCreature )
{
//같은게 있다면 리턴
return;
}
}
RIDING_INFO info;
info.player_handle = hMaster;
info.creature_handle = hCreature;
info.dwLeftTime = m_dwTime;
if( bMount )
info.mount_type = RIDING_INFO::MOUNT_TYPE::MOUNT_CREATURE_TYPE;
else
info.mount_type = RIDING_INFO::MOUNT_TYPE::UNMOUNT_CREATURE_TYPE;
m_svRidingObject.push_back( info );
}
void SCommandSystem::DeleteRidingObject( AR_HANDLE hMaster, AR_HANDLE hCreature )
{
std::vector< RIDING_INFO >::iterator iter = m_svRidingObject.begin();
for( ; iter != m_svRidingObject.end(); )
{
if( (*iter).player_handle == hMaster && (*iter).creature_handle == hCreature )
{
iter = m_svRidingObject.erase(iter);
}
else
++iter;
}
}
void SCommandSystem::FindRidingObject()
{
if( m_svRidingObject.empty() ) return;
std::vector< RIDING_INFO >::iterator iter = m_svRidingObject.begin();
for( ; iter != m_svRidingObject.end(); )
{
SGameAvatarEx* pPlayer = GetAvatar( (*iter).player_handle );
SGameAvatarEx* pCreature = GetAvatar( (*iter).creature_handle );
//플레이어 및 크리처 둘다 찾을수 없다면 삭제
/* if( pPlayer == NULL && pCreature == NULL )
{
assert( false && "FindRidingObject() pPlayer == NULL && pCreature == NULL" );
iter = m_svRidingObject.erase(iter);
}*/
bool bCheck = false;
if( pPlayer == NULL || pCreature == NULL )
bCheck = true;
else
{
if( (*iter).mount_type == RIDING_INFO::MOUNT_TYPE::MOUNT_CREATURE_TYPE )
{
KEventPointSeq* pEventPoint = pCreature->GetSaddleEffectPos();
if( pEventPoint == NULL )
bCheck = true;
else
{
pPlayer->SetMountMode();
pCreature->SetMountMode();
pPlayer->SetAniLock( false );
int nAniType = 0;
// #2.1.6 sonador
if( pPlayer->IsMoving() )
nAniType = pPlayer->GetPlayerMRunAniID();
else
nAniType = pPlayer->GetPlayerMDefAniID();
pPlayer->NPlayAnimation( nAniType, SEQTYPE_LOOP );
pPlayer->SetRiderCreatureInfo( &SGameAvatarEx::RiderCreatureInfo( (*iter).creature_handle, EFFECT_POS_SADDLE, pCreature->GetCreatureMountType() ) );
pCreature->SetAniLock( false );
if( pCreature->IsMoving()) pCreature->NPlayAnimation( ANI_RUN, SEQTYPE_LOOP );
else pCreature->NPlayAnimation( ANI_DEFAULT01, SEQTYPE_LOOP );
iter = m_svRidingObject.erase(iter);
}
}
else if( (*iter).mount_type == RIDING_INFO::MOUNT_TYPE::UNMOUNT_CREATURE_TYPE )
{
pPlayer->SetNormalMode();
pCreature->SetNormalMode();
pPlayer->SetRiderCreatureInfo();
pPlayer->SetAniLock( false );
pPlayer->Default();
pCreature->SetBestPosition();
pCreature->SetAniLock( false );
pCreature->Default();
iter = m_svRidingObject.erase(iter);
}
else
bCheck = true;
}
if( bCheck )
{
//3분이 지났다면 그냥 삭제
if( (*iter).dwLeftTime != 0 )
{
if( (m_dwTime - (*iter).dwLeftTime) > 180000 )
{
//임시로 지움
//assert( false && "FindRidingObject() 타임 오빠~" );
iter = m_svRidingObject.erase(iter);
}
else
++iter;
}
else
{
(*iter).dwLeftTime = m_dwTime;
++iter;
}
}
}
}
void SCommandSystem::ResetFailAddCreature()
{
SGameAvatarEx* pMaster(NULL);
ENTER_CREATURE_FAIL* FailInfo;
std::vector< ENTER_CREATURE_FAIL >::iterator it = m_FailAddCreatureList.begin();
while( it != m_FailAddCreatureList.end() )
{
FailInfo = &(*it);
pMaster = GetAvatar( FailInfo->hMaster );
if( pMaster )
{
if( pMaster->IsMount() || pMaster->IsMountMode() )
AddRidingObject( FailInfo->hMaster, FailInfo->hCreature, true );
// 2010.08.12 - prodongi
pMaster->SetCreature( FailInfo->hCreature, true );
it = m_FailAddCreatureList.erase( it );
}
else ++it;
}
}
SGameAvatarEx * SCommandSystem::GetAvatar( AR_HANDLE target )
{
if( m_bDestroy ) return NULL;
if( target <= 0 ) return NULL;
SGameAvatarEx * pDamager = NULL;
m_hashObject.lookup( target, pDamager );
return pDamager;
}
SGameObject * SCommandSystem::GetObject( AR_HANDLE objHandle )
{
if( m_bDestroy ) return NULL;
if( objHandle <= 0 ) return NULL;
SGameAvatarEx * pDamager = NULL;
m_hashObject.lookup( objHandle, pDamager );
return pDamager;
}
SGameAvatarEx * SCommandSystem::GetPickObject( K3DVector &vNear, K3DVector &vFar, BOOL bLocal )
{
SGameAvatarEx* pGameObject = NULL;
KSortVector< class SGameAvatarEx* >::iterator it;
// First, try it with the checkbox
float fDist = 9999999.0f;
float fTempDist = 0.0f;
SGameAvatarEx* pTempPickObj = NULL;
K3DVector vCameraPos = m_pGame->GetCamera()->GetCamPos();
for ( it = m_svObject.begin(); it != m_svObject.end(); ++it )
{
pGameObject = (*it);
if ( pGameObject != NULL )
{
SGameAvatarEx* pPickObj = NULL;
if( bLocal )
{ // Click on my character or the dead ones
if( pGameObject->GetArID() == m_LocalHandle && pGameObject->CheckCollision( vNear, vFar ) )
pPickObj = pGameObject;
if( !pGameObject->IsLive() && pGameObject->CheckCollision( vNear, vFar ) )
pPickObj = pGameObject;
}
else
{
if( pGameObject->GetObjType() == TS_ENTER::GAME_ITEM || pGameObject->GetObjType() == TS_ENTER::GAME_FIELD_PROP )
{ // Item
if( pGameObject->GetArID() != m_LocalHandle && pGameObject->CheckCollision( vNear, vFar ) )
pPickObj = pGameObject;
}
else
{
//살은 넘들 클릭
if( pGameObject->GetArID() != m_LocalHandle && pGameObject->IsLive() && pGameObject->CheckCollision( vNear, vFar ) )
pPickObj = pGameObject;
}
}
if( pPickObj )
{
fTempDist = K3DVectorLength( (*pPickObj->GetPosition() - vCameraPos) );
if( fDist > fTempDist )
{
fDist = fTempDist;
pTempPickObj = pPickObj;
}
}
}
}
if( pTempPickObj )
{
if(pTempPickObj->GetStatus() & TS_ENTER::CreatureInfo::FLAG_INVISIBLE)
pTempPickObj = NULL;
else
{
if( !pTempPickObj->IsRender() )
pTempPickObj = NULL;
}
return pTempPickObj;
}
// If there are no objects detected, expand each checkbox and check again, then select an appropriate object from the detected ones
SGameAvatarEx *pSelf = NULL, *pCorpse = NULL, *pItem = NULL, *pAliveObj = NULL;
for ( it = m_svObject.begin(); it != m_svObject.end(); ++it )
{
pGameObject = (*it);
if ( pGameObject != NULL )
{
K3DVALUE r = GetDistance( *pGameObject->GetPosition(), vNear ) * 0.005f; // A suitable value
if( bLocal )
{
if( pGameObject->GetArID() == m_LocalHandle && pGameObject->RelaxedCheckCollision( vNear, vFar, r ) ) {
pSelf = pGameObject;
continue;
}
if( !pGameObject->IsLive() && pGameObject->RelaxedCheckCollision( vNear, vFar, r ) ) {
pCorpse = pGameObject;
continue;
}
}
else
{
if( pGameObject->GetObjType() == TS_ENTER::GAME_ITEM )
{
if( pGameObject->GetArID() != m_LocalHandle && pGameObject->RelaxedCheckCollision( vNear, vFar, r ) ) {
pItem = pGameObject;
continue;
}
}
else
{
if( pGameObject->GetArID() != m_LocalHandle && pGameObject->IsLive() && pGameObject->RelaxedCheckCollision( vNear, vFar, r ) ) {
pAliveObj = pGameObject;
continue;
}
}
}
}
}
// Select in order of priority: living creatures, items, corpses, then own character
SGameAvatarEx* pPickObj = pAliveObj ? pAliveObj : pItem ? pItem : pCorpse ? pCorpse : pSelf;
if(pPickObj)
{
if(pPickObj->GetStatus() & TS_ENTER::CreatureInfo::FLAG_INVISIBLE)
pPickObj = NULL;
else
{
if( !pPickObj->IsRender() )
pPickObj = NULL;
}
}
return pPickObj;
}
SGameAvatarEx * SCommandSystem::GetTransportCreatureObject( AR_HANDLE objHandle )
{
if( m_bDestroy ) return NULL;
if( objHandle <= 0 ) return NULL;
SGameAvatarEx * pCreature = NULL;
m_hashTransportCreatureObject.lookup( objHandle, pCreature );
return pCreature;
}
void SCommandSystem::Render( unsigned long uRenderBitVector, KViewportObject** ppViewportList, int nViewportCount )
{
if( uRenderBitVector & Game_RenderAvatar )
{ //랜더링 순서 있음, 플레이어가 나중에 랜더링
SGameAvatarEx* pGameObject = NULL;
KSortVector< class SGameAvatarEx* >::iterator it = m_svOtherObject.begin();
while ( it != m_svOtherObject.end() )
{
pGameObject = (*it);
if ( pGameObject != NULL /*&& pGameObject->IsLocalPlayer()*/ )
{
if( pGameObject->GetObjType() != TS_ENTER::GAME_ITEM || GetKeyState(VK_MENU) < 0 )
{
DisplayNamePanel( pGameObject );
}
pGameObject->Render( uRenderBitVector, ppViewportList, nViewportCount );
}
++it;
}
//운송 전용 크리처
it = m_svTransportCreatureObject.begin();
for( ; it != m_svTransportCreatureObject.end(); ++it )
{
(*it)->Render( uRenderBitVector, ppViewportList, nViewportCount );
}
unsigned int nStateFlag = SGameAvatarEx::FLAG_STATE_NONE;
SGameAvatarEx* pLocalPlayer = GetLocalPlayer();
if( pLocalPlayer ) nStateFlag = pLocalPlayer->GetStateFlag();
SGamePlayer* pPlayer = (SGamePlayer*)pLocalPlayer;
AR_HANDLE hCreatureHandle = pPlayer->GetCreature();
SGameAvatarEx* _pCreature = NULL;
unsigned int nCreatureStateFlag = SGameAvatarEx::FLAG_STATE_NONE;
if (hCreatureHandle != 0)
{
_pCreature = (SGameAvatarEx*)GetObjectA(hCreatureHandle);
if (_pCreature != NULL)
nCreatureStateFlag = _pCreature->GetStateFlag();
}
it = m_svPlayerObject.begin();
if(( nStateFlag & SGameAvatarEx::FLAG_STATE_DETECT_HIDING) || (nCreatureStateFlag & SGameAvatarEx::FLAG_STATE_DETECT_HIDING))
{
float fDetectRange = pLocalPlayer->GetHidingDetectRange();
K3DVector vPos = *pLocalPlayer->GetPosition();
float fCreatureDetectRange = 0;
K3DVector vCreaturePos(0, 0, 0);
if (_pCreature != NULL)
{
if(_pCreature->GetInnObjType() == TS_ENTER::GAME_SUMMON)
{
fCreatureDetectRange = _pCreature->GetHidingDetectRange();
vCreaturePos = *_pCreature->GetPosition();
}
}
while ( it != m_svPlayerObject.end() )
{
pGameObject = (*it);
if( (pGameObject->GetStatus() & TS_ENTER::CreatureInfo::FLAG_INVISIBLE) )
{
if( pGameObject->IsLocalPlayer() )
DisplayNamePanel( pGameObject );
}
else
{
if( !pGameObject->IsLocalPlayer() )
{
if( pGameObject->GetStateFlag() & SGameAvatarEx::FLAG_STATE_HIDING )
{
if( m_pGame->IsPartyRaidMemeber( pGameObject->GetArID() ) )
{
pGameObject->SetHidingVisiblity( HIDING_VISIBILITY_RATE_PARTY_RAID ); //파티원이나 레이드원이면
}
else
{
K3DVector vTargetPos = *pGameObject->GetPosition();
float fLength = K3DVectorLength( vTargetPos - vPos );
float fCreatureLength = K3DVectorLength( vTargetPos - vCreaturePos );
if( fLength < fDetectRange || fCreatureLength < fCreatureDetectRange ) //Detect 사거리가 더 크다면
pGameObject->SetHidingVisiblity( HIDING_VISIBILITY_RATE ); //Detect 시야 안에 있다
else
{
pGameObject->SetHidingVisiblity( 0.0f ); //Detect 시야 밖에 있다
DisplayNamePanel( pGameObject );
m_pTargetMgr->LeaveTarget(pGameObject->GetArID());
// 은신 감지 거리를 벗어 날 경우, 현재 타겟 비교 후 타겟 해제. kappamind, 2010.01.28
if( g_pCurrentGameSystem->IsTarget( pGameObject->GetArID() ) )
{
g_pCurrentGameSystem->SetTarget(NULL);
pGameObject = NULL;
}
}
}
}
}
if( pGameObject )
{
DisplayNamePanel( pGameObject );
pGameObject->Render( uRenderBitVector, ppViewportList, nViewportCount );
}
}
++it;
}
}
else
{
while ( it != m_svPlayerObject.end() )
{
pGameObject = (*it);
if( (pGameObject->GetStatus() & TS_ENTER::CreatureInfo::FLAG_INVISIBLE) )
{
if( pGameObject->IsLocalPlayer() )
DisplayNamePanel( pGameObject );
}
else
{
if( !pGameObject->IsLocalPlayer() )
{
if( pGameObject->GetStateFlag() & SGameAvatarEx::FLAG_STATE_HIDING )
{
if( m_pGame->IsPartyRaidMemeber( pGameObject->GetArID() ) )
pGameObject->SetHidingVisiblity( HIDING_VISIBILITY_RATE_PARTY_RAID ); //파티원이나 레이드원이면
else
{
pGameObject->SetHidingVisiblity( 0.0f );
DisplayNamePanel( pGameObject );
pGameObject = NULL;
}
}
}
if( pGameObject )
{
DisplayNamePanel( pGameObject );
pGameObject->Render( uRenderBitVector, ppViewportList, nViewportCount );
}
}
++it;
}
}
if( m_hMouseOverItem )
{
pGameObject = GetAvatar( m_hMouseOverItem );
if( pGameObject ) DisplayNamePanel( pGameObject );
}
}
if( uRenderBitVector & Game_RenderAction )
{
if (m_pActionMgr) m_pActionMgr->Render( uRenderBitVector, ppViewportList, nViewportCount );
}
if( uRenderBitVector & Game_RenderEffect )
{
m_pOtherEffecMgr->Render( uRenderBitVector, ppViewportList, nViewportCount );
}
}
void SCommandSystem::DisplayNamePanel( SGameAvatarEx* pAvatar )
{
/// 2011.08.17 필드 프랍 체크 제거 - prodongi
if( pAvatar->GetObjType() == TS_ENTER::GAME_SKILL_PROP )
return;
if( !pAvatar->IsLoadComplete() )
return;
//내 플레이어 예외 처리
SIMSG_UI_2DPOS_INFO msg;
static K3DVector mypos, mypos_ori, mypos_middle, _2Dpos, _2Dpos_ori, _2Dpos_middle;
mypos = *pAvatar->GetPosition();
mypos_ori = *pAvatar->GetPosition();
mypos_middle = *pAvatar->GetPosition();
msg.bVisible = true;
msg.bNotClip = true;
msg.bUse = false;
msg.nObjType = pAvatar->GetObjType();
//플레이어가 마운트 모드일경우
if( pAvatar->IsMountMode() )
{
SGameAvatarEx* pCreature = (SGameAvatarEx*)GetObject( pAvatar->GetCreatureMountHandle() );
if( pCreature == NULL ) pCreature = GetTransportCreatureObject( pAvatar->GetCreatureMountHandle() );
if( pCreature )
{
mypos = *pCreature->GetPosition();
mypos_ori = *pCreature->GetPosition();
mypos_middle = *pCreature->GetPosition();
}
mypos.z += HEAD_DEF_TOP;
mypos_middle.z += HEAD_DEF_TOP/2.f;
}
else if( pAvatar->GetStatus() & TS_ENTER::PlayerInfo::FLAG_SITDOWN && pAvatar->GetCurrAnimationID() == ANI_SIT )
{
mypos.z += HEAD_DEF_HALF;
mypos_middle.z += HEAD_DEF_HALF/2.f;
}
else
{
const float* selectCube = pAvatar->GetSelectCube();
float zHeight;
if( pAvatar->GetObjType() == TS_ENTER::GAME_MOB )
{
zHeight = selectCube[ 5 ] * pAvatar->GetScale() + HEAD_GAP_MOB;
}
else if( pAvatar->GetObjType() == TS_ENTER::GAME_PET )
{
zHeight = selectCube[ 5 ] * pAvatar->GetScale() + HEAD_GAP_PET;
}
else if( pAvatar->GetObjType() == TS_ENTER::GAME_ITEM )
{
zHeight = selectCube[ 5 ] * pAvatar->GetScale() + HEAD_GAP_ITEM;
}
else
{
zHeight = selectCube[ 5 ] * pAvatar->GetScale() + HEAD_GAP_AVATAR;
}
mypos.z += zHeight;
mypos_middle.z += zHeight / 2.f;
}
msg.fCamDistance = GetDistance( m_pGame->GetCamera()->GetCamPos(), mypos );
m_pGame->Get2DPos( mypos_ori , _2Dpos_ori );
m_pGame->Get2DPos( mypos , _2Dpos );
m_pGame->Get2DPos( mypos_middle, _2Dpos_middle );
msg.handle = pAvatar->GetArID();
msg.bVisible = pAvatar->IsRender();
msg.bNotClip = pAvatar->IsRender();
msg.nX = _2Dpos.x;
msg.nY = _2Dpos.y;
msg.nX_middle = _2Dpos_middle.x;
msg.nY_middle = _2Dpos_middle.y;
msg.nX_bottom = _2Dpos_ori.x;
msg.nY_bottom = _2Dpos_ori.y;
msg.nReal_X = mypos.x;
msg.nReal_Y = mypos.y;
msg.fAlpha = 1.f;
msg.fCamDistance = GetDistance( m_pGame->GetCamera()->GetCamPos(), mypos );
if( pAvatar->GetObjType() != TS_ENTER::GAME_ITEM )
{
if( !pAvatar->IsLocalPlayer() )
{
float fLen = GetDistance( m_pGame->GetCamera()->GetTargetPos(), mypos );
//이름 판넬 컬링
if( fLen < VIEW_NAME_PLATE_CULL_SIZE )
msg.fAlpha = GetNameAlpha( fLen );
else
msg.bVisible = false;
}
}
if( pAvatar->GetObjType() == TS_ENTER::GAME_PLAYER )
{
if( pAvatar->IsLocalPlayer() )
{
SGameAvatarEx* pCreature = (SGameAvatarEx*)GetObject( pAvatar->GetCreatureMountHandle() );
if( pCreature == NULL ) pCreature = GetTransportCreatureObject( pAvatar->GetCreatureMountHandle() );
if( pCreature )
{
msg.fRadian = GetViewRadian( pCreature->GetNextPos(), mypos );
}
else
msg.fRadian = GetViewRadian( pAvatar->GetNextPos(), mypos );
msg.nObjType = SIMSG_UI_2DPOS_INFO::TY_MY;
}
else
msg.nObjType = SIMSG_UI_2DPOS_INFO::TY_PLAYER;
}
else if( pAvatar->GetObjType() == TS_ENTER::GAME_NPC )
msg.nObjType = SIMSG_UI_2DPOS_INFO::TY_NPC;
else if( pAvatar->GetObjType() == TS_ENTER::GAME_MOB )
msg.nObjType = SIMSG_UI_2DPOS_INFO::TY_MOB;
else if( pAvatar->GetObjType() == TS_ENTER::GAME_SUMMON )
{
//크리처가 마운트 모드일경우 이름 숨기자
if( pAvatar->IsMountMode() )
{
msg.bVisible = false;
msg.bNotClip = false;
}
msg.nObjType = SIMSG_UI_2DPOS_INFO::TY_CREATURE;
}
else if( pAvatar->GetObjType() == TS_ENTER::GAME_PET )
msg.nObjType = SIMSG_UI_2DPOS_INFO::TY_PET;
else if( pAvatar->GetObjType() == TS_ENTER::GAME_ITEM )
msg.nObjType = SIMSG_UI_2DPOS_INFO::TY_ITEM;
m_pGame->ProcMsgAtStatic( &msg );
}
void SCommandSystem::SetPlayerAndCreaturePosition( SMSG_UNMOUNT_SUMMON* pMsg )
{
SGameAvatarEx* pLocalPlayer = GetLocalPlayer();
ArPosition arPlayerPos;
arPlayerPos.x = pLocalPlayer->GetPosition()->x;
arPlayerPos.y = pLocalPlayer->GetPosition()->y;
m_pGame->ReqMove( pLocalPlayer->GetArID(), arPlayerPos, &arPlayerPos, 1, false );
SGameAvatarEx* pLocalCreature = GetLocalCreature( pMsg->summon_handle );
ArPosition arCreturePos;
arCreturePos.x = pLocalCreature->GetPosition()->x;
arCreturePos.y = pLocalCreature->GetPosition()->y;
m_pGame->ReqMove( pLocalCreature->GetArID(), arCreturePos, &arCreturePos, 1, false );
}
bool SCommandSystem::IsActivated()
{
SGameAvatarEx* pGameObject = NULL;
KSortVector< class SGameAvatarEx* >::iterator it = m_svObject.begin();
while ( it != m_svObject.end() )
{
pGameObject = (*it);
if ( pGameObject != NULL && pGameObject->IsActivated() == false )
{
if( pGameObject->IsPendLoading() == false ) //true면 옵션에서 타인 렌더가 꺼진 상태
return false;
}
++it;
}
return true;
}
//Leave List 삭제
void SCommandSystem::SetArrangeObject()
{
DWORD dwTime = GetSafeTickCount();
SGameAvatarExTag* pAvatarTag = NULL;
SGameAvatarEx* pObject = NULL;
std::vector< AR_HANDLE > vDeleteList;
bool res = m_hashLeaveList.get_first_value( pAvatarTag );
while ( res )
{
pObject = NULL;
if( pAvatarTag != NULL )
{
pObject = pAvatarTag->ptr;
// 일단 30초 이상 지난 애들만 지우도록 땜방.... by Testors
// NPC만 3분으로 늘리고 그외 것들은 바로 삭제 by metarrgear
//GAME_PLAYER = 0, GAME_NPC = 1, GAME_ITEM = 2, GAME_MOB = 3, GAME_SUMMON = 4, GAME_SKILL_PROP = 5, GAME_FIELD_PROP = 6,
bool bLeave = true;
if( pObject->GetObjType() == TS_ENTER::GAME_NPC )
{
bLeave = false;
}
if( pObject->IsLoadComplete() && ( bLeave || pAvatarTag->bNotUse ||
pAvatarTag->dwTime + OBJ_LEAVE_TIME < dwTime ) )
{
//성공
}
else if( pObject->IsPendLoading() )
{
//PendLoading() 중이면 바로 삭제
}
else
{
pObject = NULL;
}
}
if( pObject != NULL )
{
vDeleteList.push_back( pObject->GetArID() );
}
res = m_hashLeaveList.get_next_value( pAvatarTag );
}
pAvatarTag = NULL;
std::vector< AR_HANDLE >::iterator iter = vDeleteList.begin();
for( ; iter != vDeleteList.end(); ++iter )
{
if( m_hashLeaveList.lookup( *iter, pAvatarTag ) )
{
SAFE_DELETE( pAvatarTag->ptr );
SAFE_DELETE( pAvatarTag );
}
m_hashLeaveList.erase( *iter );
}
vDeleteList.clear();
}
void SCommandSystem::SetHeight()
{
SGameAvatarEx* pGameObject = NULL;
KSortVector< class SGameAvatarEx* >::iterator it = m_svObject.begin();
while ( it != m_svObject.end() )
{
pGameObject = (*it);
if ( pGameObject != NULL )
{
K3DVector mypos = *pGameObject->GetPosition();
WORD wTile=0;
m_pGame->GetHeight(mypos.x, mypos.y, mypos.z,wTile);
pGameObject->SetPosition( mypos );
}
it++;
}
}
float SCommandSystem::GetNameAlpha( float fLen )
{
if( fLen > (20*12) ) //20m 이상일 경우
{
float fAlpha = (1.5f-(fLen/(40*12)));
return fAlpha;
}
//20m 이하 인 경우
//// 20% 범위에 걸치면 알파 먹임
//if( fLen > ( VIEW_NAME_PLATE_CULL_SIZE * 0.9f ) )
//{
// float fAlpha = ( VIEW_NAME_PLATE_CULL_SIZE - fLen ) / ( VIEW_NAME_PLATE_CULL_SIZE * 0.1f );
// return fAlpha;
//}
return 1.f;
}
void SCommandSystem::Process( DWORD dwTime )
{
if( m_dwTime == dwTime ) return;
/// 2010.11.10 - prodongi
//#ifdef _DEV
// extern bool g_bDebugMode;
//#endif
m_dwTime = dwTime;
// 이전 프레임의 LeaveList를 정리
if( m_dwTime - m_dwCheckTime > 41 )
{
m_dwCheckTime = m_dwTime;
SetArrangeObject();
// 라이딩 안된것들 찾자
FindRidingObject();
}
// if( m_dwTime == 0 ) m_dwTime = dwTime;
if( m_dwLocalCreaturePrcessTime == 0 ) m_dwLocalCreaturePrcessTime = dwTime;
// if( m_dwCheckTime == 0 ) m_dwCheckTime = m_dwTime;
K3DVector mypos, _2Dpos;
K3DMatrix mat;
K3DMatrixIdentity(mat);
KMsgGET_BONEMATRIX2 bonemsg;
bonemsg.nDetailIndex = DETAIL_HEAD;
K3DCamera* pCamera = m_pGame->GetCamera();
SGameViewPort* pViewport = m_pGame->GetViewPort();
//Position 및 view Frustum cull
K3DVertex vtCameraTarget;
pCamera->GetTargetPos( vtCameraTarget.x, vtCameraTarget.y, vtCameraTarget.z );
K3DVector * pFrustum = pViewport->GetFrustum();
K3DVector cullPosition;
float fLen = 0.f;
//Local 은 먼저 처리
SGameAvatarEx* pGameObject = NULL;
SGameAvatarEx* pLocalObject = NULL;
if( m_hashObject.lookup( m_LocalHandle, pGameObject ) )
{
pLocalObject = pGameObject;
pGameObject->Process( dwTime );
pGameObject->SetShadowRenderFlag( true ); //우선 내것을 그림자 그림
mypos = *pGameObject->GetPosition();
cullPosition = mypos;
if( m_LocalHandle == pGameObject->GetArID() )
{
/// 2010.11.10 - prodongi
//#ifdef _DEV
if (g_UserInfo.isMonkeyTail())
{
extern bool g_bDebugMode;
if( g_bDebugMode && ( GetKeyState( VK_SCROLL ) & 0x01 ) )
{
K3DVector myLocal;
K3DVector myCreature;
K3DVector newpos;
myLocal = mypos;
if( m_vLocalCreature.empty() )
{
if( (dwTime - m_dwLocalCreaturePrcessTime) >= 100 )
{
SIMSG_UI_ETC_INFO etcmsg;
etcmsg.fps = g_dwFPS;
KDeviceManager::GetDeviceManager()->GetRenderDevice()->GetVGAMem( etcmsg.dwFree, etcmsg.dwTotal );
m_pGame->CorrectivePosition( myLocal, newpos );
etcmsg.x = newpos.x;
etcmsg.y = newpos.y;
etcmsg.z = newpos.z;
etcmsg.cx = 0;
etcmsg.cy = 0;
etcmsg.cz = 0;
m_pGame->SendGameInterfaceMsg( &etcmsg );
m_dwLocalCreaturePrcessTime = dwTime;
}
}
}
}
//#endif
}
}
pGameObject = NULL;
// { 노점 처리용
std::vector< AR_HANDLE > vBoothNameRequestList;
bool bNeedBoothProc = false;
if( m_pPrevBoothProcTime + BOOTH_CHECK_INTERVAL < dwTime )
{
bNeedBoothProc = true;
m_pPrevBoothProcTime = dwTime;
}
// }
bool bEvScene = ( m_pGame->GetGameRef() == SGame::STAGE_EVENT_SCENE ) ? true : false;
KSortVector< class SGameAvatarEx* >::iterator it = m_svObject.begin();
while ( it != m_svObject.end() )
{
pGameObject = (*it); ++it;
if( pGameObject == NULL || m_LocalHandle == pGameObject->GetArID() ) continue;
pGameObject->Process( dwTime );
pGameObject->SetShadowRenderFlag( true ); //우선 내것을 그림자 그림
if( bEvScene )
{
pGameObject->SetVisible(true);
pGameObject->ClipTest( pFrustum );
pGameObject->SetShadowRenderFlag( true );
}
else
{
mypos = *pGameObject->GetPosition();
float fCamTargetDist = GetDistance( pCamera->GetTargetPos(), mypos );
if(fCamTargetDist < m_fAvatarVisRange)
{
pGameObject->SetVisible(true);
//Vérifiez uniquement ce qui est visible
pGameObject->ClipTest( pFrustum );
}
else
{
pGameObject->SetVisible(false);
}
//시야에 안보이는것들은 프러스텀 검사를 안해도 될듯
// pGameObject->ClipTest( pFrustum );
fLen = GetDistance( cullPosition, mypos );
//그림자 컬링
if( fLen < SHADOW_RENDER_MAX_LEN )
{
pGameObject->SetShadowRenderFlag( true );
}
else
{
pGameObject->SetShadowRenderFlag( false );
}
}
// 노점 이름 요청 리스트 수집
if( bNeedBoothProc && pGameObject->GetObjType() == TS_ENTER::GAME_PLAYER )
{
if( static_cast< SGameOtherPlayer* >( pGameObject )->IsNeedBoothName( dwTime ) ) vBoothNameRequestList.push_back( pGameObject->GetArID() );
}
}
it = m_svTransportCreatureObject.begin();
while( it != m_svTransportCreatureObject.end() )
{
pGameObject = (*it);
pGameObject->Process( dwTime );
pGameObject->SetShadowRenderFlag( true ); //우선 내것을 그림자 그림
if( bEvScene )
{
pGameObject->SetVisible(true);
pGameObject->ClipTest( pFrustum ); //시야에 보이는것들만 체크
pGameObject->SetShadowRenderFlag( true );
}
else
{
mypos = *pGameObject->GetPosition();
float fCamTargetDist = GetDistance( pCamera->GetTargetPos(), mypos );
if(fCamTargetDist < m_fAvatarVisRange)
{
pGameObject->SetVisible(true);
pGameObject->ClipTest( pFrustum ); //시야에 보이는것들만 체크
}
else
pGameObject->SetVisible(false);
fLen = GetDistance( cullPosition, mypos );
if( fLen < SHADOW_RENDER_MAX_LEN ) //그림자 컬링
pGameObject->SetShadowRenderFlag( true );
else
pGameObject->SetShadowRenderFlag( false );
}
++it;
}
// { 노점 이름 요청
if( !vBoothNameRequestList.empty() )
{
SMSG_REQUEST_BOOTH_NAME msg;
msg.pvBoothList = &vBoothNameRequestList;
m_pGame->ProcMsgAtStatic( &msg );
}
vBoothNameRequestList.clear();
// }
if (m_pActionMgr) m_pActionMgr->Process( dwTime );
m_pOtherEffecMgr->Process( dwTime );
//선공몬스터 인식속도 관련. 0.3초마다 한번씩 체크해서 서버로 보낼 것... 2010.01.06 sfreer
static AR_TIME nLastGameGradeText = 0;
AR_TIME nCurArTime = GetArTime();
if(pLocalObject && (nLastGameGradeText == 0 || 30<= (nCurArTime - nLastGameGradeText) ) )
//if(false)
{
nLastGameGradeText = nCurArTime;
SGameAvatarEx* pGameObject = NULL;
KSortVector< class SGameAvatarEx* >::iterator it = m_svOtherObject.begin();
while ( it != m_svOtherObject.end() )
{
pGameObject = (*it);
if ( pGameObject != NULL /*&& pGameObject->IsLocalPlayer()*/ )
{
if(pGameObject->GetObjType() == TS_ENTER::GAME_MOB )
{
_MONSTER_INFO_FILE* pMob = GetMonsterDB().GetMonsterData( pGameObject->GetContentID() );
if(pMob)
{
bool bInsertData = true;
for( KSortVector< class SGameAvatarEx* >::iterator it2= m_svRecongnizeMobObject.begin() ; it2 != m_svRecongnizeMobObject.end() ; it2++)
{
if( (*it2) == pGameObject )
{
bInsertData = false;
break;
}
}
bool bInArea = false;
AR_HANDLE checkhandle = NULL;
float dx = pLocalObject->GetPosition()->x - pGameObject->GetPosition()->x;
float dy = pLocalObject->GetPosition()->y - pGameObject->GetPosition()->y;
int dis = sqrt( (float) dx*dx + dy*dy );
if( pMob->visible_range*GameRule::DEFAULT_UNIT_SIZE >= dis && !(pLocalObject->GetStateFlag() & SGameAvatarEx::FLAG_STATE_HIDING) )
{
bInArea = true;
checkhandle = m_LocalHandle;
}
if(!bInArea)
{
KHash< SGameAvatarEx *, hashPr_mod_basic<AR_HANDLE> >::node* _node = NULL;
bool bResult = m_hashObject.get_first_node( _node );
while ( bResult )
{
if(_node->value->IsLocalCreature())
{
float dx = _node->value->GetPosition()->x - pGameObject->GetPosition()->x;
float dy = _node->value->GetPosition()->y - pGameObject->GetPosition()->y;
int dis = sqrt( (float) dx*dx + dy*dy );
if( pMob->visible_range*GameRule::DEFAULT_UNIT_SIZE/2 >= dis )
{
bInArea = true;
checkhandle = _node->key;
break;
}
}
bResult = m_hashObject.get_next_node( _node );
}
}
if( bInArea ) //pMob->visible_range*GameRule::DEFAULT_UNIT_SIZE >= dis )
{
if(bInsertData)
{
AR_HANDLE handle = 0;
KHash< SGameAvatarEx *, hashPr_mod_basic<AR_HANDLE> >::node* _node = NULL;
bool bResult = m_hashObject.get_first_node( _node );
while ( bResult )
{
if(_node->value == pGameObject)
{
handle = _node->key;
break;
}
bResult = m_hashObject.get_next_node( _node );
}
//메시지를 보내라.
_oprint("몬스터인지패킷 %d, %s\n",handle, GetStringDB().GetString(pMob->name_id));
if(handle>0)
{
TS_CS_MONSTER_RECOGNIZE _msg;
_msg.handle = handle;
_msg.recognizer_handle = checkhandle;
m_pGame->SendMsg( &_msg );
m_svRecongnizeMobObject.insert( pGameObject );
}
}
}
else
{
if(!bInsertData)
{
m_svRecongnizeMobObject.erase( pGameObject );
}
}
}
}
}
++it;
}
}
}
SGameAvatarEx * SCommandSystem::GetLocalPlayer()
{
SGameAvatarEx * pLocal = NULL;
if( m_hashObject.lookup( m_LocalHandle, pLocal ) )
{
return pLocal;
}
return NULL;
}
SGameAvatarEx * SCommandSystem::GetLocalCreature( AR_HANDLE objHandle )
{
//내 소환수 리스트
SGameAvatarEx * pLocalCreature = NULL;
if( m_hashObject.lookup( objHandle, pLocalCreature ) )
{
return pLocalCreature;
}
return NULL;
};
//===================================================================================================
//Enter Object
void SCommandSystem::InsertAvatarEX(AR_HANDLE handle, class SGameAvatarEx* pAvatar, bool bIsTransportCreature )
{
if( bIsTransportCreature )
{
m_hashTransportCreatureObject.add( handle, pAvatar );
m_svTransportCreatureObject.insert( pAvatar );
}
else
{
m_hashObject.add(handle, pAvatar);
m_svObject.insert( pAvatar );
}
if(m_bCircleShadowEnable)
pAvatar->ActivateCircleShadow();
}
void SCommandSystem::DeleteAvatar(AR_HANDLE handle) // 2011.03.10 - servantes
{
SGameAvatarEx* pAvatar = NULL;
if( m_hashObject.lookup( handle, pAvatar ) )
{
m_hashObject.erase(handle);
m_svObject.erase( pAvatar );
}
}
void SCommandSystem::InsertPendLoading( SGameAvatarEx* pAvatar )
{
if( pAvatar == NULL ) return;
bool bLoadingNow = true;
if( g_bRenderPlayerObj )
{
//마을 안 다른 플레이어 표시 OFF
if( GetGameOption().GetRenderOtherPlayerType() == 0 )
{
//마을안에 있다
if( m_pGame->PlayerInTown( pAvatar ) )
{
bLoadingNow = false;
}
}
if( bLoadingNow )
{
pAvatar->PendLoading();
return;
}
}
SGameAvatarEx* pFindAvatar = NULL;
if( m_hashPendingObjList.lookup( pAvatar->GetArID(), pFindAvatar ) )
{
assert( false && "웨 여기 들어오냐" );
}
else
{
m_hashPendingObjList.add( pAvatar->GetArID(), pAvatar );
pAvatar->SetPendLoading( true );
}
}
void SCommandSystem::ActivatePendLoadingListByMove( SGameAvatarEx* pAvatar )
{
if( pAvatar == NULL || g_bRenderPlayerObj == false ) return;
if( pAvatar->IsPendLoading() )
{
pAvatar->SetPendLoading( false );
}
SGameAvatarEx* pPendAvatar = NULL;
if( m_hashPendingObjList.lookup( pAvatar->GetArID(), pPendAvatar ) )
{
pAvatar->PendLoading();
RefreshStateEffect( pAvatar );
m_hashPendingObjList.erase( pAvatar->GetArID() );
}
}
void SCommandSystem::ActivatePendLoadingList( int nRender, bool bGetOutTown )
{
if( nRender )
{
g_bRenderPlayerObj = true;
}
else
{
g_bRenderPlayerObj = false;
}
if( g_bRenderPlayerObj )
{
std::vector< AR_HANDLE > vDeleteList;
SMSG_STATE state;
SGameAvatarEx* pAvatar = NULL;
bool res = m_hashPendingObjList.get_first_value( pAvatar );
while ( res )
{
if ( pAvatar != NULL )
{
if( bGetOutTown && m_pGame->PlayerInTown( pAvatar ) )
{
//마을 안에 있다
}
else
{
pAvatar->SetPendLoading( false );
pAvatar->PendLoading();
vDeleteList.push_back( pAvatar->GetArID() );
}
}
res = m_hashPendingObjList.get_next_value( pAvatar );
}
pAvatar = NULL;
std::vector< AR_HANDLE >::iterator iter = vDeleteList.begin();
for( ; iter != vDeleteList.end(); ++iter )
{
if( m_hashPendingObjList.lookup( (*iter), pAvatar ) )
{
m_hashPendingObjList.erase( (*iter) );
}
}
vDeleteList.clear();
KSortVector< class SGameAvatarEx* >::iterator itObj = m_svObject.begin();
while( itObj != m_svObject.end() )
{
pAvatar = (*itObj);
++itObj;
if( pAvatar->IsLocalPlayer() || pAvatar->IsLocalCreature() )
{
continue;
}
unsigned char nObjType = pAvatar->GetObjType();
if( nObjType == TS_ENTER::GAME_PLAYER ||
nObjType == TS_ENTER::GAME_SUMMON ||
nObjType == TS_ENTER::GAME_PET )
{
if( bGetOutTown && m_pGame->PlayerInTown( pAvatar ) )
{
//마을 안에 있다
}
else
{
pAvatar->SetPendLoading( false );
RefreshStateEffect( pAvatar );
}
}
}
itObj = m_svTransportCreatureObject.begin();
while( itObj != m_svTransportCreatureObject.end() )
{
pAvatar = (*itObj);
++itObj;
if( pAvatar->IsLocalCreature() == false )
{
if( bGetOutTown && m_pGame->PlayerInTown( pAvatar ))
{
}
else
{
pAvatar->SetPendLoading( false );
RefreshStateEffect( pAvatar );
}
}
}
}
else
{
SGameAvatarEx* pAvatar = NULL;
KSortVector< class SGameAvatarEx* >::iterator itObj = m_svObject.begin();
while( itObj != m_svObject.end() )
{
pAvatar = (*itObj);
++itObj;
if( pAvatar->IsLocalPlayer() || pAvatar->IsLocalCreature() || pAvatar->IsLocalPet() ) // sonador #2.3.1.13
{
continue;
}
unsigned char nObjType = pAvatar->GetObjType();
if( nObjType == TS_ENTER::GAME_PLAYER ||
nObjType == TS_ENTER::GAME_SUMMON ||
nObjType == TS_ENTER::GAME_PET )
{
pAvatar->SetPendLoading( true );
pAvatar->RemoveAllStateEffect();
}
}
itObj = m_svTransportCreatureObject.begin();
while( itObj != m_svTransportCreatureObject.end() )
{
if( (*itObj)->IsLocalCreature() == false )
{
(*itObj)->SetPendLoading( true );
}
++itObj;
}
}
}
void SCommandSystem::AddPlayer( SMSG_ENTER* pMsg )
{
SMSG_ENTER::PlayerInfo * pPlayerInfo = (SMSG_ENTER::PlayerInfo *)(pMsg+1);
SGameOtherPlayer* pAvatar = new SGameOtherPlayer;
SMSG_STATUS_CHANGE status_change;
status_change.handle = pMsg->handle;
status_change.status = pPlayerInfo->status;
pAvatar->OnNetInput( &status_change );
pAvatar->ProcMsgAtStatic( pMsg );
pAvatar->Initialize( m_pRenderDevice );
pAvatar->SetMessageHandler( m_pGame );
pAvatar->SetArID( pMsg->handle );
pAvatar->GetArObject().type = pMsg->type;
pAvatar->GetArObject().mv.face = pPlayerInfo->face_direction;
float fHeight = 0.f;
WORD wTile=0;
m_pGame->GetHeight( pMsg->x, pMsg->y, fHeight,wTile );
K3DVector pos( pMsg->x, pMsg->y, fHeight );
pAvatar->SetArObjectPos( pos.x, pos.y, pos.z, pMsg->layer );
pAvatar->SetPosition( pos );
// pAvatar->Activate(); 플레이어들은 아이템이 오면 업데이트 시킨다.
pAvatar->SetHP( pPlayerInfo->hp, true );
pAvatar->SetVisibility( 1.0f );
// 2010.05.20 - prodongi
pAvatar->setHideEquipInfo(pPlayerInfo->hideEquipFlag);
// 2010.06.18 - prodongi
pAvatar->setDecoIndex(pPlayerInfo->faceTextureId);
#ifdef _WEAPON_FX_
pAvatar->ActivateFxSwordSlash();
#endif
pAvatar->ActivateForceSphere();
if( pPlayerInfo->energy > 0 )
pAvatar->OnMsgForceSphere( pPlayerInfo->energy );
InsertAvatarEX(pMsg->handle,pAvatar);
m_svPlayerObject.insert( pAvatar );
m_pArObject->onEnter( &pAvatar->GetArObject() );
if( pPlayerInfo->ride_handle )
AddRidingObject( pMsg->handle, pPlayerInfo->ride_handle, true );
_oprint("About to set hair color rgb! Color is: %d; index is: %d\n", pPlayerInfo->hairColorRGB, pPlayerInfo->hairColorIndex);
//pAvatar->SetHairColorIndex(pPlayerInfo->hairColorIndex);
if (pPlayerInfo->hairColorRGB > 0)
{
pAvatar->SetHairColorRGB(pPlayerInfo->hairColorRGB);
pAvatar->SetHairColorIndex(0);
}
else
{
pAvatar->SetHairColorRGB(-16777216);
pAvatar->SetHairColorIndex(pPlayerInfo->hairColorIndex);
}
if( pPlayerInfo->skin_color != 0 )
{
// 2010.04.22 - prodongi
// pAvatar->SetSkinColorized( pPlayerInfo->skin_color, K3DTexture::COLORIZED_DEF, 0 );
pAvatar->SetSkinColorized( pPlayerInfo->skin_color, K3DTexture::COLORIZED_DEF, pPlayerInfo->hairColorRGB );
}
else
{
unsigned long color_value = GetSkinColorTable().GetColorValue( pPlayerInfo->race-GCLAN_GAIA, 0 );
pAvatar->SetSkinColorized( color_value, K3DTexture::COLORIZED_DEF, pPlayerInfo->hairColorRGB );
}
InsertPendLoading( pAvatar );
if( !m_FailAddCreatureList.empty() )
ResetFailAddCreature();
}
void SCommandSystem::AddNPC ( SMSG_ENTER* pMsg )
{
SMSG_ENTER::NPCInfo * pNpcInfo = (SMSG_ENTER::NPCInfo *)(pMsg+1);
bool bIsRecycle = true;
SGameNpc * pNpc = static_cast<SGameNpc*>( GetObjectFromLeaveList( pMsg->handle ) );
if( pNpc == NULL )
{
pNpc = new SGameNpc(pNpcInfo->npc_id);
bIsRecycle = false;
}
else
{
if( pNpc->GetInnContentID() != pNpcInfo->npc_id )
{
SAFE_DELETE( pNpc );
pNpc = new SGameNpc(pNpcInfo->npc_id);
bIsRecycle = false;
}
}
pNpc->SetObjType( pMsg->ObjType );
pNpc->Initialize( m_pRenderDevice );
pNpc->ProcMsgAtStatic( pMsg );
pNpc->SetMessageHandler( m_pGame );
pNpc->SetArID( pMsg->handle );
pNpc->GetArObject().type = pMsg->type;
pNpc->GetArObject().mv.face = pNpcInfo->face_direction;
float fHeight = 0.f;
WORD wTile=0;
m_pGame->GetHeight( pMsg->x, pMsg->y, fHeight,wTile );
K3DVector pos( pMsg->x, pMsg->y, fHeight );
pNpc->SetArObjectPos( pos.x, pos.y, pos.z, pMsg->layer );
pNpc->SetPosition( pos );
pNpc->Activate();
pNpc->SetHP( 10/*pNpcInfo->hp*/ );//, true );
pNpc->SetVisibility( 1.0f );
pNpc->SetViewVectorAngle( GetNpcResourceDB().GetDirection( pNpcInfo->npc_id ) );
pNpc->OnNetInput( pMsg ); //퀘스트 상태 처리
InsertAvatarEX(pMsg->handle,pNpc);
m_svOtherObject.insert( pNpc );
m_pArObject->onEnter( &pNpc->GetArObject() );
//
int nHairColorIndex = 0;
NpcResourceBase * pNpcResourceInfo = GetNpcResourceDB().GetNpcInfo(pNpcInfo->npc_id);
if (pNpcResourceInfo)
{
switch (pNpcResourceInfo->hair_id)
{
case 101:
case 103:
case 105:
nHairColorIndex = 1;
break;
case 102:
case 104:
case 106:
nHairColorIndex = 2;
break;
}
}
pNpc->SetHairColorIndex(nHairColorIndex);
//기본 값
unsigned long color_value = GetSkinColorTable().GetColorValue( 0, 0 );
pNpc->SetSkinColorized( color_value, K3DTexture::COLORIZED_DEF, 0 );
int nRace = pNpc->GetRace();
int nSex = pNpc->GetSex();
if( bIsRecycle == false )
{
NpcResourceBase* pNpcInfoDB = GetNpcResourceDB().GetNpcInfo( pNpcInfo->npc_id );
if( pNpcInfoDB && pNpcInfoDB->sexsual_id > 0 )
{
for( int j(0); ItemBase::MAX_ITEM_WEAR>j; ++j )
{
int nItemCode = GetNpcResourceDB().GetNpcItemCode( j, pNpcInfoDB );
pNpc->SetItemCodeLevel( j, nItemCode, 0 );
SGameAvatarEx::WEAR_DATA weardata;
if( nItemCode < 10000 ) //기본 Mesh
{
weardata.strFileName = GetDefaultItemDB().GetFileName( nRace, nSex, nItemCode );
weardata.nItemClass = 0;
weardata.nWearType = j;
weardata.nItemCode = 0;
weardata.nItemLevel = 0;
weardata.nItemEnhanceLevel = 0;
}
else
{
// NPC 투구 왜 안보이게 한걸까여?
// 일단 풀어 놓음
// 2009-07-23 : hunee
//if( j == ItemBase::WEAR_HELM )
// continue;
weardata.strFileName = GetItemDB().GetFileName( nRace, nSex, nItemCode, 0 );
weardata.strFileName += ".nx3";
weardata.nItemClass = GetItemDB().GetClassID( nItemCode );
weardata.nWearType = j;
weardata.nItemCode = nItemCode;
weardata.nItemLevel = 0;
weardata.nItemEnhanceLevel = 0;
}
if( weardata.strFileName.empty() == false )
{
if( strstr( weardata.strFileName.c_str(), "NotFoundFile" ) == NULL )
pNpc->AddThreadItemWear( weardata );
}
}
}
pNpc->PendLoading();
}
}
void SCommandSystem::AddCreature ( SMSG_ENTER* pMsg )
{
//이미 소환된 크리처인가?
SMSG_ENTER::SummonInfo * pCreInfo = (SMSG_ENTER::SummonInfo *)(pMsg+1);
SGameAvatarEx * pAvatar = NULL;
struct DATA_CREATURE * pCreatureData = m_pGame->IsLocalCreature( pMsg->handle );
if( pCreatureData )
{
pAvatar = new SGameLocalCreature( pCreInfo->summon_code, pCreInfo->enhance );
pAvatar->SetLevel( pCreatureData->level );
UISendStringMessage(m_pGame->GetGameManager(), SIMSG_TOGGLE_UIWINDOW::UIWINDOW_DURABILITY, "refresh_durability");
}
else
{
pAvatar = new SGameOtherCreature( pCreInfo->summon_code, pCreInfo->enhance );
pAvatar->SetMaster( pCreInfo->master_handle, NULL );
}
pAvatar->SetName(pCreInfo->szName);
pAvatar->SetObjType( pMsg->ObjType );
pAvatar->ProcMsgAtStatic( pMsg );
pAvatar->Initialize( m_pRenderDevice );
pAvatar->SetMessageHandler( m_pGame );
pAvatar->SetArID( pMsg->handle );
pAvatar->GetArObject().type = pMsg->type;
pAvatar->GetArObject().mv.face = pCreInfo->face_direction;
float fHeight = 0.f;
WORD wTile=0;
m_pGame->GetHeight( pMsg->x, pMsg->y, fHeight,wTile);
K3DVector pos( pMsg->x, pMsg->y, fHeight );
pAvatar->SetArObjectPos( pos.x, pos.y, pos.z, pMsg->layer );
pAvatar->SetPosition( pos );
pAvatar->Activate();
pAvatar->SetHP( pCreInfo->hp, true );
pAvatar->SetCreatureMountType( GetCreatureDB().GetRidingMotionType( pCreInfo->summon_code ) );
pAvatar->ActivateForceSphere();
if( pCreInfo->energy > 0 )
pAvatar->OnMsgForceSphere( pCreInfo->energy );
if( GetCreatureDB().GetSlantType( pCreInfo->summon_code ) == 1 )
pAvatar->ActivateTerrainDegree();
InsertAvatarEX(pMsg->handle,pAvatar);
m_svOtherObject.insert( pAvatar );
/* SGameAvatarEx* pLocal = GetLocalPlayer();
//소환 이펙트 관련 처리 따로 따로 해줘야 한다.
if( pLocal && pCreInfo->is_first_enter )
{
int nMagicType = GetCreatureDB().GetMagicType( pCreInfo->summon_code );
std::string strEffect;
switch( nMagicType )
{
case StateInfo::ET_FIRE: //화속성
strEffect = "rcfx_summon_fire_call01_lv01.nx3";
break;
case StateInfo::ET_WATER: //수속성
strEffect = "rcfx_summon_water_call01_lv01.nx3";
break;
case StateInfo::ET_WIND: //풍속성
strEffect = "rcfx_summon_wind_call01_lv01.nx3";
break;
case StateInfo::ET_EARTH: //토속성
strEffect = "rcfx_summon_earth_call01_lv01.nx3";
break;
case StateInfo::ET_LIGHT: //명속성
strEffect = "rcfx_summon_light_call01_lv01.nx3";
break;
case StateInfo::ET_DARK: //암속성
strEffect = "rcfx_summon_dark_call01_lv01.nx3";
break;
}
if( strEffect.length() )
m_pGame->AddEffect( &FX_DATA_EX( strEffect.c_str(), 1, pAvatar->GetArID(), pAvatar->GetArID(), pAvatar->GetArID(), EFFECT_POS_BOTTOM ) );
}*/
OnAddOtherEffect( SGameOtherEffectMng::FX_SUMMONING_CREATURE, &OtherFxData( 0, pMsg->handle, 0 ) );
pAvatar->SetVisibility( 0.f );
//내것의 소환수면 검사 해서 넣는다.
m_pGame->AddSummon( pAvatar, pMsg );
// floyd 2008. 6. 13
// sonador #2.3.1.14
// 크리쳐 소환시 메시지 부분을 SGameSystem::AddSummon함수에서 SCommandSystem::AddCreature함수로 이동
// 크리쳐 소환때만이 아니라 시야 밖으로 벗어났던 크리쳐가 시야 안으로 다시 들어오면 메시지가 출력 되는 문제 수정
// http://bug.nflavor.com/view.php?id=3388
// 소환 메시지
if ( m_pGame->IsLocalCreature( pAvatar->GetArID() ))
m_pGame->SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_CREATURE_CALL, pAvatar->GetContentID() ) );
m_pArObject->onEnter( &pAvatar->GetArObject() );
SGameAvatarEx* pMaster = GetAvatar( pCreInfo->master_handle );
if( pMaster )
{
if( pMaster->IsMount() || pMaster->IsMountMode() )
{
//탑승가능 크리쳐 관련 버그 수정
//탑승 가능 크리쳐 와 기린처럼 타는 크리쳐가 동시 등장시
//탑승 크리쳐에 플레이어가 타는 문제 수정
//2009-03-16: hunee
//AddRidingObject( pCreInfo->master_handle, pMsg->handle, true );
AR_HANDLE rideHandle = pMaster->GetTransportCreatureHandle();//pMaster->GetCreatureMountHandle();
AddRidingObject( pCreInfo->master_handle, rideHandle, true );
}
// 2010.08.12 - prodongi
pMaster->SetCreature( pMsg->handle, true );
}
else
{
m_FailAddCreatureList.push_back( ENTER_CREATURE_FAIL(pMsg->handle, pCreInfo->master_handle) );
}
if( pAvatar->IsLocalCreature() == false )
InsertPendLoading( pAvatar );
else
pAvatar->PendLoading();
}
// sonador 10.2.1 팻 시스템 구현
void SCommandSystem::AddPet( SMSG_ENTER* pMsg )
{
SMSG_ENTER::PetInfo* PetInfo = (SMSG_ENTER::PetInfo*)( pMsg + 1 );
SGameAvatarEx* Avatar = 0;
struct DATA_PET* PetData = m_pGame->IsLocalPet( pMsg->handle );
if( PetData )
{
Avatar = new SGameLocalPet( PetInfo->pet_code );
}
else
{
Avatar = new SGameOtherPet( PetInfo->pet_code );
}
float height = 0.f;
WORD tile = 0;
m_pGame->GetHeight( pMsg->x, pMsg->y, height, tile );
K3DVector pos( pMsg->x, pMsg->y, height );
Avatar->SetName( PetInfo->szName );
Avatar->SetObjType( pMsg->ObjType );
Avatar->SetMaster( PetInfo->master_handle, 0 );
Avatar->ProcMsgAtStatic( pMsg );
Avatar->Initialize( m_pRenderDevice );
Avatar->SetMessageHandler( m_pGame );
Avatar->SetArID( pMsg->handle );
Avatar->GetArObject().type = pMsg->type;
Avatar->GetArObject().mv.face = PetInfo->face_direction;
Avatar->SetArObjectPos( pos.x, pos.y, pos.z, pMsg->layer );
Avatar->SetPosition( pos );
Avatar->SetVisibility( 0.f );
Avatar->Activate();
Avatar->ActivateForceSphere();
if( PetInfo->energy > 0 )
Avatar->OnMsgForceSphere( PetInfo->energy );
if( GetPetDB().Find( PetInfo->pet_code ).getSlantType() == 1 )
Avatar->ActivateTerrainDegree();
InsertAvatarEX( pMsg->handle, Avatar );
m_svOtherObject.insert( Avatar );
OnAddOtherEffect( SGameOtherEffectMng::FX_SUMMONING_CREATURE, &OtherFxData( 0, pMsg->handle, 0 ) );
Avatar->SetVisibility( 0.f );
m_pGame->AddPet( Avatar, pMsg );
m_pArObject->onEnter( &Avatar->GetArObject() );
/// 2011.10.24 자동 줍기 활성화 - prodongi
if (Avatar->IsLocalPet())
{
m_pGame->SendGameInterfaceMsg(&SIMSG_UI_SEND_DATA(SIMSG_TOGGLE_UIWINDOW::UIWINDOW_PET_COMMAND, "useAutoPickSkill"));
}
if( Avatar->IsLocalPet() == false ) // sonador #2.3.1.13
InsertPendLoading( Avatar );
else
Avatar->PendLoading();
}
void SCommandSystem::AddMob ( SMSG_ENTER* pMsg )
{
SMSG_ENTER::MonsterInfo * pMobInfo = (SMSG_ENTER::MonsterInfo *)(pMsg+1);
SGameMob* pMob = new SGameMob(pMobInfo->monster_id);
pMob->SetObjType( pMsg->ObjType );
pMob->Initialize( m_pRenderDevice );
pMob->ProcMsgAtStatic( pMsg );
//몬스터 스캐일
//float fScale = GetMonsterDB().GetScale( pMobInfo->monster_id );
// _oprint( "몬스터 스케일 : %f\n", fScale );
// pMob->SetScale( fScale );
pMob->SetMessageHandler( m_pGame );
pMob->SetArID( pMsg->handle );
pMob->GetArObject().type = pMsg->type;
pMob->GetArObject().mv.face = pMobInfo->face_direction;
//pMob->SetMobType( GetMonsterDB().GetFightType( pMobInfo->monster_id ) );
if( pMob->GetMobType() == SGameMob::CORE_MOB )
pMob->SetViewVectorAngle( pMobInfo->face_direction );
float fHeight = 0.f;
WORD wTile=0;
m_pGame->GetHeight( pMsg->x, pMsg->y, fHeight, wTile );
K3DVector pos( pMsg->x, pMsg->y, fHeight );
pMob->SetArObjectPos( pos.x, pos.y, pos.z, pMsg->layer );
pMob->SetPosition( pos );
pMob->Activate();
pMob->SetHP( pMobInfo->hp, true );
if( pMob->GetSlantType() == 1 )
pMob->ActivateTerrainDegree();
InsertAvatarEX(pMsg->handle,pMob);
m_svOtherObject.insert( pMob );
m_pArObject->onEnter( &pMob->GetArObject() );
pMob->PendLoading();
m_pGame->SendGameInterfaceMsg( &SIMSG_UI_ADD_MONSTER( pMob->GetArID(), pMob->GetContentID(), pMob->GetObjType(), pMob->GetNameID(), pMob->GetHP(), pMob->GetMaxHP() ) );
}
//Skill Prop
void SCommandSystem::AddSkillProp ( struct SMSG_ENTER* pMsg )
{
SMSG_ENTER::SkillInfo * pSkillInfo = (SMSG_ENTER::SkillInfo *)(pMsg+1);
pSkillInfo->start_time; //이것도 설정 해야 된다.
//
SGameSkilProp * pSkillProp = new SGameSkilProp( pSkillInfo->skill_num ) ;
pSkillProp->SetMessageHandler( m_pGame );
pSkillProp->SetArID( pMsg->handle );
pSkillProp->ProcMsgAtStatic( pMsg );
pSkillProp->Initialize( m_pRenderDevice );
pSkillProp->SetCasterHandle( pSkillInfo->caster );
pSkillProp->SetObjType( pMsg->ObjType );
pSkillProp->GetArObject().type = pMsg->type;
float fHeight = 0.f;
WORD wTile=0;
m_pGame->GetHeight( pMsg->x, pMsg->y, fHeight,wTile );
pSkillProp->SetArObjectPos( pMsg->x, pMsg->y, fHeight, pMsg->layer );
pSkillProp->Activate();
InsertAvatarEX(pMsg->handle,pSkillProp);
m_svOtherObject.insert( pSkillProp );
m_pArObject->onEnter( &pSkillProp->GetArObject() );
m_pGame->AddSkillProp( pSkillProp );
}
void SCommandSystem::AddFieldQuestProp( struct SMSG_ENTER* pMsg )
{
SMSG_ENTER::FieldPropInfo* pFieldPropInfo = (SMSG_ENTER::FieldPropInfo *)(pMsg+1);
SGameFieldQuestProp* pFieldQuestProp = new SGameFieldQuestProp(pFieldPropInfo->prop_id);
pFieldQuestProp->SetObjType( TS_ENTER::GAME_FIELD_PROP );
pFieldQuestProp->SetMessageHandler( m_pGame );
pFieldQuestProp->SetArID( pMsg->handle );
pFieldQuestProp->ProcMsgAtStatic( pMsg );
/*float fHeight = 0.f;
if( !m_pGame->GetOnlyTerrainHeight( pMsg->x, pMsg->y, fHeight ) )
pFieldQuestProp->SetTryHeightValue();*/
WORD wTile;
float fHeight = 0.f;
// 터레인 위에만 나오는 프랍이냐? 오브젝트 위에 나오는 프랍이냐? 체크 하는 부분
// 2010-3-25 : hunee
int nTerrainCheck = GetFieldPropResourceDB().GetTerrainCheck( pFieldQuestProp->GetQuestPropDBID() );
if( nTerrainCheck == 1)
{
// 2010.09.02 실패 했을 경우 처리 추가 - prodongi
//m_pGame->GetHeight( pMsg->x, pMsg->y, fHeight, wTile );
if (!m_pGame->GetHeight( pMsg->x, pMsg->y, fHeight, wTile ))
pFieldQuestProp->SetTryHeightValue();
}
else if( !m_pGame->GetOnlyTerrainHeight( pMsg->x, pMsg->y, fHeight ) )
{
pFieldQuestProp->SetTryHeightValue();
}
pFieldQuestProp->SetArObjectPos( pMsg->x, pMsg->y, fHeight, pMsg->layer );
pFieldQuestProp->SetPosition( K3DVector( pMsg->x, pMsg->y, fHeight ) );
pFieldQuestProp->SetZOffSet( pFieldPropInfo->fZOffset );
/// 2011.01.21 - prodongi
if (pFieldQuestProp->GetQuestPropDBID() == 130091)
pFieldQuestProp->SetRatation( K3DVector( 0.0f, 0.0f, 1.5f ));
else
pFieldQuestProp->SetRatation( K3DVector( pFieldPropInfo->fRotateX, pFieldPropInfo->fRotateY, pFieldPropInfo->fRotateZ ) );
pFieldQuestProp->SetPropScale( K3DVector( pFieldPropInfo->fScaleX, pFieldPropInfo->fScaleY, pFieldPropInfo->fScaleZ ) );
pFieldQuestProp->SetLockHeight( pFieldPropInfo->bLockHeight );
pFieldQuestProp->SetLockHeight( pFieldPropInfo->fLockHeight );
pFieldQuestProp->Initialize(NULL);
pFieldQuestProp->Activate();
InsertAvatarEX(pMsg->handle, pFieldQuestProp);
m_svOtherObject.insert( pFieldQuestProp );
m_pArObject->onEnter( &pFieldQuestProp->GetArObject() );
}
//TransportCreature ( 서버와 관계없음 )
void SCommandSystem::AddTransportCreature( SMSG_ENTER* pMsg, SGameAvatarEx* pPlayer )
{
_oprint( "소환수 핸들 %u\n", pMsg->handle );
//이미 소환된 크리처인가?
SMSG_ENTER::SummonInfo * pCretureInfo = (SMSG_ENTER::SummonInfo *)(pMsg+1);
SGameCreatureForTransport* pAvatar = new SGameCreatureForTransport( pCretureInfo->summon_code, pCretureInfo->enhance );
pAvatar->SetMaster( pCretureInfo->master_handle, pPlayer );
pAvatar->SetName(pCretureInfo->szName);
pAvatar->SetObjType( pMsg->ObjType );
pAvatar->ProcMsgAtStatic( pMsg );
pAvatar->Initialize( m_pRenderDevice );
pAvatar->SetMessageHandler( m_pGame );
pAvatar->SetArID( pMsg->handle );
pAvatar->GetArObject().type = pMsg->type;
pAvatar->GetArObject().mv.face = pCretureInfo->face_direction;
pAvatar->SetArObjectPos( pMsg->x, pMsg->y, pMsg->z , pMsg->layer );
pAvatar->SetPosition( K3DVector( pMsg->x, pMsg->y, pMsg->z ) );
pAvatar->Activate();
pAvatar->SetHP( pCretureInfo->hp, true );
pAvatar->SetCreatureMountType( GetCreatureDB().GetRidingMotionType( pCretureInfo->summon_code ) );
if( GetCreatureDB().GetSlantType( pCretureInfo->summon_code ) == 1 )
pAvatar->ActivateTerrainDegree();
InsertAvatarEX( pMsg->handle, pAvatar, true);
pAvatar->SetVisibility( 0.f );
if( pAvatar->IsLocalCreature() == false )
InsertPendLoading( pAvatar );
else
pAvatar->PendLoading();
pPlayer->SetTransportCreatureHandle( pMsg->handle );
m_pArObject->onEnter( &pAvatar->GetArObject() );
}
//==== 테스트용 더미 크리처
//테스트용 크리처 ( 서버와 관계없음 치트로 생성되는 크리처 )
void SCommandSystem::AddDummyNpc( int nContentID )
{
AddDummy( nContentID, TS_ENTER::GAME_NPC );
}
void SCommandSystem::AddDummySummon( int nContentID )
{
AddDummy( nContentID, TS_ENTER::GAME_SUMMON );
}
void SCommandSystem::AddDummyMob( int nContentID )
{
AddDummy( nContentID, TS_ENTER::GAME_MOB );
}
void SCommandSystem::AddDummyMobCirclePos( int nContentID, int nPosCnt, float fLength )
{
for( int i = 0; i < nPosCnt; ++i )
{
SGameAvatarEx* pDummy = AddDummy( nContentID, TS_ENTER::GAME_MOB );
if( pDummy )
{
K3DVector vTrans( fLength, fLength, 0.0f );
K3DMatrix matRot, matTrans;
K3DMatrixRotationZ( matRot, (float)i * ( ( K3D_PI*2.0f ) / nPosCnt ) );
K3DMatrixTranslation( matTrans, vTrans.x, vTrans.y, vTrans.z );
K3DMatrixMultiply( matTrans, matTrans, matRot );
K3DVector vPos = *pDummy->GetPosition();
vPos.x += matTrans._41;
vPos.y += matTrans._42;
WORD wTile=0;
m_pGame->GetHeight( vPos.x, vPos.y, vPos.z,wTile );
pDummy->SetArObjectPos( vPos.x, vPos.y, vPos.z, 0 );
pDummy->SetPosition( vPos );
}
}
}
void SCommandSystem::AddDummyMobRandomPos( int nContentID, int nPosCnt, float fLength )
{
for( int i = 0; i < nPosCnt; ++i )
{
SGameAvatarEx* pDummy = AddDummy( nContentID, TS_ENTER::GAME_MOB );
if( pDummy )
{
float fRandomX = (float)rand() / (float)RAND_MAX;
fRandomX = ((fRandomX * (float)fabs( fLength - (-fLength) ) ) + (-fLength) );
float fRandomY = (float)rand() / (float)RAND_MAX;
fRandomY = ((fRandomY * (float)fabs( fLength - (-fLength) ) ) + (-fLength) );
K3DVector vPos = *pDummy->GetPosition();
vPos.x += fRandomX;
vPos.y += fRandomY;
WORD wTile=0;
m_pGame->GetHeight( vPos.x, vPos.y, vPos.z,wTile );
pDummy->SetArObjectPos( vPos.x, vPos.y, vPos.z, 0 );
pDummy->SetPosition( vPos );
}
}
}
SGameAvatarEx* SCommandSystem::AddDummy( int nContentID, int nObjType )
{
SGameAvatarEx* pLocal = GetLocalPlayer();
if( pLocal == NULL ) return NULL;
static int nDummyHandle = 9090900;
SGameAvatarEx* pDummyCreature = NULL;
pDummyCreature = new SGameDummyCreature( nContentID, 0 );
pDummyCreature->SetObjType( nObjType );
pDummyCreature->SetHP( 9999 );
pDummyCreature->SetMaxHP( 9999 );
pDummyCreature->SetMP( 9999 );
pDummyCreature->SetMaxMP( 9999 );
pDummyCreature->SetLevel( 300 );
pDummyCreature->Initialize( m_pRenderDevice );
((SGameDummyCreature*)pDummyCreature)->SetDBData();
pDummyCreature->SetMessageHandler( m_pGame );
pDummyCreature->SetArID( nDummyHandle);
pDummyCreature->GetArObject().type = 3;
pDummyCreature->GetArObject().mv.face = 1.0f;
float fHeight = 0.f;
WORD wTile=0;
m_pGame->GetHeight( pLocal->GetPosition()->x, pLocal->GetPosition()->y, fHeight,wTile );
K3DVector pos( pLocal->GetPosition()->x, pLocal->GetPosition()->y, fHeight );
pDummyCreature->SetArObjectPos( pos.x, pos.y, pos.z, 0 );
pDummyCreature->SetPosition( pos );
pDummyCreature->SetVisibility( 1.0f );
pDummyCreature->Activate();
InsertAvatarEX( nDummyHandle, pDummyCreature );
m_svOtherObject.insert( pDummyCreature );
m_pArObject->onEnter( &pDummyCreature->GetArObject() );
pDummyCreature->PendLoading();
++nDummyHandle;
return pDummyCreature;
}
//그냥 바로 처리
void SCommandSystem::LeaveDummyCreature( SGameAvatarEx* pDummyCreature )
{
SMSG_LEAVE msg;
msg.handle = pDummyCreature->GetArID();
OnMsgLeave( &msg );
}
void SCommandSystem::SetDummyCreatureSpeed( SGameAvatarEx* pDummyCreature, float fSpeed )
{
((SGameDummyCreature*)pDummyCreature)->SetDummyCreatureSpeed( fSpeed );
}
void SCommandSystem::SetDummyCreatureSpeedWithPlayRate( SGameAvatarEx* pDummyCreature, float fSpeed )
{
((SGameDummyCreature*)pDummyCreature)->SetDummyCreatureSpeedWithPlayRate( fSpeed );
}
void SCommandSystem::SetDummyCreatureMode( SGameAvatarEx* pDummyCreature, int nMode )
{
((SGameDummyCreature*)pDummyCreature)->SetDummyCreatureMode( nMode );
}
void SCommandSystem::SetDummyCreaturePlayRate( SGameAvatarEx* pDummyCreature, float fPlayRate )
{
((SGameDummyCreature*)pDummyCreature)->SetDummyCreaturePlayRate( fPlayRate );
}
void SCommandSystem::MoveDummyCreature( SGameAvatarEx* pDummyCreature, K3DVector & res )
{
SMSG_MOVE msg;
msg.handle = pDummyCreature->GetArID();
msg.start_time = 0;
msg.pos_target = res;
msg.speed = ((SGameDummyCreature*)pDummyCreature)->GetDummyCreatureSpeed();
msg.m_vecMoveInfo.push_back( ArPosition( res.x, res.y, res.z ) );
m_pArObject->onMultiMove( msg.handle, ArPosition( res.x, res.y, res.z ), msg.m_vecMoveInfo, msg.speed, 0 );
pDummyCreature->OnNetInput( &msg );
msg.m_vecMoveInfo.clear();
}
//치트키
void SCommandSystem::CheatWhirlWindSkill()
{
SGameAvatarEx* pLocal = GetLocalPlayer();
if( pLocal == NULL ) return;
std::vector< AR_HANDLE > vHandle;
KSortVector< class SGameAvatarEx* >::iterator it = m_svObject.begin();
for( ; it != m_svObject.end(); ++it )
{
if( (*it)->GetObjType() == TS_ENTER::GAME_MOB && (*it)->GetArID() >= 9090900 )
vHandle.push_back( (*it)->GetArID() );
}
((SGamePlayer*)pLocal)->CheatWhirlWindSkill( vHandle );
vHandle.clear();
}
void SCommandSystem::CheatLightningSkill()
{
SGameAvatarEx* pLocal = GetLocalPlayer();
if( pLocal == NULL ) return;
struct SMSG_SKILL_EVENT msg;
msg.caster = pLocal->GetArID();
msg.target = 0;
msg.nType = SGameActionMgr::SKILL_LIGHTNING;
msg.skill_id = 3202;
msg.fire.count = 1;
KSortVector< class SGameAvatarEx* >::iterator it = m_svObject.begin();
for( ; it != m_svObject.end(); ++it )
{
if( (*it)->GetObjType() == TS_ENTER::GAME_MOB )
{
SkillResult damage;
damage.damage.hTarget = (*it)->GetArID();
msg.vSkillResult.push_back( damage );
msg.target = (*it)->GetArID();
}
}
if (m_pActionMgr) m_pActionMgr->AddTestAction( &msg );
}
void SCommandSystem::CheatHealingWaveSkill()
{
SGameAvatarEx* pLocal = GetLocalPlayer();
if( pLocal == NULL ) return;
struct SMSG_SKILL_EVENT msg;
msg.caster = pLocal->GetArID();
msg.target = 0;
msg.nType = SGameActionMgr::SKILL_HEALINGWAVE;
msg.skill_id = 3202;
msg.fire.count = 1;
KSortVector< class SGameAvatarEx* >::iterator it = m_svObject.begin();
for( ; it != m_svObject.end(); ++it )
{
if( (*it)->GetObjType() == TS_ENTER::GAME_MOB )
{
SkillResult damage;
damage.damage.hTarget = (*it)->GetArID();
msg.vSkillResult.push_back( damage );
msg.target = (*it)->GetArID();
}
}
if (m_pActionMgr) m_pActionMgr->AddTestAction( &msg );
}
void SCommandSystem::CheatBlessingHammerSkill()
{
SGameAvatarEx* pLocal = GetLocalPlayer();
if( pLocal == NULL ) return;
struct SMSG_SKILL_EVENT msg;
msg.caster = pLocal->GetArID();
msg.target = 0;
msg.nType = SGameActionMgr::SKILL_BLESSINGHAMMER;
msg.skill_id = 3202;
msg.fire.count = 1;
KSortVector< class SGameAvatarEx* >::iterator it = m_svObject.begin();
for( ; it != m_svObject.end(); ++it )
{
if( (*it)->GetObjType() == TS_ENTER::GAME_MOB && (*it)->GetArID() >= 9090900 )
{
SkillResult damage;
damage.damage.hTarget = (*it)->GetArID();
msg.vSkillResult.push_back( damage );
msg.target = (*it)->GetArID();
}
}
if (m_pActionMgr) m_pActionMgr->AddTestAction( &msg );
}
//테스트용 더미 크리처 ====//
void SCommandSystem::DropItem( AR_HANDLE item_handle )
{
//아이템을 보여주게 한다.
SGameAvatarEx* pItem = NULL;
if( m_hashObject.lookup( item_handle, pItem ) )
{
pItem->Activate();
pItem->DropSound();
}
//Drop Item 삭제
unsigned int nDropItemSize = m_vMobDropItemList.size();
for( unsigned int i(0); nDropItemSize>i; i++ )
{
if( m_vMobDropItemList[i].item_handle == item_handle )
{
m_vMobDropItemList.erase( m_vMobDropItemList.begin()+i );
return;
}
}
}
void SCommandSystem::AddItem ( SMSG_ENTER* pMsg )
{
SMSG_ENTER::ItemInfo * pItemInfo = (SMSG_ENTER::ItemInfo*)(pMsg+1);
#ifdef _TEST_ONLY_TAKE_CARD_ITEM_ /// 2011.01.25 - prodongi
if (GetItemDB().GetUseType(pItemInfo->code) != ItemBase::TYPE_CARD)
return ;
#endif
SGameItem * pItem = NULL;
pItem = new SGameItem( pItemInfo->code );
pItem->Initialize( m_pRenderDevice );
pItem->SetMessageHandler( m_pGame );
pItem->SetObjType( pMsg->ObjType );
pItem->SetArID( pMsg->handle );
pItem->ProcMsgAtStatic( pMsg );
//먹자 방지 설정
pItem->SetPickUpOrder( pMsg );
pItem->GetArObject().type = pMsg->type;
float fHeight = 0.f;
WORD wTile=0;
if( !m_pGame->GetHeight( pMsg->x, pMsg->y, fHeight,wTile ) )
pItem->SetTryHeightValue();
K3DVector pos( pMsg->x, pMsg->y, fHeight );
pItem->SetArObjectPos( pos.x, pos.y, pos.z, pMsg->layer );
pItem->SetPosition( pos );
pItem->PlayAnimation( 0, SEQTYPE_LOOP ); //고치자
InsertAvatarEX(pMsg->handle,pItem);
m_svOtherObject.insert( pItem );
m_pArObject->onEnter( &pItem->GetArObject() );
/// 2010.11.23 몹 아이템을 바로 드랍하도록 설정 - prodongi
/*
//몹이 떨군 아이템은 안 보여 준다.
unsigned int nDropItemSize = m_vMobDropItemList.size();
for( unsigned int i(0); nDropItemSize>i; i++ )
{
if( m_vMobDropItemList[i].item_handle == pItem->GetArID() )
return;
}
*/
//없으면, 그냥 떨굴 아이템이므로 보여 준다.
pItem->Activate();
}
//===================================================================================================
//Msg Event Process
void SCommandSystem::OnMsgChatting ( SMSG_CHATTING* pMsg )
{
//Local 채팅 Name 설정
SGameAvatarEx * pPlayer = GetAvatar( pMsg->handle );
if( pPlayer ) //지역 메세지 임..
pMsg->szSender = pPlayer->GetName();
}
//특정 Object의 모션 연출은 SGameSystem으로 옮기지 않는다.
void SCommandSystem::OnMsgStatusChange( SMSG_STATUS_CHANGE* pMsg )
{
SGameAvatarEx * pPlayer = GetAvatar( pMsg->handle );
if( pPlayer )
{
//로컬 플레이어는 StateMachine에서 모드를 바꿔준다
if( !pPlayer->IsLocalPlayer() )
{
if( !pPlayer->IsMount() && !pPlayer->IsMountMode() )
{
if( !(pMsg->status & TS_ENTER::PlayerInfo::FLAG_BATTLE_MODE) )
pPlayer->SetNormalMode();
}
}
pPlayer->OnNetInput( pMsg );
pPlayer->SetStatus( pMsg->status );
}
}
void SCommandSystem::OnMsgRegenHPMP( SMSG_REGEN_HPMP* pMsg )
{
/* SGameAvatarEx * pObject = (SGameAvatarEx*)GetObject( pMsg->handle );
if( pObject )
{
pObject->ProcMsgAtStatic( pMsg );
}*/
}
//추가, 삭제 관련===========================================================
void SCommandSystem::OnMsgLeave ( SMSG_LEAVE* pMsg )
{
// _oprint( "Leave \n" );
//사라지면, 삭제하자..
unsigned int nDropItemSize = m_vMobDropItemList.size();
for( unsigned int i(0); nDropItemSize>i; i++ )
{
if( m_vMobDropItemList[i].item_handle == pMsg->handle )
{
m_vMobDropItemList.erase( m_vMobDropItemList.begin()+i );
break;
}
}
delCustomBlock(pMsg->handle);
_Object *pObj = m_pArObject->onLeave( pMsg->handle );
onLeave( pMsg->handle, TRUE );
}
void SCommandSystem::OnMsgEnter ( SMSG_ENTER* pMsg )
{
// _oprint( "Enter : %d\n", pMsg->ObjType );
//삭제 보류중인 Object 검사
RemoveReservationObject();
SGameAvatarEx * pGameObject = NULL;
if( m_hashObject.lookup( pMsg->handle, pGameObject ) )
{
//이미 있는 게임 오브젝트
if( pMsg->ObjType == TS_ENTER::GAME_SUMMON )
{
SGameAvatarEx* pLocalSummonCreature = m_pGame->IsSummonCreature( pMsg->handle );
if( pLocalSummonCreature )
{
pLocalSummonCreature->ProcMsgAtStatic( pMsg );
pLocalSummonCreature->Activate();
pLocalSummonCreature->SetArObjectPos( pMsg->x, pMsg->y, pMsg->z, pMsg->layer );
m_pArObject->SetActivate( pMsg->handle );
OnAddOtherEffect( SGameOtherEffectMng::FX_SUMMONING_CREATURE, &OtherFxData( 0, pMsg->handle, 0 ) );
m_pGame->AddSummon( pLocalSummonCreature, pMsg );
}
return;
}
else if( pMsg->ObjType == TS_ENTER::GAME_PET ) // sonador 10.2.1 팻 시스템 구현
{
SGameAvatarEx* pLocalSummonPet = m_pGame->IsSummonPet( pMsg->handle );
if( pLocalSummonPet )
{
pLocalSummonPet->ProcMsgAtStatic( pMsg );
pLocalSummonPet->Activate();
pLocalSummonPet->SetArObjectPos( pMsg->x, pMsg->y, pMsg->z, pMsg->layer );
pLocalSummonPet->SetReservation( false );
m_pArObject->SetActivate( pMsg->handle );
m_pGame->AddPet( pLocalSummonPet, pMsg );
}
else if( pGameObject->IsReservation() )
{
m_pOtherEffecMgr->DelOtherEffect( pMsg->handle, SGameOtherEffectMng::FX_UN_SUMMONING_CREATURE, true );
pGameObject->SetReservation( false );
RemoveReservationObject();
}
return; // sonador #2.3.1.45
}
else
{
return;
}
}
if( pMsg->type == TS_ENTER::NPC )
{
if( pMsg->ObjType == TS_ENTER::GAME_MOB ) //NPC와 MOB으로 분리 하는게 좋지 않을까?
{
AddMob(pMsg);
}
else if( pMsg->ObjType == TS_ENTER::GAME_SUMMON ) //Summon
{
AddCreature(pMsg);
}
else if( pMsg->ObjType == TS_ENTER::GAME_NPC ) //NPC
{
AddNPC(pMsg);
}
else if( pMsg->ObjType == TS_ENTER::GAME_PET ) // PET // sonador 10.2.1 팻 시스템 구현
{
AddPet( pMsg );
}
}
else if( pMsg->type == TS_ENTER::PLAYER )
{
AddPlayer(pMsg);
}
else if( pMsg->type == TS_ENTER::STATIC_OBJECT ) //Item
{
if( pMsg->ObjType == TS_ENTER::GAME_ITEM )
{
AddItem(pMsg);
}
else if( pMsg->ObjType == TS_ENTER::GAME_SKILL_PROP )
{
AddSkillProp(pMsg);
}
else if( pMsg->ObjType == TS_ENTER::GAME_FIELD_PROP )
{
AddFieldQuestProp( pMsg );
}
}
}
void SCommandSystem::OnMsgHairInfo( SMSG_HAIR_INFO* pMsg )
{
assert( pMsg->hPlayer != 0 && "Handle이 0이다!!!" );
if( pMsg->hPlayer == 0 ) return;
SGameAvatarEx * pFind = NULL;
if( m_hashObject.lookup( pMsg->hPlayer, pFind ) == true )
{
// 2010.04.22 - prodongi
pFind->setHairThreadData(pMsg);
}
}
// 2010.05.19 - prodongi
void SCommandSystem::OnMsgHideEquipInfo(SMSG_HIDE_EQUIP_INFO* pMsg)
{
assert(pMsg->hPlayer && "HideEquipInfo player handle is NULL");
if( pMsg->hPlayer == 0 ) return;
SGameAvatarEx * pFind = NULL;
if( m_hashObject.lookup( pMsg->hPlayer, pFind ) == true )
{
pFind->setHideEquipInfo(pMsg->nHideEquipFlag);
pFind->RefreshItemWear();
/// 2011.05.16 ProcMsgAtStatic는 정적 입력 변수이다 - prodongi
// 꾸미기아이템 보임,숨김 처리 전달.
//m_pGame->ProcMsgAtStatic( new SIMSG_DECO_VISIBILITY_CHANGE( SIMSG_TOGGLE_UIWINDOW::UIWINDOW_EQUIPMENT ) );
m_pGame->ProcMsgAtStatic( &SIMSG_DECO_VISIBILITY_CHANGE( SIMSG_TOGGLE_UIWINDOW::UIWINDOW_EQUIPMENT ) );
}
}
void SCommandSystem::OnMsgHideEquipFlag(struct SMSG_HIDE_EQUIP_INFO * pMsg)
{
assert(pMsg->hPlayer && "HideEquipInfo player handle is NULL");
if( pMsg->hPlayer == 0 )
return;
SGameAvatarEx * pFind = NULL;
if( m_hashObject.lookup( pMsg->hPlayer, pFind ) == true )
{
unsigned int equipSet = pFind->getHideEquipInfo();
equipSet ^= ( 1 << pMsg->nHideEquipFlag ); // 토글시킴.
TS_CS_HIDE_EQUIP_INFO info;
info.nHideEquipFlag = equipSet;
this->m_pGame->PendMessage( &info );
}
}
void SCommandSystem::OnMsgLogin ( SMSG_LOGIN* pMsg )
{
assert( pMsg->handle != 0 && "Handle이 0이다!!!" );
if( pMsg->handle == 0 ) return;
SGameAvatarEx * pFind = NULL;
if( m_hashObject.lookup( pMsg->handle, pFind ) == true )
{ //이미 로그인 되었음.
return;
}
m_pArObject->onLogin( ArPosition( pMsg->x, pMsg->y, pMsg->z ), pMsg->handle );
m_pArObject->SetLayer( pMsg->layer );
m_pArObject->GetMyPos().face = pMsg->face_direction;
g_nRegionSize = pMsg->region_size;
SGameAvatarEx * pAvatar = NULL;
pAvatar = new SGameLocalPlayer;
pAvatar->ProcMsgAtStatic( pMsg );
//pAvatar->SetHairColorIndex(pMsg->hairColorIndex);
if (pMsg->hairColorRGB > 0)
{
pAvatar->SetHairColorRGB(pMsg->hairColorRGB);
pAvatar->SetHairColorIndex(0);
}
else
{
pAvatar->SetHairColorRGB(-16777216);
pAvatar->SetHairColorIndex(pMsg->hairColorIndex);
}
_oprint("[debug] pMsg->hairColorRGB: %d\n", pMsg->hairColorRGB);
if( pMsg->skin_color != 0 )
{
// 2010.04.22 - prodongi
// pAvatar->SetSkinColorized( pMsg->skin_color, K3DTexture::COLORIZED_DEF, 0 );
pAvatar->SetSkinColorized( pMsg->skin_color, K3DTexture::COLORIZED_DEF, pMsg->hairColorRGB );
}
else
{
unsigned long color_value = GetSkinColorTable().GetColorValue( pMsg->race-GCLAN_GAIA, 0 );
pAvatar->SetSkinColorized( color_value, K3DTexture::COLORIZED_DEF, pMsg->hairColorRGB );
}
pAvatar->SetArID( pMsg->handle );
pAvatar->SetArcadiaClient( m_pArObject );
pAvatar->SetArObjectPos( pMsg->x, pMsg->y, pMsg->z, pMsg->layer );
float fHeight = 0.f;
WORD wTile=0;
m_pGame->GetHeight(pMsg->x,pMsg->y,fHeight,wTile);
K3DVector mypos( pMsg->x,pMsg->y, fHeight );
pAvatar->SetPosition( mypos );
pAvatar->Initialize( m_pRenderDevice );
pAvatar->SetHP( pMsg->hp, true );
pAvatar->SetRenderFlag( AV_BASIC );
pAvatar->ActivateForceSphere();
pAvatar->SetMessageHandler( m_pGame );
// 2010.05.20 - prodongi
pAvatar->setHideEquipInfo(pMsg->hideEquipInfo);
m_pGame->SendGameInterfaceMsg(&SIMSG_HIDE_EQUIP_INFO(pMsg->hideEquipInfo));
// 2010.06.18 - prodongi
pAvatar->setDecoIndex(GetSelectedAvatarInfo().getDecoIndex());
// pAvatar->ActivateTerrainDegree();
#ifdef _WEAPON_FX_
pAvatar->ActivateFxSwordSlash();
#endif
//아이템 정보가 오면, Activate 시킨다.
m_LocalHandle = pMsg->handle;
SIMSG_UI_2DPOS_INFO msg;
K3DVector _2Dpos;
m_pGame->Get2DPos( mypos, _2Dpos );
msg.handle = pAvatar->GetArID();
msg.nX = _2Dpos.x;
msg.nY = _2Dpos.y;
m_pGame->ProcMsgAtStatic( &msg );
InsertAvatarEX(pMsg->handle,pAvatar);
m_svPlayerObject.insert( pAvatar );
pAvatar->PendLoading();
}
void SCommandSystem::OnMsgResult ( SMSG_RESULT* pMsg )
{
SGameAvatarEx* pLocalPlayer = GetLocalPlayer();
if( pLocalPlayer ) pLocalPlayer->OnNetInput( pMsg );
switch( pMsg->request_msg_id )
{
// 대련 신청시 오류 메세지 출력, kappamind.
case TM_CS_COMPETE_REQUEST:
{
if( pMsg->result == RESULT_TARGET_ALREADY_IN_COMPETE )
{
m_pGame->AddChatMessage( S( 1636 ) );
}
else if( pMsg->result == RESULT_TOO_FAR ||
pMsg->result == RESULT_ALREADY_IN_COMPETE ||
pMsg->result == RESULT_LIMIT_TARGET ||
pMsg->result == RESULT_NOT_IN_COMPETIBLE_PLACE ||
pMsg->result == RESULT_TARGET_NOT_IN_COMPETIBLE_PLACE ||
pMsg->result == RESULT_NOT_EXIST ||
pMsg->result == RESULT_WAITING_COMPETE_REQUEST_ANSWER ||
pMsg->result == RESULT_TARGET_WAITING_COMPETE_REQUEST_ANSWER )
{
m_pGame->AddChatMessage( S( 1633 ) );
g_pCurrentGameSystem->SetPVPAcceptCheck( false );
}
}
break;
case TM_CS_COMPETE_ANSWER:
{
if( pMsg->result == RESULT_ALREADY_IN_COMPETE ||
pMsg->result == RESULT_TARGET_ALREADY_IN_COMPETE )
{
m_pGame->AddChatMessage( S( 1636 ) );
}
else if( pMsg->result == RESULT_TARGET_NOT_IN_COMPETIBLE_PLACE ||
pMsg->result == RESULT_NOT_IN_COMPETIBLE_PLACE ||
pMsg->result == RESULT_NOT_IN_COMPETE ||
pMsg->result == RESULT_NOT_EXIST )
{
m_pGame->AddChatMessage( S( 1633 ) );
g_pCurrentGameSystem->SetPVPAcceptCheck( false );
}
}
break;
//
case TM_CS_DONATE_REWARD:
{
if( pMsg->result == RESULT_NOT_OWN )
m_pGame->AddChatMessage( S( 6746 ) ); // 모럴 포인트 부족 채팅 메세지
}
case TM_CS_USE_ITEM:
{
if( pMsg->result == RESULT_NOT_ACTABLE_IN_DEATHMATCH ) m_pGame->AddChatMessage( S( 9201 ) ); //데스매치에서는 아이템 사용이 불가능하다.
else if (pMsg->result == RESULT_TARGET_IN_DEATHMATCH) m_pGame->AddChatMessage(S(9252)); // 2011.07.27 - prodongi
else if (pMsg->result == RESULT_NO_SKILL) m_pGame->AddChatMessage(S(740)); /// 해당 아이템을 사용하기 위한 스킬을 습득하지 못하였습니다.
else if (pMsg->result == RESULT_ALREADY_TAMING) m_pGame->AddChatMessage(S(741)); /// 다른 몬스터를 테이밍 중입니다.
else if (pMsg->result == RESULT_NOT_TAMABLE) m_pGame->AddChatMessage(S(742)); /// 테이밍이 불가능한 몬스터 입니다.
else if (pMsg->result == RESULT_TARGET_ALREADY_BEING_TAMED) m_pGame->AddChatMessage(S(743)); /// 이미 테이밍이 진행되고 있는 몬스터 입니다.
else if (pMsg->result == RESULT_NOT_ENOUGH_TARGET_HP) m_pGame->AddChatMessage(S(325)); /// 대상의 HP가 100 %일때만 테이밍을 시도할 수 있습니다.
else if (pMsg->result == RESULT_NOT_ENOUGH_SUMMON_CARD) m_pGame->AddChatMessage(S(324)); /// 빈 크리처 카드를 보유해야만 테이밍을 시도할 수 있습니다.
else if (pMsg->result == RESULT_NOT_ENOUGH_SOUL_TAMING_CARD) m_pGame->AddChatMessage(S(324)); /// 빈 크리처 카드를 보유해야만 테이밍을 시도할 수 있습니다.
else if (pMsg->result == RESULT_NOT_ACTABLE_ON_STAND_UP) m_pGame->AddChatMessage(S(895)); /// 앉은 상태에서만 사용 가능합니다.
else if (pMsg->result == RESULT_NOT_ACTABLE_IN_BATTLE_ARENA) m_pGame->AddChatMessage(S(9243)); /// 아레나에서의 아이템 사용 불가
else if (pMsg->result == RESULT_TARGET_IN_BATTLE_ARENA) m_pGame->AddChatMessage(S(396)); /// 아레나에서의 아이템 사용 불가
else if (pMsg->result == RESULT_NOT_IN_COMPETE ) m_pGame->AddChatMessage(S(1009)); /// 대련 중에 사용 불가
else if (pMsg->result == RESULT_ALREADY_EXIST ) m_pGame->AddChatMessage(S(1008)); /// 같은 부류의 지속효과가 이미 걸려있어 사용 불가
else if (pMsg->result == RESULT_NOT_EXIST_PARTY ) m_pGame->AddChatMessage(S(434)); /// 파티 아이템 사용 불가
else if (pMsg->result == RESULT_NOT_EXIST_GUILD ) m_pGame->AddChatMessage(S(629)); /// 길드 아이템 사용 불가
}
break;
case TM_CS_TAKE_ITEM :
{
//TODO 크리처가 아이템을 습득할 경우에는 별도 처리 해줘야함
if( pMsg->result == RESULT_TOO_FAR )
{
_oprint( "아템이 너무 멀어~.\n" );
}
}
break;
case TM_CS_SKILL :
{
//현재 사용 시전 중인 Skill 을 멈춘다.
//_oprint( "공용 메세지 - 스킬 취소 : %d\n", pMsg->result );
if (pMsg->result == RESULT_NO_SKILL) m_pGame->AddChatMessage(S(740)); /// 해당 아이템을 사용하기 위한 스킬을 습득하지 못하였습니다.
else if (pMsg->result == RESULT_ALREADY_TAMING) m_pGame->AddChatMessage(S(741)); /// 다른 몬스터를 테이밍 중입니다.
else if (pMsg->result == RESULT_NOT_TAMABLE) m_pGame->AddChatMessage(S(742)); /// 테이밍이 불가능한 몬스터 입니다.
else if (pMsg->result == RESULT_TARGET_ALREADY_BEING_TAMED) m_pGame->AddChatMessage(S(743)); /// 이미 테이밍이 진행되고 있는 몬스터 입니다.
else if (pMsg->result == RESULT_NOT_ENOUGH_TARGET_HP) m_pGame->AddChatMessage(S(325)); /// 대상의 HP가 100 %일때만 테이밍을 시도할 수 있습니다.
else if (pMsg->result == RESULT_NOT_ENOUGH_SUMMON_CARD) m_pGame->AddChatMessage(S(324)); /// 빈 크리처 카드를 보유해야만 테이밍을 시도할 수 있습니다.
else if (pMsg->result == RESULT_NOT_ENOUGH_SOUL_TAMING_CARD) m_pGame->AddChatMessage(S(324)); /// 빈 크리처 카드를 보유해야만 테이밍을 시도할 수 있습니다.
}
break;
case TM_CS_MOVE_REQUEST:
{
if (pMsg->result == RESULT_ALREADY_EXIST)
_oprint("Move request results in move to current location.\n");
else
{
_oprint("It's an area I can't go to. - %d \n", pMsg->result);
}
}
break;
// PK On 모드에서 대련신청시 거부 메세지
case TM_TRADE :
{
if( pMsg->result == RESULT_PK_LIMIT )
{
m_pGame->AddChatMessage( S(1652) );
}
else if( pMsg->result == RESULT_TARGET_IS_USING_STORAGE) // 2011. 9 .16 - marine 거래 신청 대상이 창고 이용
{
m_pGame->GetGameManager()->GetGameInterface()->OpenMessageBox(SIMSG_REQ_OPEN_MSGBOX::MSGBOX_OK, SIMSG_REQ_OPEN_MSGBOX::MSGBOX_GENERAL, 0, -1, S(9824));
m_pGame->AddChatMessage( S(9824) );
}
}
break;
case TM_CS_START_BOOTH:
{
if( pMsg->result == RESULT_NOT_ACTABLE )
{
m_pGame->SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_BOOTH_NOTICE_TRANSACTION ) );
}
/*else if ( pMsg->result == RESULT_NOT_ACTABLE_HERE )
{
m_pGame->AddChatMessage( S(727) );
}*/
}
break;
case TM_CS_JOB_LEVEL_UP:
{
if( pMsg->result == RESULT_SUCCESS )
{
SGameAvatarEx* pTarget = (SGameAvatarEx *)GetObject( (unsigned int)pMsg->value );
if( pLocalPlayer && pTarget )
{
if( pLocalPlayer->GetArID() == pTarget->GetArID() )
m_pGame->SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_JLV_UP ) );
}
}
}
break;
case TM_CS_LEARN_SKILL:
{
if( pMsg->result == RESULT_SUCCESS )
m_pGame->SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_LEARN_SKILL, pMsg->value ) );
}
break;
case TM_CS_SOULSTONE_CRAFT:
{
if( pMsg->result == RESULT_ACCESS_DENIED )
m_pGame->SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_ERR_ITEM, pMsg->value ) );
else if( pMsg->result == RESULT_NOT_ACTABLE )
m_pGame->SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_CANT_EQUIP_JEWEL, pMsg->value ) );
else if( pMsg->result == RESULT_ALREADY_EXIST )
m_pGame->SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_EQUIP_JEWEL_OVER, pMsg->value ) );
else if( pMsg->result == RESULT_NOT_ENOUGH_MONEY )
m_pGame->SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_BUY_ITEM_FAIL002, pMsg->value ) );
else if( pMsg->result == RESULT_SUCCESS )
m_pGame->SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_SUCCESS_EQUIP_JEWEL, pMsg->value ) );
}
break;
case TM_CS_INSTANCE_GAME_ENTER:
{
//RESULT_NOT_ACTABLE_IN_DEATHMATCH
if( pMsg->result == RESULT_NOT_ENOUGH_MONEY )
m_pGame->AddChatMessage( S( 9234 ) ); //돈이 부족해서 베어로드에 들어갈 수 없다.
else if( pMsg->result == RESULT_NOT_ACTABLE_IN_HUNTAHOLIC || pMsg->result == RESULT_NOT_ACTABLE_IN_DEATHMATCH )
m_pGame->AddChatMessage( S( 9239 ) ); //다른 채널로 가기 위해서는 먼저 필드로 귀환 해야 합니다.
// 2010.06.09 - prodongi
else if (pMsg->result == RESULT_NOT_ACTABLE_IN_SECRET_DUNGEON)
m_pGame->AddChatMessage( S( 9245 ) ); // 숨겨진 던전 안에서는 할 수 없는 동작입니다
}
break;
case TM_CS_HUNTAHOLIC_CREATE_INSTANCE:
{
if( pMsg->result == RESULT_NOT_ENOUGH_BULLET )
m_pGame->AddChatMessage( S( 9237 ) ); //베어로드 플레이 횟수 부족으로 방 만들기 실패
else if (pMsg->result == RESULT_INVALID_TEXT)
m_pGame->AddChatMessage( S( 128 ) ); // 2012.02.08 유효하지 않은 방제를 사용 했을 때 - prodongi
}
break;
case TM_CS_HUNTAHOLIC_JOIN_INSTANCE:
{
if( pMsg->result == RESULT_NOT_ENOUGH_BULLET )
m_pGame->AddChatMessage( S( 9237 ) ); //베어로드 플레이 횟수 부족으로 입장 실패
}
break;
}
}
//특정 Object의 모션 연출은 SGameSystem으로 옮기지 않는다.
//이동, 영역 관련===========================================================
void SCommandSystem::OnMsgMove ( SMSG_MOVE* pMsg )
{
SGameAvatarEx* localPlayer = GetLocalPlayer();
if (pMsg->handle == localPlayer->GetArID())
{
#ifdef KMOVE_DEBUG
m_pArObject->addKMovePrimitive(pMsg->m_vecMoveInfo, m_pArObject->GetMyPos().GetPos(), 1);
#endif
m_pArObject->setSpeed(pMsg->handle, pMsg->speed);
/// 키보드 이동으로 보낸 좌표일 경우에는 클라이언트 자체에서 이동을 시켜 주기 때문에 그냥 리턴한다.
if (localPlayer->isKMoveTargetList(pMsg->m_vecMoveInfo))
{
return ;
}
if (localPlayer->isKMoving())
{
SGameWorld* pGameWorld = dynamicCast<SGameWorld*>(g_pCurrentGameSystem->GetGame());
if( pGameWorld != NULL )
{
pGameWorld->stopKMove();
}
}
}
//K3DVector targetpos;
{
m_pArObject->onMultiMove( pMsg->handle, ArPosition(pMsg->pos_target.x,pMsg->pos_target.y, pMsg->pos_target.z), pMsg->m_vecMoveInfo, pMsg->speed, pMsg->start_time );
//targetpos = K3DVector(pMsg->pos_target.x,pMsg->pos_target.y, pMsg->pos_target.z);
}
SGameAvatarEx * pAvatar = NULL;
if( m_hashObject.lookup( pMsg->handle, pAvatar ) )
{
if( pAvatar->IsPendLoading() )
ActivatePendLoadingListByMove( pAvatar );
pAvatar->OnNetInput( pMsg );
//플레이어냐?
if( pAvatar->GetObjType() == TS_ENTER::GAME_PLAYER )
{
//로컬 플레이어 이동 시 타겟 리스트 삭제 한다.
if( pAvatar->IsLocalPlayer() )
m_pTargetMgr->ClearTargetList();
// if( pAvatar->IsMountMode() )
{
if( pAvatar->GetCreatureMountHandle() )
{
m_pArObject->onMultiMove( pAvatar->GetCreatureMountHandle(), ArPosition(pMsg->pos_target.x,pMsg->pos_target.y, pMsg->pos_target.z), pMsg->m_vecMoveInfo, pMsg->speed, pMsg->start_time );
SGameAvatarEx* pCreature = pAvatar->GetRiderCreatureObject();
if( pCreature )
{
pCreature->OnNetInput( pMsg );
}
}
}
}
return;
}
{
//#ifndef NDEBUG
// K3DVector pos = K3DVector( m_pArObject->GetMyPos().x, m_pArObject->GetMyPos().y, 0 );
// targetpos.z = 0.f;
// float fLen = K3DVectorGetLength( pos, targetpos );
// _oprint( "!!! - 움직일 놈을 못 찾았다. 나와의 거리 : %f \n", fLen );
//#endif
//Enter 를 강제로 해달라~
TS_CS_QUERY query_msg;
query_msg.handle = pMsg->handle;
m_pGame->SendMsg( &query_msg );
}
}
void SCommandSystem::OnMsgRegionAck( SMSG_REGION_ACK* pMsg )
{
m_pArObject->onRegionAck( pMsg->rx, pMsg->ry );
}
void SCommandSystem::OnAttack( SGameAvatarEx * pAttack, SGameAvatarEx * pTarget, AR_HANDLE hAttack , AR_HANDLE hTarget, SGameMessage * pMsg )
{
if( pAttack && pTarget )
{
// TODO: 마운트 모드 이거나 마운트 상태일때는 무시한다
if( !pAttack->IsMountMode() && !pAttack->IsMount() )
{
pAttack->OnNetInput( pMsg );
pAttack->SetAttackMode();
}
//pAttacker 와 pTarget 이 Player 계열 이면, 전투 대기 중으로 변경 해달라고 한다.
//이미 전투 대기 중이거나, 공격 중이면, 무시 된다.
if(pTarget->GetObjType() == TS_ENTER::GAME_NPC )
{
pTarget->SetAttackMode();
pTarget->Default3(); //맞는 놈한테 알려 준다.
}
else
{
if( !pTarget->IsMountMode() && !pTarget->IsMount() )
{
pTarget->SetAttackMode();
pTarget->Default3(); //맞는 놈한테 알려 준다.
}
}
}
else
{
//Enter 를 강제로 해달라~
TS_CS_QUERY query_msg;
if( pAttack == NULL )
{
query_msg.handle = hAttack;
m_pGame->SendMsg( &query_msg );
#ifndef NDEBUG
_oprint( "공격 메세지 : Attacker 찾을 수 없다.\n" );
#endif
}
if( pTarget == NULL )
{
query_msg.handle = hTarget;
m_pGame->SendMsg( &query_msg );
#ifndef NDEBUG
_oprint( "공격 메세지 : Target 찾을 수 없다.\n" );
#endif
}
}
}
void SCommandSystem::OnMsgAttackDouble( struct SMSG_ATTACK_DOUBLE* pMsg )
{
// _oprint( "OnMsgAttackDouble\n" );
SGameAvatarEx * pAttacker = NULL;
SGameAvatarEx * pTarget = NULL;
pAttacker = (SGameAvatarEx *)GetObject( pMsg->attacker_handle );
pTarget = (SGameAvatarEx *)GetObject( pMsg->target_handle );
if( pTarget )
{
pMsg->pos_target = pTarget->GetCurPosWithChangeDir();
}
OnAttack( pAttacker, pTarget, pMsg->attacker_handle, pMsg->target_handle, pMsg );
}
//공격, 스킬, 명령 관련=====================================================
void SCommandSystem::OnMsgAttack ( SMSG_ATTACK* pMsg )
{
SGameAvatarEx * pAttacker = NULL;
SGameAvatarEx * pTarget = NULL;
pAttacker = (SGameAvatarEx *)GetObject( pMsg->attacker_handle );
pTarget = (SGameAvatarEx *)GetObject( pMsg->target_handle );
if( pTarget )
{
pMsg->pos_target = pTarget->GetCurPosWithChangeDir();
}
OnAttack( pAttacker, pTarget, pMsg->attacker_handle, pMsg->target_handle, pMsg );
}
void SCommandSystem::AddAction( struct SGameMessage* pMsg )
{
if (m_pActionMgr) m_pActionMgr->AddAction( pMsg );
}
//스킬
void SCommandSystem::OnMsgSkillEvent( struct SMSG_SKILL_EVENT* pMsg )
{
if( pMsg->status_type == TS_SC_SKILL::FIRE ) //뭔가 발사 되거나, 행동을 취한다.
{
std::vector<SkillResult>::iterator it;
for( it = pMsg->vSkillResult.begin(); it != pMsg->vSkillResult.end(); ++it )
{
if( (*it).GetType() == SkillResult::RUSH ) {
if( (*it).rush.bResult ) {
K3DVector vPos = K3DVector( (*it).rush.x, (*it).rush.y, 0.0f );
WORD wTile=0;
m_pGame->GetHeight( vPos.x, vPos.y, vPos.z,wTile );
m_pArObject->onMove( pMsg->caster,
ArPosition( vPos.x, vPos.y, vPos.z ),
(*it).rush.speed );
}
break;
}
}
SGameAvatarEx * pAvatar = (SGameAvatarEx *)GetObject( pMsg->caster );
if( !pAvatar ) return;
//WORK에서 호출 하도록 변경됨 ( 몬스터만 )
if( pAvatar->GetObjType() != TS_ENTER::GAME_MOB )
{
if (m_pActionMgr) m_pActionMgr->AddAction( pMsg );
}
pAvatar->OnNetInput( pMsg );
}
else if( pMsg->status_type == TS_SC_SKILL::CASTING ) //캐스팅이다~
{
SGameAvatarEx * pAvatar = (SGameAvatarEx *)GetObject( pMsg->caster );
if( pAvatar )
{
pAvatar->OnNetInput( pMsg );
K3DVector tpos; tpos.x = pMsg->x; tpos.y = pMsg->y; tpos.z = pMsg->z;
pAvatar->SetViewVector( tpos ); //몸통 방향 바꾸기
//if( vTargetPos.y == GetPosition()->y && vTargetPos.x == GetPosition()->x )
//m_fTargetRoll = atan2( vTargetPos.y-GetPosition()->y, vTargetPos.x-GetPosition()->x );
//m_dwPrevTime = m_dwTime;
//m_bUseRot = true;
/* if( pMsg->cast.nErrorCode == RESULT_NOT_ENOUGH_HP ||
pMsg->cast.nErrorCode == RESULT_NOT_ENOUGH_MP ||
pMsg->cast.nErrorCode == RESULT_COOL_TIME )
{
// pAvatar->CheckPrevState();
}*/
/// 2011.01.20 - prodongi
if (4003 == pMsg->skill_id && pAvatar->IsLocalPlayer())
{
setIsTaming(true);
}
}
}
else if( pMsg->status_type == TS_SC_SKILL::CASTING_UPDATE )
{
SGameAvatarEx * pAvatar = (SGameAvatarEx *)GetObject( pMsg->caster );
if( pAvatar )
pAvatar->OnNetInput( pMsg );
}
else if( pMsg->status_type == TS_SC_SKILL::CANCEL )
{
SGameAvatarEx * pAvatar = (SGameAvatarEx *)GetObject( pMsg->caster );
if( pAvatar )
pAvatar->OnNetInput( pMsg );
RemoveReservationObject(true);
/// 2011.01.20 - prodongi
if (4003 == pMsg->skill_id && pAvatar->IsLocalPlayer())
{
setIsTaming(false);
}
}
else if( pMsg->status_type == TS_SC_SKILL::REGION_FIRE )
{
if (m_pActionMgr) m_pActionMgr->AddAction( pMsg );
SGameAvatarEx * pAvatar = (SGameAvatarEx *)GetObject( pMsg->caster );
if( pAvatar )
pAvatar->OnNetInput( pMsg );
}
else if( pMsg->status_type == TS_SC_SKILL::COMPLETE )
{
SGameAvatarEx * pAvatar = (SGameAvatarEx *)GetObject( pMsg->caster );
if( pAvatar )
pAvatar->OnNetInput( pMsg );
}
}
////스킬 범위 데미지
//void SCommandSystem::OnMsgSkillEffect( SMSG_SKILL_EFFECT* pMsg )
//{
// _oprint( "스킬 범위 데미지\n" );
//
// m_pActionMgr->AddAction( pMsg );
//}
//명령
void SCommandSystem::OnMsgCmd ( SMSG_CMD_RESULT* pMsg )
{
//Object 찾아서 하라고 시킴.
}
//타기
void SCommandSystem::OnMsgMount( SMSG_MOUNT_SUMMON* pMsg )
{
SGameAvatarEx* pAvatar = (SGameAvatarEx *)GetObject( pMsg->handle );
SGameAvatarEx* pCreature = (SGameAvatarEx *)GetObject( pMsg->summon_handle );
if( pAvatar && pCreature )
{
DeleteRidingObject( pMsg->handle, pMsg->summon_handle );
if( !pMsg->success )
{
//타기 실패
// pAvatar->SetNormalMode();
return;
}
//살짝쿵 위치 보정
K3DVector vPos = K3DVector( pMsg->x, pMsg->y, 0.0f );
WORD wTile=0;
m_pGame->GetHeight( vPos.x, vPos.y, vPos.z,wTile );
m_pArObject->onMove( pMsg->handle,
ArPosition( vPos.x, vPos.y, vPos.z ),
(unsigned char)140 );
m_pArObject->onMove( pMsg->summon_handle,
ArPosition( vPos.x, vPos.y, vPos.z ),
(unsigned char)140 );
pAvatar->SetMountMode();
pCreature->SetMountMode();
pAvatar->OnNetInput( pMsg );
pCreature->OnNetInput( pMsg );
}
else if( pAvatar == NULL || pCreature == NULL)
{
//플레이어 및 크리처를 찾을수 없다면
AddRidingObject( pMsg->handle, pMsg->summon_handle, true );
}
}
//내리기
void SCommandSystem::OnMsgUnMount( SMSG_UNMOUNT_SUMMON* pMsg )
{
SGameAvatarEx* pAvatar = (SGameAvatarEx *)GetObject( pMsg->handle );
SGameAvatarEx* pCreature = (SGameAvatarEx *)GetObject( pMsg->summon_handle );
if(pAvatar && pCreature )
{
// 2009.02.03 kappamind. 크리처 탑승 후, 이동중 내리기를 하면 나타나던 오류를
// 내리기를 선택 시 그자리에 멈추게 한 후 동작되게 변경.
/// 2012.08.08 로컬 플레이어 일 때만 적용해 준다 - prodongi
if( pAvatar->IsLocalPlayer() )
{
SetPlayerAndCreaturePosition( pMsg );
}
DeleteRidingObject( pMsg->handle, pMsg->summon_handle );
//로컬 플레이어가 아닐경우 바로 노멀 모드로
if( !pAvatar->IsLocalPlayer() )
{
pAvatar->SetNormalMode();
pCreature->SetNormalMode();
}
pAvatar->OnNetInput( pMsg );
pCreature->OnNetInput( pMsg );
}
else if( pAvatar == NULL || pCreature == NULL )
{
//플레이어 및 크리처를 찾을수 없다면
AddRidingObject( pMsg->handle, pMsg->summon_handle, false );
}
}
void SCommandSystem::OnMount( const StateInfoEx* pStateInfoEx, SGameAvatarEx* pPlayer, bool bWithEffect )
{
if( pPlayer == NULL || pStateInfoEx == NULL ) return;
AR_HANDLE hCreature = pPlayer->GetArID() + 1000000000;
SMSG_ENTER entermsg;// = (SMSG_ENTER*)pEnterMsg;
entermsg.handle = hCreature;
entermsg.x = pPlayer->GetPosition()->x;
entermsg.y = pPlayer->GetPosition()->y;
entermsg.z = pPlayer->GetPosition()->z;
entermsg.layer = 0;
entermsg.nType = MSG_ENTER;
entermsg.type = TS_ENTER::NPC;
entermsg.ObjType = TS_ENTER::GAME_SUMMON;
char* pEnterMsg = new char[sizeof(SMSG_ENTER)+sizeof(SMSG_ENTER::SummonInfo)];
memcpy( pEnterMsg, &entermsg, sizeof(SMSG_ENTER) );
SMSG_ENTER* pEnterSummon = (SMSG_ENTER*)pEnterMsg;
SMSG_ENTER::SummonInfo * pCretureInfo = (SMSG_ENTER::SummonInfo *)(pEnterSummon+1);
pCretureInfo->hp = 1;
pCretureInfo->mp = 1;
pCretureInfo->max_hp = 1;
pCretureInfo->max_mp = 1;
pCretureInfo->level = 1;
pCretureInfo->master_handle = pPlayer->GetArID();
pCretureInfo->summon_code = pStateInfoEx->fValue[1];
pCretureInfo->energy = 0;
pCretureInfo->face_direction = 0;
// 2011.3.4 marine - enhance 초기화
pCretureInfo->enhance = 0;
strcpy( pCretureInfo->szName, "summon" );
AddTransportCreature( pEnterSummon, pPlayer );
SAFE_DELETE_ARRAY( pEnterMsg );
SWorkMountWithOutAnimation* pMount = NULL;
if( bWithEffect )
pMount = new SWorkMountWithOutAnimation( pPlayer, hCreature, pStateInfoEx->fValue[2], pStateInfoEx->fValue[3] );
else
pMount = new SWorkMountWithOutAnimation( pPlayer, hCreature, 0, 0 );
pPlayer->AllWorkEnd();
pPlayer->AddWork( pMount );
}
void SCommandSystem::OnUnMount( const struct StateInfoEx* pStateInfoEx, SGameAvatarEx* pPlayer, bool bForceUnMount )
{
if( pPlayer == NULL ) return;
AR_HANDLE hCreature = pPlayer->GetTransportCreatureHandle();
if( hCreature == 0 ) return;
SMSG_LEAVE msgleave;
msgleave.handle = hCreature;
OnMsgLeave( &msgleave );
if( bForceUnMount )
{
pPlayer->SetMotionBlend( true );
pPlayer->SetNormalMode();
pPlayer->SetRiderCreatureInfo();
pPlayer->SetDefaultView();
if( pPlayer->IsMoving() ) pPlayer->Run();
else pPlayer->Default();
return;
}
SWorkUnMountWithOutAnimation* pUnMount = NULL;
if( pStateInfoEx == NULL )
pUnMount = new SWorkUnMountWithOutAnimation( pPlayer, hCreature, 0, 0 );
else
pUnMount = new SWorkUnMountWithOutAnimation( pPlayer, hCreature, pStateInfoEx->fValue[4], pStateInfoEx->fValue[5] );
pPlayer->AllWorkEnd();
pPlayer->AddWork( pUnMount );
}
//Item 관련=================================================================
void SCommandSystem::OnMsgTakeResult( SMSG_ITEM_TAKE* pMsg )
{
int x = 0;
// _oprint( "SCommandSystem::아이템 먹었다\n" );
}
void SCommandSystem::OnMsgDropResult( SMSG_ITEM_DROP* pMsg )
{
//몬스터가 가진 아이템은 보여 주지 않는다.
unsigned int nDropItemSize = m_vMobDropItemList.size();
for( unsigned int i(0); nDropItemSize>i; i++ )
{
if( m_vMobDropItemList[i].item_handle == pMsg->item_handle )
return;
}
SGameAvatarEx * pItem = NULL;
if( m_hashObject.lookup( pMsg->item_handle, pItem ) )
{
pItem->Activate();
}
// assert( 0 && "아이템 에러 : 보여줄 아이템을 찾을 수 없다!!!" );
}
void SCommandSystem::OnMsgDropInfo ( SMSG_ITEM_DROP_INFO* pMsg )
{
/// 2010.11.23 - prodongi
/*
//몹이 떨어 트리는, 아이템
DROP_INFO drop_info;
drop_info.item_handle = pMsg->item_handle;
drop_info.mob_handle = pMsg->monster_handle;
m_vMobDropItemList.push_back( drop_info );
SGameAvatarEx* pMob = (SGameAvatarEx*)GetObject( pMsg->monster_handle );
if( pMob )
{
//내가 떨굴 아이템
pMob->SetDropItemInfo( pMsg->item_handle );
}
else
{
_oprint( "아이템을 보여 줄 수 없다.\n" );
}
*/
}
void SCommandSystem::OnMsgWearInfo ( SMSG_ITEM_WEAR* pMsg )
{
//Local Player
SGameAvatarEx* pPlayer = GetAvatar( pMsg->handle );
if( !pPlayer ) return;
//쌓여 있는 것을 지운다.
pPlayer->ClearThreadLoadWear();
int nRace = 0, nSex = 0;
for( int j(0); ItemBase::WEAR_FACE >= j; j++ ) //WEAR_FACE까지가 기본 장비
{
nRace = pPlayer->GetRace();
nSex = pPlayer->GetSex();
pPlayer->SetItemCodeLevel( j, pMsg->nItemCode[j], pMsg->nItemLevel[j] );
SGameAvatarEx::WEAR_DATA weardata;
if( pMsg->nItemCode[j] < 10000 ) //기본 Mesh
{
if( pMsg->nItemCode[j] != 0 ) weardata.strFileName = GetDefaultItemDB().GetFileName( nRace, nSex, pMsg->nItemCode[j] );
else weardata.strFileName = "_NoItem_";
weardata.nItemCode = pMsg->nItemCode[j];
weardata.nItemClass = 0;
weardata.nItemLevel = 0;
weardata.nItemEnhanceLevel = 0;
}
else //Item
{
// 2012. 7. 24 - marine 아이템 형상변환.. 형상변환 아이템 코드가 있으면 모델과 텍스쳐를 바꿔준다.
if( pMsg->nAppearanceItemCode[j] )
{
weardata.strFileName = GetItemDB().GetFileName( nRace, nSex, pMsg->nAppearanceItemCode[j], pMsg->nItemLevel[j] );
weardata.strTextureName = GetItemDB().GetAdditionalTexture(pMsg->nAppearanceItemCode[j]);
weardata.nItemClass = GetItemDB().GetClassID( pMsg->nAppearanceItemCode[j] );
}
else
{
weardata.strFileName = GetItemDB().GetFileName( nRace, nSex, pMsg->nItemCode[j], pMsg->nItemLevel[j] );
weardata.strTextureName = GetItemDB().GetAdditionalTexture(pMsg->nItemCode[j]);
weardata.nItemClass = GetItemDB().GetClassID( pMsg->nItemCode[j] );
}
weardata.strFileName += ".nx3";
weardata.nItemCode = pMsg->nItemCode[j];
weardata.nItemLevel = pMsg->nItemLevel[j];
weardata.nItemEnhanceLevel = pMsg->nItemEnhance[j];
weardata.cElementalEffect = pMsg->elemental_effect_type[j];
weardata.nAppearanceItemCode = pMsg->nAppearanceItemCode[j];
}
ItemBase::ItemWearType nDecoWearType = ItemBase::WEAR_NONE;
switch( j )
{
case ItemBase::WEAR_WEAPON: nDecoWearType = ItemBase::WEAR_DECO_WEAPON; break;
case ItemBase::WEAR_SHIELD: nDecoWearType = ItemBase::WEAR_DECO_SHIELD; break;
case ItemBase::WEAR_ARMOR: nDecoWearType = ItemBase::WEAR_DECO_ARMOR; break;
case ItemBase::WEAR_HELM: nDecoWearType = ItemBase::WEAR_DECO_HELM; break;
case ItemBase::WEAR_GLOVE: nDecoWearType = ItemBase::WEAR_DECO_GLOVE; break;
case ItemBase::WEAR_BOOTS: nDecoWearType = ItemBase::WEAR_DECO_BOOTS; break;
case ItemBase::WEAR_MANTLE: nDecoWearType = ItemBase::WEAR_DECO_MANTLE; break;
}
if( nDecoWearType != ItemBase::WEAR_NONE )
{
if( pMsg->nItemCode[nDecoWearType] != 0 )
{
if( pMsg->nAppearanceItemCode[nDecoWearType] != 0 )
{
weardata.strDecoFileName = GetItemDB().GetFileName( nRace, nSex, pMsg->nAppearanceItemCode[nDecoWearType], pMsg->nAppearanceItemCode[nDecoWearType] );
weardata.strDecoTextureName = GetItemDB().GetAdditionalTexture( pMsg->nAppearanceItemCode[nDecoWearType] );
weardata.nDecoItemClass = GetItemDB().GetClassID( pMsg->nAppearanceItemCode[nDecoWearType] );
}
else
{
weardata.strDecoFileName = GetItemDB().GetFileName( nRace, nSex, pMsg->nItemCode[nDecoWearType], pMsg->nItemLevel[nDecoWearType] );
weardata.strDecoTextureName = GetItemDB().GetAdditionalTexture( pMsg->nItemCode[nDecoWearType] );
weardata.nDecoItemClass = GetItemDB().GetClassID( pMsg->nItemCode[nDecoWearType] );
}
weardata.strDecoFileName += ".nx3";
weardata.nDecoItemCode = pMsg->nItemCode[nDecoWearType];
weardata.bAttachDecoItem = GetItemDB().GetDecoModelChange( pMsg->nItemCode[nDecoWearType] );
weardata.bWithDecoItem = true;
weardata.nAppearanceItemCode = pMsg->nAppearanceItemCode[nDecoWearType];
pPlayer->SetItemCodeLevel( nDecoWearType, pMsg->nItemCode[nDecoWearType], pMsg->nItemLevel[nDecoWearType] );
}
}
weardata.nWearType = j;
pPlayer->AddThreadItemWear( weardata );
}
ItemBase::ItemWearType itemwear = ItemBase::WEAR_BACKPACK;
if( pMsg->nItemCode[itemwear] != 0 )
{
SGameAvatarEx::WEAR_DATA weardata;
if( pMsg->nAppearanceItemCode[itemwear] != 0 )
{
weardata.strDecoFileName = GetItemDB().GetFileName( nRace, nSex, pMsg->nAppearanceItemCode[itemwear], pMsg->nAppearanceItemCode[itemwear] );
weardata.strDecoTextureName = GetItemDB().GetAdditionalTexture( pMsg->nAppearanceItemCode[itemwear] );
weardata.nDecoItemClass = GetItemDB().GetClassID( pMsg->nAppearanceItemCode[itemwear] );
}
else
{
weardata.strDecoFileName = GetItemDB().GetFileName( nRace, nSex, pMsg->nItemCode[itemwear], pMsg->nItemLevel[itemwear] );
weardata.strDecoTextureName = GetItemDB().GetAdditionalTexture( pMsg->nItemCode[itemwear] );
weardata.nDecoItemClass = GetItemDB().GetClassID( pMsg->nItemCode[itemwear] );
}
weardata.strDecoFileName += ".nx3";
weardata.nItemCode = pMsg->nItemCode[itemwear];
weardata.nItemLevel = pMsg->nItemLevel[itemwear];
weardata.nItemEnhanceLevel = pMsg->nItemEnhance[itemwear];
weardata.cElementalEffect = pMsg->elemental_effect_type[itemwear];
weardata.nWearType = itemwear;
//어깨 장식이 출력되지 않아 수정함 2009.04.13 sfreer
weardata.nDecoItemCode = pMsg->nItemCode[itemwear];
weardata.bAttachDecoItem = GetItemDB().GetDecoModelChange( pMsg->nItemCode[itemwear] );
weardata.bWithDecoItem = true;
weardata.nAppearanceItemCode = pMsg->nAppearanceItemCode[itemwear];
pPlayer->SetItemCodeLevel( itemwear, pMsg->nItemCode[itemwear], pMsg->nItemLevel[itemwear] );
pPlayer->AddThreadItemWear( weardata );
}
itemwear = ItemBase::WEAR_DECO_SHOULDER;
if (pMsg->nItemCode[itemwear] != 0)
{
SGameAvatarEx::WEAR_DATA weardata;
if (pMsg->nAppearanceItemCode[itemwear] != 0)
{
weardata.strDecoFileName = GetItemDB().GetFileName(nRace, nSex, pMsg->nAppearanceItemCode[itemwear], pMsg->nAppearanceItemCode[itemwear]);
weardata.strDecoTextureName = GetItemDB().GetAdditionalTexture(pMsg->nAppearanceItemCode[itemwear]);
weardata.nDecoItemClass = GetItemDB().GetClassID(pMsg->nAppearanceItemCode[itemwear]);
}
else
{
weardata.strDecoFileName = GetItemDB().GetFileName(nRace, nSex, pMsg->nItemCode[itemwear], pMsg->nItemLevel[itemwear]);
weardata.strDecoTextureName = GetItemDB().GetAdditionalTexture(pMsg->nItemCode[itemwear]);
weardata.nDecoItemClass = GetItemDB().GetClassID(pMsg->nItemCode[itemwear]);
}
weardata.strDecoFileName += ".nx3";
weardata.nItemCode = pMsg->nItemCode[itemwear];
weardata.nItemLevel = pMsg->nItemLevel[itemwear];
weardata.nItemEnhanceLevel = pMsg->nItemEnhance[itemwear];
weardata.cElementalEffect = pMsg->elemental_effect_type[itemwear];
weardata.nWearType = itemwear;
//어깨 장식이 출력되지 않아 수정함 2009.04.13 sfreer
weardata.nDecoItemCode = pMsg->nItemCode[itemwear];
weardata.bAttachDecoItem = GetItemDB().GetDecoModelChange(pMsg->nItemCode[itemwear]);
weardata.bWithDecoItem = true;
weardata.nAppearanceItemCode = pMsg->nAppearanceItemCode[itemwear];
pPlayer->SetItemCodeLevel(itemwear, pMsg->nItemCode[itemwear], pMsg->nItemLevel[itemwear]);
pPlayer->AddThreadItemWear(weardata);
}
//itemwear = ItemBase::WEAR_DECO_HAIR;
//if( pMsg->nItemCode[itemwear] != 0 )
//{
// SGameAvatarEx::WEAR_DATA weardata;
// weardata.strDecoFileName = GetItemDB().GetFileName( nRace, nSex, pMsg->nItemCode[itemwear], pMsg->nItemLevel[itemwear] );
// weardata.strDecoFileName += ".nx3";
//
// weardata.nItemClass = GetItemDB().GetClassID( pMsg->nItemCode[itemwear] );
// weardata.nItemCode = pMsg->nItemCode[itemwear];
// weardata.nItemLevel = pMsg->nItemLevel[itemwear];
// weardata.nItemEnhanceLevel = pMsg->nItemEnhance[itemwear];
// weardata.cElementalEffect = pMsg->elemental_effect_type[itemwear];
// weardata.nWearType = itemwear;
//
// weardata.nDecoItemCode = pMsg->nItemCode[itemwear];
// weardata.bAttachDecoItem = GetItemDB().GetDecoModelChange( pMsg->nItemCode[itemwear] );
// weardata.bWithDecoItem = true;
//
// pPlayer->SetItemCodeLevel( itemwear, pMsg->nItemCode[itemwear], pMsg->nItemLevel[itemwear] );
// pPlayer->AddThreadItemWear( weardata );
//}
}
void SCommandSystem::OnMsgBoothClosed( struct SMSG_BOOTH_CLOSED * pMsg )
{
SGameAvatarEx * pAvatar = static_cast< SGameAvatarEx * >( GetObject( pMsg->hTarget ) );
if( !pAvatar ) return;
static_cast< SGameOtherPlayer* >( pAvatar )->SetBoothName( "" );
}
void SCommandSystem::OnMsgBoothName ( struct SMSG_BOOTH_NAME* pMsg )
{
for( size_t idx = 0; idx < pMsg->vBoothName.size(); ++idx )
{
SGameAvatarEx * pAvatar = static_cast< SGameAvatarEx * >( GetObject( pMsg->vBoothName[idx].handle ) );
if( !pAvatar ) continue;
static_cast< SGameOtherPlayer* >( pAvatar )->SetBoothName( pMsg->vBoothName[idx].name );
}
}
void SCommandSystem::OnMsgProperty ( SMSG_PROPERTY* pGameMsg )
{
SGameAvatarEx * pAvatar = (SGameAvatarEx *)GetObject(pGameMsg->handle);
if( !pAvatar ) return;
if( pGameMsg->nPropertyType == SMSG_PROPERTY::PROPERTY_JOB_LEVEL )
{
if( pAvatar->SetJobLevel( atoi(pGameMsg->strValue.c_str()) ) )
{
AR_HANDLE handle = pAvatar->GetArID();
FX_DATA fx_data;
fx_data.attack = handle;
fx_data.owner = handle;
fx_data.target = handle;
fx_data.fPlayRate = 1.f;
fx_data.nEffPos = EFFECT_POS_BOTTOM;
fx_data.nPlayID = 1;
fx_data.nFX_ID = 8002;
m_pGame->AddEffect( &fx_data );
}
}
else if( pGameMsg->nPropertyType == SMSG_PROPERTY::PROPERTY_LEVEL )
{
if( pAvatar->SetLevel( atoi(pGameMsg->strValue.c_str()) ) )
{
AR_HANDLE handle = pAvatar->GetArID();
FX_DATA fx_data;
fx_data.attack = handle;
fx_data.owner = handle;
fx_data.target = handle;
fx_data.fPlayRate = 1.f;
fx_data.nEffPos = EFFECT_POS_BOTTOM;
fx_data.nPlayID = 1;
fx_data.nFX_ID = 8001;
m_pGame->AddEffect( &fx_data );
}
}
else if( pGameMsg->nPropertyType == SMSG_PROPERTY::PROPERTY_SEX )
{
pAvatar->SetSex( _ttoi( pGameMsg->strValue.c_str() ) );
pAvatar->SetReloadWearListFileName( true );
pAvatar->PendLoading();
}
else if( pGameMsg->nPropertyType == SMSG_PROPERTY::PROPERTY_HP )
{
pAvatar->ProcMsgAtStatic( pGameMsg );
}
/// 2011.07.11 - prodongi
else if (pGameMsg->nPropertyType == SMSG_PROPERTY::PROPERTY_JOB)
{
int oldJobId = pAvatar->GetJobID();
int newJobId = atoi(pGameMsg->strValue.c_str());
if (oldJobId != newJobId)
{
pAvatar->SetJobID(newJobId);
// 2011. 7. 12 - marine
if((pAvatar->IsMasterClass(newJobId)) && (oldJobId != 0))
{
AR_HANDLE handle = pAvatar->GetArID();
FX_DATA fx_data;
fx_data.attack = handle;
fx_data.owner = handle;
fx_data.target = handle;
fx_data.fPlayRate = 1.f;
fx_data.nEffPos = EFFECT_POS_BOTTOM;
fx_data.nPlayID = 1;
fx_data.nFX_ID = 8005;
m_pGame->AddEffect( &fx_data );
}
}
}
else if(pGameMsg->nPropertyType == SMSG_PROPERTY::PROPERTY_RACE)
{
int type = atoi(pGameMsg->strValue.c_str());
if( pAvatar->GetRace() == 0 )
return;
if( pAvatar->GetRace() != type)
{
pAvatar->SetRace(type);
pAvatar->SetReloadWearListFileName( true );
pAvatar->PendLoading();
}
}
}
void SCommandSystem::OnMsgHPMP( SMSG_HPMP* pGameMsg )
{
/* SGameAvatarEx * pObject = (SGameAvatarEx*)GetObject( pGameMsg->handle );
if( pObject )
{
pObject->ProcMsgAtStatic( pGameMsg );
}*/
}
const int PRELOAD_LEVEL_VALUE = 95;
void SCommandSystem::OnMsgExpUpdate ( SMSG_EXP_UPDATE* pMsg )
{
SGameAvatarEx * pObject = (SGameAvatarEx*)GetObject( pMsg->handle );
if( pObject )
{
pObject->ProcMsgAtStatic( pMsg );
if( pObject->GetPercentEXP() > PRELOAD_LEVEL_VALUE )
{
SGamePreLoad preload;
preload.RequestThreadLoading( 8001 );
}
}
}
void SCommandSystem::OnMsgState ( SMSG_STATE* pGameMsg )
{
// if( pGameMsg->state_code == 9004 )
// { //시크루드 패스는 처리 안함.
// return;
// }
SGameOption& gameoption = GetGameOption();
bool bNewStateEffect = true;
SGameAvatarEx * pObject = (SGameAvatarEx*)GetObject( pGameMsg->handle );
if( pObject )
{
// _oprint( "상태 이상 걸렸구나~\n" );
//상태 이상 추가
if( pGameMsg->state_level )
{
int nPos = 0;
SStateSlot* pOldState = pObject->GetOldStateInfo(pGameMsg, nPos);
SStateSlot* pOldCashState = pObject->GetOldCashStateInfo(pGameMsg, nPos);
if( pOldState )
{
if( pOldState->GetStateLevel() == pGameMsg->state_level ) bNewStateEffect = false;
}
if( pOldCashState )
{
if( pOldCashState->GetStateLevel() == pGameMsg->state_level ) bNewStateEffect = false;
}
pGameMsg->isNewState = bNewStateEffect; /// 2012.02.01 - prodongi
if( bNewStateEffect )
{
//기존 상태이상 이펙트는 삭제
m_pGame->DelStateEffect( pGameMsg );
//상태 이상은 따라다님.
bool bAdd = false;
unsigned char Type;
int handleType = m_pGame->IsFriend(pGameMsg->handle, Type);
if( (handleType==SUIDisplayInfo::LocalPlayer || handleType==SUIDisplayInfo::Creature) && gameoption.IsStatePlayerEftRend() )
bAdd = true;
else if( (handleType==SUIDisplayInfo::Party || handleType==SUIDisplayInfo::PartyCreature) && gameoption.IsStatePartyEftRend() )
bAdd = true;
else
{
if( gameoption.IsStateEnemyEftRend() )
bAdd = true;
}
if( pObject->GetStatus() & TS_ENTER::CreatureInfo::FLAG_INVISIBLE ||
pObject->GetStateFlag() & SGameAvatarEx::FLAG_STATE_HIDING )
{
bAdd = false; //Invisible모드이거나 은신모드일경우 이펙트를 보여주지 않는다
}
if( bAdd ) m_pGame->AddStateEffect( pGameMsg );
}
else
{
m_pGame->UpdateStateEffect( pGameMsg );
}
}
//상태 이상 삭제 한다.
else if( pGameMsg->state_level == 0 )
{
m_pGame->DelStateEffect( pGameMsg );
}
pObject->ProcMsgAtStatic( pGameMsg );
}
if( pObject == NULL ) return;
StateInfoEx* pStateInfo = GetTenacityDB().GetTenacityData( pGameMsg->state_code );
if( pStateInfo )
{
switch( pStateInfo->effect_type )
{
case STATE_TYPE::STATE_RIDING:
{
if( pObject->GetObjType() == TS_ENTER::GAME_PLAYER )
{
if( pGameMsg->state_level > 0 && bNewStateEffect )
{
OnUnMount( pStateInfo, pObject, true );
OnMount( pStateInfo, pObject );
}
else if( pGameMsg->state_level == 0 )
{
OnUnMount( pStateInfo, pObject );
}
}
}
break;
case STATE_TYPE::STATE_MUTATION_B:
{
if( pGameMsg->state_level > 0 )
{
SIMSG_UI_CHANGE_DISPLAY_NAME disname( pObject->GetArID(), pGameMsg->state_string_value.c_str(), false );
m_pGame->SendGameInterfaceMsg( &disname );
}
else if( pGameMsg->state_level == 0 )
{
SIMSG_UI_CHANGE_DISPLAY_NAME disname( pObject->GetArID(), NULL, true );
m_pGame->SendGameInterfaceMsg( &disname );
}
}
break;
case STATE_TYPE::STATE_DETECT_HIDING:
{
if( pGameMsg->state_level == 0 ) //상태이상 종료
{
SGameAvatarEx* pGameObject = NULL;
KSortVector< class SGameAvatarEx* >::iterator it = m_svPlayerObject.begin();
while ( it != m_svPlayerObject.end() )
{
pGameObject = (*it);
if( !pGameObject->IsLocalPlayer() && pGameObject->GetObjType() == TS_ENTER::GAME_PLAYER )
{
if( pGameObject->GetStateFlag() & SGameAvatarEx::FLAG_STATE_HIDING )
pGameObject->SetHidingVisiblity( 0.0f );
}
++it;
}
}
}
break;
}
}
}
void SCommandSystem::OnMsgInventory ( SMSG_ITEM_INVEN* pMsg )
{
//SGameAvatarEx* pPlayer = GetLocalPlayer(); //플레이어 핸들이 안넘어 온다 임시로 로컬 플에이어만 적용
//if( pPlayer == NULL ) return;
//bool bUpdate = false;
//SGameAvatarEx::WEAR_DATA weardata;
//weardata.strFileName = GetItemDB().GetFileName( pPlayer->GetRace(), pPlayer->GetSex(), pMsg->pItemInfo->Code, pMsg->pItemInfo->level );
//weardata.strFileName += ".nx3";
//std::string strWeaponName = weardata.strFileName;
//if( pMsg->pItemInfo->wear_position == ItemBase::WEAR_LEFTHAND )
//{
// strWeaponName.replace( strWeaponName.size() - 4, 1, "_L." );
// bUpdate = true;
//}
//else if( pMsg->pItemInfo->wear_position == ItemBase::WEAR_RIGHTHAND )
//{
// bUpdate = true;
//}
//if( bUpdate )
//{
// weardata.nItemClass = GetItemDB().GetClassID( pMsg->pItemInfo->Code );
// weardata.nWearType = pMsg->pItemInfo->wear_position;
// weardata.nItemCode = pMsg->pItemInfo->Code;
// weardata.nItemLevel = pMsg->pItemInfo->level;
// weardata.nItemEnhanceLevel = pMsg->pItemInfo->enhance;
// std::string strEffectPosName = "wfx_" + strWeaponName;
// pPlayer->SetWeaponInfo( pPlayer->GetSeqForm() , weardata, strEffectPosName.c_str() );
// pPlayer->RefreshEffectPos();
//}
}
void SCommandSystem::OnMsgItemUse()
{
}
void SCommandSystem::OnMsgItemDrop()
{
}
void SCommandSystem::OnMsgTakeItemResult( struct SMSG_TAKE_ITEM_RESULT* pMsg )
{
SGameAvatarEx* pItem = (SGameAvatarEx *)GetObject( pMsg->item_handle );
if( pItem && pItem->GetObjType() == TS_ENTER::GAME_ITEM )
{
SGameAvatarEx * pPlayer = (SGameAvatarEx *)GetObject( pMsg->item_taker );
if( pPlayer )
{
if( !pPlayer->IsMountMode() ) //탑승된 상태면 줍기 모션은 생략
{
SWorkPickUp* pPickUpWork = new SWorkPickUp( pPlayer, pItem );
pPlayer->AllWorkEnd();
pPlayer->AddWork( pPickUpWork );
}
}
SPetMgr* petMgr = static_cast< SPetMgr* >( GameUIMgrInstance.GetUIMgr( SGameUIInstance::PET_MGR ) );
SGameLocalPet* petAvatar = static_cast< SGameLocalPet* >( petMgr->GetSummonPetData().pet_avatar );
if (petAvatar != NULL)
{
petAvatar->DeleteItemFromIgnoreQueue(pMsg->item_handle);
} // 펫 자동줍기가 설정되어있을때 한번 줍기를 시도한 아이템은 10분간 다시 안 줍는데, 만일 줍는데 성공(인벤으로 들어옴)하면 안 주울 아이템 리스트에서 지워버려도 된다.
}
}
void SCommandSystem::OnMsgLevelUpdate ( SMSG_LEVEL_UPDATE* pMsg )
{
//Level Update
SGameAvatarEx * pAvatar = (SGameAvatarEx *)GetObject(pMsg->handle);
if( pAvatar )
{
if( pAvatar->GetLevel() < pMsg->level && pAvatar->GetLevel() != 0 )
{
AR_HANDLE handle = pAvatar->GetArID();
FX_DATA fx_data;
fx_data.attack = handle;
fx_data.owner = handle;
fx_data.target = handle;
fx_data.fPlayRate = 1.f;
fx_data.nEffPos = EFFECT_POS_BOTTOM;
fx_data.nPlayID = 1;
fx_data.nFX_ID = 8001;
m_pGame->AddEffect( &fx_data );
SGameAvatarEx* pLocalPlayer = GetLocalPlayer();
if( pLocalPlayer )
{
if( pAvatar->GetArID() == pLocalPlayer->GetArID() )
m_pGame->SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_LV_UP ) );
}
}
pAvatar->SetLevel( pMsg->level );
}
}
void SCommandSystem::OnMsgEmotion( SMSG_EMOTION* pMsg )
{
PlayerEmotion( pMsg->handle, pMsg->emotion );
}
void SCommandSystem::OnMsgAddOtherEffect( SGameMessage* pGameMsg )
{
if( m_pOtherEffecMgr == NULL ) return;
switch( pGameMsg->nType )
{
case MSG_GET_CHAOS:
{
SMSG_GET_CHAOS* pChaos = static_cast<SMSG_GET_CHAOS*>(pGameMsg);
SGameAvatarEx* pPlayer = GetLocalPlayer();
if( pPlayer )
{
if( pPlayer->GetArID() == pChaos->hPlayer )
{
// sonador 3.10.2 PC 방 혜택 관련 라크 획득 시스템 메시지 변경
if( pChaos->nBonusType == SMSG_GET_CHAOS::CHAOS_BONUS_PCBANG ||
pChaos->nBonusType == SMSG_GET_CHAOS::CHAOS_BONUS_PREMIUM_PCBANG )
((SGameLocalPlayer*)pPlayer)->SetLakSize( pChaos->nChaos, pChaos->nBonus, pChaos->nBonusPercent, pChaos->nBonusType );
else
((SGameLocalPlayer*)pPlayer)->SetLakSize( pChaos->nChaos, -1, 0, SMSG_GET_CHAOS::CHAOS_BONUS_NONE );
}
}
m_pOtherEffecMgr->AddChaosEffect( pChaos );
break;
}
}
}
int SCommandSystem::OnAddOtherEffect( int nFxID, struct OtherFxData* fxdata )
{
if( m_pOtherEffecMgr == NULL ) return 0;
switch( nFxID )
{
case SGameOtherEffectMng::FX_CREATURE_EVOLUTION:
{
return m_pOtherEffecMgr->AddCreatureEvolutionEffect( nFxID, fxdata );
}
case SGameOtherEffectMng::FX_CAST_SUMMONING_CREATURE:
{
return m_pOtherEffecMgr->AddCastSummoningCreatureEffect( nFxID, fxdata );
}
case SGameOtherEffectMng::FX_SUMMONING_CREATURE:
{
return m_pOtherEffecMgr->AddSummoningCreatureEffect( nFxID, fxdata );
}
case SGameOtherEffectMng::FX_UN_SUMMONING_CREATURE:
{
return m_pOtherEffecMgr->AddUnSummoningCreatureEffect( nFxID, fxdata );
}
case SGameOtherEffectMng::FX_MONSTER_TAMING:
{
return m_pOtherEffecMgr->AddMonsterTamingEffect( nFxID, fxdata );
}
}
return 0;
}
void SCommandSystem::SetNextStepOtherEffect( int nFxID )
{
if( m_pOtherEffecMgr )
m_pOtherEffecMgr->SetNextStepOtherEffect( nFxID );
}
void SCommandSystem::SetNextStepOtherEffect( AR_HANDLE hHandle, int nFxType, bool bCheckTargetHandle )
{
if( m_pOtherEffecMgr )
m_pOtherEffecMgr->SetNextStepOtherEffect( hHandle, nFxType, bCheckTargetHandle );
}
void SCommandSystem::EndOtherEffect( int nFxID )
{
if( m_pOtherEffecMgr ) m_pOtherEffecMgr->EndOtherEffect( nFxID );
}
void SCommandSystem::EndOtherEffect( AR_HANDLE hHandle, int nFxType, bool bCheckTargetHandle )
{
if( m_pOtherEffecMgr ) m_pOtherEffecMgr->EndOtherEffect( hHandle, nFxType, bCheckTargetHandle );
}
void SCommandSystem::SetCircleShadowEnable(bool bEnable)
{
m_bCircleShadowEnable = bEnable;
if(m_bCircleShadowEnable)
{
for_each(m_svObject.begin(), m_svObject.end(), std::mem_fun<void>(&SGameAvatarEx::ActivateCircleShadow) );
}
else
{
for_each(m_svObject.begin(), m_svObject.end(), std::mem_fun<void>(&SGameAvatarEx::DeActivateCircleShadow) );
}
}
void SCommandSystem::SetEffectSpeed( float fSpeed )
{
if( m_pActionMgr ) m_pActionMgr->SetSpeed( fSpeed );
}
void SCommandSystem::OnMsgAddForceSphere( SMSG_ENERGY* pMsg )
{
SGameAvatarEx* pPlayer = (SGameAvatarEx*)GetObject( pMsg->handle );
if( pPlayer )
{
pPlayer->OnMsgForceSphere( pMsg->energy );
pPlayer->m_nEnergy = pMsg->energy;
}
}
void SCommandSystem::OnTamingInfo( SMSG_TAMING_INFO* pMsg )
{
if( pMsg->mode == 0 ) //테이밍 걸었다면 이펙트 생김
OnAddOtherEffect( SGameOtherEffectMng::FX_MONSTER_TAMING, &OtherFxData( 0, pMsg->target_handle, 0 ) );
else if( pMsg->mode == 1 ) //테이밍 초기화 됐다면 이펙트 삭제
EndOtherEffect( pMsg->target_handle, SGameOtherEffectMng::FX_MONSTER_TAMING, true );
else if( pMsg->mode == 2 || pMsg->mode == 3 ) //테이밍 성공 됐다면 마지막 이펙트 플레이
{
FX_DATA fx_data;
fx_data.attack = pMsg->target_handle;
fx_data.owner = pMsg->target_handle;
fx_data.target = pMsg->target_handle;
fx_data.fPlayRate = 1.f;
fx_data.nEffPos = EFFECT_POS_TOP;
fx_data.nPlayID = 1;
if( pMsg->mode == 2 ) //테이밍 성공
{
fx_data.nFX_ID = 18018;
}
else //테이밍 실패
{
fx_data.nFX_ID = 18019;
}
m_pGame->AddEffect( &fx_data );
EndOtherEffect( pMsg->target_handle, SGameOtherEffectMng::FX_MONSTER_TAMING, true );
// SetNextStepOtherEffect( pMsg->target_handle, SGameOtherEffectMng::FX_MONSTER_TAMING, true );
}
/* else if( pMsg->mode == 3 ) //테이밍 실패 했다면 마지막 이펙트 플레이
{
SetNextStepOtherEffect( pMsg->target_handle, SGameOtherEffectMng::FX_MONSTER_TAMING, true );
}*/
/*
SGameAvatarEx* pPlayer = GetLocalPlayer();
if( !pPlayer ) return;
if( pMsg->tamer_handle == pPlayer->GetArID() )
{
if( pMsg->mode == 0 ) //테이밍 걸었음
{
int nCode = GetMonsterNameID( pMsg->target_handle );
if( nCode != -1 )
m_pGame->SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_CREATURE_TAME_SUCCESS, nCode ) );
}
else if( pMsg->mode == 1 )
m_pGame->AddChatMessage( "테이밍 초기화 됨" );
테이밍 성공 실패 메세지를 파티원들에게 뿌려주기로 설정이 바뀌어서 서버에서 파티쳇으로 방송하기로 결정
else if( pMsg->mode == 2 ) //테이밍 성공
{
int nCode = GetMonsterNameID( pMsg->target_handle );
if( nCode != -1 )
m_pGame->SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_CREATURE_TAME_SUCCESS_BONUS, nCode ) );
}
else if( pMsg->mode == 3 ) //테이밍 실패
{
int nCode = GetMonsterNameID( pMsg->target_handle );
if( nCode != -1 )
m_pGame->SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_CREATURE_TAME_DISAPPEAR, nCode ) );
}
}
*/
/// 2011.01.20 - prodongi
if (SMSG_TAMING_INFO::START == pMsg->mode)
{
setIsTaming(true);
}
else
{
setIsTaming(false);
}
}
int SCommandSystem::GetCretureNameID( AR_HANDLE handle )
{
SGameAvatarEx* pMonster = (SGameAvatarEx*)GetObject( handle );
if( pMonster )
return pMonster->GetContentID();
return -1;
}
int SCommandSystem::GetMonsterNameID( AR_HANDLE handle )
{
SGameAvatarEx* pMonster = (SGameAvatarEx*)GetObject( handle );
if( pMonster )
return pMonster->GetContentID();
return -1;
}
void SCommandSystem::SetSkyType( DWORD dwSkyType )
{
BOOL bShadowRender = FALSE;
if( dwSkyType == 0 || dwSkyType == 2 ) //1은 하늘 도시임
bShadowRender = TRUE;
SGameAvatarEx* pGameObject = NULL;
KSortVector< class SGameAvatarEx* >::iterator it = m_svObject.begin();
while ( it != m_svObject.end() )
{
pGameObject = (*it); ++it;
if ( pGameObject != NULL )
{
pGameObject->SetShadowRenderFlag( bShadowRender );
}
}
}
//===================================================================================================
//Cheating 관련
//Warp
//다른 방법을 연구 해 보자...
void SCommandSystem::OnMsgWarp( SCMSG_WARP* pMsg )
{
//이동할 넘을 찾은 다음에~
//이동 시키자~
//맵 로딩과, Leave, Enter 는 어떻게 처리 하나?
SGameAvatarEx* pAvatar = GetLocalPlayer();
if( pAvatar )
{
SWorkWarp * pWarpWork = new SWorkWarp( pAvatar, pMsg );
pAvatar->AllWorkEnd();
pAvatar->AddWork( pWarpWork );
pAvatar->ClearPendingNextState();
pAvatar->InputFreezing(); //워프가 완료 되기 전까지 입력 안 되도록 설정
pAvatar->SetIng( false );
//마운트 모드이면 크리처도 같은 위치로 워프 시킨다
if( pAvatar->IsMountMode() )
{
SGameAvatarEx* pCreature = (SGameAvatarEx*)GetObject( pAvatar->GetCreatureMountHandle() );
if( pCreature == NULL ) pCreature = GetTransportCreatureObject( pAvatar->GetCreatureMountHandle() );
if( pCreature )
{
pCreature->SetArObjectPos( pMsg->x, pMsg->y, pMsg->z, pMsg->layer );
float fHeight = 0.f;
WORD wTile=0;
pAvatar->GetHeight(pMsg->x,pMsg->y,fHeight,wTile);
pCreature->SetPosition( K3DVector( pMsg->x, pMsg->y, fHeight ) );
}
}
}
}
//===================================================================================================
//Target 관련
SGameAvatarEx * SCommandSystem::GetNextTarget( float fMaxLen, bool bIsResetTargetList )
{
if( bIsResetTargetList ) //타겟 리스트를 새로 작성해야 한다면
m_pTargetMgr->ClearTargetList();
K3DVector cullPosition;
if( GetLocalPlayer() )
{
cullPosition = *GetLocalPlayer()->GetPosition();
}
if( !m_pTargetMgr->IsTarget() )
{
K3DVector mypos;
float fLen = 0.f;
SGameAvatarEx* pGameObject = NULL;
KSortVector< class SGameAvatarEx* >::iterator it = m_svObject.begin();
while ( it != m_svObject.end() )
{
pGameObject = (*it); ++it;
if( pGameObject == NULL ) continue;
if( pGameObject->IsLocalPlayer() || pGameObject->IsLocalCreature() ) continue;
if( pGameObject->GetObjType() == TS_ENTER::GAME_MOB ||
pGameObject->GetObjType() == TS_ENTER::GAME_PLAYER ||
pGameObject->GetObjType() == TS_ENTER::GAME_SUMMON )
{
if( pGameObject->IsActivated() && pGameObject->GetHP() != 0 && pGameObject->IsRender() )
{
//탈것 이용시 z축 값에 문제가 있어서 일단 임시 수정 2009.08.24 sfreer
K3DVector local = cullPosition;
K3DVector object = *pGameObject->GetPosition();
local.z = 0;
object.z = 0;
float fLen = GetDistance( local, object);
if( fLen < fMaxLen )
{
//자동 타겟에 넣는다. 거리는 임의이기 때문에 자동타겟 거리는 별도로 나중에 수정 하자.
if( pGameObject->GetObjType() != TS_ENTER::GAME_MOB )
{
if( m_pGame->IsAttack( pGameObject ) == false )
pGameObject = NULL;
}
if( pGameObject )
m_pTargetMgr->AddTarget( pGameObject );
}
}
}
}
}
if( m_pTargetMgr->IsTarget() )
{
//LocalPlayer 중심으로 소팅
m_pTargetMgr->SortTarget( &cullPosition );
}
return m_pTargetMgr->GetNextTarget();
};
void SCommandSystem::OnMsgItemResult( SMSG_USE_ITEM_RESULT* pMsg )
{
SGameAvatarEx * pAvatar = NULL;
if( pMsg->target_handle == 0 )
{
pAvatar = GetLocalPlayer();
if( pAvatar )
{
pAvatar->OnNetInput( pMsg );
}
}
else
{
pAvatar = (SGameAvatarEx *)GetObject( pMsg->target_handle );
if( pAvatar )
{
pAvatar->OnNetInput( pMsg );
}
}
}
void SCommandSystem::MoveImpossibleMsg()
{
m_pGame->SendGameInterfaceMsg( &SIMSG_UI_DISPLAY_SYS_MSG( SYS_MSG_MOVE_IMPOSSIBLE ) );
}
void SCommandSystem::DeleteRenderBooth()
{
SGameAvatarEx* pGameObject = NULL;
KSortVector< class SGameAvatarEx* >::iterator it = m_svPlayerObject.begin();
while ( it != m_svPlayerObject.end() )
{
pGameObject = (*it);
if( !pGameObject->IsLocalPlayer() && pGameObject->GetObjType() == TS_ENTER::GAME_PLAYER )
{
((SGameOtherPlayer*)pGameObject)->DeleteRenderBooth();
}
++it;
}
}
void SCommandSystem::refreshWinkAllPlayerObj()
{
KSortVector< class SGameAvatarEx* >::iterator it = m_svPlayerObject.begin();
while ( it != m_svPlayerObject.end() )
{
(*it)->refreshWinkByOption();
++it;
}
}
void SCommandSystem::getOtherObjectList(std::vector<SGameAvatarEx*>& objList)
{
objList.clear();
objList.assign(m_svOtherObject.begin(), m_svOtherObject.end());
}
void SCommandSystem::addCustomBlock(SGameFieldQuestProp* prop)
{
/// 2012.06.26 이동 불가 프랍일 경우에 블럭 정보 추가 - prodongi
FieldPropResource* res = GetFieldPropResourceDB().GetFieldPropResource(prop->GetQuestPropDBID());
/// 이동 제한, 타입을 따로 정의해 놓은게 없다.. 정의가 필요할 것 같긴 한데,,우선 이렇게 함
if (res && 50 == res->type)
{
CTerrainMapEngine* mapEngine = m_pGame->getTerrainMapEngine();
if (mapEngine)
{
int blockLine[4];
prop->getBlockLine(blockLine);
mapEngine->addCustomBlock(prop->GetArID(), blockLine);
}
}
}
void SCommandSystem::delCustomBlock(AR_HANDLE handle)
{
SGameAvatarEx* avatar = (SGameAvatarEx*)m_pGame->GetGameObject(handle);
if (!avatar)
return ;
/// 이동 블럭 프랍일 경우에는 지형 엔진에서 해당 내용을 삭제해 줘야 한다
if (TS_ENTER::GAME_FIELD_PROP == avatar->GetObjType())
{
SGameFieldQuestProp* prop = dynamicCast<SGameFieldQuestProp*>(avatar);
if (prop)
{
FieldPropResource* res = GetFieldPropResourceDB().GetFieldPropResource(prop->GetQuestPropDBID());
if (res && 50 == res->type)
{
CTerrainMapEngine* mapEngine = m_pGame->getTerrainMapEngine();
if (mapEngine)
{
mapEngine->delCustomBlock(prop->GetArID());
}
}
}
}
}
void SCommandSystem::OnMsgKMove(SMSG_KMOVE* pMsg)
{
{
m_pArObject->onMultiMove( pMsg->handle, ArPosition(pMsg->pos_target.x,pMsg->pos_target.y, pMsg->pos_target.z), pMsg->m_vecMoveInfo, pMsg->speed, pMsg->start_time );
}
SGameAvatarEx * pAvatar = NULL;
if( m_hashObject.lookup( pMsg->handle, pAvatar ) )
{
if( pAvatar->IsPendLoading() )
ActivatePendLoadingListByMove( pAvatar );
pAvatar->OnNetInput( pMsg );
//플레이어냐?
if( pAvatar->GetObjType() == TS_ENTER::GAME_PLAYER )
{
//로컬 플레이어 이동 시 타겟 리스트 삭제 한다.
if( pAvatar->IsLocalPlayer() )
m_pTargetMgr->ClearTargetList();
// if( pAvatar->IsMountMode() )
{
if( pAvatar->GetCreatureMountHandle() )
{
m_pArObject->onMultiMove( pAvatar->GetCreatureMountHandle(), ArPosition(pMsg->pos_target.x,pMsg->pos_target.y, pMsg->pos_target.z), pMsg->m_vecMoveInfo, pMsg->speed, pMsg->start_time );
SGameAvatarEx* pCreature = pAvatar->GetRiderCreatureObject();
if( pCreature )
{
pCreature->OnNetInput( pMsg );
}
}
}
}
return;
}
{
//Enter 를 강제로 해달라~
TS_CS_QUERY query_msg;
query_msg.handle = pMsg->handle;
m_pGame->SendMsg( &query_msg );
}
}
bool SCommandSystem::IsTarget()
{
return m_pTargetMgr->IsTarget();
}