#pragma once //======================================================================================================================= /// GameField class /** @author Kim Min Wook < taiyo@webzen.com > @since 2006. 2. 20~ @history - 2006/8/5 : ObjectMangerÅëÇÕ ÀÛ¾÷ @todo - MapObjectÀÇ ObjectKey Á¤¸®, ´Ù¸¥ object¿Í °ãÄ¡Áö ¾Ê°Ô */ //======================================================================================================================= //¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬ #include "Player.h" #include "Field.h" #include "Sector.h" #include "SectorInfo.h" #include //__NA001144_080828_HIGH_RESOLUTION_SECTOR_LOAD_BALANCE_POS_SYNC__ #include "UnitRegenManager.h" //¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬ class EffectManager; class UnitRegenManager; class UnitRegenInfoManager; class UnitGroupManager; class UnitGroupInfoManager; class UnitRegenInfo; class RegenLocation; class Monster; class TotemNpc; class TriggerManagerEx; class Collection; class CollectionManager; struct IsSendPlayer; class CrystalWarp; // //_NA_0_20100222_UNIT_TRIGGERS_FRIEND_MONSTER struct TargetFinderArg; struct IObjectFinder; //¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬ // // class GameField : public Field { __DECL_CUSTOMPOOL_PTR(GameField) enum { DEFAULT_PLAYER_POOL_SIZE = 10, DEFAULT_NPC_POOL_SIZE = 70, DEFAULT_MAPOBJECT_POOL_SIZE = 100, DEFAULT_FIELDITEM_POOL_SIZE = 20, DEFAULT_DEADOBJECT_POOL_SIZE = 20, }; #ifdef _NA_0_20100416_RELOAD_MAPOBJECT friend class ZoneReloader; #endif public: GameField(); public: virtual ~GameField(); virtual VOID Release(); virtual VOID Init( GameZone* pZone , FieldInfo* pFieldInfo , const TCHAR* pszGroupName , UnitRegenInfoManager* pUnitRegenInfoMgr , UnitGroupInfoManager* pUnitGroupInfoMgr , bool bPreMapLoading , bool bUsingViewPort , bool bPreRegen ); virtual VOID Update( DWORD dwDeltaTick ); // ¿ÀºêÁ§Æ® ÀÔÀå, ÅðÀå virtual BOOL EnterField( Object* pObject, const WzVector* pwzVec, int iAngle=-1 ); virtual BOOL LeaveField( Object* pObject ); //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ // const SectorGridVR* GetSectorGridVR( const SECTOR_IDX coordinates, const float radius) const; template void SendPacketAroundForSync(Character* const sender, const _MSGSUBTYPE* const sub_msg, const BOOLEAN bPostAction = false); template void SendPacketAroundForSync(const SECTOR_IDX coordinates, const _MSGSUBTYPE* const sub_msg); private: VOID SendPacketAroundForSync_(const SECTOR_IDX coordinates, const BYTE _TAG, WAR_TAG_V* const IN pMsg, const WORD wSize, const BOOLEAN bPostAction = FALSE); public: inline VOID SendPacket( Player* const pReceiver, MSG_BASE_FORWARD* pMsg, WORD wSize ); VOID SendExPacket( Player* const pReceiver, const DWORD numberOfMsgs, BYTE** const IN ppMsg, WORD* const pwSize ); inline VOID SendPacketAround( const SECTOR_IDX sector_idx, MSG_BASE_FORWARD* pMsg, WORD wSize, const DWORD except_objkey = 0 ); VOID SendExPacketAround( const SECTOR_IDX sector_idx, const DWORD numberOfMsgs, BYTE** const IN ppMsg, WORD* const pwSize, const DWORD except_objkey = 0 ); inline VOID SendPacketToAll( MSG_BASE_FORWARD* pMsg, WORD wSize, const DWORD except_objkey = 0 ); VOID SendExPacketToAll( const DWORD numberOfMsgs, BYTE** const IN ppMsg, WORD* const pwSize, const DWORD except_objkey = 0 ); //{ __NA000000_090716_HIGH_LOAD_BALANCED_NETWORK_TUNEUP__ // (WAVERIX) (090716) (ADD-IN) for High-load balanced network support inline VOID SendPacketToAgent(MSG_BASE_FORWARD* pMsg, WORD wSize); VOID SendExPacketToAgent(const DWORD numberOfMsgs, BYTE** const IN ppMsg, WORD* const pwSize); //} VOID SendAIMessageAroundExceptMe( NPC* const pSender, AI_MSG* const pMsg, const WORD wSize, const DWORD delay = 0 ); inline void SendPacketToSector(const SECTOR_IDX sector_idx, MSG_BASE_FORWARD* pMsg, WORD wSize, const DWORD except_objkey = 0); void SendExPacketToSector(const SECTOR_IDX sector_idx, const DWORD numberOfMsgs, BYTE** const IN ppMsg, WORD* const pwSize, const DWORD except_objkey = 0); // (CHANGES) (f100504.1L) change the interface specification to support a complex condition // the replacement facility for SendXXPacketToSector inline void SendPacketToSector(const SECTOR_IDX sector_idx, MSG_BASE_FORWARD* pMsg, WORD wSize, IObjectFinder* finder); void SendExPacketToSector(const SECTOR_IDX sector_idx, const DWORD numberOfMsgs, BYTE** const IN ppMsg, WORD* const pwSize, IObjectFinder* finder); // //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ // BOOL TeleportObject( Character* const pCharacter, const WzVector* pPos, const BOOLEAN bForcedCommand=FALSE ); RC::eSYNC_RESULT JumpObject( Character* const pCharacter, const WzVector* const pPos ); public: inline EffectManager* GetEffectManager() { return m_pEffectManager; } inline TriggerManagerEx* GetTriggerManager() { return m_pTriggerManager; } inline CollectionManager* GetCollectManeger() { return m_pCollectionManager; } Character* SearchTarget(const TargetFinderArg& find_arg); public: // CHANGES: f110303.1L, added new interface for enhanced target searching. // added by _NA000000_110210_ENHANCED_TARGET_SEARCH_ALGORITHM bool FindTargetsForNpcAI( const ns_object::SearchOption::NpcAI& search_option, ns_object::SearchOption::NpcAI::result_type* const search_result); bool FindTargetsUsingSingleSearch( const ns_object::SearchOption::SingleSearch& search_option, ns_object::SearchOption::SingleSearch::result_type* const search_result); public: // ÁÖº¯ ¼½ÅÍ ·çÇÁ // (CHANGES) (f100503.3L) change the interface specification so that finders is very rare NPC* SearchNeighborNpc(SECTOR_IDX sector_index, DWORD object_key) const; NPC* SearchNeighborNpc(SECTOR_IDX sector_index, const IObjectFinder* filter) const; Item* SearchNeighborItem(SECTOR_IDX sector_index, DWORD object_key) const; Item* SearchNeighborItem(SECTOR_IDX sector_index, const IObjectFinder* filter) const; public: inline UnitGroupManager* GetUnitGroupMgr() { return m_pUnitGroupMgr; } inline UnitRegenManager* GetUnitRegenMgr() { return m_pUnitRegenManager; } // _NA_002098_20110307_ADD_NPC_CONTROL_TRIGGER_BASE ns_trigger::TriggerNpcLinkMatchTable* GetNpcTriggerEvents() const; public: void DestroyObject( Object* pObj ); private: VOID AddMapObjectAll(); void _AddObject( Object* pObj ); bool _DeleteObject( Object* pObj ); void _LinkedMapNpc(Object* pObj); void _UnLinkedMapNpc(Object* pObj); VOID SpawnSector( DWORD dwSectorIndex, Object* pObject ); public: VOID BuildInstanceInfo(); // Player ÃÖÃÊ ÀÔÀå½Ã ÃʱâÈ­ ÇÏ´Â °Íµé. private: // ¸ó½ºÅÍ °ü·Ã public: typedef STLX_HASH_MAP _CHARACTER_HASH; typedef STLX_HASH_MAP _PLAYER_HASH; typedef STLX_HASH_MAP _NPC_HASH; typedef STLX_HASH_MAP _ITEM_HASH; typedef STLX_HASH_MAP _COLLECTION_HASH; typedef STLX_HASH_MAP _MAPOBJECT_HASH; public: inline const _CHARACTER_HASH& GetRefCharacterList() const { return m_CharacterHash; } inline const _PLAYER_HASH& GetRefPlayerList() const { return m_PlayerHash; } inline const _NPC_HASH& GetRefNPCList() const { return m_NPCHash; } VOID AddExpAllMember( DWORD64 Exp ); private: __PTR_PROPERTY( GameZone, GameZone ); private: EffectManager* m_pEffectManager; TriggerManagerEx* m_pTriggerManager; UnitRegenManager* m_pUnitRegenManager; UnitGroupManager* m_pUnitGroupMgr; UnitGroupInfoManager* m_pUnitGroupInfoMgr; CollectionManager* m_pCollectionManager; // bool m_bPreRegen; bool instanced_resourse_; static const DWORD SECTOR_SYNC_UPDATE_INTERVAL; struct { ITimerBase m_SyncUpdater; HLB_BufferInfo* m_pHLB; }; friend class HighLoadBalancer; private: _CHARACTER_HASH m_CharacterHash; _PLAYER_HASH m_PlayerHash; // PlayerÀÇ »ý¼ºÁÖ±â´Â GameField¿Í °°ÀÌÇÏÁö ¾Ê´Â´Ù. _NPC_HASH m_NPCHash; // NPC, Item, MapObjectµéÀº GameField°¡ »ç¶óÁú ¶§ °°ÀÌ ¼Ò¸êµÈ´Ù. _NPC_HASH m_NPCHashForUnitID; _ITEM_HASH m_FieldItemHash; _COLLECTION_HASH m_FieldCollectHash; _MAPOBJECT_HASH m_MapObjectHash; // _NA_002098_20110307_ADD_NPC_CONTROL_TRIGGER_BASE ns_trigger::TriggerNpcLinkMatchTable* npc_trigger_events_; TCHAR m_tszTriggerGroupName[MAX_MAPNAME_LENGTH+1]; public: // Çʵ峻 ¸ðµÎ ·çÇÁ template void ForAllPlayer(OPERATOR_T& op) { for (_PLAYER_HASH::iterator it = m_PlayerHash.begin(); it != m_PlayerHash.end(); ) { Player* const player = it->second; if (obj_util::IsValid(player, __FUNCTION__, __LINE__)) { op(player); ++it; } else { // ¸Ê°ú ¹éÅÍ ±¸ºÐ ÁÖÀÇ m_PlayerHash.erase(it++); } } } template void ForAllNPC(OPERATOR_T& op) { for (_NPC_HASH::iterator it = m_NPCHash.begin(); it != m_NPCHash.end(); ) { NPC* const npc = it->second; if (obj_util::IsValid(npc, __FUNCTION__, __LINE__)) { op(npc); ++it; } else { // ¸Ê°ú ¹éÅÍ ±¸ºÐ ÁÖÀÇ m_NPCHash.erase(it++); } } } MapNpc* FindMapNpc(const Object::Key object_key) const; MapObject* FindMapObject(const Object::Key object_key) const; Character* FindCharacter(const Object::Key object_key) const; NPC* FindNPCForUnitID(const DWORD unit_id) const; Object* FindObject(const eOBJECT_TYPE object_type, const Object::Key object_key) const; public: virtual int GetPlayerNum() { return (int)m_PlayerHash.size(); } int GetNPCNum() const { return (int)m_NPCHash.size(); } int GetDeadNPCNum() const { return (int)m_pUnitRegenManager->GetCount(); } // ¸®Á¨À» ÀÌ¿ëÇÑ ¸ó½ºÅÍ »ý¼º // ÃÖÀûÈ­ ÇÊ¿ä ÇÔ¼öµé!!!! public: Monster* CreateMonster( WORD NPCCode, const WzVector* pvPos, WORD wGroupID=0, int iAngle=-1, BYTE byMoveType=0, DWORD dwMoveAreaID=0, WORD MissionAreaID=0 ); Summoned* CreateSummonByPlayer( WORD NPCCode, const WzVector* pvPos, Character* pSummoner, SummonedNPCs* pOwnerSummonNPCs, DWORD dwExpireTime, SLOTCODE SkillCode, const PLAYER_SUMMON_INFO* const summon_info); Summoned* CreateSummonDeadMonster( WORD NPCCode, const WzVector* pvPos, Character *pSummoner, SummonedNPCs* pOwnerSummonNPCs, SLOTCODE SkillCode ); CrystalWarp* CreateSummonCrystalWarp( WORD NPCCode, const WzVector* pvPos, DWORD dwGuildGuid, DWORD dwExpireTime ); Monster* CreateSummonByNPC( WORD NPCCode, const WzVector* pvPos, Character* pSummoner, SummonedNPCs* pOwnerSummonNPCs ); MapNpc* CreateMapNPC( WORD NPCCode, const WzVector* pvPos, MAPOBJECT_INFO* pMapInfo ); TotemNpc* CreateTotemNPC( WORD NPCCode, const WzVector* pvPos, Player* pSummoner, SCItemSlot & IN slot ); Collection* CreateCollection( MAPOBJECT_INFO *pMapInfo ); Monster* SpawnMonster( UnitRegenInfo* pUnitRegenInfo ); Item* CreateItem( const WzVector* pvPos, DWORD dwPlayerKey, DWORD dwFromMonsterKey, SCItemSlot & slot ); Item* CreateMoney(const WzVector* creating_pos, DWORD owner_key, DWORD from_monster_key, const MONEY& money); BOOL KillNPC(Player* pPlayer, NPC* pNPC, BOOL bIsDrop, BOOLEAN bBrd = TRUE); BOOL GmDamageNPC(Player* pPlayer, NPC* pNPC, const FLOAT fDamagePercent); VOID KillAllNPC( Player* pPlayer, int iRange, const FLOAT fDamagePercent ); VOID KillAllItem( Player* pPlayer, int iRange ); VOID KillOneMonster( NPC* pNPC, Player* pPlayer, BOOL IsExpItemDrop ); VOID KillMonster( MONSTERCODE MonsterCode, Player* pPlayer, BOOL IsExpItemDrop ); // add a function to support gm command 'pickup'. the pick up event has many events \ // even though the all acquisition by gm command is a test. bool PickupAllItems(Player* gm_player, bool use_duplicable_slot_mode); private: Monster* AllocMonster( WORD NPCCode, BYTE byMoveType, DWORD dwMoveAreaID ); }; //¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬¦¬ // inline VOID GameField::SendPacketAround( const SECTOR_IDX sector_idx, MSG_BASE_FORWARD* pMsg, WORD wSize, const DWORD except_objkey ) { SendExPacketAround( sector_idx, 1, reinterpret_cast(&pMsg), &wSize, except_objkey ); } inline VOID GameField::SendPacketToAll( MSG_BASE_FORWARD* pMsg, WORD wSize, const DWORD except_objkey ) { SendExPacketToAll( 1, reinterpret_cast(&pMsg), &wSize, except_objkey ); } //__NA000000_090716_HIGH_LOAD_BALANCED_NETWORK_TUNEUP__ // (WAVERIX) (090716) (ADD-IN) for High-load balanced network support inline VOID GameField::SendPacketToAgent(MSG_BASE_FORWARD* pMsg, WORD wSize) { SendExPacketToAgent(1, reinterpret_cast(&pMsg), &wSize); } template< typename _MSGSUBTYPE > inline void GameField::SendPacketAroundForSync(Character* const sender, const _MSGSUBTYPE* const sub_msg, const BOOLEAN post_action) { if (sender == NULL) { return; } const BYTE _TAG = sub_msg->value; SendPacketAroundForSync_(sender->GetSectorIndex(), _TAG, static_cast(const_cast<_MSGSUBTYPE*>(sub_msg)), sub_msg->GetSize(), post_action); } // f110106.1L, added by _NA001605_EP2_CHANGE_SKILL_BROADCASTER_ template< typename _MSGSUBTYPE > inline void GameField::SendPacketAroundForSync(const SECTOR_IDX coordinates, const _MSGSUBTYPE* const sub_msg) { const BYTE _TAG = sub_msg->value; SendPacketAroundForSync_(coordinates, _TAG, static_cast(const_cast<_MSGSUBTYPE*>(sub_msg)), sub_msg->GetSize(), false); } inline VOID GameField::SendPacket( Player* const pReceiver, MSG_BASE_FORWARD* pMsg, WORD wSize ) { SendExPacket( pReceiver, 1, (BYTE**)&pMsg, &wSize ); } inline void GameField::SendPacketToSector(const SECTOR_IDX sector_idx, MSG_BASE_FORWARD* pMsg, WORD wSize, const DWORD except_objkey) { SendExPacketToSector(sector_idx, 1, reinterpret_cast(&pMsg), &wSize, except_objkey); } // (CHANGES) (f100504.1L) change the interface specification to support a complex condition // the replacement facility for SendXXPacketToSector inline void GameField::SendPacketToSector(const SECTOR_IDX sector_idx, MSG_BASE_FORWARD* pMsg, WORD wSize, IObjectFinder* finder) { SendExPacketToSector(sector_idx, 1, reinterpret_cast(&pMsg), &wSize, finder); } // _NA_002098_20110307_ADD_NPC_CONTROL_TRIGGER_BASE inline ns_trigger::TriggerNpcLinkMatchTable* GameField::GetNpcTriggerEvents() const { return npc_trigger_events_; };