Files
Sun1602/Server/GameServer/Player_Grid.cpp
T
2022-10-26 12:25:11 +08:00

669 lines
22 KiB
C++

#include "stdafx.h"
#include "./Player.h"
//#include "ServerOptionParser.h"
#include <ServerOptionParserEx.h>
#include <SkillAttrCalculator.h>
#include "ObjectDefine.h"
#include "GameZone.h"
#include "GameField.h"
#include "Sector.h"
#include "Item.h"
#include "TriggerManagerEx.h"
#include "StatusManager.h"
#include "ChaoState.h"
#include "DragonTransStatus.h"
#include "MovementChecker.h"
#include "View.h"
#include "Summoned.h"
#include "SummonManager.h"
#include "SummonedNPCs.h"
#include "CollectedList.h"
//#include "PacketStruct_DG.h"
//#include "PacketStruct_AG.h"
VarMsg2
Player::m_VarMsg2[Player::SENDINFO_MAX_BUFFER_SIZE];
#include "Player_Grid_Operator.h"
#include "GameDominationManager.h"
#include "DominationInfoParser.h"
#include "SkillSystem/PerkManager.h"
#ifdef _NA_007128_20140326_MONDSCHIEN_DOMINATION
#include "MapInfoParser.h"
#endif //_NA_007128_20140326_MONDSCHIEN_DOMINATION
#ifdef _NA_008166_20150330_MODIFY_AC_LEVELUP
#include "AchievementManager.h"
#endif //_NA_008166_20150330_MODIFY_AC_LEVELUP
//==================================================================================================
//
//==================================================================================================
//
// for GameField
void
Player::OnEnterField(GameField& IN rField, const WzVector& IN rwzVec, int iAngle)
{
Character::OnEnterField(rField, rwzVec, iAngle);
SetState(PLAYER_MAP_ENTER);
#ifdef _DEV_TAIYO_PATHENGINE_CODE
// 플레이어 컬리전 등록
GetWorldBase()->x_pPathFinder->FindPath_Requst_NewAgent(GetPathExplorer());
#endif
Rider.SyncUpdateRidingStatus(this);
// CHANGES: f110727.2L, fixed a missing stopped timer resume event
this->perk_manager_->OnEnterField(&rField);
;{
MSG_CG_STATUS_ATTR_CHANGE_BRD sendMsg;
sendMsg.m_dwObjKey = GetObjectKey();
sendMsg.m_AttrType = (BYTE)eATTR_ATTACK_SPEED;
sendMsg.m_dwValue = GetAttSpeedRatio();
SendPacket(&sendMsg, sizeof(sendMsg));
};
;{
MSG_CG_STATUS_ATTR_CHANGE_BRD sendMsg;
sendMsg.m_dwObjKey = GetObjectKey();
sendMsg.m_AttrType = (BYTE)eATTR_MOVE_SPEED;
sendMsg.m_dwValue = GetMoveSpeedRatio();
SendPacket(&sendMsg, sizeof(sendMsg));
};
GetExtraInfoManager().OnEnterField();
#ifdef _NA_008166_20150330_MODIFY_AC_LEVELUP
AchievementManager* ac_manager = this->GetACManager();
if (ac_manager != NULL)
{
if (ac_manager->GetFlag_InitializeLevelUpAC() == FALSE) {
this->GetACManager()->ProcessLevelUp(this->GetLevel());
}
}
#endif //_NA_008166_20150330_MODIFY_AC_LEVELUP
}
// __NA_S00015_20080828_NEW_HOPE_SHADOW
// 포털이동이나 필드이동시 몬스터를 다시 보여지게 만드는 함수.
void
Player::CallSummonMonster()
{
#if !defined _NA_002962_20110630_CHANGE_SUMMONED_PORTAL_MOVE
// 쉐도우일때만 다시 생성한다.
if (GetCharType() != eCHAR_SHADOW)
{
return;
}
#endif
//현재 소환 NPC 리스트가 있는지 확인한다. 없으면 생성한다.
SummonedNPCs* summoned_npcs = SummonManager::Instance()->FindSummonNPCs(GetObjectKey());
if (summoned_npcs == NULL)
{
summoned_npcs = SummonManager::Instance()->AllocSummonNPCs(this, TRUE);
if (summoned_npcs == NULL)
{
return;
}
}
#if !defined(_NA_000000_20140224_SUMMONER_REFACTORING)
SetSummonerKey(summoned_npcs->GetSummonerKey());
#endif //_NA_000000_20140224_SUMMONER_REFACTORING
WzVector summon_pos;
GetPos(&summon_pos);
PLAYER_SUMMON_INFO_LIST::const_iterator it = m_listPlayerSummonInfo.begin();
for (; it != m_listPlayerSummonInfo.end(); ++it)
{
const PLAYER_SUMMON_INFO* const summon_info = *it;
if (summon_info == NULL)
{
continue;
}
//3. 해당 몬스터를 소환한다.
if (GetCharType() == eCHAR_SHADOW)
{
Summoned* const summoned = GetField()->CreateSummonDeadMonster(
summon_info->monster_code, &summon_pos, this, summoned_npcs, 0);
if (summoned == NULL)
{
continue;
}
//몬스터의 HP를 비율만큼 줄인다.
summoned->SetHP(summon_info->hp);
#ifdef _NA_006352_20121228_IF_STEEL_MODE_VALKYRIES_MODIFY_SUMMON_POIICY
// 필드 이동 시 섀도우 소울컨트롤(소환수)도 강철모드 적용..
ALLOC_STATUS_PAIR steel = summoned->GetStatusManager()->AllocStatus(eCHAR_STATE_STEEL,
LOADING_STEEL_MODE_TIME);
if (steel.second)
steel.second->SendStatusAddBRD();
#endif //_NA_006352_20121228_IF_STEEL_MODE_VALKYRIES_MODIFY_SUMMON_POIICY
#ifdef _CN_000000_20130731_STATE_STEEL_MOD_BUG_LOG
SUNLOG(eCRITICAL_LOG, "["__FUNCTION__"] : AllocStatus(eCHAR_STATE_STEEL)");
#endif // _CN_000000_20130731_STATE_STEEL_MOD_BUG_LOG
// 위에 Create할때 벌써 클라한테 HP정보가 보내진다. 그후에 HP를 변경하니 변경된 정보를 보내준다.
MSG_CG_SUMMON_CURRENT_HP_BRD brdMsg;
brdMsg.m_dwSummonedObjKey = summoned->GetObjectKey();
brdMsg.m_dwMaxHP = summoned->GetMaxHP();
brdMsg.m_dwHP = summoned->GetHP();
brdMsg.m_dwSpeedRatio = summoned->GetMoveSpeedRatio();
summoned->SendPacketAround(&brdMsg, sizeof(MSG_CG_SUMMON_CURRENT_HP_BRD));
continue;
}
#ifdef _NA_007667_20141001_WITCHBLADE_SKILL
//
#endif //_NA_007667_20141001_WITCHBLADE_SKILL
// 한번에 이전 상태를 반영하여 생성한다. 쉐도우 같은 방식은 메시지가 두번 간다.
Summoned* const summoned = GetField()->CreateSummonByPlayer(
summon_info->monster_code,
&summon_pos,
this,
summoned_npcs,
summon_info->remained_time,
summon_info->skill_code,
summon_info);
#ifdef _NA_006352_20121228_IF_STEEL_MODE_VALKYRIES_MODIFY_SUMMON_POIICY
if (summoned == NULL)
{
continue;
}
// 필드 이동 시 발키리 소환수 강철모드 적용..
ALLOC_STATUS_PAIR steel = summoned->GetStatusManager()->AllocStatus(eCHAR_STATE_STEEL,
LOADING_STEEL_MODE_TIME);
if (steel.second)
steel.second->SendStatusAddBRD();
#endif //_NA_006352_20121228_IF_STEEL_MODE_VALKYRIES_MODIFY_SUMMON_POIICY
#ifdef _CN_000000_20130731_STATE_STEEL_MOD_BUG_LOG
SUNLOG(eCRITICAL_LOG, "["__FUNCTION__"] : AllocStatus(eCHAR_STATE_STEEL)");
#endif // _CN_000000_20130731_STATE_STEEL_MOD_BUG_LOG
}
}
// __NA_S00015_20080828_NEW_HOPE_SHADOW
void
Player::InsertSummonInfo(PLAYER_SUMMON_INFO* pInfo)
{
if(!pInfo) return;
m_listPlayerSummonInfo.push_back(pInfo);
}
// __NA_S00015_20080828_NEW_HOPE_SHADOW
void
Player::DestroySummonInfo()
{
PLAYER_SUMMON_INFO_LIST_ITER iter;
for(iter = m_listPlayerSummonInfo.begin(); iter != m_listPlayerSummonInfo.end(); ++iter)
{
delete *iter;
}
m_listPlayerSummonInfo.clear();
}
//--------------------------------------------------------------------------------------------------
// __NA_S00015_20080828_NEW_HOPE_SHADOW
class GetSummonInfo
{
public:
GetSummonInfo(Player* pPlayer):player_(pPlayer) {}
~GetSummonInfo() {}
public:
void operator()(const SUMMONED_MAP_PAIR& value)
{
if (player_ == NULL)
{
return;
}
NPC* const summoned_npc = static_cast<NPC*>(value.second);
if (obj_util::IsValid(summoned_npc, __FUNCTION__, __LINE__) == false) {
return;
}
PLAYER_SUMMON_INFO* summon_info = new PLAYER_SUMMON_INFO;
summon_info->monster_code = summoned_npc->GetBaseInfo()->m_MonsterCode;
summon_info->hp = summoned_npc->GetHP();
const Summoned* const summoned = static_cast<const Summoned* const>(summoned_npc);
if (player_->GetCharType() != eCHAR_SHADOW)
{
summon_info->mp = summoned->GetMP();
summon_info->remained_time = summoned->GetRemainedTime();
summon_info->command = summoned->GetCommandState();
summon_info->skill_code = summoned->GetSummonSkillCode();
}
#ifdef _NA_007667_20141001_WITCHBLADE_SKILL
summon_info->summoned_type = summoned->GetSummonType();
if (summon_info->summoned_type != eSUMMON_IMMOVABLE) {
player_->InsertSummonInfo(summon_info);
}
#else
player_->InsertSummonInfo(summon_info);
#endif //_NA_007667_20141001_WITCHBLADE_SKILL
}
private:
Player* player_;
};
//--------------------------------------------------------------------------------------------------
void
Player::OnLeaveField()
{
GameField* pGameField = GetField();
if(pGameField == 0)
return;
GetExtraInfoManager().OnLeaveField();
#ifdef _DEV_TAIYO_PATHENGINE_CODE
// 플레이어 컬리전 해제
GetWorldBase()->x_pPathFinder->FindPath_Requst_DestroyAgent(GetPathExplorer());
#endif
// field를 떠나면 트리거에서 나왔다고 알려준다.
// (CHANGES) (f100614.4L) add a slot type for a trigger area linker to support a multi-area link
trigger_links_.Disconnect(pGameField->GetTriggerManager());
//pGameField->GetTriggerManager()->Disconnected(&m_TriggerLink);
#ifdef _NA000000_SPEED_HACK_PREVENTION_SUPPORT
if (nsSync::CSSyncTuner* manager = m_pMovementChecker->GetSyncTuner()) {
manager->Initialize(this);
}
#endif
// __NA_S00015_20080828_NEW_HOPE_SHADOW
DestroySummonInfo();
#if !defined _NA_002962_20110630_CHANGE_SUMMONED_PORTAL_MOVE
if (GetCharType() == eCHAR_SHADOW)
#endif
{
SummonedNPCs* pSummonNPCs = SummonManager::Instance()->FindSummonNPCs(GetObjectKey());
if(pSummonNPCs)
{
// 0을 입력하면 현재 소환된 몬스터들을 모두 필드에서 없앤다...
// 그리고, 이동해도 기억할 만한 소환수 정보를 저장하자.
GetSummonInfo SummonInfo(this);
pSummonNPCs->ForeachSummonedList(SummonInfo);
}
}
// TODO: check sequence... _NA001385_20090924_DOMINATION_ETC
_LeaveEtcStatus();
Character::OnLeaveField();
}
void
Player::OnEnterSector()
{
//__NA_001290_20090525_SHIELD_SYSTEM_NOTIFY_NOTABILITY_STATE
_EnterEtcStatus(); // 서버에서 부여하는 상태 추가.
// 자신의 위치 정보
MSG_AG_SYNC_PLAYER_ENTER_ACK msgACK;
GetPos((WzVector*)msgACK.m_fPos);
msgACK.m_TransSkillCode = 0;
StatusManager* pSTATMGR = GetStatusManager();
if(pSTATMGR->Status.IsDragonTransforming())
{
DragonTransStatus* pDragonTransStatus = (DragonTransStatus*)pSTATMGR->FindStatus(eCHAR_STATE_TRANSFORMATION);
msgACK.m_TransSkillCode = pDragonTransStatus->GetSkillCode();
};
//_KR_001385_20091103_DOMINATION_ZONEMOVE_NOTIC
GameField* pGameField = GetField();
if (pGameField == NULL) {
return;
};
msgACK.continued_wings_spreading_ = false;
#ifdef _NA001955_110210_WING_COSTUME
msgACK.continued_wings_spreading_ = pSTATMGR->Status.IsSpreadWings();
#endif
MAPCODE mapCode = pGameField->GetFieldCode();
ZeroMemory(&msgACK.m_GuildInfo, sizeof(msgACK.m_GuildInfo));
mapCode = DominationInfoParser::Instance()->GetDominationFieldCode( mapCode );
if (mapCode != 0)
{
GameDominationManager::Instance()->GetInGuildInfo(mapCode, msgACK.m_GuildInfo);
}
#ifdef _NA_007128_20140326_MONDSCHIEN_DOMINATION
//필드로 진입할 시에 대륙 영주 정보도 보내준다.
MAPCODE field_code = pGameField->GetFieldCode();
const sMAPINFO* pInfo = MapInfoParser::Instance()->FindMapInfo(field_code);
if (pInfo != NULL)
{
const sDOMINATION_CONTINENT_LORD_INFO* lord_info =
GameDominationManager::Instance()->GetDominationContinentLordInfo(pInfo->ContienetNumber);
//lord_info가 NULL일 경우는 해당 대륙은 영주가 없거나 대륙번호가 잘못되었을 경우이다.
if (lord_info != NULL)
{
msgACK.m_ContinentLordInfo = (*lord_info);
}
}
#endif //_NA_007128_20140326_MONDSCHIEN_DOMINATION
SendPacket(&msgACK, sizeof(msgACK));
MSG_CG_STATUS_ALL_STATEINFO_CMD msgCMD;
pSTATMGR->SerialzieStatusInfo(msgCMD.m_StateTotalInfo);
if(msgCMD.m_StateTotalInfo.m_Count)
{
SendPacket(&msgCMD, msgCMD.GetSize());
}
//{__NA_001290_20090525_SHIELD_SYSTEM_NOTIFY_NOTABILITY_STATE
MSG_CG_STATUS_ETC_STATEINFO_CMD msgEtcCMD;
BYTE cntEtcState = pSTATMGR->SerialzieEtcStatusInfo(msgEtcCMD.m_stEtcStateTotalInfo);
if(cntEtcState)
SendPacket(&msgEtcCMD, msgEtcCMD.GetSize());
//}
ApplyGMState();
#ifdef __NA_821_STAT_BUG_RECOVERY
if(!IsGMUser() && !GetCheckedStat())
//if(!GetCheckedStat())
{
if(!CheckValidStatPoint())
{
RecoveryStatPoint();
}
}
#endif
UnexpectedUserEnterRoom() = FALSE;
GetChaoState().SendLeavedChaoTime();
;{
m_pMovementChecker->Reset();
#ifdef _NA000000_SPEED_HACK_PREVENTION_SUPPORT
if (nsSync::CSSyncTuner* manager = m_pMovementChecker->GetSyncTuner())
{
manager->Initialize(this);
MSG_CG_MAP_KBMOVE_SERIAL_CHECK_CMD msg_cmd;
manager->EnterField(&msg_cmd);
this->SendPacket(&msg_cmd, sizeof(msg_cmd));
}
#endif
};
// 섹터 진입 처리와 기타 상태 설정이 끝난 후 펫 소환 정보를 설정하도록 한다.
m_PetManager.SetSummonInfo();
//_NA_004035_20120227_COSTUME_ITEM
costume_handler_.SetCostumeInfo();
GAMELOG->LogAction(ACT_JOIN_MAP, this);
}
//{__NA_001290_20090525_SHIELD_SYSTEM_NOTIFY_NOTABILITY_STATE
void
Player::_EnterEtcStatus()
{
SERVER_COMMON_OPTION& stServerOptionInfo = ServerOptionParserEx::Instance()->GetServerOption();
const INT iExpireTime = BASE_EXPIRE_TIME_INFINITY;
const int iHPPeriod = stServerOptionInfo.m_wPLAYER_HP_REGEN_PERIOD;
const int iMPPeriod = stServerOptionInfo.m_wPLAYER_MP_REGEN_PERIOD;
const int iSDPeriod = stServerOptionInfo.m_wPLAYER_SD_REGEN_PERIOD;
#ifdef _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
const int FP_period = stServerOptionInfo.player_fp_regen_period;
const int FP_maintain_time = stServerOptionInfo.player_fp_maintain_time;
#endif //_NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
const eCHAR_STATE_TYPE eStateIDHP = eCHAR_STATE_ETC_AUTO_RECOVER_HP;
const eCHAR_STATE_TYPE eStateIDMP = eCHAR_STATE_ETC_AUTO_RECOVER_MP;
const eCHAR_STATE_TYPE eStateIDSD = eCHAR_STATE_ETC_AUTO_RECOVER_SD;
const eCHAR_STATE_TYPE eStateIDHPMP = eCHAR_STATE_ETC_AUTO_RECOVER_HPMP;
#ifdef _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
const eCHAR_STATE_TYPE state_id_FP = eCHAR_STATE_ETC_AUTO_RECOVER_FP;
#endif //_NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
// SD가 0인 상태(신규케릭등...) 에서 Enter시
// RECOVER되는 SD값의 변화로 상태정보를 클라에 주는것을 막는다. [8/20/2009 lst1024]
if(0 == GetSD())
SetSD(1);
if(GetCharType() == eCHAR_BERSERKER) // 버서커와 섀도우는 HP, MP 리젠 주기가 다르다.
{
m_pStatusManager->AllocStatus(eStateIDHP, iExpireTime, iHPPeriod); // HP 리젠
m_pStatusManager->AllocStatus(eStateIDMP, iExpireTime, iMPPeriod); // MP 리젠
}
#ifdef _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
else if (GetCharType() == eCHAR_WITCHBLADE)
{
m_pStatusManager->AllocStatus(eStateIDHPMP, iExpireTime, iHPPeriod); // HP, MP 리젠
ALLOC_STATUS_PAIR fp_status = m_pStatusManager->AllocStatus(state_id_FP, iExpireTime, FP_period); // FP 리젠
if (fp_status.first == true) {
fp_status.second->SetFPMaintainTime(FP_maintain_time);
}
}
#endif //_NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
else // 발키리, 엘리, 드래곤
{
m_pStatusManager->AllocStatus(eStateIDHPMP, iExpireTime, iHPPeriod); // HP, MP 리젠
}
m_pStatusManager->AllocStatus(eStateIDSD, iExpireTime, iSDPeriod); // SD 리젠
eZONE_STATE zsSTATE = GetGameZoneState();
BOOL bApplySheld = ePRS_AT_LOBBY != zsSTATE;
if(bApplySheld)
m_pStatusManager->AllocStatus(eCHAR_STATE_ETC_EXIST_SHELD_POINT);
BOOL bApplySteelMode = TRUE; // 로딩시간을 벌어주기 위하여 강철상태를 걸어준다.
switch(zsSTATE)
{
case ePRS_AT_INSTANCE:
case ePRS_AT_MISSION:
case ePRS_AT_VILLAGE:
case ePRS_AT_LOBBY:
bApplySteelMode = UnexpectedUserEnterRoom();
break;
}
if(bApplySteelMode)
{
int steel_time = LOADING_STEEL_MODE_TIME;
// 점령전에서 로딩 강철 상태 악용으로 변경.
if (zsSTATE == ePRS_AT_DOMINATION_FIELD)
steel_time = DOMINATION_LOADING_STEEL_MODE_TIME;
m_pStatusManager->AllocStatus(eCHAR_STATE_STEEL, steel_time);
#ifdef _CN_000000_20130731_STATE_STEEL_MOD_BUG_LOG
SUNLOG(eCRITICAL_LOG, "["__FUNCTION__"] : AllocStatus(eCHAR_STATE_STEEL)");
#endif // _CN_000000_20130731_STATE_STEEL_MOD_BUG_LOG
}
if (INVALID_GUILDGUID != GetGuildGuid())
GameDominationManager::Instance()->ApplyRewardField(this, GetField()->GetFieldCode());
}
//}__NA_001290_20090525_SHIELD_SYSTEM_NOTIFY_NOTABILITY_STATE
void
Player::_LeaveEtcStatus()
{
if (INVALID_GUILDGUID != GetGuildGuid())
GameDominationManager::Instance()->ApplyRewardField(this, GetField()->GetFieldCode(),false);
}
// for Sector
// 자신의 정보를 주변에게 알림
void
Player::OnEnterObject(const Sector& IN rSector)
{
GameZone* pGameZone = GetGameZonePtr();
if(pGameZone == 0)
return;
// CHANGES: f110415.6L, at this point in time, the usage case of 'OnEnterObject' only has
// notification to users so that if the sector has no users,
// it is no need to process contiuously.
// in this case, that player is related to other player, skip check this player
// because it's complex that finding a player whether this player is located in this sector
if (rSector.GetPlayerNum() == 0) {
return;
};
GameField* const pGameField = GetField();
if (pGameField == NULL)
{
SUNLOG(eCRITICAL_LOG, "["__FUNCTION__"][SectorBug] Invalid GameField![PlayerGuid:%d][ZoneMapCode:%d][EntryFieldCode:%d]",
this->GetCharGuid(), pGameZone->GetMapCode(), pGameZone->GetEntryFieldCode());
return;
}
StatusManager* const pStatusManager = GetStatusManager();
StatusField& rStatus = pStatusManager->Status;
const BOOLEAN bNeedNtf = !(rStatus.FIELD & rStatus.ENABLE_OBSERVER_MODE);
if(!bNeedNtf)
return;
// 나의 정보를 주변에 알릴 필요가 없다. 각각의 플레이어마다 주기적으로 주변을 체크해서 정보를 갱신한다.
VarMsg2* pVarMsgEnterObj = &(m_VarMsg2[Player::SENDINFO_ENTER_OBJECT]);
MSG_CG_SYNC_PLAYER_ENTER_BRD* pEnterBrdMsg = \
pVarMsgEnterObj->StartTypePtr(Param2Class<MSG_CG_SYNC_PLAYER_ENTER_BRD>());
pVarMsgEnterObj->SetSize(pEnterBrdMsg->GetSize());
{
PLAYER_RENDER_INFO_EX* pack_info = (PLAYER_RENDER_INFO_EX*)pVarMsgEnterObj->NextPtr();
int packed_len = this->GetPlayerRenderInfo(pGameZone->GetZoneType() != eZONETYPE_VILLAGE, pack_info);
pVarMsgEnterObj->SetSize((WORD)packed_len);
};
//{__NA_001290_20090525_SHIELD_SYSTEM_NOTIFY_NOTABILITY_STATE
{
ETC_STATE_TOTAL_INFO *pStateRenderMsg = (ETC_STATE_TOTAL_INFO*)pVarMsgEnterObj->NextPtr();
this->GetEtcStateTotalInfo(pStateRenderMsg);
pVarMsgEnterObj->SetSize(pStateRenderMsg->GetSize());
}
//}
//__NA_0_20090720_GUILD_RENDER_INFO_MODIFY
// 길드 정보는 따로 보낸다.(대인 관계 포함됨)
const DWORD object_key = GetObjectKey();
// 장착 정보 셋팅
{
EQUIP_ITEM_BASEINFO* pEquipMsg = (EQUIP_ITEM_BASEINFO*)pVarMsgEnterObj->NextPtr();
pEquipMsg->m_dwObjectKey = object_key;
EQUIP_ITEM_BASEINFO::data_type* pItemSlot =
(EQUIP_ITEM_BASEINFO::data_type*)((BYTE*)pEquipMsg + sizeof(EQUIP_ITEM_BASEINFO));
pEquipMsg->m_Count = this->SerializeRenderEquipItemBaseInfo(pItemSlot);
pVarMsgEnterObj->SetSize(pEquipMsg->GetSize());
}
// 아이템 이펙트 랜더링 정보를 설정한다.
{
sMSG_RENDER_EFFECT_ITEM_LIST* const render_effect =
(sMSG_RENDER_EFFECT_ITEM_LIST*)pVarMsgEnterObj->NextPtr();
render_effect->m_PlayerKey = object_key;
const DWORD render_item_count = RENDER_EFFECT.SerializeRenderInfo(
render_effect->m_BitRender,
render_effect->m_ItemCodes,
sMSG_RENDER_EFFECT_ITEM_LIST::MAX_EFFECT_ITEMS);
render_effect->m_ItemCount = static_cast<BYTE>(render_item_count);
pVarMsgEnterObj->SetSize(render_effect->GetSize());
};
pGameField->SendExPacketToSector(rSector.GetSectorIndex(),
pVarMsgEnterObj->GetMsgCount(),
pVarMsgEnterObj->GetMsgPPtr(),
pVarMsgEnterObj->GetMsgSizePtr(),
object_key);
// added by __NA_0_20090720_GUILD_RENDER_INFO_MODIFY
OnSendAllPlayersGuildRenderInfoToNeighbor(rSector);
#ifdef _NA_008012_20150204_SUN_RANKING_SYSTEM
OnSendAllPlayersSunRankingGradeInfoToNeighbor(rSector);
#endif // _NA_008012_20150204_SUN_RANKING_SYSTEM
// 자신의 이동정보를 보낸다.
this->SendMoveInfo(NULL, rSector);
}
// 주변정보를 자신에게 알림
void
Player::OnEnterNeighbor(const Sector& IN rSector)
{
// 주변정보를 바로 받을 필요가 없다. 어차피 주기적으로 주변을 체크해서 정보를 갱신한다.
{
OnSendAllPlayersRenderInfoAllKinds(rSector);
// added by __NA_0_20090720_GUILD_RENDER_INFO_MODIFY
OnSendAllPlayersGuildRenderInfo(rSector);
#ifdef _NA_008012_20150204_SUN_RANKING_SYSTEM
OnSendAllPlayersSunRankingGradeInfo(rSector);
#endif // _NA_008012_20150204_SUN_RANKING_SYSTEM
}
// 주변 몬스터 정보
OnSendAllMonsterInfo(rSector);
// 주변 아이템 정보
OnSendAllFieldItemInfo(rSector);
// 주변 채집물 정보
OnSendAllFieldCollectionInfo(rSector);
}
void
Player::FirstGuildMemberEnter()
{
GameField* pGameField = GetField();
if(NULL == pGameField)
return;
pGameField->FirstGuildMemberEnter(this);
}
// 자신의 정보를 주변에게
void
Player::OnLeaveObject(const Sector& IN rSector)
{
StatusManager* const pStatusManager = GetStatusManager();
StatusField& rStatus = pStatusManager->Status;
const BOOLEAN bSendPacket = !(rStatus.FIELD & rStatus.ENABLE_OBSERVER_MODE);
// 나의 정보를 주변에 알릴 필요가 없다. 각각의 플레이어마다 주기적으로 주변을 체크해서 정보를 갱신한다.
if(bSendPacket)
{
MSG_CG_SYNC_PLAYER_LEAVE_BRD brdMsg;
brdMsg.m_byCount = 1;
const DWORD object_key = this->GetObjectKey();
brdMsg.m_PlayerKey[0] = (WORD)object_key;
GameField* const pGameField = GetField();
pGameField->SendPacketToSector(rSector.GetSectorIndex(), &brdMsg, brdMsg.GetSize(), object_key);
}
}
//==================================================================================================
// <Spec.>
//