feat(Core/Quests): Implemented quest_money_rewards (for quest with Qu… (#8610)

Fixes #8440
This commit is contained in:
UltraNix
2021-10-20 10:45:56 +02:00
committed by GitHub
parent 07484d0439
commit 1fb6830b15
12 changed files with 652 additions and 78 deletions

View File

@@ -424,7 +424,7 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU
data << uint32(0);
}
data << uint32(quest->GetRewOrReqMoney());
data << uint32(quest->GetRewOrReqMoney(_session->GetPlayer()));
data << uint32(quest->XPValue(_session->GetPlayer()) * _session->GetPlayer()->GetQuestRate());
}
@@ -506,7 +506,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
if (quest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
data << uint32(0); // Hide money rewarded
else
data << uint32(quest->GetRewOrReqMoney()); // reward money (below max lvl)
data << uint32(quest->GetRewOrReqMoney(_session->GetPlayer())); // reward money (below max lvl)
data << uint32(quest->GetRewMoneyMaxLevel()); // used in XP calculation at client
data << uint32(quest->GetRewSpell()); // reward spell, this spell will display (icon) (cast if RewSpellCast == 0)
@@ -650,7 +650,7 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUI
data << uint32(0);
}
data << uint32(quest->GetRewOrReqMoney());
data << uint32(quest->GetRewOrReqMoney(_session->GetPlayer()));
data << uint32(quest->XPValue(_session->GetPlayer()) * _session->GetPlayer()->GetQuestRate());
// rewarded honor points. Multiply with 10 to satisfy client

View File

@@ -751,8 +751,10 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
}
// Give player extra money if GetRewOrReqMoney > 0 and get ReqMoney if negative
if (quest->GetRewOrReqMoney())
moneyRew += quest->GetRewOrReqMoney();
if (int32 rewOrReqMoney = quest->GetRewOrReqMoney(this))
{
moneyRew += rewOrReqMoney;
}
if (moneyRew)
{
@@ -2084,23 +2086,30 @@ void Player::MoneyChanged(uint32 count)
if (!questid)
continue;
Quest const* qInfo = sObjectMgr->GetQuestTemplate(questid);
if (qInfo && qInfo->GetRewOrReqMoney() < 0)
if (Quest const* qInfo = sObjectMgr->GetQuestTemplate(questid))
{
QuestStatusData& q_status = m_QuestStatus[questid];
int32 rewOrReqMoney = qInfo->GetRewOrReqMoney();
if (rewOrReqMoney < 0)
{
QuestStatusData& q_status = m_QuestStatus[questid];
if (q_status.Status == QUEST_STATUS_INCOMPLETE)
{
if (int32(count) >= -qInfo->GetRewOrReqMoney())
if (q_status.Status == QUEST_STATUS_INCOMPLETE)
{
if (CanCompleteQuest(questid))
CompleteQuest(questid);
if (int32(count) >= -rewOrReqMoney)
{
if (CanCompleteQuest(questid))
{
CompleteQuest(questid);
}
}
}
else if (q_status.Status == QUEST_STATUS_COMPLETE)
{
if (int32(count) < -rewOrReqMoney)
{
IncompleteQuest(questid);
}
}
}
else if (q_status.Status == QUEST_STATUS_COMPLETE)
{
if (int32(count) < -qInfo->GetRewOrReqMoney())
IncompleteQuest(questid);
}
}
}
@@ -2262,12 +2271,12 @@ void Player::SendQuestReward(Quest const* quest, uint32 XP)
if (getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
{
data << uint32(XP);
data << uint32(quest->GetRewOrReqMoney());
data << uint32(quest->GetRewOrReqMoney(this));
}
else
{
data << uint32(0);
data << uint32(quest->GetRewOrReqMoney() + quest->GetRewMoneyMaxLevel());
data << uint32(quest->GetRewOrReqMoney(this) + quest->GetRewMoneyMaxLevel());
}
data << uint32(10 * quest->CalculateHonorGain(GetQuestLevel(quest)));

View File

@@ -4050,27 +4050,27 @@ void ObjectMgr::LoadQuests()
"ID, QuestType, QuestLevel, MinLevel, QuestSortID, QuestInfoID, SuggestedGroupNum, TimeAllowed, AllowableRaces,"
// 9 10 11 12
"RequiredFactionId1, RequiredFactionId2, RequiredFactionValue1, RequiredFactionValue2, "
// 13 14 15 16 17 18 19 20
"RewardNextQuest, RewardXPDifficulty, RewardMoney, RewardBonusMoney, RewardDisplaySpell, RewardSpell, RewardHonor, RewardKillHonor, "
// 21 22 23 24 25 26
// 13 14 15 16 17 18 19 20 21
"RewardNextQuest, RewardXPDifficulty, RewardMoney, RewardMoneyDifficulty, RewardBonusMoney, RewardDisplaySpell, RewardSpell, RewardHonor, RewardKillHonor, "
// 22 23 24 25 26 27
"StartItem, Flags, RewardTitle, RequiredPlayerKills, RewardTalents, RewardArenaPoints, "
// 27 28 29 30 31 32 33 34
// 28 29 30 31 32 33 34 35
"RewardItem1, RewardAmount1, RewardItem2, RewardAmount2, RewardItem3, RewardAmount3, RewardItem4, RewardAmount4, "
// 35 36 37 38 39 40 41 42 43 44 45 46
// 36 37 38 39 40 41 42 43 44 45 46 47
"RewardChoiceItemID1, RewardChoiceItemQuantity1, RewardChoiceItemID2, RewardChoiceItemQuantity2, RewardChoiceItemID3, RewardChoiceItemQuantity3, RewardChoiceItemID4, RewardChoiceItemQuantity4, RewardChoiceItemID5, RewardChoiceItemQuantity5, RewardChoiceItemID6, RewardChoiceItemQuantity6, "
// 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
// 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
"RewardFactionID1, RewardFactionValue1, RewardFactionOverride1, RewardFactionID2, RewardFactionValue2, RewardFactionOverride2, RewardFactionID3, RewardFactionValue3, RewardFactionOverride3, RewardFactionID4, RewardFactionValue4, RewardFactionOverride4, RewardFactionID5, RewardFactionValue5, RewardFactionOverride5,"
// 62 63 64 65
// 62 64 65 66
"POIContinent, POIx, POIy, POIPriority, "
// 66 67 68 69 70
// 67 68 69 70 71
"LogTitle, LogDescription, QuestDescription, AreaDescription, QuestCompletionLog, "
// 71 72 73 74 75 76 77 78
// 72 73 74 75 76 77 78 79
"RequiredNpcOrGo1, RequiredNpcOrGo2, RequiredNpcOrGo3, RequiredNpcOrGo4, RequiredNpcOrGoCount1, RequiredNpcOrGoCount2, RequiredNpcOrGoCount3, RequiredNpcOrGoCount4, "
// 79 80 81 82 83 84 85 86
// 80 81 82 83 84 85 86 87
"ItemDrop1, ItemDrop2, ItemDrop3, ItemDrop4, ItemDropQuantity1, ItemDropQuantity2, ItemDropQuantity3, ItemDropQuantity4, "
// 87 88 89 90 91 92 93 94 95 96 97 98
// 88 89 90 91 92 93 94 95 96 97 98 99
"RequiredItemId1, RequiredItemId2, RequiredItemId3, RequiredItemId4, RequiredItemId5, RequiredItemId6, RequiredItemCount1, RequiredItemCount2, RequiredItemCount3, RequiredItemCount4, RequiredItemCount5, RequiredItemCount6, "
// 99 100 101 102 103
// 100 101 102 103 104
"Unknown0, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4"
" FROM quest_template");
if (!result)
@@ -9341,3 +9341,50 @@ void ObjectMgr::LoadCreatureQuestItems()
LOG_INFO("server.loading", ">> Loaded %u creature quest items in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
LOG_INFO("server.loading", " ");
}
void ObjectMgr::LoadQuestMoneyRewards()
{
uint32 oldMSTime = getMSTime();
_questMoneyRewards.clear();
// 0 1 2 3 4 5 6 7 8 9 10
QueryResult result = WorldDatabase.Query("SELECT `Level`, Money0, Money1, Money2, Money3, Money4, Money5, Money6, Money7, Money8, Money9 FROM `quest_money_reward` ORDER BY `Level`");
if (!result)
{
LOG_ERROR("server.loading", ">> Loaded 0 quest money rewards. DB table `quest_money_reward` is empty.");
return;
}
uint32 count = 0;
do
{
Field* fields = result->Fetch();
uint32 Level = fields[0].GetUInt32();
QuestMoneyRewardArray& questMoneyReward = _questMoneyRewards[Level];
questMoneyReward.fill(0);
for (uint8 i = 0; i < MAX_QUEST_MONEY_REWARDS; ++i)
{
questMoneyReward[i] = fields[1 + i].GetUInt32();
++count;
}
} while (result->NextRow());
LOG_INFO("server.loading", ">> Loaded %u Quest Money Rewards in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
uint32 ObjectMgr::GetQuestMoneyReward(uint8 level, uint32 questMoneyDifficulty) const
{
if (questMoneyDifficulty < MAX_QUEST_MONEY_REWARDS)
{
auto const& itr = _questMoneyRewards.find(level);
if (itr != _questMoneyRewards.end())
{
return itr->second.at(questMoneyDifficulty);
}
}
return 0;
}

View File

@@ -690,6 +690,10 @@ struct DungeonEncounter
typedef std::list<DungeonEncounter const*> DungeonEncounterList;
typedef std::unordered_map<uint32, DungeonEncounterList> DungeonEncounterContainer;
static constexpr uint32 MAX_QUEST_MONEY_REWARDS = 10;
typedef std::array<uint32, MAX_QUEST_MONEY_REWARDS> QuestMoneyRewardArray;
typedef std::unordered_map<uint32, QuestMoneyRewardArray> QuestMoneyRewardStore;
class PlayerDumpReader;
class ObjectMgr
@@ -915,6 +919,7 @@ public:
}
void LoadQuests();
void LoadQuestMoneyRewards();
void LoadQuestStartersAndEnders()
{
LOG_INFO("server.loading", "Loading GO Start Quest Data...");
@@ -1361,6 +1366,8 @@ public:
[[nodiscard]] bool IsTransportMap(uint32 mapId) const { return _transportMaps.count(mapId) != 0; }
[[nodiscard]] uint32 GetQuestMoneyReward(uint8 level, uint32 questMoneyDifficulty) const;
private:
// first free id for selected id type
uint32 _auctionId; // pussywizard: accessed by a single thread
@@ -1523,6 +1530,8 @@ private:
};
std::set<uint32> _transportMaps; // Helper container storing map ids that are for transports only, loaded from gameobject_template
QuestMoneyRewardStore _questMoneyRewards;
};
#define sObjectMgr ObjectMgr::instance()

View File

@@ -205,7 +205,7 @@ void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recvData*
if (quest)
{
data << uint8(done);
data << uint32(quest->GetRewOrReqMoney());
data << uint32(quest->GetRewOrReqMoney(GetPlayer()));
data << uint32(quest->XPValue(GetPlayer()));
data << uint32(0);
data << uint32(0);
@@ -496,7 +496,7 @@ void WorldSession::SendLfgPlayerReward(lfg::LfgPlayerRewardData const& rewardDat
data << uint32(rewardData.sdungeonEntry); // Dungeon Finished
data << uint8(rewardData.done);
data << uint32(1);
data << uint32(rewardData.quest->GetRewOrReqMoney());
data << uint32(rewardData.quest->GetRewOrReqMoney(GetPlayer()));
data << uint32(rewardData.quest->XPValue(GetPlayer()));
data << uint32(0);
data << uint32(0);

View File

@@ -46,22 +46,23 @@ Quest::Quest(Field* questRecord)
RewardNextQuest = questRecord[13].GetUInt32();
RewardXPDifficulty = questRecord[14].GetUInt8();
RewardMoney = questRecord[15].GetInt32();
RewardBonusMoney = questRecord[16].GetUInt32();
RewardDisplaySpell = questRecord[17].GetUInt32();
RewardSpell = questRecord[18].GetInt32();
RewardHonor = questRecord[19].GetUInt32();
RewardKillHonor = questRecord[20].GetFloat();
StartItem = questRecord[21].GetUInt32();
Flags = questRecord[22].GetUInt32();
RewardTitleId = questRecord[23].GetUInt8();
RequiredPlayerKills = questRecord[24].GetUInt8();
RewardTalents = questRecord[25].GetUInt8();
RewardArenaPoints = questRecord[26].GetUInt16();
RewardMoneyDifficulty = questRecord[16].GetUInt32();
RewardBonusMoney = questRecord[17].GetUInt32();
RewardDisplaySpell = questRecord[18].GetUInt32();
RewardSpell = questRecord[19].GetInt32();
RewardHonor = questRecord[20].GetUInt32();
RewardKillHonor = questRecord[21].GetFloat();
StartItem = questRecord[22].GetUInt32();
Flags = questRecord[23].GetUInt32();
RewardTitleId = questRecord[24].GetUInt8();
RequiredPlayerKills = questRecord[25].GetUInt8();
RewardTalents = questRecord[26].GetUInt8();
RewardArenaPoints = questRecord[27].GetUInt16();
for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
{
RewardItemId[i] = questRecord[27 + i * 2].GetUInt32();
RewardItemIdCount[i] = questRecord[28 + i * 2].GetUInt16();
RewardItemId[i] = questRecord[28 + i * 2].GetUInt32();
RewardItemIdCount[i] = questRecord[29 + i * 2].GetUInt16();
if (RewardItemId[i])
++_rewItemsCount;
@@ -69,8 +70,8 @@ Quest::Quest(Field* questRecord)
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
{
RewardChoiceItemId[i] = questRecord[35 + i * 2].GetUInt32();
RewardChoiceItemCount[i] = questRecord[36 + i * 2].GetUInt16();
RewardChoiceItemId[i] = questRecord[36 + i * 2].GetUInt32();
RewardChoiceItemCount[i] = questRecord[37 + i * 2].GetUInt16();
if (RewardChoiceItemId[i])
++_rewChoiceItemsCount;
@@ -78,26 +79,26 @@ Quest::Quest(Field* questRecord)
for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
{
RewardFactionId[i] = questRecord[47 + i * 3].GetUInt16();
RewardFactionValueId[i] = questRecord[48 + i * 3].GetInt32();
RewardFactionValueIdOverride[i] = questRecord[49 + i * 3].GetInt32();
RewardFactionId[i] = questRecord[48 + i * 3].GetUInt16();
RewardFactionValueId[i] = questRecord[49 + i * 3].GetInt32();
RewardFactionValueIdOverride[i] = questRecord[50 + i * 3].GetInt32();
}
POIContinent = questRecord[62].GetUInt16();
POIx = questRecord[63].GetFloat();
POIy = questRecord[64].GetFloat();
POIPriority = questRecord[65].GetUInt32();
Title = questRecord[66].GetString();
Objectives = questRecord[67].GetString();
Details = questRecord[68].GetString();
AreaDescription = questRecord[69].GetString();
CompletedText = questRecord[70].GetString();
POIContinent = questRecord[63].GetUInt16();
POIx = questRecord[64].GetFloat();
POIy = questRecord[65].GetFloat();
POIPriority = questRecord[66].GetUInt32();
Title = questRecord[67].GetString();
Objectives = questRecord[68].GetString();
Details = questRecord[69].GetString();
AreaDescription = questRecord[70].GetString();
CompletedText = questRecord[71].GetString();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
{
RequiredNpcOrGo[i] = questRecord[71 + i].GetInt32();
RequiredNpcOrGoCount[i] = questRecord[75 + i].GetUInt16();
ObjectiveText[i] = questRecord[100 + i].GetString();
RequiredNpcOrGo[i] = questRecord[72 + i].GetInt32();
RequiredNpcOrGoCount[i] = questRecord[76 + i].GetUInt16();
ObjectiveText[i] = questRecord[101 + i].GetString();
if (RequiredNpcOrGo[i])
++_reqCreatureOrGOcount;
@@ -105,21 +106,21 @@ Quest::Quest(Field* questRecord)
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
{
ItemDrop[i] = questRecord[79 + i].GetUInt32();
ItemDropQuantity[i] = questRecord[83 + i].GetUInt16();
ItemDrop[i] = questRecord[80 + i].GetUInt32();
ItemDropQuantity[i] = questRecord[84 + i].GetUInt16();
}
for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
{
RequiredItemId[i] = questRecord[87 + i].GetUInt32();
RequiredItemCount[i] = questRecord[93 + i].GetUInt16();
RequiredItemId[i] = questRecord[88 + i].GetUInt32();
RequiredItemCount[i] = questRecord[94 + i].GetUInt16();
if (RequiredItemId[i])
++_reqItemsCount;
}
// int8 Unknown0 = questRecord[99].GetUInt8();
// int32 VerifiedBuild = questRecord[104].GetInt32();
// int8 Unknown0 = questRecord[100].GetUInt8();
// int32 VerifiedBuild = questRecord[105].GetInt32();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
{
@@ -214,12 +215,23 @@ uint32 Quest::XPValue(Player* player) const
return 0;
}
int32 Quest::GetRewOrReqMoney() const
int32 Quest::GetRewOrReqMoney(Player* player /*= nullptr*/) const
{
if (RewardMoney <= 0)
return RewardMoney;
int32 rewardedMoney = RewardMoney;
if (rewardedMoney < 0)
{
return rewardedMoney;
}
return static_cast<int32>(RewardMoney * sWorld->getRate(RATE_DROP_MONEY));
if (player && RewardMoneyDifficulty)
{
if (uint32 questRewardedMoney = sObjectMgr->GetQuestMoneyReward(player->getLevel(), RewardMoneyDifficulty))
{
rewardedMoney = questRewardedMoney;
}
}
return static_cast<int32>(rewardedMoney * sWorld->getRate(RATE_DROP_MONEY));
}
uint32 Quest::GetRewMoneyMaxLevel() const
@@ -311,9 +323,9 @@ void Quest::InitializeQueryData()
queryData << uint32(GetXPId()); // used for calculating rewarded experience
if (HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
queryData << uint32(0); // Hide money rewarded
queryData << uint32(0); // Hide money rewarded
else
queryData << uint32(GetRewOrReqMoney()); // reward money (below max lvl)
queryData << int32(GetRewOrReqMoney()); // reward money (below max lvl)
queryData << uint32(GetRewMoneyMaxLevel()); // used in XP calculation at client
queryData << uint32(GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast == 0)

View File

@@ -258,7 +258,7 @@ public:
[[nodiscard]] std::string const& GetRequestItemsText() const { return RequestItemsText; }
[[nodiscard]] std::string const& GetAreaDescription() const { return AreaDescription; }
[[nodiscard]] std::string const& GetCompletedText() const { return CompletedText; }
[[nodiscard]] int32 GetRewOrReqMoney() const;
[[nodiscard]] int32 GetRewOrReqMoney(Player* player = nullptr) const;
[[nodiscard]] uint32 GetRewHonorAddition() const { return RewardHonor; }
[[nodiscard]] float GetRewHonorMultiplier() const { return RewardKillHonor; }
[[nodiscard]] uint32 GetRewMoneyMaxLevel() const; // use in XP calculation at client
@@ -366,6 +366,7 @@ protected:
uint32 RewardHonor;
float RewardKillHonor;
int32 RewardMoney;
uint32 RewardMoneyDifficulty;
uint32 RewardBonusMoney;
uint32 RewardDisplaySpell;
int32 RewardSpell;

View File

@@ -1706,6 +1706,9 @@ void World::SetInitialWorldSettings()
LOG_INFO("server.loading", "Loading Quests Starters and Enders...");
sObjectMgr->LoadQuestStartersAndEnders(); // must be after quest load
LOG_INFO("server.loading", "Loading Quest Money Rewards...");
sObjectMgr->LoadQuestMoneyRewards();
LOG_INFO("server.loading", "Loading Objects Pooling Data...");
sPoolMgr->LoadFromDB();

View File

@@ -238,7 +238,7 @@ public:
}
// If the quest requires money
int32 ReqOrRewMoney = quest->GetRewOrReqMoney();
int32 ReqOrRewMoney = quest->GetRewOrReqMoney(player);
if (ReqOrRewMoney < 0)
player->ModifyMoney(-ReqOrRewMoney);