aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormegamage <none@none>2009-01-06 13:55:14 -0600
committermegamage <none@none>2009-01-06 13:55:14 -0600
commit6288ca7c687bba7180f4aa6a3ac1de64abbfbe66 (patch)
tree39284cf3dea1d6deefce7ed699ba9bbf3a516910
parent5b2c61e95e3c46fbeaef53f4651c8198b68e4d3d (diff)
*Mangos [7040] Move achievment rewards dat to new DB table. Implement sending item rewards by mail. By VladimirMangos.
Support localization string fields for new table. Move achievments related code and data from ObjectMgr to new AcievmentGlobalMgr. *Mangos [7041] Add 7-8 rank warlock stone. By GriffonHeart. --HG-- branch : trunk
-rw-r--r--sql/updates/7040_01_mangos_achievement_reward.sql36
-rw-r--r--sql/updates/TBC-WLK_world.sql36
-rw-r--r--src/game/AchievementMgr.cpp373
-rw-r--r--src/game/AchievementMgr.h79
-rw-r--r--src/game/ObjectMgr.cpp33
-rw-r--r--src/game/ObjectMgr.h15
-rw-r--r--src/game/SpellEffects.cpp8
-rw-r--r--src/game/World.cpp19
-rw-r--r--src/shared/revision_nr.h2
9 files changed, 433 insertions, 168 deletions
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 00000000000..0402a002526
--- /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/TBC-WLK_world.sql b/sql/updates/TBC-WLK_world.sql
index 21ffaa1f17d..6a549ed4132 100644
--- a/sql/updates/TBC-WLK_world.sql
+++ b/sql/updates/TBC-WLK_world.sql
@@ -1,3 +1,39 @@
+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;
+
+
DELETE FROM battleground_template WHERE id IN (9,10,11);
INSERT INTO battleground_template VALUES
(9,0,0,0,0,1367,0,1368,0),
diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp
index 44df14bf15b..c4a634c15c0 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; i<CRITERIA_CAST_SPELL_REQ_COUNT; i++)
- {
- if (criteriaCastSpellRequirements[i].achievementCriteriaId == achievementCriteria->ID)
- {
- requirement = &criteriaCastSpellRequirements[i];
- break;
- }
- }
-
- if (requirement)
+ // those requirements couldn't be found in the dbc
+ 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; i<ACHIEVEMENT_REWARD_COUNT; i++)
- {
- if (achievementRewards[i].achievementId == achievement->ID)
- {
- reward = &achievementRewards[i];
- break;
- }
- }
+ // reward items and titles if any
+ AchievementReward const* reward = achievementmgr.GetAchievementReward(achievement);
+
+ // no rewards
+ if(!reward)
+ return;
- if (reward)
+ // 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)
- {
- GetPlayer()->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
- return;
- }
+ // item
+ mi.AddItem(item->GetGUIDLow(), item->GetEntry(), item);
+ }
- ItemPosCountVec dest;
- uint32 no_space = 0;
- uint8 msg = GetPlayer()->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, reward->itemId, 1, &no_space );
+ int loc_idx = GetPlayer()->GetSession()->GetSessionDbLocaleIndex();
- if( msg != EQUIP_ERR_OK )
- {
- GetPlayer()->SendEquipError( msg, NULL, NULL );
- return;
- }
- Item* pItem = GetPlayer()->StoreNewItem( dest, reward->itemId, true);
-
- if(!pItem)
+ // 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;
+ 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; entryId<sAchievementCriteriaStore.GetNumRows(); entryId++)
+ {
+ AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId);
+ if(!criteria)
+ continue;
+
+ m_AchievementCriteriasByType[criteria->requiredType].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 6392a9fc647..19dc31c64e3 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 <map>
+#include <string>
+
#define CRITERIA_CAST_SPELL_REQ_COUNT 46
#define ACHIEVEMENT_REWARD_COUNT 57
+typedef std::list<const AchievementCriteriaEntry*> 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<uint32,AchievementReward> AchievementRewards;
+
+struct AchievementRewardLocale
+{
+ std::vector<std::string> subject;
+ std::vector<std::string> text;
+};
+
+typedef std::map<uint32,AchievementRewardLocale> 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<uint32> AllCompletedAchievements;
+ AllCompletedAchievements m_allCompletedAchievements;
+
+ AchievementRewards m_achievementRewards;
+ AchievementRewardLocales m_achievementRewardLocales;
+};
+
+#define achievementmgr MaNGOS::Singleton<AchievementGlobalMgr>::Instance()
+
#endif
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
index 0b2815c8beb..3e7a9d2925f 100644
--- a/src/game/ObjectMgr.cpp
+++ b/src/game/ObjectMgr.cpp
@@ -642,22 +642,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
@@ -6493,23 +6477,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; entryId<sAchievementCriteriaStore.GetNumRows(); entryId++)
- {
- AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId);
- if(!criteria)
- continue;
-
- m_AchievementCriteriasByType[criteria->requiredType].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 4216792743c..e4383cae605 100644
--- a/src/game/ObjectMgr.h
+++ b/src/game/ObjectMgr.h
@@ -264,8 +264,6 @@ typedef std::list<GossipOption> CacheNpcOptionList;
typedef UNORDERED_MAP<uint32, VendorItemData> CacheVendorItemMap;
typedef UNORDERED_MAP<uint32, TrainerSpellData> CacheTrainerSpellMap;
-typedef std::list<const AchievementCriteriaEntry*> AchievementCriteriaEntryList;
-
enum SkillRangeType
{
SKILL_RANGE_LANGUAGE, // 300..300
@@ -595,8 +593,7 @@ class ObjectMgr
void LoadNpcTextId();
void LoadVendors();
void LoadTrainerSpell();
- void LoadCompletedAchievements();
-
+
std::string GeneratePetName(uint32 entry);
uint32 GetBaseXP(uint32 level);
@@ -809,14 +806,12 @@ class ObjectMgr
bool RemoveVendorItem(uint32 entry,uint32 item, bool savetodb = true); // for event
bool IsVendorItemValid( uint32 vendor_entry, uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL, std::set<uint32>* skip_vendors = NULL, uint32 ORnpcflag = 0 ) const;
- void LoadAchievementCriteriaList();
- AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type);
- std::set<uint32> 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
@@ -888,7 +883,6 @@ class ObjectMgr
typedef std::vector<LocaleConstant> LocalForIndex;
LocalForIndex m_LocalForIndex;
- int GetOrNewIndexForLocale(LocaleConstant loc);
int DBCLocaleIndex;
@@ -942,9 +936,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 Trinity::Singleton<ObjectMgr>::Instance()
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index d57c8875041..11d1fa7f501 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -4750,13 +4750,15 @@ void Spell::EffectScriptEffect(uint32 effIndex)
}
}
- static uint32 const itypes[6][3] = {
+ static uint32 const itypes[8][3] = {
{ 5512,19004,19005}, // Minor Healthstone
{ 5511,19006,19007}, // Lesser Healthstone
{ 5509,19008,19009}, // Healthstone
{ 5510,19010,19011}, // Greater Healthstone
{ 9421,19012,19013}, // Major Healthstone
- {22103,22104,22105} // Master Healthstone
+ {22103,22104,22105}, // Master Healthstone
+ {36889,36890,36891}, // Demonic Healthstone
+ {36892,36893,36894} // Fel Healthstone
};
switch(m_spellInfo->Id)
@@ -4767,6 +4769,8 @@ void Spell::EffectScriptEffect(uint32 effIndex)
case 11729: itemtype=itypes[3][rank];break; // Greater Healthstone
case 11730: itemtype=itypes[4][rank];break; // Major Healthstone
case 27230: itemtype=itypes[5][rank];break; // Master Healthstone
+ case 47871: itemtype=itypes[6][rank];break; // Demonic Healthstone
+ case 47878: itemtype=itypes[7][rank];break; // Fel Healthstone
default:
return;
}
diff --git a/src/game/World.cpp b/src/game/World.cpp
index 3f1fc1773f1..f8bdd9f24c2 100644
--- a/src/game/World.cpp
+++ b/src/game/World.cpp
@@ -37,6 +37,7 @@
#include "SkillDiscovery.h"
#include "World.h"
#include "AccountMgr.h"
+#include "AchievementMgr.h"
#include "ObjectMgr.h"
#include "SpellMgr.h"
#include "Chat.h"
@@ -1106,12 +1107,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();
@@ -1285,6 +1280,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 c956a070555..05ad9af7f9c 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 "7041"
#endif // __REVISION_NR_H__