Core/Reputation: Implemented paragon reputation

Port From (https://github.com/TrinityCore/TrinityCore/commit/b01fba4bd9530213ee0c9547e09d1f16b3ce5d67)
This commit is contained in:
hondacrx
2021-06-05 20:35:26 -04:00
parent 6ab6fc81a5
commit 21d8fbee40
8 changed files with 148 additions and 13 deletions
@@ -773,6 +773,9 @@ namespace Framework.Database
PrepareStatement(HotfixStatements.SEL_OVERRIDE_SPELL_DATA, "SELECT ID, Spells1, Spells2, Spells3, Spells4, Spells5, Spells6, Spells7, Spells8, Spells9, " +
"Spells10, PlayerActionBarFileDataID, Flags FROM override_spell_data");
// ParagonReputation.db2
PrepareStatement(HotfixStatements.SEL_PARAGON_REPUTATION, "SELECT ID, FactionID, LevelThreshold, QuestID FROM paragon_reputation");
// Phase.db2
PrepareStatement(HotfixStatements.SEL_PHASE, "SELECT ID, Flags FROM phase");
@@ -1586,6 +1589,8 @@ namespace Framework.Database
SEL_OVERRIDE_SPELL_DATA,
SEL_PARAGON_REPUTATION,
SEL_PHASE,
SEL_PHASE_X_PHASE_GROUP,
+1 -2
View File
@@ -1152,8 +1152,7 @@ namespace Game
}
case ConditionTypes.ReputationRank:
{
FactionRecord factionEntry = CliDB.FactionStorage.LookupByKey(cond.ConditionValue1);
if (factionEntry == null)
if (!CliDB.FactionStorage.ContainsKey(cond.ConditionValue1))
{
Log.outError(LogFilter.Sql, "{0} has non existing faction ({1}), skipped.", cond.ToString(true), cond.ConditionValue1);
return false;
+2
View File
@@ -227,6 +227,7 @@ namespace Game.DataStorage
NamesReservedLocaleStorage = ReadDB2<NamesReservedLocaleRecord>("NamesReservedLocale.db2", HotfixStatements.SEL_NAMES_RESERVED_LOCALE);
NumTalentsAtLevelStorage = ReadDB2<NumTalentsAtLevelRecord>("NumTalentsAtLevel.db2", HotfixStatements.SEL_NUM_TALENTS_AT_LEVEL);
OverrideSpellDataStorage = ReadDB2<OverrideSpellDataRecord>("OverrideSpellData.db2", HotfixStatements.SEL_OVERRIDE_SPELL_DATA);
ParagonReputationStorage = ReadDB2<ParagonReputationRecord>("ParagonReputation.db2", HotfixStatements.SEL_PARAGON_REPUTATION);
PhaseStorage = ReadDB2<PhaseRecord>("Phase.db2", HotfixStatements.SEL_PHASE);
PhaseXPhaseGroupStorage = ReadDB2<PhaseXPhaseGroupRecord>("PhaseXPhaseGroup.db2", HotfixStatements.SEL_PHASE_X_PHASE_GROUP);
PlayerConditionStorage = ReadDB2<PlayerConditionRecord>("PlayerCondition.db2", HotfixStatements.SEL_PLAYER_CONDITION, HotfixStatements.SEL_PLAYER_CONDITION_LOCALE);
@@ -594,6 +595,7 @@ namespace Game.DataStorage
public static DB6Storage<NamesReservedLocaleRecord> NamesReservedLocaleStorage;
public static DB6Storage<NumTalentsAtLevelRecord> NumTalentsAtLevelStorage;
public static DB6Storage<OverrideSpellDataRecord> OverrideSpellDataStorage;
public static DB6Storage<ParagonReputationRecord> ParagonReputationStorage;
public static DB6Storage<PhaseRecord> PhaseStorage;
public static DB6Storage<PhaseXPhaseGroupRecord> PhaseXPhaseGroupStorage;
public static DB6Storage<PlayerConditionRecord> PlayerConditionStorage;
+10
View File
@@ -414,6 +414,10 @@ namespace Game.DataStorage
}
}
foreach (ParagonReputationRecord paragonReputation in CliDB.ParagonReputationStorage.Values)
if (CliDB.FactionStorage.HasRecord(paragonReputation.FactionID))
_paragonReputations[paragonReputation.FactionID] = paragonReputation;
foreach (var group in CliDB.PhaseXPhaseGroupStorage.Values)
{
PhaseRecord phase = CliDB.PhaseStorage.LookupByKey(group.PhaseId);
@@ -1722,6 +1726,11 @@ namespace Game.DataStorage
return 0;
}
public ParagonReputationRecord GetParagonReputation(uint factionId)
{
return _paragonReputations.LookupByKey(factionId);
}
public PvpDifficultyRecord GetBattlegroundBracketByLevel(uint mapid, uint level)
{
PvpDifficultyRecord maxEntry = null; // used for level > max listed level case
@@ -2275,6 +2284,7 @@ namespace Game.DataStorage
MultiMap<uint, MountXDisplayRecord> _mountDisplays = new();
Dictionary<uint, List<NameGenRecord>[]> _nameGenData = new();
List<string>[] _nameValidators = new List<string>[(int)Locale.Total + 1];
Dictionary<uint, ParagonReputationRecord> _paragonReputations = new();
MultiMap<uint, uint> _phasesByGroup = new();
Dictionary<PowerType, PowerTypeRecord> _powerTypes = new();
Dictionary<uint, byte> _pvpItemBonus = new();
@@ -19,6 +19,14 @@ using Framework.Constants;
namespace Game.DataStorage
{
public sealed class ParagonReputationRecord
{
public uint Id;
public uint FactionID;
public int LevelThreshold;
public int QuestID;
}
public sealed class PhaseRecord
{
public uint Id;
+8
View File
@@ -7442,6 +7442,14 @@ namespace Game
}
}
// Make all paragon reward quests repeatable
foreach (ParagonReputationRecord paragonReputation in CliDB.ParagonReputationStorage.Values)
{
Quest quest = GetQuestTemplate((uint)paragonReputation.QuestID);
if (quest != null)
quest.SetSpecialFlag(QuestSpecialFlags.Repeatable);
}
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} quests definitions in {1} ms", _questTemplates.Count, Time.GetMSTimeDiffToNow(oldMSTime));
}
public void LoadQuestStartersAndEnders()
+99 -11
View File
@@ -121,12 +121,32 @@ namespace Game
int GetMaxReputation(FactionRecord factionEntry)
{
ParagonReputationRecord paragonReputation = Global.DB2Mgr.GetParagonReputation(factionEntry.Id);
if (paragonReputation != null)
{
// 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
int reputation = GetReputation(factionEntry);
int cap = reputation + paragonReputation.LevelThreshold - reputation % paragonReputation.LevelThreshold - 1;
if (_player.GetQuestStatus((uint)paragonReputation.QuestID) == QuestStatus.None)
cap += paragonReputation.LevelThreshold;
return cap;
}
var friendshipReactions = Global.DB2Mgr.GetFriendshipRepReactions(factionEntry.FriendshipRepID);
if (!friendshipReactions.Empty())
return friendshipReactions.LastOrDefault().ReactionThreshold;
int dataIndex = GetFactionDataIndexForRaceAndClass(factionEntry);
if (dataIndex >= 0 && factionEntry.ReputationMax[dataIndex] != 0)
if (dataIndex >= 0)
return factionEntry.ReputationMax[dataIndex];
return ReputationRankThresholds.LastOrDefault();
@@ -162,6 +182,23 @@ namespace Game
return GetForcedRankIfAny(factionTemplateEntry.Faction);
}
int GetParagonLevel(uint paragonFactionId)
{
return GetParagonLevel(CliDB.FactionStorage.LookupByKey(paragonFactionId));
}
int GetParagonLevel(FactionRecord paragonFactionEntry)
{
if (paragonFactionEntry == null)
return 0;
ParagonReputationRecord paragonReputation = Global.DB2Mgr.GetParagonReputation(paragonFactionEntry.Id);
if (paragonReputation != null)
return GetReputation(paragonFactionEntry) / paragonReputation.LevelThreshold;
return 0;
}
public void ApplyForceReaction(uint faction_id, ReputationRank rank, bool apply)
{
if (apply)
@@ -172,11 +209,16 @@ namespace Game
ReputationFlags GetDefaultStateFlags(FactionRecord factionEntry)
{
int dataIndex = GetFactionDataIndexForRaceAndClass(factionEntry);
if (dataIndex < 0)
return ReputationFlags.None;
ReputationFlags flags = ReputationFlags.None;
return (ReputationFlags)factionEntry.ReputationFlags[dataIndex];
int dataIndex = GetFactionDataIndexForRaceAndClass(factionEntry);
if (dataIndex > 0)
flags = (ReputationFlags)factionEntry.ReputationFlags[dataIndex];
if (Global.DB2Mgr.GetParagonReputation(factionEntry.Id) != null)
flags |= ReputationFlags.ShowPropagated;
return flags;
}
public void SendForceReactions()
@@ -356,12 +398,22 @@ namespace Game
var faction = _factions.LookupByKey(factionEntry.ReputationIndex);
if (faction != null)
{
// if we update spillover only, do not update main reputation (rank exceeds creature reward rate)
if (!spillOverOnly)
res = SetOneFactionReputation(factionEntry, standing, incremental);
FactionRecord primaryFactionToModify = factionEntry;
if (incremental && standing > 0 && CanGainParagonReputationForFaction(factionEntry))
{
primaryFactionToModify = CliDB.FactionStorage.LookupByKey(factionEntry.ParagonFactionID);
faction = _factions.LookupByKey(primaryFactionToModify.ReputationIndex);
}
// only this faction gets reported to client, even if it has no own visible standing
SendState(faction);
if (faction != null)
{
// 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);
}
}
return res;
}
@@ -388,6 +440,7 @@ namespace Game
ReputationRank old_rank = ReputationToRank(factionEntry, factionState.Standing + BaseRep);
ReputationRank new_rank = ReputationToRank(factionEntry, standing);
int oldStanding = factionState.Standing + BaseRep;
int newStanding = standing - BaseRep;
_player.ReputationChanged(factionEntry, newStanding - factionState.Standing);
@@ -404,7 +457,20 @@ namespace Game
if (new_rank > old_rank)
_sendFactionIncreased = true;
if (factionEntry.FriendshipRepID == 0)
ParagonReputationRecord paragonReputation = Global.DB2Mgr.GetParagonReputation(factionEntry.Id);
if (paragonReputation != null)
{
int oldParagonLevel = oldStanding / paragonReputation.LevelThreshold;
int newParagonLevel = standing / paragonReputation.LevelThreshold;
if (oldParagonLevel != newParagonLevel)
{
Quest paragonRewardQuest = Global.ObjectMgr.GetQuestTemplate((uint)paragonReputation.QuestID);
if (paragonRewardQuest != null)
_player.AddQuestAndCheckCompletion(paragonRewardQuest, null);
}
}
if (factionEntry.FriendshipRepID == 0 && paragonReputation == null)
UpdateRankCounters(old_rank, new_rank);
_player.UpdateCriteria(CriteriaTypes.KnownFactions, factionEntry.Id);
@@ -451,6 +517,9 @@ namespace Game
if (faction.Flags.HasFlag(ReputationFlags.Header) && !faction.Flags.HasFlag(ReputationFlags.HeaderShowsBar))
return;
if (Global.DB2Mgr.GetParagonReputation(faction.Id) != null)
return;
// already set
if (faction.Flags.HasFlag(ReputationFlags.Visible))
return;
@@ -640,6 +709,25 @@ namespace Game
return -1;
}
bool CanGainParagonReputationForFaction(FactionRecord factionEntry)
{
if (!CliDB.FactionStorage.ContainsKey(factionEntry.ParagonFactionID))
return false;
if (GetRank(factionEntry) != ReputationRank.Exalted)
return false;
ParagonReputationRecord paragonReputation = Global.DB2Mgr.GetParagonReputation(factionEntry.ParagonFactionID);
if (paragonReputation == null)
return false;
Quest quest = Global.ObjectMgr.GetQuestTemplate((uint)paragonReputation.QuestID);
if (quest == null)
return false;
return _player.GetLevel() >= _player.GetQuestMinLevel(quest);
}
public byte GetVisibleFactionCount() { return _visibleFactionCount; }
@@ -0,0 +1,15 @@
--
-- Table structure for table `paragon_reputation`
--
DROP TABLE IF EXISTS `paragon_reputation`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `paragon_reputation` (
`ID` int(10) unsigned NOT NULL DEFAULT '0',
`FactionID` int(10) unsigned NOT NULL DEFAULT '0',
`LevelThreshold` int(11) NOT NULL DEFAULT '0',
`QuestID` int(11) NOT NULL DEFAULT '0',
`VerifiedBuild` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`,`VerifiedBuild`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;