#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(pGameMsg) ); break; } case MSG_CHATTING : { OnMsgChatting ( static_cast(pGameMsg) ); break; } case MSG_MOVE : { OnMsgMove ( static_cast(pGameMsg) ); break; //이동 } case MSG_KMOVE: { OnMsgKMove(dynamic_cast(pGameMsg)); break; } case MSG_REGION_ACK : { OnMsgRegionAck ( static_cast(pGameMsg) ); break; //영역 요청 } case MSG_LOGIN : { OnMsgLogin ( static_cast(pGameMsg) ); break; //Login (Local Player) } case MSG_HAIR_INFO: { OnMsgHairInfo ( static_cast(pGameMsg) ); break; //Login (Local Player) } // 2010.05.19 - prodongi case MSG_HIDE_EQUIP_INFO: { OnMsgHideEquipInfo(static_cast(pGameMsg)); break; } // 꾸미기아이템 보임숨김 개별 정보. case MSG_HIDE_EQUIP_FLAG: OnMsgHideEquipFlag(static_cast(pGameMsg)); break; case MSG_LEAVE : { OnMsgLeave ( static_cast(pGameMsg) ); break; //Leave (Other Player) } case MSG_ENTER : { OnMsgEnter ( static_cast(pGameMsg) ); break; //Enter (Other Player) } case MSG_ATTACK : { OnMsgAttack ( static_cast(pGameMsg) ); break; //공격 } case MSG_ATTACK_DOUBLE : { OnMsgAttackDouble ( static_cast(pGameMsg) ); break; } case MSG_CANT_ATTACK : { SMSG_CANT_ATTACK* pCantMsg = static_cast(pGameMsg); SGameAvatarEx * pAvatar = NULL; if( (pAvatar = (SGameAvatarEx*)GetObject( pCantMsg->attacker_handle )) != NULL ) pAvatar->OnNetInput( pGameMsg ); break; } case MSG_UNSUMMON : { SMSG_UNSUMMON* pUnsummonMsg = static_cast(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(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(pGameMsg) ); break; } case MSG_UNMOUNT_SUMMON : { OnMsgUnMount( static_cast(pGameMsg) ); break; } case MSG_USE_ITEM_RESULT: { OnMsgItemResult( static_cast(pGameMsg) ); break; } case MSG_SKILL_EVENT : { OnMsgSkillEvent ( static_cast(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(pGameMsg) ); // break; //Skill Effect // } case MSG_TAMING_INFO: { OnTamingInfo( static_cast(pGameMsg) ); break; } case MSG_CMD_RESULT : { OnMsgCmd ( static_cast(pGameMsg) ); break; //Cmd } case MSG_ITEM_TAKE_RESULT : { OnMsgTakeResult( static_cast(pGameMsg) ); break; //인벤에 넣기 } case MSG_ITEM_DROP_RESULT : { OnMsgDropResult( static_cast(pGameMsg) ); break; //인벤에서 삭제 } case MSG_ITEM_DROP_INFO : { OnMsgDropInfo ( static_cast(pGameMsg)); break; } case MSG_ITEM_WEAR : { OnMsgWearInfo ( static_cast(pGameMsg) ); break; //아이템 변경 } case MSG_ITEM_INVEN : { OnMsgInventory ( static_cast(pGameMsg) ); break; //인벤 정보 } case MSG_ITEM_DESTROY : { break; //Item Destroy } case MSG_TAKE_ITEM_RESULT : { OnMsgTakeItemResult( static_cast(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(pGameMsg); SGameAvatarEx * pPlayer = GetAvatar( pTradeMsg->target_player ); if( pPlayer ) pTradeMsg->target_Name = pPlayer->GetName(); break; //Trade } case MSG_STATE : { OnMsgState( static_cast(pGameMsg) ); break; //상태 이상 시간 } case MSG_PROPERTY : { OnMsgProperty( static_cast(pGameMsg) ); break; //각종 상태 } case MSG_HPMP : { OnMsgHPMP( static_cast(pGameMsg) ); break; //HPMP 동시에 } case MSG_EXP_UPDATE : { OnMsgExpUpdate( static_cast(pGameMsg) ); break; } case MSG_MARKET : { break; //Market } case MSG_NPC_DIALOG : { break; //NPC Dialog } case MSG_LEVEL_UPDATE : { OnMsgLevelUpdate( static_cast(pGameMsg) ); break; } case CMSG_WARP : { OnMsgWarp ( static_cast(pGameMsg) ); break; //Warp } case MSG_STATUS_CHANGE : { OnMsgStatusChange( static_cast(pGameMsg) ); break; //Warp } case MSG_REGEN_HPMP : { OnMsgRegenHPMP( static_cast(pGameMsg)); break; } case IMSG_REQ_OPEN_MSGBOX: { SIMSG_REQ_OPEN_MSGBOX* pReqOpenMsg = static_cast(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(pGameMsg) ); break; } //연출이 필요한 이펙트 모음 case MSG_GET_CHAOS: { OnMsgAddOtherEffect( pGameMsg ); break; } case MSG_ENERGY: { OnMsgAddForceSphere( static_cast(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& vecResult, const K3DVector& dist_pos, std::vector& 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); iRefreshAllStateEffect(); SGameOption& gameoption = GetGameOption(); std::vector vecStateList; SStateSlot* pStateSlot(NULL); pAvatar->GetAllStateList( vecStateList, false ); SMSG_STATE state; std::vector::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 >::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 >::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( 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(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::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(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(&SGameAvatarEx::ActivateCircleShadow) ); } else { for_each(m_svObject.begin(), m_svObject.end(), std::mem_fun(&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& 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(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(); }