aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/base/world_database.sql48
-rw-r--r--sql/updates/9743_world_command.sql4
-rw-r--r--sql/updates/9743_world_lfg_dungeon_encounters.sql6
-rw-r--r--sql/updates/9743_world_lfg_dungeon_rewards.sql12
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp9
-rw-r--r--src/server/game/Chat/Chat.cpp2
-rw-r--r--src/server/game/Chat/Chat.h2
-rw-r--r--src/server/game/Chat/Commands/Level3.cpp17
-rw-r--r--src/server/game/DataStores/DBCStructure.h6
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp380
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.h104
-rw-r--r--src/server/game/Entities/Player/Player.cpp16
-rw-r--r--src/server/game/Entities/Player/Player.h1
-rw-r--r--src/server/game/World/World.cpp6
14 files changed, 434 insertions, 179 deletions
diff --git a/sql/base/world_database.sql b/sql/base/world_database.sql
index f74f8bbbcab..d5fe2a57039 100644
--- a/sql/base/world_database.sql
+++ b/sql/base/world_database.sql
@@ -592,6 +592,8 @@ INSERT INTO `command` VALUES
('reload item_enchantment_template',3,'Syntax: .reload item_enchantment_template\nReload item_enchantment_template table.'),
('reload item_loot_template',3,'Syntax: .reload item_loot_template\nReload item_loot_template table.'),
('reload item_set_names',3,'Syntax: .reload item_set_names\nReload item_set_names table.'),
+('reload lfg_dungeon_encounters',3,'Syntax: .reload lfg_dungeon_encounters\nReload lfg_dungeon_encounters table.'),
+('reload lfg_dungeon_rewards',3,'Syntax: .reload lfg_dungeon_rewards\nReload lfg_dungeon_rewards table.'),
('reload locales_creature',3,'Syntax: .reload locales_creature\nReload locales_creature table.'),
('reload locales_gameobject',3,'Syntax: .reload locales_gameobject\nReload locales_gameobject table.'),
('reload locales_gossip_menu_option',3, 'Syntax: .reload locales_gossip_menu_option\nReload locales_gossip_menu_option table.'),
@@ -3091,6 +3093,52 @@ LOCK TABLES `item_template` WRITE;
UNLOCK TABLES;
--
+-- Table structure for table `lfg_dungeon_encounters`
+--
+
+DROP TABLE IF EXISTS `lfg_dungeon_encounters`;
+CREATE TABLE `lfg_dungeon_encounters` (
+ `achievementId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Achievement marking final boss completion',
+ `dungeonId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Dungeon entry from dbc',
+ PRIMARY KEY (`achievementId`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `lfg_dungeon_encounters`
+--
+
+LOCK TABLES `lfg_dungeon_encounters` WRITE;
+/*!40000 ALTER TABLE `lfg_dungeon_encounters` DISABLE KEYS */;
+/*!40000 ALTER TABLE `lfg_dungeon_encounters` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `lfg_dungeon_rewards`
+--
+
+DROP TABLE IF EXISTS `lfg_dungeon_rewards`;
+CREATE TABLE `lfg_dungeon_rewards` (
+ `dungeonId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Dungeon entry from dbc',
+ `maxLevel` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Max level at which this reward is rewarded',
+ `firstQuestId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Quest id with rewards for first dungeon this day',
+ `firstMoneyVar` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Money multiplier for completing the dungeon first time in a day with less players than max',
+ `firstXPVar` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Experience multiplier for completing the dungeon first time in a day with less players than max',
+ `otherQuestId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Quest id with rewards for Nth dungeon this day',
+ `otherMoneyVar` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Money multiplier for completing the dungeon Nth time in a day with less players than max',
+ `otherXPVar` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Experience multiplier for completing the dungeon Nth time in a day with less players than max',
+ PRIMARY KEY (`dungeonId`,`maxLevel`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `lfg_dungeon_rewards`
+--
+
+LOCK TABLES `lfg_dungeon_rewards` WRITE;
+/*!40000 ALTER TABLE `lfg_dungeon_rewards` DISABLE KEYS */;
+/*!40000 ALTER TABLE `lfg_dungeon_rewards` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
-- Table structure for table `locales_achievement_reward`
--
diff --git a/sql/updates/9743_world_command.sql b/sql/updates/9743_world_command.sql
new file mode 100644
index 00000000000..4309c51db98
--- /dev/null
+++ b/sql/updates/9743_world_command.sql
@@ -0,0 +1,4 @@
+DELETE FROM `command` WHERE `name` IN ('reload lfg_dungeon_encounters','reload lfg_dungeon_rewards');
+INSERT INTO `command` (`name`,`security`,`help`) VALUES
+('reload lfg_dungeon_encounters',3,'Syntax: .reload lfg_dungeon_encounters\nReload lfg_dungeon_encounters table.'),
+('reload lfg_dungeon_rewards',3,'Syntax: .reload lfg_dungeon_rewards\nReload lfg_dungeon_rewards table.');
diff --git a/sql/updates/9743_world_lfg_dungeon_encounters.sql b/sql/updates/9743_world_lfg_dungeon_encounters.sql
new file mode 100644
index 00000000000..2e436b0edb2
--- /dev/null
+++ b/sql/updates/9743_world_lfg_dungeon_encounters.sql
@@ -0,0 +1,6 @@
+DROP TABLE IF EXISTS `lfg_dungeon_encounters`;
+CREATE TABLE `lfg_dungeon_encounters` (
+ `achievementId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Achievement marking final boss completion',
+ `dungeonId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Dungeon entry from dbc',
+ PRIMARY KEY (`achievementId`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
diff --git a/sql/updates/9743_world_lfg_dungeon_rewards.sql b/sql/updates/9743_world_lfg_dungeon_rewards.sql
new file mode 100644
index 00000000000..0b762b59aca
--- /dev/null
+++ b/sql/updates/9743_world_lfg_dungeon_rewards.sql
@@ -0,0 +1,12 @@
+DROP TABLE IF EXISTS `lfg_dungeon_rewards`;
+CREATE TABLE `lfg_dungeon_rewards` (
+ `dungeonId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Dungeon entry from dbc',
+ `maxLevel` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'Max level at which this reward is rewarded',
+ `firstQuestId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Quest id with rewards for first dungeon this day',
+ `firstMoneyVar` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Money multiplier for completing the dungeon first time in a day with less players than max',
+ `firstXPVar` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Experience multiplier for completing the dungeon first time in a day with less players than max',
+ `otherQuestId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Quest id with rewards for Nth dungeon this day',
+ `otherMoneyVar` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Money multiplier for completing the dungeon Nth time in a day with less players than max',
+ `otherXPVar` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Experience multiplier for completing the dungeon Nth time in a day with less players than max',
+ PRIMARY KEY (`dungeonId`,`maxLevel`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index d91ae2eec0c..ad1aef0b42a 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -39,6 +39,7 @@
#include "BattlegroundAB.h"
#include "Map.h"
#include "InstanceScript.h"
+#include "LFGMgr.h"
namespace Trinity
{
@@ -744,6 +745,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
if (!miscvalue1)
continue;
@@ -1476,9 +1478,9 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE:
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL:
- case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
break; // Not implemented yet :(
}
+
if (IsCompletedCriteria(achievementCriteria,achievement))
CompletedCriteriaFor(achievement);
@@ -1496,6 +1498,9 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if (IsCompletedAchievement(*itr))
CompletedAchievement(*itr);
}
+
+ if (const uint32 dungeonId = sLFGMgr.GetDungeonIdForAchievement(achievement->ID))
+ sLFGMgr.RewardDungeonDoneFor(dungeonId, GetPlayer());
}
}
@@ -1625,6 +1630,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
return progress->counter >= achievementCriteria->honorable_kill.killCount;
case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
return progress->counter >= 9000;
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
+ return progress->counter >= achievementCriteria->use_lfg.dungeonsComplete;
// handle all statistic-only criteria here
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index 9ff18aba367..581145a1e5f 100644
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -492,6 +492,8 @@ ChatCommand * ChatHandler::getCommandTable()
{ "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL },
{ "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL },
{ "item_set_names", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemSetNamesCommand, "", NULL },
+ { "lfg_dungeon_encounters", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLfgEncountersCommand, "", NULL },
+ { "lfg_dungeon_rewards", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLfgRewardsCommand, "", NULL },
{ "locales_achievement_reward", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesAchievementRewardCommand,"", NULL },
{ "locales_creature", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesCreatureCommand, "", NULL },
{ "locales_gameobject", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesGameobjectCommand, "", NULL },
diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h
index 6e84ae67511..b966a76c622 100644
--- a/src/server/game/Chat/Chat.h
+++ b/src/server/game/Chat/Chat.h
@@ -387,6 +387,8 @@ class ChatHandler
bool HandleReloadGOQuestInvRelationsCommand(const char* args);
bool HandleReloadItemEnchantementsCommand(const char* args);
bool HandleReloadItemSetNamesCommand(const char* args);
+ bool HandleReloadLfgEncountersCommand(const char* args);
+ bool HandleReloadLfgRewardsCommand(const char* args);
bool HandleReloadLocalesAchievementRewardCommand(const char* args);
bool HandleReloadLocalesCreatureCommand(const char* args);
bool HandleReloadLocalesGameobjectCommand(const char* args);
diff --git a/src/server/game/Chat/Commands/Level3.cpp b/src/server/game/Chat/Commands/Level3.cpp
index ee1dddc966a..de5c99e27ba 100644
--- a/src/server/game/Chat/Commands/Level3.cpp
+++ b/src/server/game/Chat/Commands/Level3.cpp
@@ -59,6 +59,7 @@
#include "Transport.h"
#include "WeatherMgr.h"
#include "ScriptMgr.h"
+#include "LFGMgr.h"
//reload commands
bool ChatHandler::HandleReloadAllCommand(const char*)
@@ -1055,6 +1056,22 @@ bool ChatHandler::HandleReloadLocalesAchievementRewardCommand(const char*)
return true;
}
+bool ChatHandler::HandleReloadLfgEncountersCommand(const char*)
+{
+ sLog.outString("Re-Loading dungeon encounter lfg associations...");
+ sLFGMgr.LoadDungeonEncounters();
+ SendGlobalGMSysMessage("DB table `lfg_dungeon_encounters` reloaded.");
+ return true;
+}
+
+bool ChatHandler::HandleReloadLfgRewardsCommand(const char*)
+{
+ sLog.outString("Re-Loading lfg dungeon rewards...");
+ sLFGMgr.LoadRewards();
+ SendGlobalGMSysMessage("DB table `lfg_dungeon_rewards` reloaded.");
+ return true;
+}
+
bool ChatHandler::HandleReloadLocalesCreatureCommand(const char* /*arg*/)
{
sLog.outString("Re-Loading Locales Creature ...");
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index 14876543a5c..e9297f29cfb 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -483,6 +483,12 @@ struct AchievementCriteriaEntry
struct
{
+ uint32 unused;
+ uint32 dungeonsComplete;
+ } use_lfg;
+
+ struct
+ {
uint32 field3; // 3 main requirement
uint32 count; // 4 main requirement count
} raw;
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index 49bcaffdc5a..056ffed393c 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -25,6 +25,7 @@
#include "ObjectMgr.h"
#include "DisableMgr.h"
#include "WorldPacket.h"
+#include "ProgressBar.h"
LFGMgr::LFGMgr()
{
@@ -43,15 +44,11 @@ LFGMgr::LFGMgr()
LFGMgr::~LFGMgr()
{
- // FIXME: RewardList to be removed -> query quest system
- for (LfgRewardList::iterator it = m_RewardList.begin(); it != m_RewardList.end(); ++it)
- delete *it;
- m_RewardList.clear();
+ for (LfgRewardMap::iterator itr = m_RewardMap.begin(); itr != m_RewardMap.end(); ++itr)
+ delete itr->second;
+ m_RewardMap.clear();
- // FIXME: RewardDoneList to be removed -> query quest system
- for (LfgRewardList::iterator it = m_RewardDoneList.begin(); it != m_RewardDoneList.end(); ++it)
- delete *it;
- m_RewardDoneList.clear();
+ m_EncountersByAchievement.clear();
for (LfgQueueInfoMap::iterator it = m_QueueInfoMap.begin(); it != m_QueueInfoMap.end(); ++it)
delete it->second;
@@ -363,40 +360,138 @@ void LFGMgr::Update(uint32 diff)
/// </summary>
void LFGMgr::InitLFG()
{
- // Fill reward data (to be removed -> query quest system)
- LfgReward *reward;
- for (uint8 i = 0; i <= LFG_REWARD_DATA_SIZE; ++i)
- {
- reward = new LfgReward();
- reward->strangers = 0;
- reward->baseXP = RewardDungeonData[i][0];
- reward->baseMoney = RewardDungeonData[i][1];
- reward->variableMoney = 0;
- reward->variableXP = 0;
- reward->itemId = RewardDungeonData[i][2];
- reward->displayId = RewardDungeonData[i][3];
- reward->stackCount = RewardDungeonData[i][4];
- m_RewardList.push_back(reward);
- }
-
- for (uint8 i = 0; i < LFG_REWARD_DATA_SIZE; ++i)
- {
- reward = new LfgReward();
- reward->strangers = 0;
- reward->baseXP = RewardDungeonDoneData[i][0];
- reward->baseMoney = RewardDungeonDoneData[i][1];
- reward->variableMoney = 0;
- reward->variableXP = 0;
- reward->itemId = RewardDungeonDoneData[i][2];
- reward->displayId = RewardDungeonDoneData[i][3];
- reward->stackCount = RewardDungeonDoneData[i][4];
- m_RewardDoneList.push_back(reward);
- }
// Initialize dungeonMap
GetAllDungeons();
}
/// <summary>
+/// Load achievement <-> encounter associations
+/// </summary>
+void LFGMgr::LoadDungeonEncounters()
+{
+ m_EncountersByAchievement.clear();
+
+ uint32 count = 0;
+ QueryResult_AutoPtr result = WorldDatabase.Query("SELECT achievementId, dungeonId FROM lfg_dungeon_encounters");
+
+ if (!result)
+ {
+ barGoLink bar(1);
+ bar.step();
+
+ sLog.outString();
+ sLog.outErrorDb(">> Loaded 0 dungeon encounter lfg associations. DB table `lfg_dungeon_encounters` is empty!");
+ return;
+ }
+
+ barGoLink bar(result->GetRowCount());
+
+ Field* fields = NULL;
+ do
+ {
+ fields = result->Fetch();
+ uint32 achievementId = fields[0].GetUInt32();
+ uint32 dungeonId = fields[1].GetUInt32();
+
+ if (AchievementEntry const* achievement = sAchievementStore.LookupEntry(achievementId))
+ {
+ if (!(achievement->flags & ACHIEVEMENT_FLAG_COUNTER))
+ {
+ sLog.outErrorDb("Achievement %u specified in table `lfg_dungeon_encounters` is not a statistic!", achievementId);
+ continue;
+ }
+ }
+ else
+ {
+ sLog.outErrorDb("Achievement %u specified in table `lfg_dungeon_encounters` does not exist!", achievementId);
+ continue;
+ }
+
+ if (!sLFGDungeonStore.LookupEntry(dungeonId))
+ {
+ sLog.outErrorDb("Dungeon %u specified in table `lfg_dungeon_encounters` does not exist!", dungeonId);
+ continue;
+ }
+
+ m_EncountersByAchievement[achievementId] = dungeonId;
+ ++count;
+ } while (result->NextRow());
+
+ sLog.outString();
+ sLog.outString(">> Loaded %u dungeon encounter lfg associations.", count);
+}
+
+/// <summary>
+/// Load rewards for completing dungeons
+/// </summary>
+void LFGMgr::LoadRewards()
+{
+ for (LfgRewardMap::iterator itr = m_RewardMap.begin(); itr != m_RewardMap.end(); ++itr)
+ delete itr->second;
+ m_RewardMap.clear();
+
+ uint32 count = 0;
+ // ORDER BY is very important for GetRandomDungeonReward!
+ QueryResult_AutoPtr result = WorldDatabase.Query("SELECT dungeonId, maxLevel, firstQuestId, firstMoneyVar, firstXPVar, otherQuestId, otherMoneyVar, otherXPVar FROM lfg_dungeon_rewards ORDER BY dungeonId, maxLevel ASC");
+
+ if (!result)
+ {
+ barGoLink bar(1);
+ bar.step();
+
+ sLog.outString();
+ sLog.outErrorDb(">> Loaded 0 lfg dungeon rewards. DB table `lfg_dungeon_rewards` is empty!");
+ return;
+ }
+
+ barGoLink bar(result->GetRowCount());
+
+ Field* fields = NULL;
+ do
+ {
+ fields = result->Fetch();
+ uint32 dungeonId = fields[0].GetUInt32();
+ uint32 maxLevel = fields[1].GetUInt8();
+ uint32 firstQuestId = fields[2].GetUInt32();
+ uint32 firstMoneyVar = fields[3].GetUInt32();
+ uint32 firstXPVar = fields[4].GetUInt32();
+ uint32 otherQuestId = fields[5].GetUInt32();
+ uint32 otherMoneyVar = fields[6].GetUInt32();
+ uint32 otherXPVar = fields[7].GetUInt32();
+
+ if (!sLFGDungeonStore.LookupEntry(dungeonId))
+ {
+ sLog.outErrorDb("Dungeon %u specified in table `lfg_dungeon_rewards` does not exist!", dungeonId);
+ continue;
+ }
+
+ if (!maxLevel || maxLevel > sWorld.getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
+ {
+ sLog.outErrorDb("Level %u specified for dungeon %u in table `lfg_dungeon_rewards` can never be reached!", maxLevel, dungeonId);
+ maxLevel = sWorld.getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
+ }
+
+ if (firstQuestId && !sObjectMgr.GetQuestTemplate(firstQuestId))
+ {
+ sLog.outErrorDb("First quest %u specified for dungeon %u in table `lfg_dungeon_rewards` does not exist!", firstQuestId, dungeonId);
+ firstQuestId = 0;
+ }
+
+ if (otherQuestId && !sObjectMgr.GetQuestTemplate(otherQuestId))
+ {
+ sLog.outErrorDb("Other quest %u specified for dungeon %u in table `lfg_dungeon_rewards` does not exist!", otherQuestId, dungeonId);
+ otherQuestId = 0;
+ }
+
+ m_RewardMap.insert(LfgRewardMap::value_type(dungeonId, new LfgReward(maxLevel, firstQuestId, firstMoneyVar, firstXPVar, otherQuestId, otherMoneyVar, otherXPVar)));
+ ++count;
+ } while (result->NextRow());
+
+ sLog.outString();
+ sLog.outString(">> Loaded %u lfg dungeon rewards.", count);
+}
+
+/// <summary>
/// Adds the player/group to lfg queue
/// </summary>
/// <param name="Player *">Player</param>
@@ -1566,24 +1661,47 @@ void LFGMgr::SendLfgPlayerInfo(Player *plr)
data << uint8(0);
else
{
- LfgReward *reward;
+ LfgReward const* reward = NULL;
+ Quest const* qRew = NULL;
+
data << uint8(randomlist->size()); // Random Dungeon count
for (LfgDungeonSet::iterator it = randomlist->begin(); it != randomlist->end(); ++it)
{
done = plr->isLfgDungeonDone(*it);
- reward = GetRandomDungeonReward(*it, done, plr->getLevel());
+ reward = GetRandomDungeonReward(*it, plr->getLevel());
data << uint32(*it); // Entry
data << uint8(done);
- data << uint32(reward->baseMoney);
- data << uint32(reward->baseXP);
- data << uint32(reward->variableMoney);
- data << uint32(reward->variableXP);
- data << uint8(reward->itemId != 0);
- if (reward->itemId)
+ if (reward)
{
- data << uint32(reward->itemId);
- data << uint32(reward->displayId);
- data << uint32(reward->stackCount);
+ qRew = sObjectMgr.GetQuestTemplate(reward->reward[done].questId);
+ data << uint32(qRew ? qRew->GetRewOrReqMoney() : 0);
+ data << uint32(qRew ? qRew->XPValue(plr) : 0);
+ data << uint32(reward->reward[done].variableMoney);
+ data << uint32(reward->reward[done].variableXP);
+ data << uint8(qRew ? qRew->GetRewItemsCount() : 0);
+ if (qRew && qRew->GetRewItemsCount())
+ {
+ ItemPrototype const* iProto = NULL;
+ for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
+ {
+ if (!qRew->RewItemId[i])
+ continue;
+
+ iProto = ObjectMgr::GetItemPrototype(qRew->RewItemId[i]);
+
+ data << uint32(qRew->RewItemId[i]);
+ data << uint32(iProto ? iProto->DisplayInfoID : 0);
+ data << uint32(qRew->RewItemCount[i]);
+ }
+ }
+ }
+ else
+ {
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0);
+ data << uint8(0);
}
}
randomlist->clear();
@@ -1661,29 +1779,55 @@ void LFGMgr::SendLfgPlayerReward(Player *plr)
if (plr->GetGroup())
sdungeonId = plr->GetGroup()->GetLfgDungeonEntry(false);
bool done = plr->isLfgDungeonDone(rdungeonId);
- LfgReward *reward = GetRandomDungeonReward(rdungeonId, done, plr->getLevel());
- if (!reward)
- return;
+ LfgReward const* reward = GetRandomDungeonReward(rdungeonId, plr->getLevel());
- uint8 itemNum = uint8(reward->itemId != 0);
+ uint8 itemNum = 0;
+ Quest const* qRew = NULL;
+ if (reward)
+ {
+ qRew = sObjectMgr.GetQuestTemplate(reward->reward[done].questId);
+ if (qRew)
+ itemNum = qRew->GetRewItemsCount();
+ }
sLog.outDebug("SMSG_LFG_PLAYER_REWARD");
WorldPacket data(SMSG_LFG_PLAYER_REWARD, 4 + 4 + 1 + 4 + 4 + 4 + 4 + 4 + 1 + itemNum * (4 + 4 + 4));
data << uint32(rdungeonId); // Random Dungeon Finished
data << uint32(sdungeonId); // Dungeon Finished
data << uint8(done);
- data << uint32(reward->strangers);
- data << uint32(reward->baseMoney);
- data << uint32(reward->baseXP);
- data << uint32(reward->variableMoney);
- data << uint32(reward->variableXP);
- data << uint8(itemNum);
- if (itemNum)
- {
- data << uint32(reward->itemId);
- data << uint32(reward->displayId);
- data << uint32(reward->stackCount);
+ data << uint32(reward ? 1 : 0);
+ if (reward)
+ {
+ data << uint32(qRew ? qRew->GetRewOrReqMoney() : 0);
+ data << uint32(qRew ? qRew->XPValue(plr) : 0);
+ data << uint32(reward->reward[done].variableMoney);
+ data << uint32(reward->reward[done].variableXP);
+ data << uint8(itemNum);
+ if (qRew && itemNum)
+ {
+ ItemPrototype const* iProto = NULL;
+ for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
+ {
+ if (!qRew->RewItemId[i])
+ continue;
+
+ iProto = ObjectMgr::GetItemPrototype(qRew->RewItemId[i]);
+
+ data << uint32(qRew->RewItemId[i]);
+ data << uint32(iProto ? iProto->DisplayInfoID : 0);
+ data << uint32(qRew->RewItemCount[i]);
+ }
+ }
}
+ else
+ {
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0);
+ data << uint8(0);
+ }
+
plr->GetSession()->SendPacket(&data);
}
@@ -1733,6 +1877,65 @@ void LFGMgr::BuildPlayerLockDungeonBlock(WorldPacket &data, LfgLockStatusSet *lo
delete lockSet;
}
+/// <summary>
+/// Give completion reward to player
+/// </summary>
+/// <param name="const uint32">dungeonId</param>
+/// <param name="Player *">player</param>
+void LFGMgr::RewardDungeonDoneFor(const uint32 dungeonId, Player *player)
+{
+ player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS, 1);
+
+ if (isRandomDungeon(dungeonId))
+ player->SetLfgDungeonDone(dungeonId);
+
+ LfgReward const* reward = GetRandomDungeonReward(dungeonId, player->getLevel());
+ if (!reward)
+ return;
+
+ uint8 index = player->isLfgDungeonDone(dungeonId) ? 1 : 0;
+ Quest const* qReward = sObjectMgr.GetQuestTemplate(reward->reward[index].questId);
+ if (!qReward)
+ return;
+
+ if (qReward->GetRewItemsCount() > 0)
+ {
+ for (uint32 i = 0; i < QUEST_REWARDS_COUNT; ++i)
+ {
+ if (uint32 itemId = qReward->RewItemId[i])
+ {
+ ItemPosCountVec dest;
+ if (player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemId, qReward->RewItemCount[i]) == EQUIP_ERR_OK)
+ {
+ Item* item = player->StoreNewItem(dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId));
+ player->SendNewItem(item, qReward->RewItemCount[i], true, false);
+ }
+ }
+ }
+ }
+
+ // Not give XP in case already completed once repeatable quest
+ uint32 XP = qReward->XPValue(player) * sWorld.getRate(RATE_XP_QUEST);
+
+ Group* group = player->GetGroup();
+ if (group)
+ XP += (5 - group->GetMembersCount()) * reward->reward[index].variableXP;
+
+ // Give player extra money if GetRewOrReqMoney > 0 and get ReqMoney if negative
+ int32 moneyRew = qReward->GetRewOrReqMoney();
+
+ if (player->getLevel() < sWorld.getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
+ player->GiveXP(XP, NULL);
+ else
+ moneyRew += int32(qReward->GetRewMoneyMaxLevel() * sWorld.getRate(RATE_DROP_MONEY));
+
+ if (group)
+ moneyRew += (5 - group->GetMembersCount()) * reward->reward[index].variableMoney;
+
+ if (moneyRew)
+ player->ModifyMoney(moneyRew);
+}
+
// --------------------------------------------------------------------------//
// Auxiliar Functions
// --------------------------------------------------------------------------//
@@ -1945,47 +2148,22 @@ LfgDungeonSet* LFGMgr::GetRandomDungeons(uint8 level, uint8 expansion)
/// Get the reward of a given random dungeon at a certain level
/// </summary>
/// <param name="uint32">random dungeon id</param>
-/// <param name="bool">Dungeon previously done</param>
/// <param name="uint8">Player level</param>
-/// <returns>LfgReward*</returns>
-LfgReward* LFGMgr::GetRandomDungeonReward(uint32 dungeon, bool done, uint8 level)
+/// <returns>LfgReward const*</returns>
+LfgReward const* LFGMgr::GetRandomDungeonReward(uint32 dungeon, uint8 level)
{
+ LfgReward const* rew = NULL;
+ LfgRewardMapBounds bounds = m_RewardMap.equal_range(dungeon & 0x00FFFFFF);
uint8 index = 0;
- switch((dungeon & 0x00FFFFFF)) // Get dungeon id from dungeon entry
- {
- case LFG_RANDOM_CLASSIC:
- if (level < 15)
- index = LFG_REWARD_LEVEL0;
- else if (level < 24)
- index = LFG_REWARD_LEVEL1;
- else if (level < 35)
- index = LFG_REWARD_LEVEL2;
- else if (level < 46)
- index = LFG_REWARD_LEVEL3;
- else if (level < 56)
- index = LFG_REWARD_LEVEL4;
- else
- index = LFG_REWARD_LEVEL5;
- break;
- case LFG_RANDOM_BC_NORMAL:
- index = LFG_REWARD_BC_NORMAL;
- break;
- case LFG_RANDOM_BC_HEROIC:
- index = LFG_REWARD_BC_HEROIC;
- break;
- case LFG_RANDOM_LK_NORMAL:
- index = level == 80 ? LFG_REWARD_LK_NORMAL80 : LFG_REWARD_LK_NORMAL;
- break;
- case LFG_RANDOM_LK_HEROIC:
- index = LFG_REWARD_LK_HEROIC;
- break;
- default: // This should never happen!
- done = false;
- index = LFG_REWARD_LEVEL0;
- sLog.outError("LFGMgr::GetRandomDungeonReward: Dungeon %u is not random dungeon!", dungeon);
- break;
- }
- return done ? m_RewardDoneList.at(index) : m_RewardList.at(index);
+ for (LfgRewardMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
+ {
+ rew = itr->second;
+ // ordered properly at loading
+ if (itr->second->maxLevel >= level)
+ break;
+ }
+
+ return rew;
}
/// <summary>
diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h
index 25e7d431174..cc932c5817f 100644
--- a/src/server/game/DungeonFinding/LFGMgr.h
+++ b/src/server/game/DungeonFinding/LFGMgr.h
@@ -131,62 +131,6 @@ enum LfgRoleCheckResult
LFG_ROLECHECK_NO_ROLE = 6, // Someone selected no role
};
-// TODO: Remove me, will not be needed when Reward moved to quest system
-enum LfgRandomDungeonEntries
-{
- LFG_ALL_DUNGEONS = 0,
- LFG_RANDOM_CLASSIC = 258,
- LFG_RANDOM_BC_NORMAL = 259,
- LFG_RANDOM_BC_HEROIC = 260,
- LFG_RANDOM_LK_NORMAL = 261,
- LFG_RANDOM_LK_HEROIC = 262,
-};
-
-enum LfgRewardEnums
-{
- LFG_REWARD_LEVEL0 = 10,
- LFG_REWARD_LEVEL1 = 0,
- LFG_REWARD_LEVEL2 = 1,
- LFG_REWARD_LEVEL3 = 2,
- LFG_REWARD_LEVEL4 = 3,
- LFG_REWARD_LEVEL5 = 4,
- LFG_REWARD_BC_NORMAL = 5,
- LFG_REWARD_BC_HEROIC = 6,
- LFG_REWARD_LK_NORMAL = 7,
- LFG_REWARD_LK_NORMAL80 = 7,
- LFG_REWARD_LK_HEROIC = 8,
- LFG_REWARD_DATA_SIZE = 10,
-};
-
-const uint32 RewardDungeonData[LFG_REWARD_DATA_SIZE+1][5] =
-{ // XP, money, item, item display, count
- {310, 3500, 51999, 56915, 1}, // Classic 15-23
- {470, 7000, 52000, 56915, 1}, // Classic 24-34
- {825, 13000, 52001, 56915, 1}, // Classic 35-45
- {12250, 16500, 52002, 56915, 1}, // Classic 46-55
- {14300, 18000, 52003, 56915, 1}, // Classic 56-60
- {1600, 62000, 52004, 56915, 1}, // BC Normal
- {1900, 88000, 52005, 56915, 1}, // BC Heroic
- {33100, 148000, 47241, 62232, 2}, // LK Normal
- {0, 198600, 47241, 62232, 2}, // LK Normal - Level 80
- {0, 264600, 49426, 64062, 2}, // LK Heroic
- {0, 0, 0, 0, 0}, // Classic - No level
-};
-
-const uint32 RewardDungeonDoneData[LFG_REWARD_DATA_SIZE][5] =
-{ // XP, money, item, item display, count
- {200, 1800, 51999, 56915, 1}, // Classic 15-23
- {310, 3500, 52000, 56915, 1}, // Classic 24-34
- {550, 6500, 52001, 56915, 1}, // Classic 35-45
- {8150, 8500, 52002, 56915, 1}, // Classic 46-55
- {9550, 9000, 52003, 56915, 1}, // Classic 56-60
- {1100, 31000, 52004, 56915, 1}, // BC Normal
- {12650, 44000, 52005, 56915, 1}, // BC Heroic
- {16550, 74000, 0, 0, 0}, // LK Normal
- {0, 99300, 0, 0, 0}, // LK Normal - Level 80
- {0, 132300, 47241, 62232, 2}, // LK Heroic
-};
-
// Dungeon and reason why player can't join
struct LfgLockStatus
{
@@ -197,14 +141,24 @@ struct LfgLockStatus
// Reward info
struct LfgReward
{
- uint32 strangers;
- uint32 baseMoney;
- uint32 baseXP;
- uint32 variableMoney;
- uint32 variableXP;
- uint32 itemId;
- uint32 displayId;
- uint32 stackCount;
+ uint32 maxLevel;
+ struct
+ {
+ uint32 questId;
+ uint32 variableMoney;
+ uint32 variableXP;
+ } reward[2];
+
+ LfgReward(uint32 _maxLevel, uint32 firstQuest, uint32 firstVarMoney, uint32 firstVarXp, uint32 otherQuest, uint32 otherVarMoney, uint32 otherVarXp)
+ : maxLevel(_maxLevel)
+ {
+ reward[0].questId = firstQuest;
+ reward[0].variableMoney = firstVarMoney;
+ reward[0].variableXP = firstVarXp;
+ reward[1].questId = otherQuest;
+ reward[1].variableMoney = otherVarMoney;
+ reward[1].variableXP = otherVarXp;
+ }
};
typedef std::map<uint32, uint8> LfgRolesMap;
@@ -279,14 +233,14 @@ struct LfgPlayerBoot
typedef std::set<Player*> PlayerSet;
typedef std::set<LfgLockStatus*> LfgLockStatusSet;
-typedef std::vector<LfgReward*> LfgRewardList;
-typedef std::map<uint32, LfgReward*> LfgRewardMap;
typedef std::vector<LfgProposal*> LfgProposalList;
typedef std::map<uint32, LfgLockStatusSet*> LfgLockStatusMap;
typedef std::map<uint64, LfgQueueInfo*> LfgQueueInfoMap;
typedef std::map<uint32, LfgRoleCheck*> LfgRoleCheckMap;
typedef std::map<uint32, LfgProposal*> LfgProposalMap;
typedef std::map<uint32, LfgPlayerBoot*> LfgPlayerBootMap;
+typedef std::multimap<uint32, LfgReward const*> LfgRewardMap;
+typedef std::pair<LfgRewardMap::const_iterator, LfgRewardMap::const_iterator> LfgRewardMapBounds;
typedef std::list<Player *> LfgPlayerList;
class LFGMgr
@@ -311,6 +265,18 @@ class LFGMgr
bool isRandomDungeon(uint32 dungeonId);
void InitBoot(Group *grp, uint32 plowGuid, uint32 vlowGuid, std::string reason);
+ void LoadDungeonEncounters();
+ void LoadRewards();
+ void RewardDungeonDoneFor(const uint32 dungeonId, Player* player);
+ const uint32 GetDungeonIdForAchievement(uint32 achievementId)
+ {
+ std::map<uint32, uint32>::iterator itr = m_EncountersByAchievement.find(achievementId);
+ if (itr != m_EncountersByAchievement.end())
+ return itr->second;
+
+ return 0;
+ }
+
private:
void Cleaner();
void AddGuidToNewQueue(uint64 guid);
@@ -337,11 +303,11 @@ class LFGMgr
LfgDungeonSet* GetDungeonsByRandom(uint32 randomdungeon);
LfgDungeonSet* GetRandomDungeons(uint8 level, uint8 expansion);
LfgDungeonSet* GetAllDungeons();
- LfgReward* GetRandomDungeonReward(uint32 dungeon, bool done, uint8 level);
+ LfgReward const* GetRandomDungeonReward(uint32 dungeon, uint8 level);
uint8 GetDungeonGroupType(uint32 dungeon);
- LfgRewardList m_RewardList; // TODO: Change it to list of quests
- LfgRewardList m_RewardDoneList; // TODO: Change it to list of quests
+ LfgRewardMap m_RewardMap; // Stores rewards for random dungeons
+ std::map<uint32, uint32> m_EncountersByAchievement; // Stores dungeon ids associated with achievements (for rewards)
LfgDungeonMap m_CachedDungeonMap; // Stores all dungeons by groupType
LfgQueueInfoMap m_QueueInfoMap; // Queued groups
LfgGuidList m_currentQueue; // Ordered list. Used to find groups
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index ae636dcca5e..ceb6e0605b4 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -14373,22 +14373,22 @@ void Player::RewardQuest(Quest const *pQuest, uint32 reward, Object* questGiver,
for (Unit::AuraEffectList::const_iterator i = ModXPPctAuras.begin(); i != ModXPPctAuras.end(); ++i)
XP = uint32(XP*(1.0f + (*i)->GetAmount() / 100.0f));
+ int32 moneyRew = 0;
if (getLevel() < sWorld.getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
GiveXP(XP, NULL);
else
- {
- uint32 money = uint32(pQuest->GetRewMoneyMaxLevel() * sWorld.getRate(RATE_DROP_MONEY));
- ModifyMoney(money);
- GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, money);
- }
+ moneyRew = int32(pQuest->GetRewMoneyMaxLevel() * sWorld.getRate(RATE_DROP_MONEY));
// Give player extra money if GetRewOrReqMoney > 0 and get ReqMoney if negative
if (pQuest->GetRewOrReqMoney())
+ moneyRew += pQuest->GetRewOrReqMoney();
+
+ if (moneyRew)
{
- ModifyMoney(pQuest->GetRewOrReqMoney());
+ ModifyMoney(moneyRew);
- if (pQuest->GetRewOrReqMoney() > 0)
- GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, pQuest->GetRewOrReqMoney());
+ if (moneyRew > 0)
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, uint32(moneyRew));
}
// honor reward
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 267abba9e9f..e82b6c823fd 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2251,6 +2251,7 @@ class Player : public Unit, public GridObject<Player>
bool isLfgDungeonDone(const uint32 entry) { return m_LookingForGroup.donerandomDungeons.find(entry) != m_LookingForGroup.donerandomDungeons.end(); }
LfgDungeonSet *GetLfgDungeons() { return &m_LookingForGroup.applyDungeons; }
LfgDungeonSet *GetLfgDungeonsDone() { return &m_LookingForGroup.donerandomDungeons; }
+ void SetLfgDungeonDone(const uint32 entry) { m_LookingForGroup.donerandomDungeons.insert(entry); }
std::string GetLfgComment() { return m_LookingForGroup.comment; }
void SetLfgComment(std::string _comment) { m_LookingForGroup.comment = _comment; }
uint8 GetLfgRoles() { return m_LookingForGroup.roles; }
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 65a631c71e3..9a12e2be60b 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1431,6 +1431,12 @@ void World::SetInitialWorldSettings()
sLog.outString("Loading Quests Relations...");
sObjectMgr.LoadQuestRelations(); // must be after quest load
+ sLog.outString("Loading Dungeon boss data...");
+ sLFGMgr.LoadDungeonEncounters();
+
+ sLog.outString("Loading LFG rewards...");
+ sLFGMgr.LoadRewards();
+
sLog.outString("Loading UNIT_NPC_FLAG_SPELLCLICK Data...");
sObjectMgr.LoadNPCSpellClickSpells();