From dc19fc4ca3fe059ec650511ad44dfe9966e128c9 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 6 Jan 2009 16:18:06 +0300 Subject: [PATCH] [7040] Move achievment rewards dat to new DB table. Implement sending item rewards by mail. Support localization string fields for new table. Move achievments related code and data from ObjectMgr to new AcievmentGlobalMgr. --- sql/mangos.sql | 62 ++- .../7040_01_mangos_achievement_reward.sql | 36 ++ sql/updates/Makefile.am | 2 + src/game/AchievementMgr.cpp | 377 ++++++++++++------ src/game/AchievementMgr.h | 79 +++- src/game/ObjectMgr.cpp | 33 -- src/game/ObjectMgr.h | 12 +- src/game/World.cpp | 19 +- src/shared/revision_nr.h | 2 +- 9 files changed, 455 insertions(+), 167 deletions(-) create mode 100644 sql/updates/7040_01_mangos_achievement_reward.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 2a1545ae5..1f737da9e 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_7034_01_mangos_spell_proc_event` bit(1) default NULL + `required_7040_01_mangos_achievement_reward` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -36,6 +36,31 @@ INSERT INTO `db_version` VALUES /*!40000 ALTER TABLE `db_version` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `achievement_reward` +-- + +DROP TABLE IF EXISTS `achievement_reward`; +CREATE TABLE `achievement_reward` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `title_A` mediumint(8) unsigned NOT NULL default '0', + `title_H` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `sender` mediumint(8) unsigned NOT NULL default '0', + `subject` varchar(255) default NULL, + `text` text, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +-- +-- Dumping data for table `achievement_reward` +-- + +LOCK TABLES `achievement_reward` WRITE; +/*!40000 ALTER TABLE `achievement_reward` DISABLE KEYS */; +/*!40000 ALTER TABLE `achievement_reward` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `areatrigger_involvedrelation` -- @@ -1764,6 +1789,41 @@ INSERT INTO `item_template` VALUES /*!40000 ALTER TABLE `item_template` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `locales_achievement_reward` +-- + +DROP TABLE IF EXISTS `locales_achievement_reward`; +CREATE TABLE `locales_achievement_reward` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `subject_loc1` varchar(100) NOT NULL default '', + `subject_loc2` varchar(100) NOT NULL default '', + `subject_loc3` varchar(100) NOT NULL default '', + `subject_loc4` varchar(100) NOT NULL default '', + `subject_loc5` varchar(100) NOT NULL default '', + `subject_loc6` varchar(100) NOT NULL default '', + `subject_loc7` varchar(100) NOT NULL default '', + `subject_loc8` varchar(100) NOT NULL default '', + `text_loc1` text default NULL, + `text_loc2` text default NULL, + `text_loc3` text default NULL, + `text_loc4` text default NULL, + `text_loc5` text default NULL, + `text_loc6` text default NULL, + `text_loc7` text default NULL, + `text_loc8` text default NULL, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `locales_achievement_reward` +-- + +LOCK TABLES `locales_achievement_reward` WRITE; +/*!40000 ALTER TABLE `locales_achievement_reward` DISABLE KEYS */; +/*!40000 ALTER TABLE `locales_achievement_reward` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `locales_creature` -- diff --git a/sql/updates/7040_01_mangos_achievement_reward.sql b/sql/updates/7040_01_mangos_achievement_reward.sql new file mode 100644 index 000000000..0402a0025 --- /dev/null +++ b/sql/updates/7040_01_mangos_achievement_reward.sql @@ -0,0 +1,36 @@ +ALTER TABLE db_version CHANGE COLUMN required_7034_01_mangos_spell_proc_event required_7040_01_mangos_achievement_reward bit; + +DROP TABLE IF EXISTS `achievement_reward`; +CREATE TABLE `achievement_reward` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `title_A` mediumint(8) unsigned NOT NULL default '0', + `title_H` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `sender` mediumint(8) unsigned NOT NULL default '0', + `subject` varchar(255) default NULL, + `text` text, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + + +DROP TABLE IF EXISTS `locales_achievement_reward`; +CREATE TABLE `locales_achievement_reward` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `subject_loc1` varchar(100) NOT NULL default '', + `subject_loc2` varchar(100) NOT NULL default '', + `subject_loc3` varchar(100) NOT NULL default '', + `subject_loc4` varchar(100) NOT NULL default '', + `subject_loc5` varchar(100) NOT NULL default '', + `subject_loc6` varchar(100) NOT NULL default '', + `subject_loc7` varchar(100) NOT NULL default '', + `subject_loc8` varchar(100) NOT NULL default '', + `text_loc1` text default NULL, + `text_loc2` text default NULL, + `text_loc3` text default NULL, + `text_loc4` text default NULL, + `text_loc5` text default NULL, + `text_loc6` text default NULL, + `text_loc7` text default NULL, + `text_loc8` text default NULL, + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 9926b5a80..b42eb7212 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -114,6 +114,7 @@ pkgdata_DATA = \ 7031_01_mangos_spell_proc_event.sql \ 7033_01_mangos_spell_proc_event.sql \ 7034_01_mangos_spell_proc_event.sql \ + 7040_01_mangos_achievement_reward.sql \ README ## Additional files to include when running 'make dist' @@ -208,4 +209,5 @@ EXTRA_DIST = \ 7031_01_mangos_spell_proc_event.sql \ 7033_01_mangos_spell_proc_event.sql \ 7034_01_mangos_spell_proc_event.sql \ + 7040_01_mangos_achievement_reward.sql \ README diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 29503502b..fb6684892 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -27,8 +27,13 @@ #include "GameEvent.h" #include "World.h" #include "SpellMgr.h" +#include "ProgressBar.h" -const CriteriaCastSpellRequirement AchievementMgr::criteriaCastSpellRequirements[CRITERIA_CAST_SPELL_REQ_COUNT] = +#include "Policies/SingletonImp.h" + +INSTANTIATE_SINGLETON_1(AchievementGlobalMgr); + +const CriteriaCastSpellRequirement AchievementGlobalMgr::m_criteriaCastSpellRequirements[CRITERIA_CAST_SPELL_REQ_COUNT] = { {5272, 3057, 0, 0}, {5273, 2784, 0, 0}, @@ -76,68 +81,6 @@ const CriteriaCastSpellRequirement AchievementMgr::criteriaCastSpellRequirements {6320, 0, CLASS_PALADIN, RACE_DRAENEI}, {6321, 0, CLASS_HUNTER, RACE_DWARF}, {6662, 31261, 0, 0} - }; - -const AchievementReward AchievementMgr::achievementRewards[ACHIEVEMENT_REWARD_COUNT] = - { - // achievementId, horde titleid, alliance titleid, itemid - {45, 0, 0, 43348}, - {46, 78, 78, 0}, - {230, 72, 72, 0}, - {456, 139, 139, 0}, - {614, 0, 0, 44223}, - {619, 0, 0, 44224}, - {714, 47, 47, 0}, - {762, 130, 130, 0}, - {870, 127, 126, 0}, - {871, 144, 144, 0}, - {876, 0, 0, 43349}, - {907, 48, 48, 0}, - {913, 74, 74, 0}, - {942, 79, 79, 0}, - {943, 79, 79, 0}, - {945, 131, 131, 0}, - {948, 130, 130, 0}, - {953, 132, 132, 0}, - {978, 81, 81, 0}, - {1015, 77, 77, 0}, - {1021, 0, 0, 40643}, - {1038, 75, 75, 0}, - {1039, 76, 76, 0}, - {1163, 128, 128, 0}, - {1174, 82, 82, 0}, - {1175, 72, 72, 0}, - {1250, 0, 0, 40653}, - {1400, 120, 120, 0}, - {1402, 122, 122, 0}, - {1516, 83, 83, 0}, - {1563, 84, 84, 0}, - {1656, 124, 124, 0}, - {1657, 124, 124, 0}, - {1658, 129, 129, 0}, - {1681, 125, 125, 43300}, - {1682, 125, 125, 43300}, - {1683, 133, 133, 0}, - {1684, 133, 133, 0}, - {1691, 134, 134, 0}, - {1692, 134, 134, 0}, - {1693, 135, 135, 0}, - {1707, 135, 135, 0}, - {1784, 84, 84, 0}, - {1793, 137, 137, 0}, - {1956, 0, 0, 43824}, - {2051, 140, 140, 0}, - {2054, 121, 121, 0}, - {2096, 0, 0, 44430}, - {2136, 0, 0, 0},// <- TODO: find item for spell 59961 - {2137, 0, 0, 0},// <- TODO: find item for spell 60021 - {2138, 0, 0, 0},// <- TODO: find item for spell 59976 - {2143, 0, 0, 44178}, - {2144, 0, 0, 0},// <- TODO: find item for spell 60024 - {2145, 0, 0, 0},// <- TODO: find item for spell 60024 - {2186, 141, 141, 0}, - {2187, 142, 142, 0}, - {2188, 143, 143, 0} }; AchievementMgr::AchievementMgr(Player *player) @@ -364,7 +307,7 @@ void AchievementMgr::CheckAllAchievementCriteria() void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1, uint32 miscvalue2, Unit *unit, uint32 time) { sLog.outDetail("AchievementMgr::UpdateAchievementCriteria(%u, %u, %u, %u)", type, miscvalue1, miscvalue2, time); - AchievementCriteriaEntryList const& achievementCriteriaList = objmgr.GetAchievementCriteriaByType(type); + AchievementCriteriaEntryList const& achievementCriteriaList = achievementmgr.GetAchievementCriteriaByType(type); for(AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i!=achievementCriteriaList.end(); ++i) { AchievementCriteriaEntry const *achievementCriteria = (*i); @@ -523,19 +466,9 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui { if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID) continue; + // those requirements couldn't be found in the dbc - - const CriteriaCastSpellRequirement *requirement = NULL; - for (uint32 i=0; iID) - { - requirement = &criteriaCastSpellRequirements[i]; - break; - } - } - - if (requirement) + if (CriteriaCastSpellRequirement const* requirement = AchievementGlobalMgr::GetCriteriaCastSpellRequirement(achievementCriteria)) { if (!unit) continue; @@ -549,6 +482,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if (requirement->playerClass && (unit->GetTypeId() != TYPEID_PLAYER || unit->getClass()!=requirement->playerClass)) continue; } + SetCriteriaProgress(achievementCriteria, 1, true); break; } @@ -653,7 +587,7 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve if(achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL)) { // someone on this realm has already completed that achievement - if(objmgr.allCompletedAchievements.find(achievement->ID)!=objmgr.allCompletedAchievements.end()) + if(achievementmgr.IsRealmCompleted(achievement)) return false; } @@ -838,55 +772,58 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) // don't insert for ACHIEVEMENT_FLAG_REALM_FIRST_KILL since otherwise only the first group member would reach that achievement // TODO: where do set this instead? if(!(achievement->flags & ACHIEVEMENT_FLAG_REALM_FIRST_KILL)) - objmgr.allCompletedAchievements.insert(achievement->ID); + achievementmgr.SetRealmCompleted(achievement); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT); - // reward items and titles - // TODO: rewards should be send by mail - AchievementReward const* reward = NULL; - for (uint32 i=0; iID) - { - reward = &achievementRewards[i]; - break; - } - } + // reward items and titles if any + AchievementReward const* reward = achievementmgr.GetAchievementReward(achievement); - if (reward) + // no rewards + if(!reward) + return; + + // titles + if(uint32 titleId = reward->titleId[GetPlayer()->GetTeam() == HORDE?0:1]) { - uint32 titleId = reward->titleId[GetPlayer()->GetTeam() == HORDE?0:1]; if(CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId)) GetPlayer()->SetTitle(titleEntry); + } - if (reward->itemId) + // mail + if(reward->sender) + { + Item* item = reward->itemId ? Item::CreateItem(reward->itemId,1,GetPlayer ()) : NULL; + + MailItemsInfo mi; + if(item) { - ItemPrototype const *pProto = objmgr.GetItemPrototype( reward->itemId ); + // save new item before send + item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted - if(!pProto) + // item + mi.AddItem(item->GetGUIDLow(), item->GetEntry(), item); + } + + int loc_idx = GetPlayer()->GetSession()->GetSessionDbLocaleIndex(); + + // subject and text + std::string subject = reward->subject; + std::string text = reward->text; + if ( loc_idx >= 0 ) + { + if(AchievementRewardLocale const* loc = achievementmgr.GetAchievementRewardLocale(achievement)) { - GetPlayer()->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); - return; - } - - ItemPosCountVec dest; - uint32 no_space = 0; - uint8 msg = GetPlayer()->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, reward->itemId, 1, &no_space ); - - if( msg != EQUIP_ERR_OK ) - { - GetPlayer()->SendEquipError( msg, NULL, NULL ); - return; - } - Item* pItem = GetPlayer()->StoreNewItem( dest, reward->itemId, true); - - if(!pItem) - { - GetPlayer()->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); - return; + if (loc->subject.size() > size_t(loc_idx) && !loc->subject[loc_idx].empty()) + subject = loc->subject[loc_idx]; + if (loc->text.size() > size_t(loc_idx) && !loc->text[loc_idx].empty()) + text = loc->text[loc_idx]; } } + + uint32 itemTextId = objmgr.CreateItemText( text ); + + WorldSession::SendMailTo(GetPlayer(), MAIL_CREATURE, MAIL_STATIONERY_NORMAL, reward->sender, GetPlayer()->GetGUIDLow(), subject, itemTextId , &mi, 0, 0, MAIL_CHECK_MASK_NONE); } } @@ -932,3 +869,217 @@ void AchievementMgr::BuildAllDataPacket(WorldPacket *data) *data << int32(-1); } + +//========================================================== +AchievementCriteriaEntryList const& AchievementGlobalMgr::GetAchievementCriteriaByType(AchievementCriteriaTypes type) +{ + return m_AchievementCriteriasByType[type]; +} + +void AchievementGlobalMgr::LoadAchievementCriteriaList() +{ + for (uint32 entryId = 0; entryIdrequiredType].push_back(criteria); + } +} + + +void AchievementGlobalMgr::LoadCompletedAchievements() +{ + QueryResult *result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement"); + + if(!result) + return; + + do + { + Field *fields = result->Fetch(); + m_allCompletedAchievements.insert(fields[0].GetUInt32()); + } while(result->NextRow()); + + delete result; +} + +void AchievementGlobalMgr::LoadRewards() +{ + m_achievementRewards.clear(); // need for reload case + + // 0 1 2 3 4 5 6 + QueryResult *result = WorldDatabase.Query("SELECT entry, title_A, title_H, item, sender, subject, text FROM achievement_reward"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(""); + sLog.outString(">> Loaded 0 achievement rewards. DB table `achievement_reward` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + if (!sAchievementStore.LookupEntry(entry)) + { + sLog.outErrorDb( "Table `achievement_reward` has wrong achievement (Entry: %u), ignore", entry); + continue; + } + + AchievementReward reward; + reward.titleId[0] = fields[1].GetUInt32(); + reward.titleId[1] = fields[2].GetUInt32(); + reward.itemId = fields[3].GetUInt32(); + reward.sender = fields[4].GetUInt32(); + reward.subject = fields[5].GetCppString(); + reward.text = fields[6].GetCppString(); + + if ((reward.titleId[0]==0)!=(reward.titleId[1]==0)) + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) has title (A: %u H: %u) only for one from teams.", entry, reward.titleId[0], reward.titleId[1]); + + // must be title or mail at least + if (!reward.titleId[0] && !reward.titleId[1] && !reward.sender) + { + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) not have title or item reward data, ignore.", entry); + continue; + } + + if (reward.titleId[0]) + { + CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(reward.titleId[0]); + if (!titleEntry) + { + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) has invalid title id (%u) in `title_A`, set to 0", entry, reward.titleId[0]); + reward.titleId[0] = 0; + } + } + + if (reward.titleId[1]) + { + CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(reward.titleId[1]); + if (!titleEntry) + { + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) has invalid title id (%u) in `title_A`, set to 0", entry, reward.titleId[1]); + reward.titleId[1] = 0; + } + } + + //check mail data before item for report including wrong item case + if (reward.sender) + { + if (!objmgr.GetCreatureTemplate(reward.sender)) + { + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) has invalid creature entry %u as sender, mail reward skipped.", entry, reward.sender); + reward.sender = 0; + } + } + else + { + if (reward.itemId) + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) not have sender data but have item reward, item will not rewarded", entry); + + if (!reward.subject.empty()) + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) not have sender data but have mail subject.", entry); + + if (!reward.text.empty()) + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) not have sender data but have mail text.", entry); + } + + if (reward.itemId) + { + if (!objmgr.GetItemPrototype(reward.itemId)) + { + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) has invalid item id %u, reward mail will be without item.", entry, reward.itemId); + reward.itemId = 0; + } + } + + m_achievementRewards[entry] = reward; + + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u achievement reward locale strings", m_achievementRewardLocales.size() ); +} + +void AchievementGlobalMgr::LoadRewardLocales() +{ + m_achievementRewardLocales.clear(); // need for reload case + + QueryResult *result = WorldDatabase.Query("SELECT entry,subject_loc1,text_loc1,subject_loc2,text_loc2,subject_loc3,text_loc3,subject_loc4,text_loc4,subject_loc5,text_loc5,subject_loc6,text_loc6,subject_loc7,text_loc7,subject_loc8,text_loc8 FROM locales_achievement_reward"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(""); + sLog.outString(">> Loaded 0 achievement reward locale strings. DB table `locales_achievement_reward` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + + if(m_achievementRewards.find(entry)==m_achievementRewards.end()) + { + sLog.outErrorDb( "Table `locales_achievement_reward` (Entry: %u) has locale strings for not existed achievement reward .", entry); + continue; + } + + AchievementRewardLocale& data = m_achievementRewardLocales[entry]; + + for(int i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[1+2*(i-1)].GetCppString(); + if(!str.empty()) + { + int idx = objmgr.GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.subject.size() <= idx) + data.subject.resize(idx+1); + + data.subject[idx] = str; + } + } + str = fields[1+2*(i-1)+1].GetCppString(); + if(!str.empty()) + { + int idx = objmgr.GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.text.size() <= idx) + data.text.resize(idx+1); + + data.text[idx] = str; + } + } + } + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u achievement reward locale strings", m_achievementRewardLocales.size() ); +} diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index 871d3d5d8..a34729519 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -19,13 +19,19 @@ #define __MANGOS_ACHIEVEMENTMGR_H #include "Common.h" +#include "Policies/Singleton.h" #include "Database/DBCEnums.h" #include "Database/DBCStores.h" #include "Database/DatabaseEnv.h" +#include +#include + #define CRITERIA_CAST_SPELL_REQ_COUNT 46 #define ACHIEVEMENT_REWARD_COUNT 57 +typedef std::list AchievementCriteriaEntryList; + struct CriteriaProgress { uint32 counter; @@ -43,11 +49,24 @@ struct CriteriaCastSpellRequirement struct AchievementReward { - uint32 achievementId; uint32 titleId[2]; uint32 itemId; + uint32 sender; + std::string subject; + std::string text; }; +typedef std::map AchievementRewards; + +struct AchievementRewardLocale +{ + std::vector subject; + std::vector text; +}; + +typedef std::map AchievementRewardLocales; + + struct CompletedAchievementData { time_t date; @@ -95,7 +114,61 @@ class AchievementMgr Player* m_player; CriteriaProgressMap m_criteriaProgress; CompletedAchievementMap m_completedAchievements; - static const CriteriaCastSpellRequirement criteriaCastSpellRequirements[]; - static const AchievementReward achievementRewards[]; }; + +class AchievementGlobalMgr +{ + public: + AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type); + + AchievementReward const* GetAchievementReward(AchievementEntry const* achievement) const + { + AchievementRewards::const_iterator iter = m_achievementRewards.find(achievement->ID); + return iter!=m_achievementRewards.end() ? &iter->second : NULL; + } + + AchievementRewardLocale const* GetAchievementRewardLocale(AchievementEntry const* achievement) const + { + AchievementRewardLocales::const_iterator iter = m_achievementRewardLocales.find(achievement->ID); + return iter!=m_achievementRewardLocales.end() ? &iter->second : NULL; + } + + static CriteriaCastSpellRequirement const * GetCriteriaCastSpellRequirement(AchievementCriteriaEntry const *achievementCriteria) + { + for (uint32 i=0; i < CRITERIA_CAST_SPELL_REQ_COUNT; ++i) + if (m_criteriaCastSpellRequirements[i].achievementCriteriaId == achievementCriteria->ID) + return &m_criteriaCastSpellRequirements[i]; + + return NULL; + } + + bool IsRealmCompleted(AchievementEntry const* achievement) const + { + return m_allCompletedAchievements.find(achievement->ID) != m_allCompletedAchievements.end(); + } + + void SetRealmCompleted(AchievementEntry const* achievement) + { + m_allCompletedAchievements.insert(achievement->ID); + } + + void LoadAchievementCriteriaList(); + void LoadCompletedAchievements(); + void LoadRewards(); + void LoadRewardLocales(); + private: + static const CriteriaCastSpellRequirement m_criteriaCastSpellRequirements[]; + + // store achievement criterias by type to speed up lookup + AchievementCriteriaEntryList m_AchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL]; + + typedef std::set AllCompletedAchievements; + AllCompletedAchievements m_allCompletedAchievements; + + AchievementRewards m_achievementRewards; + AchievementRewardLocales m_achievementRewardLocales; +}; + +#define achievementmgr MaNGOS::Singleton::Instance() + #endif diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index b2fceffbc..6613128b7 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -580,22 +580,6 @@ void ObjectMgr::LoadCreatureLocales() sLog.outString( ">> Loaded %u creature locale strings", mCreatureLocaleMap.size() ); } -void ObjectMgr::LoadCompletedAchievements() -{ - QueryResult *result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement"); - - if(!result) - return; - - do - { - Field *fields = result->Fetch(); - allCompletedAchievements.insert(fields[0].GetUInt32()); - } while(result->NextRow()); - - delete result; -} - void ObjectMgr::LoadNpcOptionLocales() { mNpcOptionLocaleMap.clear(); // need for reload case @@ -6333,23 +6317,6 @@ int ObjectMgr::GetOrNewIndexForLocale( LocaleConstant loc ) return m_LocalForIndex.size()-1; } -AchievementCriteriaEntryList const& ObjectMgr::GetAchievementCriteriaByType(AchievementCriteriaTypes type) -{ - return m_AchievementCriteriasByType[type]; -} - -void ObjectMgr::LoadAchievementCriteriaList() -{ - for (uint32 entryId = 0; entryIdrequiredType].push_back(criteria); - } -} - void ObjectMgr::LoadBattleMastersEntry() { mBattleMastersMap.clear(); // need for reload case diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index dafa115c3..eac5a6bf2 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -242,8 +242,6 @@ typedef std::list CacheNpcOptionList; typedef UNORDERED_MAP CacheVendorItemMap; typedef UNORDERED_MAP CacheTrainerSpellMap; -typedef std::list AchievementCriteriaEntryList; - enum SkillRangeType { SKILL_RANGE_LANGUAGE, // 300..300 @@ -567,7 +565,6 @@ class ObjectMgr void LoadNpcTextId(); void LoadVendors(); void LoadTrainerSpell(); - void LoadCompletedAchievements(); std::string GeneratePetName(uint32 entry); uint32 GetBaseXP(uint32 level); @@ -772,14 +769,13 @@ class ObjectMgr void AddVendorItem(uint32 entry,uint32 item, uint32 maxcount, uint32 incrtime, uint32 ExtendedCost); bool RemoveVendorItem(uint32 entry,uint32 item); bool IsVendorItemValid( uint32 vendor_entry, uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL, std::set* skip_vendors = NULL ) const; - void LoadAchievementCriteriaList(); - AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type); - std::set allCompletedAchievements; void LoadScriptNames(); ScriptNameMap &GetScriptNames() { return m_scriptNames; } const char * GetScriptName(uint32 id) { return id < m_scriptNames.size() ? m_scriptNames[id].c_str() : ""; } uint32 GetScriptId(const char *name); + + int GetOrNewIndexForLocale(LocaleConstant loc); protected: // first free id for selected id type @@ -848,7 +844,6 @@ class ObjectMgr typedef std::vector LocalForIndex; LocalForIndex m_LocalForIndex; - int GetOrNewIndexForLocale(LocaleConstant loc); int DBCLocaleIndex; @@ -902,9 +897,6 @@ class ObjectMgr CacheNpcTextIdMap m_mCacheNpcTextIdMap; CacheVendorItemMap m_mCacheVendorItemMap; CacheTrainerSpellMap m_mCacheTrainerSpellMap; - - // store achievement criterias by type to speed up lookup - AchievementCriteriaEntryList m_AchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL]; }; #define objmgr MaNGOS::Singleton::Instance() diff --git a/src/game/World.cpp b/src/game/World.cpp index 766a574ee..74be1cbe8 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -35,6 +35,7 @@ #include "SkillDiscovery.h" #include "World.h" #include "AccountMgr.h" +#include "AchievementMgr.h" #include "ObjectMgr.h" #include "SpellMgr.h" #include "Chat.h" @@ -1072,12 +1073,6 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading InstanceTemplate" ); objmgr.LoadInstanceTemplate(); - sLog.outString( "Loading AchievementCriteriaList..." ); - objmgr.LoadAchievementCriteriaList(); - - sLog.outString( "Loading completed achievements..." ); - objmgr.LoadCompletedAchievements(); - sLog.outString( "Loading SkillLineAbilityMultiMap Data..." ); spellmgr.LoadSkillLineAbilityMap(); @@ -1236,6 +1231,18 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading Skill Fishing base level requirements..." ); objmgr.LoadFishingBaseSkillLevel(); + sLog.outString( "Loading AchievementCriteriaList..." ); + achievementmgr.LoadAchievementCriteriaList(); + + sLog.outString( "Loading achievement rewards..." ); + achievementmgr.LoadRewards(); + + sLog.outString( "Loading achievement reward locale strings..." ); + achievementmgr.LoadRewardLocales(); + + sLog.outString( "Loading completed achievements..." ); + achievementmgr.LoadCompletedAchievements(); + ///- Load dynamic data tables from the database sLog.outString( "Loading Auctions..." ); objmgr.LoadAuctionItems(); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c956a0705..802bcea25 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7039" + #define REVISION_NR "7040" #endif // __REVISION_NR_H__