#include "stdafx.h" #include "./DropManager.h" //================================================================================================== #include #include // #include #include "StatisticsManager.h" #include "FunctionalRestrictManager.h" #include "GameZone.h" #include "GameField.h" #include "GameHuntingRoom.h" #include "ItemManager.h" #include "StatusManager.h" // #include "QuestInfoManagerEx.h" #include "QuestManager_Concrete.h" #include "GameParty/NewGamePartyManager.h" #include #include #include "DropRatioInfoList.h" //================================================================================================== DropManager g_DropManager; //================================================================================================== namespace ns_functor { ; inline static BOOL _CheckValidPlayer(Player* IN player, GameZone* IN drop_zone) { GameZone* pPlayerZone = player->GetGameZonePtr(); return (pPlayerZone && (pPlayerZone->GetKey() == drop_zone->GetKey()) && player->IsAlive()); } inline static BOOL _CheckFindQuest(Player* IN player, QCODE questCode) { return player && player->GetQuestManager()->FindQuest(questCode); } class QuestItemDropControl { typedef DWORD QUEST_IDX_BITSET; typedef QCODE QUEST_CODE_TYPE; typedef DWORD QUEST_DROPIDX_TYPE; static const DWORD MAX_QUEST_ITEM_DROP_NUM = BASE_NPCINFO::MAX_QUEST_ITEM_DROP_NUM; static const QUEST_IDX_BITSET QUEST_IDX_BITSET_EMPTY = 0; public: QuestItemDropControl(const BASE_NPCINFO* pInfo) : m_pNpcInfo(pInfo) { #ifdef _NA_004509_20120314_QUESTDROPINDEX10 BOOST_STATIC_ASSERT(MAX_QUEST_ITEM_DROP_NUM==10); #else BOOST_STATIC_ASSERT(MAX_QUEST_ITEM_DROP_NUM==5); #endif //_NA_004509_20120314_QUESTDROPINDEX10 m_QuestCodes = m_pNpcInfo->m_QuestCode; m_QuestDrops = m_pNpcInfo->m_dwQuestDropIndex; ZeroMemory(m_Quests, sizeof(m_Quests)); } BOOL CheckAndAlignQuest(const DWORD index) { if (MAX_QUEST_ITEM_DROP_NUM > index) { if (m_QuestCodes[index] && m_QuestDrops[index]) { m_CheckIndex = index; return true; } } m_CheckIndex = MAX_QUEST_ITEM_DROP_NUM; return false; } QCODE GetCurCheckQuestCode() { return MAX_QUEST_ITEM_DROP_NUM > m_CheckIndex ? m_QuestCodes[m_CheckIndex] : 0; } DWORD GetCurCheckQuestDrop() { return MAX_QUEST_ITEM_DROP_NUM > m_CheckIndex ? m_QuestDrops[m_CheckIndex] : 0; } private: const BASE_NPCINFO* m_pNpcInfo; const QUEST_CODE_TYPE* m_QuestCodes; const QUEST_DROPIDX_TYPE* m_QuestDrops; DWORD m_CheckIndex; Quest* m_Quests[MAX_QUEST_ITEM_DROP_NUM]; }; class SearchPartyHasQuest : public std::unary_function { public: SearchPartyHasQuest(QuestItemDropControl& IN rDropControl, Player* IN pMember) : m_rDropControl(rDropControl), m_pMember(pMember) { m_bSatisfy = false; } void Reuse() { m_bSatisfy = false; } BOOL IsSatisfy() const { return m_bSatisfy; } BOOL operator () (Player* player) const { if (m_bSatisfy) { return true; }; if (_CheckValidPlayer(player, m_pMember->GetGameZonePtr()) && _CheckFindQuest(player, m_rDropControl.GetCurCheckQuestCode())) { m_bSatisfy = true; return true; } return false; } private: QuestItemDropControl& m_rDropControl; mutable BOOL m_bSatisfy; Player* m_pMember; }; //================================================================================================== #if defined(_YJ_TOOLTIP_ON_TEXT_001277) && !defined(__NA_0_20081124_PARTY_REFACTORING_GAMESERVER) #error "Impossible Build!! - Reason: Violation Dependency Chain" #endif template class AcquireQuestItem : public std::unary_function { public: AcquireQuestItem(QCODE aQuestCode, ZONEKEY aZoneKey, SCItemSlot* pQuestItem) : m_QuestCode(aQuestCode) // Äù½ºÆ® ÄÚµå , m_ZoneKey(aZoneKey) // ¼ÒÀ¯±ÇÀÚÀÇ Á¸Å° , m_pQuestItem(pQuestItem) // »ý¼ºµÈ Äù½ºÆ®¾ÆÀÌÅÛ ½½·Ô { } void operator() (Character* character) const { Player* player = static_cast(character); if (player == NULL) { return; }; GameZone* game_zone = character->GetGameZonePtr(); if (game_zone == NULL) { return; }; if (!(player->IsDead()) && // »ýÁ¸ (game_zone->GetKey() == m_ZoneKey) && // ¼ÒÀ¯±ÇÀÚ¿Í °°Àº Á¸ (player->GetQuestManager()->FindQuest(m_QuestCode))) // Äù½ºÆ® ¼ÒÀ¯ { #ifdef _YJ_TOOLTIP_ON_TEXT_001277 WORD itemCode = m_pQuestItem->GetItemCode(); POSTYPE itemNum = m_pQuestItem->GetNum(); m_Packet.m_QuestCode = m_QuestCode; //!~ #3669 Äù½ºÆ® ¾ÆÀÌÅÛ ¼öÁý ¿Ï·á½Ã, ´õÀÌ»ó Äù½ºÆ® ¾ÆÀÌÅÛÀ» ÀÔ¼öÇÏÁö ¾ÊÀ½ - arycoat 2011.11.15 ItemManager* item_manager = player->GetItemManager(); QuestInfo* quest_info = g_QuestInfoManager.FindQuestInfo(m_QuestCode); if(!quest_info) { SUNLOG(eCRITICAL_LOG, _T("[%s:%d] cannot find quest info : %d"), __FUNCTION__, __LINE__, m_QuestCode); return; } QUEST_CONDITION_ITEM_INFO* quest_condition_item_info = \ static_cast( quest_info->FindCompleteCondition(eQUEST_CONDITION_ITEM)); if(!quest_condition_item_info) { SUNLOG(eCRITICAL_LOG, _T("[%s:%d] cannot find quest complete condition item info : %d"), __FUNCTION__, __LINE__, m_QuestCode); return; } for(int i = 0; i < quest_condition_item_info->GetItemArrayCount(); ++i) { if(quest_condition_item_info->GetItemCode(i) == itemCode) { // ÃæºÐÇÑ °³¼öÀÇ ¾ÆÀÌÅÛÀÌ ÀÖ´ÂÁö üũ int item_count = quest_condition_item_info->GetItemNum(i); int ExistCount = item_manager->ExistItem(SI_INVENTORY, itemCode, item_count); if (ExistCount >= item_count) return; } } //~! RC::eITEM_RESULT ret = player->GetItemManager()->Obtain( \ (*m_pQuestItem), itemNum, &m_Packet.m_TotalInfo); if (ret == RC::RC_ITEM_SUCCESS) player->SendPacket(&m_Packet, m_Packet.GetSize()); #else static SCItemSlot ItemSlot; ItemSlot = *m_pQuestItem; if (RC::RC_ITEM_SUCCESS == player->GetItemManager()->Pick(1, ItemSlot, &m_Packet.m_ItemInfo)) { player->SendPacket(&m_Packet, m_Packet.GetSize()); } #endif } } private: QCODE m_QuestCode; ZONEKEY m_ZoneKey; SCItemSlot* m_pQuestItem; mutable _PackType m_Packet; }; }; //end of namespace 'ns_functor' //================================================================================================== // //{__NA000000_20090320_DELAY_ITEM_DROP_TIME struct DropManager::DelayDropInfo { DelayDropInfo() { ZeroMemory(this, static_cast(\ reinterpret_cast(&drop_timer_) - reinterpret_cast(this))); monster_grade_ = eNPC_GENERAL; } // GameField* game_field_; DWORD sector_index_; WzVector drop_center_pos_; // Player* owner_; DWORD monster_key_; const BASE_NPCINFO* monster_info_; eNPC_GRADE monster_grade_; LEVELTYPE monster_display_level_; // util::Timer drop_timer_; }; struct DropManager::DelayedFieldObject { GameField* game_field_; util::SimpleTimer delayed_drop_timer_; DWORD monster_key_; PLAYERKEY player_key_; bool is_item_object; WzVector drop_center_pos_; // MONEY scheduled_drop_money_; SCItemSlot scheduled_drop_item_; }; //================================================================================================== // void DropManager::Init(DWORD pool_size) { __UNUSED(pool_size); } void DropManager::OnFieldRelease(ZONEKEY zone_key) { DELAY_DROPINFO_LIST::_Pairii ranges = delay_drop_info_list_.equal_range(zone_key); if (ranges.first == ranges.second) { // changes comparision return; }; DELAY_DROPINFO_LIST::const_iterator it = ranges.first; for (; it != ranges.second; ++it) { DelayDropInfo* delay_drop_info = it->second; if (FlowControl::FCAssert(delay_drop_info != NULL) == false) { continue; }; TAllocDelete(DelayDropInfo, delay_drop_info); }; delay_drop_info_list_.erase(ranges.first, ranges.second); // } void DropManager::DelayedDrop_(GameField* game_field, DWORD sector_index, const WzVector* origin_pos, Player* owner, DWORD monster_key, const BASE_NPCINFO* monster_info, eNPC_GRADE npc_grade, LEVELTYPE monster_display_level) { static const DWORD& kDelayInterval = \ ServerOptionParserEx::Instance()->GetServerOption().m_DelayDropTime; if (game_field == NULL) { return; }; DelayDropInfo* const delay_drop_info = TAllocNew(DelayDropInfo); delay_drop_info->game_field_ = game_field; delay_drop_info->sector_index_ = sector_index; delay_drop_info->owner_ = owner; delay_drop_info->monster_key_ = monster_key; delay_drop_info->monster_info_ = monster_info; delay_drop_info->monster_grade_ = npc_grade; delay_drop_info->monster_display_level_ = monster_display_level; delay_drop_info->drop_center_pos_ = *origin_pos; delay_drop_info->drop_timer_.SetTimer(kDelayInterval); ZONEKEY zone_key = game_field->GetGameZone()->GetKey(); delay_drop_info_list_.insert(DELAY_DROPINFO_LIST::value_type(zone_key, delay_drop_info)); } void DropManager::UpdateDelayedItemDrop() { DELAY_DROPINFO_LIST::iterator it = delay_drop_info_list_.begin(); while (it != delay_drop_info_list_.end()) { DelayDropInfo* delay_drop_info = it->second; if (FlowControl::FCAssert(delay_drop_info != NULL) == false) { it = delay_drop_info_list_.erase(it); continue; }; const bool dropped = (delay_drop_info->drop_timer_.IsExpiredManual(false) != false); if (dropped) { this->InstantDrop_(delay_drop_info->game_field_, delay_drop_info->sector_index_, &delay_drop_info->drop_center_pos_, delay_drop_info->owner_, delay_drop_info->monster_key_, delay_drop_info->monster_info_, delay_drop_info->monster_grade_, delay_drop_info->monster_display_level_); // TAllocDelete(DelayDropInfo, delay_drop_info); it = delay_drop_info_list_.erase(it); continue; }; // ++it; // }; //end 'while' } //}__NA000000_20090320_DELAY_ITEM_DROP_TIME //================================================================================================== //================================================================================================== //================================================================================================== DropManager::DropManager() { } DropManager::~DropManager() { } void DropManager::Release() { DELAYEDFOBJ_LIST::const_iterator it = delayed_field_object_list_.begin(); const DELAYEDFOBJ_LIST::const_iterator end = delayed_field_object_list_.end(); // CHANGES: f110715.2L, fixed the infinite loop for (; it != end; ++it) { DelayedFieldObject* delayed_field_object = *it; TAllocDelete(DelayedFieldObject, delayed_field_object); } delayed_field_object_list_.clear(); drop_core_.Unload(); } void DropManager::InstantDrop_(GameField* game_field, DWORD sector_index, const WzVector* origin_pos, Player* owner, DWORD monster_key, const BASE_NPCINFO* monster_info, eNPC_GRADE npc_grade, LEVELTYPE monster_display_level) { __UNUSED(sector_index); if (game_field == NULL) { return; }; GameZone* const game_zone = game_field->GetGameZone(); if (game_zone == NULL) { return; }; if (g_FunctionalRestrictMgr.IsRestrictFunction(eFUNCTIONALRESTRICT_USE_MONSTERDROP)) { static bool reported = false; if (reported == false) { SUNLOG(eCRITICAL_LOG, "¸ó½ºÅÍ µå¶ø ¼­ºñ½º°¡ ÁßÁöÁßÀÔ´Ï´Ù"); reported = true; }; return; }; if (FlowControl::FCAssert(npc_grade < eNPC_GRADE_MAX) == false) { return; }; // NOTE: f110414.4L, apply weight value about heim based on number of party members. float heim_weight_based_on_party_members = 1.0f; DWORD owner_key = 0; //---------------------------------------------------------------------------------------------- if (owner) { // µô·¹ÀÌ µå¶ø¿¡ µû¶ó °£´ÜÇÑ À¯È¿¼º üũ ÇÑ´Ù. if (0 == owner->GetObjectKey()) { SUNLOG(eCRITICAL_LOG, _T("|[%s]|À¯È¿ÇÏÁö ¾ÊÀº Ç÷¹À̾îŰ|"), __FUNCTION__); return; }; GameZone* const game_zone_of_owner = owner->GetGameZonePtr(); if (game_zone_of_owner == NULL) { // ¸ó½ºÅÍ ÀâÀºÈÄ Á¢¼Ó Á¾·á½Ã SUNLOG(eCRITICAL_LOG, _T("|[%s]|À¯È¿ÇÏÁö ¾ÊÀº Owner|"), __FUNCTION__); return; }; if (game_zone_of_owner != game_zone) { SUNLOG(eCRITICAL_LOG, _T("|[%s]|OwnerÀÇ Á¸Å°¿Í ÇʵåÀÇ Á¸Å°°¡ ÀÏÄ¡ÇÏÁö ¾Ê´Â´Ù"), __FUNCTION__); return; }; // ÆÄƼ »óÅÂÀÌ¸é ¾ÆÀÌÅÛ ºÐ¹è ½Ã½ºÅÛÀ» Àû¿ë ½Ã۰í ÀÖ´Â ½ÃÁ¡ÀÌ´Ù. const WORD party_key = owner->GetPartyState().GetPartyKey(); if (party_key) { owner_key = owner->GetObjectKey(); #ifdef _NA_0_20111021_EDIT_HEIM_DROP_RATIO_BY_PARTY_USER_COUNT // _CHINA int party_members = NewGamePartyManager::Instance()->FindNearPartyUserCount(owner); heim_weight_based_on_party_members = ns_formula::GetRoomHeimPartyBonusFactor(party_members); #else // CHANGES: f110414.4L, apply weight value about heim based on number of party members. const BaseParty* party = static_cast(\ NewGamePartyManager::Instance()->FindParty(party_key)); if (party != NULL) { int number_of_party_members = party->GetMemberNum(); #ifdef _NA_004651_20120404_CHANGE_PARTY_HEIM_WEIGHT_v02 bool zone_type_top_of_trial = false; if (game_zone->GetZoneType() == eZONETYPE_INSTANCE) { GameInstanceDungeon* instance_dungeon = \ static_cast(game_zone); if (instance_dungeon && \ instance_dungeon->GetTypeOfIndun() == INDUN_KIND_TOP_OF_TRIAL) { zone_type_top_of_trial = true; } } /* // ºûÀÇ ½Ã·Ã ÇÏÀÓ µå¶ø ¹æ½ÄÀ» ¹Ì¼Ç µå¶ø ¹æ½ÄÀ» µû¸£µµ·Ï ÇÔ - arycoat 2014.08.11 #ifdef _NA_007156_20140703_TOP_OF_TRIAL_LIGHT if (game_zone->GetZoneType() == eZONETYPE_MISSION) { GameMissionRoom* mission_room = static_cast(game_zone); if (mission_room) { PartyZoneType party_zone_type = mission_room->GetPartyZoneType(); if (party_zone_type == PartyOfTopOfTrialLight_normal || party_zone_type == PartyOfTopOfTrialLight_cash) { zone_type_top_of_trial = true; } } } #endif //_NA_007156_20140703_TOP_OF_TRIAL_LIGHT */ heim_weight_based_on_party_members = \ (zone_type_top_of_trial) ? \ ns_formula::GetRoomHeimPartyBonusFactorType2(number_of_party_members) : \ ns_formula::GetRoomHeimPartyBonusFactor(number_of_party_members); #else heim_weight_based_on_party_members = ns_formula::GetRoomHeimPartyBonusFactor(number_of_party_members); #endif //_NA_004651_20120404_CHANGE_PARTY_HEIM_WEIGHT_v02 }; #endif //_NA_0_20111021_EDIT_HEIM_DROP_RATIO_BY_PARTY_USER_COUNT } else { const SERVER_COMMON_OPTION& server_option = \ ServerOptionParserEx::Instance()->GetServerOption(); if (server_option.m_byApplyItemOwnerShipByLevel != false) { //·¹º§Â÷°¡ 10ÀÌÇϸ¸ ¼ÒÀ¯±Ç Á¸Àç. int LVInterval = (owner->GetLevel() - monster_display_level); if (LVInterval < DONT_DROP_LEVEL_INTERVAL) { owner_key = owner->GetObjectKey(); }; } else { owner_key = owner->GetObjectKey(); }; } } //---------------------------------------------------------------------------------------------- #if SUN_CODE_BACKUP FLOAT PlusBonusPercent = 1.0f; if (game_zone->GetZoneType() == eZONETYPE_HUNTING) { // ÇåÆÃ º¸³Ê½º °¡ÁßÄ¡ // ???? -> °æÀïÇåÆÃÀ¸·Î ¹Ù²ã¾ß ÇÏÁö ¾Ê³ª? GameHuntingRoom* pHuntingRoom = static_cast(game_zone); if (pHuntingRoom->GetAdditionalInfo()->m_Bonus == eHUNTING_BONUS_TYPE_ITEM) { PlusBonusPercent = 1.1f; }; } #endif // CHANGES: f110715.2L, removed the unused section // CHANGES: f110414.4L, apply HEIM weight value about heim based on number of party members. // subtract default percentage to prevent the point that is percentage of a percentage. float added_bonus_percentage = heim_weight_based_on_party_members; //---------------------------------------------------------------------------------------------- // Äù½ºÆ® ¾ÆÀÌÅÛ µå¶ø DropQuest(game_field, monster_info, owner, npc_grade, added_bonus_percentage, game_zone, origin_pos, monster_key, owner_key); //---------------------------------------------------------------------------------------------- static SCItemSlot dropping_item_slot_static; // typedef const DWORD DropIndexArray[_countof(monster_info->m_dwFieldDropIndex)]; const DropIndexArray* __drop_index_array = (monster_info->m_bRegion == 0) ? &monster_info->m_dwDropIndex // °øÅë Drop : (g_pGameServer->GetServerType() == FIELD_SERVER) ? &monster_info->m_dwFieldDropIndex // Çʵå Drop : &monster_info->m_dwBattleDropIndex; // ¹èƲÁ¸ Drop // const DropIndexArray& drop_index_array = *__drop_index_array; bool gm_drop_process = false; ;{ const StatusField& status_field = owner->GetStatusManager()->Status; if (status_field.FIELD & status_field.ENABLE_GM_DROP_LIST_ALL) { gm_drop_process = true; }; }; // ±âº» ¾ÆÀÌÅÛ µå¶ø for (int i = 0; i < _countof(drop_index_array); ++i) { const DWORD drop_index = drop_index_array[i]; if (0 == drop_index) { continue; }; BOOST_STATIC_ASSERT(\ _countof(drop_index_array) == _countof(monster_info->m_bOwnerShipForDropIndex)); //------------------------------------------------------------------------------------------ if (gm_drop_process) { DWORD temp_player_key = owner_key; if (monster_info->m_bOwnerShipForDropIndex[i] == false) { temp_player_key = 0; }; this->GMDrop(game_field, origin_pos, owner, monster_key, monster_info, game_zone->GetZoneType(), drop_index, npc_grade, added_bonus_percentage, temp_player_key); continue; }; //------------------------------------------------------------------------------------------ // NOTE: default drop processing int number_of_drop_items = 0; MONEY dropping_money = 0; DWORD decided_seed_value = 0; eDROP_TYPE_ dropping_type; SCItemSlot& dropping_item_slot = dropping_item_slot_static; bool does_drop_exist = (drop_core_.Drop(game_zone->GetZoneType(), drop_index, npc_grade, added_bonus_percentage, dropping_type, dropping_money, dropping_item_slot, decided_seed_value, &number_of_drop_items) != false); if (does_drop_exist == false) { continue; }; DWORD temp_player_key = owner_key; // ¼ÒÀ¯±ÇÀÌ ¾ø´Ù¸é if (monster_info->m_bOwnerShipForDropIndex[i] == false) { temp_player_key = 0; }; //------------------------------------------------------------------------------------------ ;;;; if (dropping_type == DROP_TYPE_ITEM) { if (temp_player_key != 0) { temp_player_key = GetSecondItemOwnershipUserKey(owner, dropping_item_slot); }; // NOTE: f110401.3L for (int counter = 0; counter < number_of_drop_items; ++counter) { this->DropItem(game_field, origin_pos, monster_key, temp_player_key, monster_info, dropping_item_slot); }; } else if (dropping_type == DROP_TYPE_MONEY) { ASSERT(decided_seed_value != 0 && number_of_drop_items == 1); const int log_type = (decided_seed_value > 1) ? MONEY_MONSTER_JACKPOT_DROP : MONEY_MONSTER_DROP; // ¸ó½ºÅÍ µ· µå¶ø ·Î±× GAMELOG->LogMonsterMoneyDrop(log_type, dropping_money, monster_info->m_MonsterCode, npc_grade, game_zone->GetMapCode(), *origin_pos, game_zone->GetKey()); #ifdef _NA_007750_20141113_WZDAT_MODIFY_LOG GameBattleResult* battle_result = game_zone->GetGameBattleResult(); if (battle_result != NULL) { battle_result->AddToTalDropHeim(dropping_money); } #endif // _NA_007750_20141113_WZDAT_MODIFY_LOG if (temp_player_key != 0) { temp_player_key = GetSecondHeimOwnershipUserKey(owner); }; this->DropMoney((log_type == MONEY_MONSTER_JACKPOT_DROP), game_field, origin_pos, monster_key, temp_player_key, dropping_money); }; //------------------------------------------------------------------------------------------ }; //end 'for' } DWORD DropManager::GetSecondItemOwnershipUserKey(Player* pre_owner, SCItemSlot& dropped_item) { // NOTE: f110424.1L, logic improvements DWORD default_owner_key = pre_owner->GetObjectKey(); GameField* const game_field = pre_owner->GetField(); if (game_field == NULL) { return 0; }; const BASE_ITEMINFO* const item_info = dropped_item.GetItemInfo(); // REMOVED: rules = ¹èƲ¼­¹ö´Â ¾ÆÀÌÅÛº°·Î ¾ÆÀÌÅۺйè Àû¿ë¿©ºÎ¸¦ È®ÀÎÇÑ´Ù. //if (g_pGameServer->GetServerType() == BATTLE_SERVER && \ // item_info->IsApplyItemDistribution() == false) { // return default_owner_key; //}; #ifdef _NA_003033_20110831_DICECAST_ITEM_ROUTING if(item_info) { // ÁÖ»çÀ§ ¹æ½Ä ȹµæ ¾ÆÀÌÅÛµµ ºÐ¹è±ÔÄ¢À» Àû¿ëÇÏÁö ¾ÊÀ½. if(BYTE dicecast_type = item_info->dice_cast_type > 0) { bool all_party_member_obtain_type = false; #ifdef _NA_004204_20120131_BATTLE_ZONE_PARTY_OBTAIN // ÆÄƼ¿ø Àü¿ø ȹµæ Á¸¿¡¼­´Â ÁÖ»çÀ§ Àû¿ë¾ÈÇÔ. arycoat.2012.02.08 sPOLICY_ZONE& Policyment = game_field->GetGameZone()->Policyment; if(Policyment.FIELD & Policyment.ENABLE_ITEM_OBTAIN_ALL_PARTY_MEMBER) { all_party_member_obtain_type = true; } #endif //_NA_004204_20120131_BATTLE_ZONE_PARTY_OBTAIN eITEM_DISTRIBUTION_TYPE type = \ static_cast( \ NewGamePartyManager::Instance()->GetDistributionType( \ pre_owner->GetPartyState().GetPartyKey())); if( all_party_member_obtain_type == false && (type == eITEM_DISTRIBUTION_DICE_AND_DEFAULT || \ type == eITEM_DISTRIBUTION_DICE_AND_FIFO)) { dropped_item.SetDiceCastType(dicecast_type); return default_owner_key; } } } #endif //_NA_003033_20110831_DICECAST_ITEM_ROUTING #ifdef _NA_002399_20110323_ITEM_ROUTING_METHOD_CHANGE if(item_info) { // AC¾ÆÀÌÅÛÀº ºÐ¹è±ÔÄ¢À» Àû¿ëÇÏÁö ¾ÊÀ½. arycoat - 2011.07.20 const eITEMTYPE type = static_cast(item_info->m_wType); if (type == eITEMTYPE_AC) { return default_owner_key; } } DWORD next_owner_key = default_owner_key; if (WORD party_key = pre_owner->GetPartyState().GetPartyKey()) { const eCHAR_TYPE char_type = item_info->GetFirstAvailableClass(); if (NewGamePartyManager* party_manager = NewGamePartyManager::Instance()) { next_owner_key = party_manager->GetDistributionMemberKey(party_key, default_owner_key, char_type); if(next_owner_key != 0) { // ¾ÆÀÌÅÛ ¼ÒÀ¯±ÇÀÚ°¡ Á×¾ú°Å³ª ´Ù¸¥¸Ê¿¡ ÀÖÀ»°æ¿ì ÀÚÀ¯È¹µæ - arycoat 2011.07.20 Player* player = PlayerManager::Instance()->FindPlayerByObjKey(next_owner_key); if(player) { if(player->IsDead() || player->GetField() != game_field) { next_owner_key = 0; } } else { next_owner_key = 0; } } }; } #else DWORD next_owner_key = default_owner_key; if (WORD party_key = pre_owner->GetPartyState().GetPartyKey()) { const eCHAR_TYPE char_type = item_info->GetFirstAvailableClass(); if (NewGamePartyManager* party_manager = NewGamePartyManager::Instance()) { next_owner_key = party_manager->GetDistributionMemberKey(party_key, default_owner_key, char_type); // no-check member_key integrity }; } #endif //_NA_002399_20110323_ITEM_ROUTING_METHOD_CHANGE return next_owner_key; } DWORD DropManager::GetSecondHeimOwnershipUserKey(Player* pre_owner) { GameField *game_field = pre_owner->GetField(); if (game_field == NULL) { return 0; }; const DWORD default_owner_key = pre_owner->GetObjectKey(); #ifdef _NA_002399_20110323_ITEM_ROUTING_METHOD_CHANGE // ÇÏÀÓÀº ºÐ¹è±ÔÄ¢À» Àû¿ëÇÏÁö ¾ÊÀ½. arycoat - 2011.07.20 #else const WORD party_key = pre_owner->GetPartyState().GetPartyKey(); if (party_key == 0) { return default_owner_key; }; // DWORD member_key = NewGamePartyManager::Instance()->GetDistributionMemberKey( party_key, default_owner_key, eCHAR_TYPE_MAX); if (Player* member = PlayerManager::Instance()->FindPlayerByObjKey(member_key)) { return member_key; } #endif //_NA_002399_20110323_ITEM_ROUTING_METHOD_CHANGE return default_owner_key; } void DropManager::DropQuest(GameField* game_field, const BASE_NPCINFO* monster_info, Player* owner, eNPC_GRADE npc_grade, float added_bonus_percentage, GameZone* game_zone, const WzVector* creating_pos, DWORD monster_key, DWORD unused__owner_object_key) { __UNUSED((game_field, creating_pos, monster_key, unused__owner_object_key)); // assert(owner->GetPlayerKey() == dwPlayerKey) GameZone* game_zone_of_owner = owner->GetGameZonePtr(); if (game_zone_of_owner == NULL) { return; }; ns_functor::QuestItemDropControl questControl(monster_info); ns_functor::SearchPartyHasQuest searchControl(questControl, owner); WORD PartyKey = owner->GetPartyState().GetPartyKey(); MONEY DroppedMoney = 0; DWORD dwDecidedSeed = 0; static SCItemSlot QuestItemSlot; eDROP_TYPE_ DroppedType; int number_of_drop_items = 0; for (DWORD index = 0 ; index < BASE_NPCINFO::MAX_QUEST_ITEM_DROP_NUM; ++index) { if (false == questControl.CheckAndAlignQuest(index)) { continue; }; if (!NewGamePartyManager::Instance()->For_eachPlayers(PartyKey, searchControl)) { searchControl(owner); }; if (searchControl.IsSatisfy() && drop_core_.Drop(game_zone->GetZoneType(), questControl.GetCurCheckQuestDrop(), npc_grade, added_bonus_percentage, DroppedType, DroppedMoney, QuestItemSlot, dwDecidedSeed, &number_of_drop_items)) { if (DROP_TYPE_ITEM != DroppedType || number_of_drop_items != 1) { SUNLOG(eCRITICAL_LOG, _T("Drop of QuestItem is WRONG!!! : ") _T("MONSTER_NAME[%s], MONSTER_CODE[%d], QUEST_NUM[%d], ") _T("number of separately paid items = %d"), monster_info->m_pszName, monster_info->m_NCode, index, number_of_drop_items); return; } // ¾ÆÀÌÅÛ È¹µæ #ifdef _YJ_TOOLTIP_ON_TEXT_001277 ns_functor::AcquireQuestItem Opr(\ questControl.GetCurCheckQuestCode(), game_zone_of_owner->GetKey(), &QuestItemSlot); if (!NewGamePartyManager::Instance()->For_eachPlayers(PartyKey, Opr)) { Opr(owner); } #else AcquireQuestItem Opr(questControl.GetCurCheckQuestCode(), game_zone_of_owner->GetKey(), &QuestItemSlot); if (!NewGamePartyManager::Instance()->For_eachPlayers(PartyKey, Opr)) { Opr(owner); } #endif } searchControl.Reuse(); } } void DropManager::DropMoney(bool jackpot, GameField* game_field, const WzVector* origin_pos, DWORD monster_key, DWORD player_key, MONEY& dropped_money) { // µå¶ø ÇÏÀÓÀ² 2¹è if (eSERVER_TESTLIVE == g_pGameServer->GetMode()) { dropped_money <<= 1; }; if (dropped_money == 0) { SUNLOG(eCRITICAL_LOG, "¸ó½ºÅÍ µå¶øµÇ´Â µ·ÀÌ 0ÀÌ´Ù.\n"); }; WzVector droppable_pos; if (jackpot == false) { if (game_field->GetRandomPosInAround(origin_pos, 2, droppable_pos) == false) { droppable_pos = *origin_pos; }; bool succeeded_dropped = this->DropMoneyToField(\ game_field, &droppable_pos, player_key, monster_key, dropped_money); assert(succeeded_dropped);__TOUCHED(succeeded_dropped); return; }; assert(jackpot != false); //< 1¸¸ ÀÌ»óÀÇ ±Ý¾×ÀÏ ¶§ ÀèÆÌ // NOTE: delayed dropping jackpot playing MONEY remains_money = dropped_money; DWORD sliced_money_tokens[4] = { util::LL_Round(remains_money * 0.03f), util::LL_Round(remains_money * 0.04f), util::LL_Round(remains_money * 0.05f), util::LL_Round(remains_money * 0.06f), }; for (int interval_index = 0; remains_money > 0; ++interval_index, (interval_index &= 0x1F)) { BOOST_STATIC_ASSERT(util::bit_count_<_countof(sliced_money_tokens)>::value == 1); MONEY sliced_money = sliced_money_tokens[\ interval_index & (_countof(sliced_money_tokens) - 1)]; if (remains_money < sliced_money) { sliced_money = remains_money; }; remains_money -= sliced_money; // if (game_field->GetRandomPosInAround(origin_pos, 3, droppable_pos) == false) { droppable_pos = *origin_pos; }; bool succeeded_dropped = DropMoneyToField(\ game_field, &droppable_pos, player_key, monster_key, sliced_money, (100 * interval_index)); assert(succeeded_dropped);__TOUCHED(succeeded_dropped); }; // ÀèÆÌ Åë°è·Î ±â·Ï(¼ºÇöâ) //g_pGameServer->AddJackpot(dropped_money); g_StatisticsManager.PlusStatisticType(eSTATISTIC_JACKPOT_COUNT, 1); g_StatisticsManager.PlusStatisticType(eSTATISTIC_JACKPOT_MONEY, dropped_money); } void DropManager::DropItem(GameField* game_field, const WzVector* creating_pos, DWORD monster_key, DWORD player_key, const BASE_NPCINFO* npc_info, SCItemSlot& dropped_item_slot) { // (CHANGES) (WAVERIX) add item rule check const nsSlot::ItemRuleInfo& item_rule_info = dropped_item_slot.GetItemRuleInfo(); if (item_rule_info.is_valid_item == false) { return; }; WzVector droppable_pos; if (game_field->GetRandomPosInAround(creating_pos, 3, droppable_pos) == false) { droppable_pos = *creating_pos; }; BOOL dropped_result = DropItemToField(game_field, &droppable_pos, player_key, monster_key, dropped_item_slot); if (dropped_result != false) { GameZone* game_zone = game_field->GetGameZone(); // ¸ó½ºÅÍ ¾ÆÀÌÅÛ µå¶ø ·Î±× ³²±â±â GAMELOG->LogMonsterItemDrop(dropped_item_slot, npc_info->m_MonsterCode, npc_info->m_Level, game_zone->GetMapCode(), droppable_pos, game_zone->GetKey()); // ¸ó½ºÅÍ ¾ÆÀÌÅÛ µå¶ø ·Î±× ³²±â±â ³¡ }; } bool DropManager::DropItemToField(GameField* game_field, const WzVector* creating_pos, PLAYERKEY player_key, DWORD from_monster_key, SCItemSlot& drop_item_slot, DWORD delaying_interval) { if (game_field == NULL || game_field->IsReady() == false) { return false; } else if (delaying_interval == 0) { // instant drop Item* field_item = game_field->CreateItem(creating_pos, player_key, from_monster_key, drop_item_slot); if (field_item != NULL) { return true; }; } else if (DelayedFieldObject* scheduled_item = TAllocNew(DelayedFieldObject)) { // delayed drop scheduled_item->drop_center_pos_ = *creating_pos; scheduled_item->game_field_ = game_field; scheduled_item->delayed_drop_timer_.SetTimer(delaying_interval); scheduled_item->monster_key_ = from_monster_key; scheduled_item->player_key_ = player_key; scheduled_item->is_item_object = true; scheduled_item->scheduled_drop_item_.Copy(drop_item_slot); delayed_field_object_list_.push_back(scheduled_item); return true; } return false; } bool DropManager::DropMoneyToField(GameField* game_field, const WzVector* creating_pos, PLAYERKEY player_key, DWORD from_monster_key, const MONEY& money, DWORD delaying_interval) { if (game_field == NULL || game_field->IsReady() == false) { return false; } else if (delaying_interval == 0) { // instant drop Item* field_item = game_field->CreateMoney(creating_pos, player_key, from_monster_key, money); if (field_item != NULL) { return true; }; } else if (DelayedFieldObject* scheduled_item = TAllocNew(DelayedFieldObject)) { // delayed drop scheduled_item->drop_center_pos_ = *creating_pos; scheduled_item->game_field_ = game_field; scheduled_item->delayed_drop_timer_.SetTimer(delaying_interval); scheduled_item->monster_key_ = from_monster_key; scheduled_item->player_key_ = player_key; scheduled_item->is_item_object = false; scheduled_item->scheduled_drop_money_ = money; delayed_field_object_list_.push_back(scheduled_item); return true; } return false; } void DropManager::Process() { UpdateDelayedItemDrop(); DELAYEDFOBJ_LIST::iterator it = delayed_field_object_list_.begin(); const DELAYEDFOBJ_LIST::const_iterator end = delayed_field_object_list_.end(); while (it != end) { DelayedFieldObject* scheduled_item = *it; if (scheduled_item->delayed_drop_timer_.IsExpired() == false) { ++it; continue; }; // if (scheduled_item->is_item_object) { scheduled_item->game_field_->CreateItem(\ &scheduled_item->drop_center_pos_, scheduled_item->player_key_, scheduled_item->monster_key_, scheduled_item->scheduled_drop_item_); } else { scheduled_item->game_field_->CreateMoney(\ &scheduled_item->drop_center_pos_, scheduled_item->player_key_, scheduled_item->monster_key_, scheduled_item->scheduled_drop_money_); }; TAllocDelete(DelayedFieldObject, scheduled_item); it = delayed_field_object_list_.erase(it); } } BOOL DropManager::Load(eSCRIPT_CODE script_code, const TCHAR* file_name, BOOL bBigData, eSEPERATOR_MODE mode, const TCHAR* pack_file_name, BOOL bReload) { // NOTE: f110401.1L, added by _NA002479_20110401_DROP_RATIO_SELECTOR_EXTENTION drop_core_.SetupDropRatioTable(g_pGameServer->GetServerType() != FIELD_SERVER); // return drop_core_.Load(script_code, file_name, bBigData, mode, pack_file_name, bReload); } BOOL DropManager::SolarLoad(eSCRIPT_CODE script_code, BYTE* pSTREAM, DWORD dwSize, BOOL bBigData) { // NOTE: f110401.1L, added by _NA002479_20110401_DROP_RATIO_SELECTOR_EXTENTION drop_core_.SetupDropRatioTable(g_pGameServer->GetServerType() != FIELD_SERVER); // const char* file_name = FindFileName(script_code); drop_core_.InsertFileName(script_code, file_name); return drop_core_.SolarLoad(script_code, pSTREAM, dwSize, bBigData); } //================================================================================================== //==================================================================================================