Core/Dungeon Finder: Added support for rewards for random dungeons

Core/Quests: Simplified rewarding money from quests, now ModifyMoney and UpdateAchievementCriteria are called only once per quest
Core/Achievements: Implemented ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS

--HG--
branch : trunk
This commit is contained in:
Shauren
2010-09-03 20:11:14 +02:00
parent d7f9cea305
commit d5115ca687
14 changed files with 432 additions and 177 deletions
+48
View File
@@ -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.'),
@@ -3090,6 +3092,52 @@ LOCK TABLES `item_template` WRITE;
/*!40000 ALTER TABLE `item_template` ENABLE KEYS */;
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`
--
+4
View File
@@ -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.');
@@ -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;
@@ -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;
@@ -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:
+2
View File
@@ -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 },
+2
View File
@@ -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);
+17
View File
@@ -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 ...");
@@ -481,6 +481,12 @@ struct AchievementCriteriaEntry
uint32 killCount; // 4
} honorable_kill;
struct
{
uint32 unused;
uint32 dungeonsComplete;
} use_lfg;
struct
{
uint32 field3; // 3 main requirement
+276 -98
View File
@@ -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,39 +360,137 @@ 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>
@@ -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 ? 1 : 0);
if (reward)
{
data << uint32(reward->itemId);
data << uint32(reward->displayId);
data << uint32(reward->stackCount);
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
for (LfgRewardMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
{
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;
rew = itr->second;
// ordered properly at loading
if (itr->second->maxLevel >= level)
break;
}
return done ? m_RewardDoneList.at(index) : m_RewardList.at(index);
return rew;
}
/// <summary>
+35 -69
View File
@@ -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
+9 -9
View File
@@ -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())
{
ModifyMoney(pQuest->GetRewOrReqMoney());
moneyRew += pQuest->GetRewOrReqMoney();
if (pQuest->GetRewOrReqMoney() > 0)
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, pQuest->GetRewOrReqMoney());
if (moneyRew)
{
ModifyMoney(moneyRew);
if (moneyRew > 0)
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, uint32(moneyRew));
}
// honor reward
+1
View File
@@ -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; }
+6
View File
@@ -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();