aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2021-06-06 00:11:06 +0200
committerShauren <shauren.trinity@gmail.com>2021-06-06 00:11:06 +0200
commitb01fba4bd9530213ee0c9547e09d1f16b3ce5d67 (patch)
tree7e9fde1a68f804791cbb53a8d4127ceab4c961ef /src
parentf6b919fafe45aaeba0c5572925e47562158314b1 (diff)
Core/Reputation: Implemented paragon reputation
Diffstat (limited to 'src')
-rw-r--r--src/server/database/Database/Implementation/HotfixDatabase.cpp5
-rw-r--r--src/server/database/Database/Implementation/HotfixDatabase.h3
-rw-r--r--src/server/game/DataStores/DB2LoadInfo.h16
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp12
-rw-r--r--src/server/game/DataStores/DB2Stores.h2
-rw-r--r--src/server/game/DataStores/DB2Structure.h8
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp5
-rw-r--r--src/server/game/Reputation/ReputationMgr.cpp108
-rw-r--r--src/server/game/Reputation/ReputationMgr.h4
9 files changed, 152 insertions, 11 deletions
diff --git a/src/server/database/Database/Implementation/HotfixDatabase.cpp b/src/server/database/Database/Implementation/HotfixDatabase.cpp
index 208d9ca486b..57c1d975348 100644
--- a/src/server/database/Database/Implementation/HotfixDatabase.cpp
+++ b/src/server/database/Database/Implementation/HotfixDatabase.cpp
@@ -1054,6 +1054,11 @@ void HotfixDatabaseConnection::DoPrepareStatements()
"Spells10, PlayerActionBarFileDataID, Flags FROM override_spell_data WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
PREPARE_MAX_ID_STMT(HOTFIX_SEL_OVERRIDE_SPELL_DATA, "SELECT MAX(ID) + 1 FROM override_spell_data", CONNECTION_SYNCH);
+ // ParagonReputation.db2
+ PrepareStatement(HOTFIX_SEL_PARAGON_REPUTATION, "SELECT ID, FactionID, LevelThreshold, QuestID FROM paragon_reputation"
+ " WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
+ PREPARE_MAX_ID_STMT(HOTFIX_SEL_PARAGON_REPUTATION, "SELECT MAX(ID) + 1 FROM paragon_reputation", CONNECTION_SYNCH);
+
// Phase.db2
PrepareStatement(HOTFIX_SEL_PHASE, "SELECT ID, Flags FROM phase WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
PREPARE_MAX_ID_STMT(HOTFIX_SEL_PHASE, "SELECT MAX(ID) + 1 FROM phase", CONNECTION_SYNCH);
diff --git a/src/server/database/Database/Implementation/HotfixDatabase.h b/src/server/database/Database/Implementation/HotfixDatabase.h
index e2d4a788865..77d62fae5db 100644
--- a/src/server/database/Database/Implementation/HotfixDatabase.h
+++ b/src/server/database/Database/Implementation/HotfixDatabase.h
@@ -613,6 +613,9 @@ enum HotfixDatabaseStatements : uint32
HOTFIX_SEL_OVERRIDE_SPELL_DATA,
HOTFIX_SEL_OVERRIDE_SPELL_DATA_MAX_ID,
+ HOTFIX_SEL_PARAGON_REPUTATION,
+ HOTFIX_SEL_PARAGON_REPUTATION_MAX_ID,
+
HOTFIX_SEL_PHASE,
HOTFIX_SEL_PHASE_MAX_ID,
diff --git a/src/server/game/DataStores/DB2LoadInfo.h b/src/server/game/DataStores/DB2LoadInfo.h
index 885d366c000..4763c7d13ed 100644
--- a/src/server/game/DataStores/DB2LoadInfo.h
+++ b/src/server/game/DataStores/DB2LoadInfo.h
@@ -3971,6 +3971,22 @@ struct OverrideSpellDataLoadInfo
}
};
+struct ParagonReputationLoadInfo
+{
+ static DB2LoadInfo const* Instance()
+ {
+ static DB2FieldMeta const fields[] =
+ {
+ { false, FT_INT, "ID" },
+ { false, FT_INT, "FactionID" },
+ { true, FT_INT, "LevelThreshold" },
+ { true, FT_INT, "QuestID" },
+ };
+ static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ParagonReputationMeta::Instance(), HOTFIX_SEL_PARAGON_REPUTATION);
+ return &loadInfo;
+ }
+};
+
struct PhaseLoadInfo
{
static DB2LoadInfo const* Instance()
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index 0e2ffc7222b..564967cfd0b 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -218,6 +218,7 @@ DB2Storage<NamesReservedEntry> sNamesReservedStore("NamesReserv
DB2Storage<NamesReservedLocaleEntry> sNamesReservedLocaleStore("NamesReservedLocale.db2", NamesReservedLocaleLoadInfo::Instance());
DB2Storage<NumTalentsAtLevelEntry> sNumTalentsAtLevelStore("NumTalentsAtLevel.db2", NumTalentsAtLevelLoadInfo::Instance());
DB2Storage<OverrideSpellDataEntry> sOverrideSpellDataStore("OverrideSpellData.db2", OverrideSpellDataLoadInfo::Instance());
+DB2Storage<ParagonReputationEntry> sParagonReputationStore("ParagonReputation.db2", ParagonReputationLoadInfo::Instance());
DB2Storage<PhaseEntry> sPhaseStore("Phase.db2", PhaseLoadInfo::Instance());
DB2Storage<PhaseXPhaseGroupEntry> sPhaseXPhaseGroupStore("PhaseXPhaseGroup.db2", PhaseXPhaseGroupLoadInfo::Instance());
DB2Storage<PlayerConditionEntry> sPlayerConditionStore("PlayerCondition.db2", PlayerConditionLoadInfo::Instance());
@@ -437,6 +438,7 @@ namespace
MountDisplaysCointainer _mountDisplays;
NameGenContainer _nameGenData;
NameValidationRegexContainer _nameValidators;
+ std::unordered_map<uint32, ParagonReputationEntry const*> _paragonReputations;
PhaseGroupContainer _phasesByGroup;
PowerTypesContainer _powerTypes;
std::unordered_map<uint32, uint8> _pvpItemBonus;
@@ -761,6 +763,7 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul
LOAD_DB2(sNamesReservedLocaleStore);
LOAD_DB2(sNumTalentsAtLevelStore);
LOAD_DB2(sOverrideSpellDataStore);
+ LOAD_DB2(sParagonReputationStore);
LOAD_DB2(sPhaseStore);
LOAD_DB2(sPhaseXPhaseGroupStore);
LOAD_DB2(sPlayerConditionStore);
@@ -1226,6 +1229,10 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul
}
}
+ for (ParagonReputationEntry const* paragonReputation : sParagonReputationStore)
+ if (sFactionStore.HasRecord(paragonReputation->FactionID))
+ _paragonReputations[paragonReputation->FactionID] = paragonReputation;
+
for (PhaseXPhaseGroupEntry const* group : sPhaseXPhaseGroupStore)
if (PhaseEntry const* phase = sPhaseStore.LookupEntry(group->PhaseID))
_phasesByGroup[group->PhaseGroupID].push_back(phase->ID);
@@ -2650,6 +2657,11 @@ int32 DB2Manager::GetNumTalentsAtLevel(uint32 level, Classes playerClass)
return 0;
}
+ParagonReputationEntry const* DB2Manager::GetParagonReputation(uint32 factionId) const
+{
+ return Trinity::Containers::MapGetValuePtr(_paragonReputations, factionId);
+}
+
PVPDifficultyEntry const* DB2Manager::GetBattlegroundBracketByLevel(uint32 mapid, uint32 level)
{
PVPDifficultyEntry const* maxEntry = nullptr; // used for level > max listed level case
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index 99b29d64be7..3025bb73ce4 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -162,6 +162,7 @@ TC_GAME_API extern DB2Storage<MountCapabilityEntry> sMountCapabi
TC_GAME_API extern DB2Storage<MountEntry> sMountStore;
TC_GAME_API extern DB2Storage<MovieEntry> sMovieStore;
TC_GAME_API extern DB2Storage<OverrideSpellDataEntry> sOverrideSpellDataStore;
+TC_GAME_API extern DB2Storage<ParagonReputationEntry> sParagonReputationStore;
TC_GAME_API extern DB2Storage<PhaseEntry> sPhaseStore;
TC_GAME_API extern DB2Storage<PlayerConditionEntry> sPlayerConditionStore;
TC_GAME_API extern DB2Storage<PowerDisplayEntry> sPowerDisplayStore;
@@ -393,6 +394,7 @@ public:
std::string GetNameGenEntry(uint8 race, uint8 gender) const;
ResponseCodes ValidateName(std::wstring const& name, LocaleConstant locale) const;
static int32 GetNumTalentsAtLevel(uint32 level, Classes playerClass);
+ ParagonReputationEntry const* GetParagonReputation(uint32 factionId) const;
std::vector<uint32> const* GetPhasesForGroup(uint32 group) const;
PowerTypeEntry const* GetPowerTypeEntry(Powers power) const;
PowerTypeEntry const* GetPowerTypeByName(std::string const& name) const;
diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h
index 8823e2b01d9..d8f32bc1bf9 100644
--- a/src/server/game/DataStores/DB2Structure.h
+++ b/src/server/game/DataStores/DB2Structure.h
@@ -2453,6 +2453,14 @@ struct OverrideSpellDataEntry
uint8 Flags;
};
+struct ParagonReputationEntry
+{
+ uint32 ID;
+ uint32 FactionID;
+ int32 LevelThreshold;
+ int32 QuestID;
+};
+
struct PhaseEntry
{
uint32 ID;
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 909660aa310..8bd7173f44f 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -4935,6 +4935,11 @@ void ObjectMgr::LoadQuests()
}
}
+ // Make all paragon reward quests repeatable
+ for (ParagonReputationEntry const* paragonReputation : sParagonReputationStore)
+ if (Quest const* quest = GetQuestTemplate(paragonReputation->QuestID))
+ const_cast<Quest*>(quest)->SetSpecialFlag(QUEST_SPECIAL_FLAGS_REPEATABLE);
+
TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " quests definitions in %u ms", _questTemplates.size(), GetMSTimeDiffToNow(oldMSTime));
}
diff --git a/src/server/game/Reputation/ReputationMgr.cpp b/src/server/game/Reputation/ReputationMgr.cpp
index b7fa7ddc567..e662daf4a97 100644
--- a/src/server/game/Reputation/ReputationMgr.cpp
+++ b/src/server/game/Reputation/ReputationMgr.cpp
@@ -136,11 +136,30 @@ int32 ReputationMgr::GetMinReputation(FactionEntry const* factionEntry) const
int32 ReputationMgr::GetMaxReputation(FactionEntry const* factionEntry) const
{
+ if (ParagonReputationEntry const* paragonReputation = sDB2Manager.GetParagonReputation(factionEntry->ID))
+ {
+ // has reward quest, cap is just before threshold for another quest reward
+ // for example: if current reputation is 12345 and questa are given every 10000 and player has unclaimed reward
+ // then cap will be 19999
+
+ // otherwise cap is one theshold level larger
+ // if current reputation is 12345 and questa are given every 10000 and player does NOT have unclaimed reward
+ // then cap will be 29999
+
+ int32 reputation = GetReputation(factionEntry);
+ int32 cap = reputation + paragonReputation->LevelThreshold - reputation % paragonReputation->LevelThreshold - 1;
+
+ if (_player->GetQuestStatus(paragonReputation->QuestID) == QUEST_STATUS_NONE)
+ cap += paragonReputation->LevelThreshold;
+
+ return cap;
+ }
+
if (std::set<FriendshipRepReactionEntry const*> const* friendshipReactions = sDB2Manager.GetFriendshipRepReactions(factionEntry->FriendshipRepID))
return (*friendshipReactions->rbegin())->ReactionThreshold;
int32 dataIndex = GetFactionDataIndexForRaceAndClass(factionEntry);
- if (dataIndex >= 0 && factionEntry->ReputationMax[dataIndex])
+ if (dataIndex >= 0)
return factionEntry->ReputationMax[dataIndex];
return *ReputationRankThresholds.rbegin();
@@ -191,6 +210,22 @@ ReputationRank const* ReputationMgr::GetForcedRankIfAny(FactionTemplateEntry con
return GetForcedRankIfAny(factionTemplateEntry->Faction);
}
+int32 ReputationMgr::GetParagonLevel(uint32 paragonFactionId) const
+{
+ return GetParagonLevel(sFactionStore.LookupEntry(paragonFactionId));
+}
+
+int32 ReputationMgr::GetParagonLevel(FactionEntry const* paragonFactionEntry) const
+{
+ if (!paragonFactionEntry)
+ return 0;
+
+ if (ParagonReputationEntry const* paragonReputation = sDB2Manager.GetParagonReputation(paragonFactionEntry->ID))
+ return GetReputation(paragonFactionEntry) / paragonReputation->LevelThreshold;
+
+ return 0;
+}
+
void ReputationMgr::ApplyForceReaction(uint32 faction_id, ReputationRank rank, bool apply)
{
if (apply)
@@ -201,11 +236,19 @@ void ReputationMgr::ApplyForceReaction(uint32 faction_id, ReputationRank rank, b
ReputationFlags ReputationMgr::GetDefaultStateFlags(FactionEntry const* factionEntry) const
{
- int32 dataIndex = GetFactionDataIndexForRaceAndClass(factionEntry);
- if (dataIndex < 0)
- return ReputationFlags::None;
+ ReputationFlags flags = [&]()
+ {
+ int32 dataIndex = GetFactionDataIndexForRaceAndClass(factionEntry);
+ if (dataIndex < 0)
+ return ReputationFlags::None;
+
+ return static_cast<ReputationFlags>(factionEntry->ReputationFlags[dataIndex]);
+ }();
+
+ if (sDB2Manager.GetParagonReputation(factionEntry->ID))
+ flags |= ReputationFlags::ShowPropagated;
- return static_cast<ReputationFlags>(factionEntry->ReputationFlags[dataIndex]);
+ return flags;
}
void ReputationMgr::SendForceReactions()
@@ -374,12 +417,22 @@ bool ReputationMgr::SetReputation(FactionEntry const* factionEntry, int32 standi
FactionStateList::iterator faction = _factions.find(factionEntry->ReputationIndex);
if (faction != _factions.end())
{
- // if we update spillover only, do not update main reputation (rank exceeds creature reward rate)
- if (!spillOverOnly)
- res = SetOneFactionReputation(factionEntry, standing, incremental);
+ FactionEntry const* primaryFactionToModify = factionEntry;
+ if (incremental && standing > 0 && CanGainParagonReputationForFaction(factionEntry))
+ {
+ primaryFactionToModify = sFactionStore.AssertEntry(factionEntry->ParagonFactionID);
+ faction = _factions.find(primaryFactionToModify->ReputationIndex);
+ }
+
+ if (faction != _factions.end())
+ {
+ // if we update spillover only, do not update main reputation (rank exceeds creature reward rate)
+ if (!spillOverOnly)
+ res = SetOneFactionReputation(primaryFactionToModify, standing, incremental);
- // only this faction gets reported to client, even if it has no own visible standing
- SendState(&faction->second);
+ // only this faction gets reported to client, even if it has no own visible standing
+ SendState(&faction->second);
+ }
}
return res;
}
@@ -406,6 +459,7 @@ bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, in
ReputationRank old_rank = ReputationToRank(factionEntry, itr->second.Standing + BaseRep);
ReputationRank new_rank = ReputationToRank(factionEntry, standing);
+ int32 oldStanding = itr->second.Standing + BaseRep;
int32 newStanding = standing - BaseRep;
_player->ReputationChanged(factionEntry, newStanding - itr->second.Standing);
@@ -422,7 +476,17 @@ bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, in
if (new_rank > old_rank)
_sendFactionIncreased = true;
- if (!factionEntry->FriendshipRepID)
+ ParagonReputationEntry const* paragonReputation = sDB2Manager.GetParagonReputation(factionEntry->ID);
+ if (paragonReputation)
+ {
+ int32 oldParagonLevel = oldStanding / paragonReputation->LevelThreshold;
+ int32 newParagonLevel = standing / paragonReputation->LevelThreshold;
+ if (oldParagonLevel != newParagonLevel)
+ if (Quest const* paragonRewardQuest = sObjectMgr->GetQuestTemplate(paragonReputation->QuestID))
+ _player->AddQuestAndCheckCompletion(paragonRewardQuest, nullptr);
+ }
+
+ if (!factionEntry->FriendshipRepID && !paragonReputation)
UpdateRankCounters(old_rank, new_rank);
_player->UpdateCriteria(CRITERIA_TYPE_KNOWN_FACTIONS, factionEntry->ID);
@@ -468,6 +532,9 @@ void ReputationMgr::SetVisible(FactionState* faction)
if (faction->Flags.HasFlag(ReputationFlags::Header) && !faction->Flags.HasFlag(ReputationFlags::HeaderShowsBar))
return;
+ if (sDB2Manager.GetParagonReputation(faction->ID))
+ return;
+
// already set
if (faction->Flags.HasFlag(ReputationFlags::Visible))
return;
@@ -661,3 +728,22 @@ int32 ReputationMgr::GetFactionDataIndexForRaceAndClass(FactionEntry const* fact
return -1;
}
+
+bool ReputationMgr::CanGainParagonReputationForFaction(FactionEntry const* factionEntry) const
+{
+ if (!sFactionStore.LookupEntry(factionEntry->ParagonFactionID))
+ return false;
+
+ if (GetRank(factionEntry) != REP_EXALTED)
+ return false;
+
+ ParagonReputationEntry const* paragonReputation = sDB2Manager.GetParagonReputation(factionEntry->ParagonFactionID);
+ if (!paragonReputation)
+ return false;
+
+ Quest const* quest = sObjectMgr->GetQuestTemplate(paragonReputation->QuestID);
+ if (!quest)
+ return false;
+
+ return _player->getLevel() >= _player->GetQuestMinLevel(quest);
+}
diff --git a/src/server/game/Reputation/ReputationMgr.h b/src/server/game/Reputation/ReputationMgr.h
index 1ca2c9afbaa..3d3d411fe1e 100644
--- a/src/server/game/Reputation/ReputationMgr.h
+++ b/src/server/game/Reputation/ReputationMgr.h
@@ -121,6 +121,9 @@ class TC_GAME_API ReputationMgr
return forceItr != _forcedReactions.end() ? &forceItr->second : nullptr;
}
+ int32 GetParagonLevel(uint32 paragonFactionId) const;
+ int32 GetParagonLevel(FactionEntry const* paragonFactionEntry) const;
+
public: // modifiers
bool SetReputation(FactionEntry const* factionEntry, int32 standing)
{
@@ -156,6 +159,7 @@ class TC_GAME_API ReputationMgr
void SendVisible(FactionState const* faction, bool visible = true) const;
void UpdateRankCounters(ReputationRank old_rank, ReputationRank new_rank);
int32 GetFactionDataIndexForRaceAndClass(FactionEntry const* factionEntry) const;
+ bool CanGainParagonReputationForFaction(FactionEntry const* factionEntry) const;
private:
Player* _player;