#include "StdAfx.h" //_NA_005026_20120527_CHAOS_ZONE_BATTLE_GROUND #include "ChaosZoneSystem/BattleGroundManager.h" #include #include #include #include #include #include #include #include #include #ifdef _NA_008679_20160202_REWORK_BATTLEGROUND #include #endif // _NA_008679_20160202_REWORK_BATTLEGROUND #ifdef _NA_007135_20140402_MODIFY_BATTLE_GROUND_RESERVATION_AVAILABLE_IN_BATTLE_GROUND_CHANNEL #include #endif BattleGroundManager::BattleGroundManager() { battle_ground_member_pool_ = NULL; battle_ground_member_list_pool_ = NULL; //_NA_007065_20140217_BATTLEGROUND_REFACTORYING battleground_matching_system_ = NULL; } BattleGroundManager::~BattleGroundManager() { } void BattleGroundManager::Init() { //_NA_007065_20140217_BATTLEGROUND_REFACTORYING battleground_matching_system_ = new BattleGroundMatchingSystem(); battleground_matching_system_->Init(); key_generater_.Create(1, 6000); battle_ground_member_pool_ = new BattleGroundMemberPool(); battle_ground_member_list_pool_ = new BattleGroundMemberListPool(); battle_ground_member_pool_->Initialize(60); battle_ground_member_list_pool_->Initialize(10); #ifdef _NA_008679_20160202_REWORK_BATTLEGROUND cur_time_mode_ = ns_func::eNONE; open_time_mgr_ = new BattleGroundOpenTimeManager(this); #endif //_NA_008679_20160202_REWORK_BATTLEGROUND } void BattleGroundManager::Release() { // Àüü ´ë±â¿­ Release BattleGroundMemberMap::const_iterator const_itr_members = reservation_total_members_.begin(); for (; const_itr_members != reservation_total_members_.end(); ++const_itr_members) { BattleGroundMemberInfo* const battle_ground_member = const_itr_members->second; if (battle_ground_member == NULL) { continue; } battle_ground_member_pool_->Free(battle_ground_member); } reservation_total_members_.clear(); // ±×·ìº° ´ë±â¿­ Release StandbyGroupMap::const_iterator const_itr_groups = standby_groups_.begin(); for (; const_itr_groups != standby_groups_.end(); ++const_itr_groups) { BattleGroundMemberList* const memeber_list = const_itr_groups->second; if (memeber_list == NULL) { continue; } battle_ground_member_list_pool_->Free(memeber_list); } standby_groups_.clear(); SAFE_DELETE(battle_ground_member_pool_); SAFE_DELETE(battle_ground_member_list_pool_); //_NA_007065_20140217_BATTLEGROUND_REFACTORYING if (battleground_matching_system_) battleground_matching_system_->Release(); SAFE_DELETE(battleground_matching_system_); #ifdef _NA_008679_20160202_REWORK_BATTLEGROUND SAFE_DELETE(open_time_mgr_); #endif //_NA_008679_20160202_REWORK_BATTLEGROUND } #ifdef _NA_008679_20160202_REWORK_BATTLEGROUND void BattleGroundManager::Update(const util::TimeInfoPerFrame& time_info) { ns_func::eBATTLEGROUND_TIMEMODE temp_time_mode = ns_func::eNONE; open_time_mgr_->Update(time_info, temp_time_mode); if (temp_time_mode != ns_func::eNONE) { ChangeTimeMode(temp_time_mode); } } #endif //_NA_008679_20160202_REWORK_BATTLEGROUND bool BattleGroundManager::LeaveRoom(User* const user, const ZONEKEY zone_key, const eREASON_LEAVE_PARTY& reason/* = eREASON_LEAVE_PARTY_INTEND*/) { if (user == NULL) { return false; } BattleGroundMemberInfo* const member_info = FindBattleGroundMember(user->GetUserKey()); if (member_info == NULL) { return false; } // Àüü ´ë±â¿­¿¡¼­ Á¦°Å RemoveReservationMember(user->GetUserKey()); // ±×·ìŰ ¹× ÆÀ ÃʱâÈ­.. user->SetGroupKey(0); user->SetTeam(kChaosZoneTeamNone); // ÇØ´ç À¯Àú¸¦ ¸ÅĪ ±×·ì¿¡¼­ Á¦°Å //_NA_007065_20140217_BATTLEGROUND_REFACTORYING if (battleground_matching_system_->RemoveMemberMatchingGroup(member_info) == false) { return false; } // ¸ÅĪ ±×·ì¸®½ºÆ®¿¡ ¾Æ¹«µµ ¾øÀ¸¸é ¸®½ºÆ® Á¦°Å //_NA_007065_20140217_BATTLEGROUND_REFACTORYING MatchingGroup* const matching_group = \ battleground_matching_system_->FindMatchingGroupByZoneKey(zone_key); if (matching_group == NULL) { return false; } if (matching_group->matching_group_list.size() <= 0) { //_NA_007065_20140217_BATTLEGROUND_REFACTORYING if (battleground_matching_system_->RemoveMatchigGroup(matching_group->group_key) == false) { return false; } } return true; } RC::eBATTLE_GROUND_RESULT BattleGroundManager::CanReservation(const User* user, const MAPCODE map_code) { if (user == NULL) { return RC::RC_BATTLE_GROUND_IS_NOT_USER; } #ifdef _NA_007135_20140402_MODIFY_BATTLE_GROUND_RESERVATION_AVAILABLE_IN_BATTLE_GROUND_CHANNEL AgentServer* pAgentServer = AgentServer::GetInstance(); SERVER_KEY rKey(pAgentServer->GetKey()); ServerOptionParserEx* const server_option_parser = ServerOptionParserEx::Instance(); const int by_channel = server_option_parser->GetServerOption().m_byBattleGroundChannel; // ÀüÀå ¿¹¾à °¡´É ä³ÎÀÌ -1ÀÏ °æ¿ì ¸ðµç ä³Î¿¡¼­ ¿¹¾àÀÌ °¡´ÉÇÏ´Ù if (by_channel != rKey.GetChannelID() && by_channel != -1) { return RC::RC_BATTLE_GROUND_RESERVATION_NOT_AVAILABLE_CHANNEL; } #endif #ifdef _NA_008679_20160202_REWORK_BATTLEGROUND // ½Ã°£Á¦¾î Ȱ¼ºÈ­ ¹× ÀÔÀå½Ã°£ È®ÀÎ if (open_time_mgr_->CanReservationTime() == FALSE) { return RC::RC_BATTLE_GROUND_RESERVATION_FAILED_ADMISSION_TIME; } #endif // _NA_008679_20160202_REWORK_BATTLEGROUND // À¯Àú »óÅ ȮÀÎ.. if (user->GetBehaveState() != PLAYER_BEHAVE_IDLE_STATE) { return RC::RC_BATTLE_GROUND_RESERVATION_FAIL; } // ÆÄƼ ¿©ºÎ È®ÀÎ.. if ((const_cast(user))->GetPartyState().GetPartyKey() != 0) { return RC::RC_BATTLE_GROUND_ALREADY_EXIST_PARTY; } //ÀÔÀå Á¦ÇÑ ¿©ºÎ const BattleGroundInfoParser* const battle_ground_Info_parser = BattleGroundInfoParser::Instance(); const BattleGroundInfo* battle_ground_Info = battle_ground_Info_parser->FindData(map_code); if (battle_ground_Info == NULL) { return RC::RC_BATTLE_GROUND_NOT_INCORRECT_MAPCODE; } // Á¦ÇÑ ·¹¹ú if (user->GetSelectedCharLV() < battle_ground_Info->limit_level) { return RC::RC_BATTLE_GROUND_IS_NOT_QUALIFIED_LEVEL; } BattleGroundMemberMap::const_iterator it = reservation_total_members_.find(user->GetUserKey()); if (it != reservation_total_members_.end()) { // ÀÌ¹Ì ÀüÀå ¿¹¾àÁß..´ë±â¿­¿¡ µé¾îÀÖÀ½.. return RC::RC_BATTLE_GROUND_RESERVATION_ALREADY; } return RC::RC_BATTLE_GROUND_RESERVATION_SUCCESS; } bool BattleGroundManager::InsertReservationMember(const USERGUID guid, MAPCODE map_code, int equip_item_score, eCHAR_TYPE class_code, bool is_healer, OUT BattleGroundMemberInfo*& member_info, BOOL insert_standby_group /*= TRUE*/) { BattleGroundMemberMap::const_iterator itr = reservation_total_members_.find(guid); if (itr != reservation_total_members_.end()) { // ÀÌ¹Ì ÀüÀå ¿¹¾àÁß..´ë±â¿­¿¡ µé¾îÀÖÀ½.. return false; } BattleGroundMemberInfo* const battle_ground_member = static_cast(battle_ground_member_pool_->Alloc()); ZeroMemory(battle_ground_member, sizeof(BattleGroundMemberInfo)); battle_ground_member->user_guid = guid; battle_ground_member->map_code = map_code; battle_ground_member->reservation_key = key_generater_.GetKey(); battle_ground_member->group_key = 0; battle_ground_member->reservation_time = util::TimeSync::_time64(NULL); battle_ground_member->member_state = kStandby; battle_ground_member->team_division = kChaosZoneTeamNone; battle_ground_member->equip_item_score = equip_item_score; battle_ground_member->class_code = class_code; battle_ground_member->is_healer = is_healer; reservation_total_members_.insert( \ BattleGroundMemberMap::value_type(guid,battle_ground_member)); // ½ºÅĹÙÀÌ ±×·ì¿¡ µî·Ï if (insert_standby_group == TRUE) { _InsertMemberStandbyGroup(battle_ground_member); } member_info = battle_ground_member; return true; } BOOL BattleGroundManager::RemoveReservationMember(const USERGUID guid) { BattleGroundMemberMap::iterator itr = reservation_total_members_.find(guid); if (itr == reservation_total_members_.end()) { return FALSE; } BattleGroundMemberInfo* const battle_ground_member = itr->second; RemoveMemberStandbyGroup(battle_ground_member); key_generater_.RestoreKey(battle_ground_member->reservation_key); battle_ground_member_pool_->Free(battle_ground_member); reservation_total_members_.erase(itr); return TRUE; } void BattleGroundManager::_InsertMemberStandbyGroup(const BattleGroundMemberInfo* battle_ground_member) { if (battle_ground_member == NULL) { return; } StandbyGroupMap::const_iterator const_itr = standby_groups_.find(battle_ground_member->map_code); if (const_itr != standby_groups_.end()) { BattleGroundMemberList* const battle_ground_member_list = const_itr->second; battle_ground_member_list->push_back( \ const_cast(battle_ground_member)); } else { MAPCODE map_code = battle_ground_member->map_code; BattleGroundMemberList* const battle_ground_member_list = \ static_cast(battle_ground_member_list_pool_->Alloc()); battle_ground_member_list->push_back( \ const_cast(battle_ground_member)); standby_groups_.insert( \ StandbyGroupMap::value_type(map_code,battle_ground_member_list)); } } bool BattleGroundManager::RemoveMemberStandbyGroup(const BattleGroundMemberInfo* battle_ground_member) { if (battle_ground_member == NULL) { return false; } StandbyGroupMap::const_iterator const_itr = standby_groups_.find(battle_ground_member->map_code); if (const_itr == standby_groups_.end()) { return false; } BattleGroundMemberList* const battle_ground_member_list = const_itr->second; BattleGroundMemberList::iterator member_list_itr = battle_ground_member_list->begin(); for ( ;member_list_itr != battle_ground_member_list->end(); ++member_list_itr) { const BattleGroundMemberInfo* find_member = *member_list_itr; if (battle_ground_member->user_guid == find_member->user_guid) { battle_ground_member_list->erase(member_list_itr); return true; } } return false; } bool BattleGroundManager::IsValidReservationMember(const USERGUID guid) { if (reservation_total_members_.find(guid) == reservation_total_members_.end()) { return false; } return true; } bool BattleGroundManager::IsValidStandbyGroupMember(const USERGUID guid) { BattleGroundMemberInfo* const member_info = FindBattleGroundMember(guid); if (member_info == NULL) { return false; } BattleGroundMemberList* memeber_list = FindStandbyGroupMemberList(member_info->map_code); if (memeber_list == NULL) { return false; } BattleGroundMemberList::const_iterator const_itr = memeber_list->begin(); for (; const_itr != memeber_list->end(); ++const_itr) { BattleGroundMemberInfo* const member = *const_itr; if (member && member->user_guid == guid) { return true; } } return false; } bool BattleGroundManager::ReturnUserInsertStandbyGroupList(const BattleGroundMemberInfo* battle_ground_member) { if (battle_ground_member == NULL) { return false; } StandbyGroupMap::const_iterator const_itr = standby_groups_.find(battle_ground_member->map_code); if (const_itr != standby_groups_.end()) { BattleGroundMemberList* const battle_ground_member_list = const_itr->second; // push_front... battle_ground_member_list->insert( \ battle_ground_member_list->begin(), \ const_cast(battle_ground_member)); return true; } return false; } BattleGroundMemberList* BattleGroundManager::FindStandbyGroupMemberList(const MAPCODE map_code) { StandbyGroupMap::iterator itr = standby_groups_.find(map_code); if (itr != standby_groups_.end()) { return itr->second; } return NULL; } BattleGroundMemberInfo* BattleGroundManager::FindBattleGroundMember(const USERGUID guid) { BattleGroundMemberMap::const_iterator const_itr = reservation_total_members_.find(guid); if (const_itr == reservation_total_members_.end()) { return NULL; } return const_itr->second; } void BattleGroundManager::SendPacketAllMember(const BattleGroundMemberList* member_list, MSG_BASE* msg, WORD size) { UserManager* const user_manager = UserManager::Instance(); BattleGroundMemberList::const_iterator const_itr = member_list->begin(); for (; const_itr != member_list->end(); ++const_itr) { const BattleGroundMemberInfo* const member = *const_itr; if (member== NULL) { continue; } User* const user = user_manager->GetUser(member->user_guid); if (user == NULL) { SUNLOG(eCRITICAL_LOG, __FUNCTION__" : Not found user : GUID(%d)", member->user_guid); continue; } user->SendPacket(msg, size); } } RC::eBATTLE_GROUND_RESULT BattleGroundManager::CancelReservation( User* user ) { RC::eBATTLE_GROUND_RESULT result_code = RC::RC_BATTLE_GROUND_RESERVATION_CANCEL_FAIL; USERGUID user_guid = user->GetUserKey(); MAPCODE bg_mapcode = 0; if (IsValidReservationMember(user_guid) == true) { BattleGroundMemberInfo* member = FindBattleGroundMember(user_guid); if (member != NULL) { if (member->group_key == 0) //1Â÷¸ÅĪ ÇÏÁö ¾ÊÀº À¯Àú { //¿¹¾àÀÚ Á¤º¸ º¯°æ RemoveReservationMember(user_guid); bg_mapcode = member->map_code; result_code = RC::RC_BATTLE_GROUND_RESERVATION_CANCEL_SUCCESS; } else { result_code = RC::RC_BATTLE_GROUND_STATE_INCLUDE_MATCHING_GROUPS; } } } //GameServer¿¡ Ç÷¹ÀÌ¾î »óź¯°æ Àü´Þ if (result_code == RC::RC_BATTLE_GROUND_RESERVATION_CANCEL_SUCCESS) { SendReservationMemberCountToClient(user_guid, bg_mapcode); // »óꝰæ.. MSG_AG_BATTLE_GROUND_STATUS_CHANGE_STATE_CMD cmd_msg; cmd_msg.behave_sate = PLAYER_BEHAVE_IDLE_STATE; user->SendToLinkedServer(&cmd_msg, sizeof(cmd_msg)); } return result_code; } #ifdef _NA_008679_20160202_REWORK_BATTLEGROUND void BattleGroundManager::ChangeTimeMode( const ns_func::eBATTLEGROUND_TIMEMODE& time_mode ) { if (cur_time_mode_ != time_mode) { cur_time_mode_ = time_mode; if (time_mode == ns_func::eOPENED) { //ÀüÀå ½ÃÀÛ½ÃŲ´Ù StartBattleGround(); } } } BOOL BattleGroundManager::StartBattleGround() { FOREACH_CONTAINER(StandbyGroupMap::value_type& node, standby_groups_, StandbyGroupMap) { MAPCODE map_code = node.first; //¸ÅĪ±×·ì »ý¼º + ±×·ì´ç InstanceDungeon»ý¼º battleground_matching_system_->ProcessMatching(map_code); //ÆÀ ¼³Á¤, battleground_matching_system_->StartBattleGround(); } return TRUE; } BOOL BattleGroundManager::GetMemberFalseName( User* user, TCHAR* OUT false_name ) { USERGUID user_guid = user->GetUserGUID(); BattleGroundMemberInfo* member_info = FindBattleGroundMember(user_guid);; if (member_info == NULL) { return FALSE; } if (member_info->team_index_ == 0) { return FALSE; } if(member_info->team_division == kRed) { _sntprintf(false_name, MAX_CHARNAME_LENGTH, _T("·¹µå%d"),member_info->team_index_); } else // if (member_info->team_division == kblue) { _sntprintf(false_name, MAX_CHARNAME_LENGTH, _T("ºí·ç%d"),member_info->team_index_); } false_name[MAX_CHARNAME_LENGTH]='\0'; return TRUE; } bool BattleGroundManager::SetupMessage( const util::TimeInfoPerFrame& time_info, MSG_CG_BATTLE_GROUND_GET_OPEN_TIME_ACK* const msg_ack ) { if (open_time_mgr_ == NULL) { return false; } return open_time_mgr_->SetupMessage(time_info, msg_ack); } VOID BattleGroundManager::ReInsertAbnormalExitMemberToTotalList( User* user, const WORD& party_key ) { // ÀÌ¹Ì ¿¹¾à¸â¹ö¸®½ºÆ®¿¡ ÀÖ´Ù¸é ³ÖÁö¾Ê´Â´Ù if (IsValidReservationMember(user->GetUserGUID()) == true) { return; } eCHAR_TYPE char_class = (eCHAR_TYPE)user->GetSelectedCharClass(); bool is_healer = (char_class == eCHAR_ELEMENTALIST) ? true : false; BattleGroundMemberInfo* user_info = NULL; InsertReservationMember(user->GetUserGUID(), 0, 0, char_class, is_healer, user_info, FALSE); AgentParty* party = static_cast(AgentPartyManager::Instance()->FindEditableParty(party_key)); PARTY_MEMBER_TOTAL_INFO member_total_info; party->GetMemberInfoAll(member_total_info); //ÆÀ À妽º°ª ¼³Á¤------------------------------------------------------------------- std::vector temp_index_list; for(int count = 0; count < member_total_info.m_Count; ++count) { _PARTY_MEMBER_INFO& info = member_total_info.m_Slot[count]; User* member_user = UserManager::Instance()->GetUserByObjKey(info.m_dwMemberKey); if (member_user == NULL) { continue; } BattleGroundMemberInfo* member_info = FindBattleGroundMember(member_user->GetUserGUID()); if (member_info == NULL) { continue; } if (user_info->team_division == kChaosZoneTeamNone) { user_info->team_division = member_info->team_division; user_info->map_code = member_info->map_code; } temp_index_list.push_back(member_info->team_index_); } user_info->team_index_ = 1; // break¿¡ ÀÇÁ¸ÇÏ´Â ¹«ÇÑ ¹Ýº¹¹®Àº À§ÇèÇϹǷΠȽ¼öÁ¦ÇÑ BYTE count = 0; while(count < 10) { std::vector::iterator itr = std::find(temp_index_list.begin(), temp_index_list.end(), user_info->team_index_); if (itr == temp_index_list.end()) { break; } ++user_info->team_index_; ++count; } } #else //_NA_007065_20140217_BATTLEGROUND_REFACTORYING bool BattleGroundManager::CheckMatching( const MAPCODE map_code ) { const BattleGroundMemberList* const member_list = FindStandbyGroupMemberList(map_code); if (member_list == NULL) { return false; } if (battleground_matching_system_->CanCreateMatchingGroup(map_code) == false) { return false; } if (battleground_matching_system_->ProcessMatching(map_code) == false) { //¸ÅĪ±×·ì ¸¸µé±â ½ÇÆÐ, ¸Þ½ÃÁö Àü´ÞÇÑ´Ù. return false; } return true; } void BattleGroundManager::Update() { //_NA_007065_20140217_BATTLEGROUND_REFACTORYING battleground_matching_system_->Update(); // Àοø¼ö°¡ °ú¹ÝÀÌ ³Ñ°í ù¹øÂ° ¿¹¾àÀÚ°¡ 20ºÐÀÌ»ó ´ë±âÇßÀ» °æ¿ì °­Á¦¸ÅĪ const BattleGroundInfoParser* const battle_ground_info_parser = \ BattleGroundInfoParser::Instance(); CTime current_time = util::TimeSync::_time64(NULL); StandbyGroupMap::const_iterator const_itr = standby_groups_.begin(); for (; const_itr != standby_groups_.end(); ++const_itr) { BattleGroundMemberList* const member_list = const_itr->second; if (member_list == NULL) { continue; } const BattleGroundInfo* const battle_ground_Info = \ battle_ground_info_parser->FindData(const_itr->first); int extract_list = static_cast(battle_ground_Info->team_max); if ((extract_list%2) != 0) { extract_list += 1; } if ((int)member_list->size() < extract_list) // °ú¹Ý ÃʰúÀÏ °æ¿ì.. { continue; } // ´ë±â¿­ÀÇ Ã¹¹øÂ° ¿¹¾àÀÚÀÇ ½Ã°£.. BattleGroundMemberInfo* const first_member_info = member_list->front(); if (first_member_info == NULL) { continue; } if (current_time < first_member_info->reservation_time + CTimeSpan(0, 0, 0, battle_ground_Info->max_match_time)) { continue; } // °­Á¦¸ÅĪ //_NA_007065_20140217_BATTLEGROUND_REFACTORYING if (battleground_matching_system_->ProcessMatching(first_member_info->map_code) == false) { continue; } } } #endif //_NA_008679_20160202_REWORK_BATTLEGROUND VOID BattleGroundManager::SendReservationMemberCountToClient(USERGUID user_guid, MAPCODE map_code) { MSG_CG_BATTLE_GROUND_RESERVATION_BRD brd_msg; BattleGroundMemberList* const member_list = FindStandbyGroupMemberList(map_code); if (member_list == NULL) { return; } brd_msg.current_reservation_memeber_count = member_list->size(); //ÀÚ±âÀڽſ¡°Ôµµ º¸³Â´ÂÁö üũ, ¾Èº¸³ÂÀ¸¸é º¸³»Áà¾ßÇÔ //¿¹¾àÃë¼Ò ¶§¹® BOOL is_send_myself = FALSE; BattleGroundMemberList::const_iterator const_itr = member_list->begin(); for (; const_itr != member_list->end(); ++const_itr) { BattleGroundMemberInfo* const member = *const_itr; if (member == NULL) { continue; } User* const user = UserManager::Instance()->GetUser(member->user_guid); if (user == NULL) { continue; } user->SendPacket(&brd_msg, sizeof(brd_msg)); if (user->GetUserGUID() == user_guid) { is_send_myself = TRUE; } } if (is_send_myself == FALSE) { User* const cancel_user = UserManager::Instance()->GetUser(user_guid); if (cancel_user == NULL) { return; } cancel_user->SendPacket(&brd_msg, sizeof(brd_msg)); } } VOID BattleGroundManager::ProcessDisconnectUser( User* user, const KEYTYPE& zone_key, const eREASON_LEAVE_PARTY& reason ) { USERGUID user_guid = user->GetUserGUID(); if (IsValidReservationMember(user_guid)) { BattleGroundMemberInfo* const member = FindBattleGroundMember(user_guid); if (member) { if (member->group_key == 0) { RemoveReservationMember(user_guid); } else { LeaveRoom(user, zone_key, reason); } } } } #ifdef _NA_007065_20140217_CHAOSZONE_GOLDRUSH void BattleGroundManager::ProcessPacket_CG( const ChaosZoneCategory& category_type, User* user, MSG_BASE* packet, WORD size ) { switch(category_type) { case kCategoryBattleGround: { handler_cg_battle_ground_.OnCG_ProcessPacket(user, packet, size); }break; case eCHAOSZONE_CATEGORY_GOLDRUSH: { handler_cg_goldrush_.OnCG_ProcessPacket(user, packet, size); }break; } } void BattleGroundManager::ProcessPacket_AG( const ChaosZoneCategory& category_type, GameServerSession* server_session, MSG_BASE* packet, WORD size ) { switch(category_type) { case kCategoryBattleGround: { handler_ag_battle_ground_.OnAG_ProcessPacket(server_session, packet, size); }break; case eCHAOSZONE_CATEGORY_GOLDRUSH: { handler_ag_goldrush_.OnAG_ProcessPacket(server_session, packet, size); }break; } } #endif //_NA_007065_20140217_CHAOSZONE_GOLDRUSH