Core/Reputation: Implemented paragon reputation
Port From (https://github.com/TrinityCore/TrinityCore/commit/b01fba4bd9530213ee0c9547e09d1f16b3ce5d67)
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
@@ -354,15 +396,25 @@ namespace Game
|
||||
|
||||
// spillover done, update faction itself
|
||||
var faction = _factions.LookupByKey(factionEntry.ReputationIndex);
|
||||
if (faction != null)
|
||||
{
|
||||
FactionRecord primaryFactionToModify = factionEntry;
|
||||
if (incremental && standing > 0 && CanGainParagonReputationForFaction(factionEntry))
|
||||
{
|
||||
primaryFactionToModify = CliDB.FactionStorage.LookupByKey(factionEntry.ParagonFactionID);
|
||||
faction = _factions.LookupByKey(primaryFactionToModify.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);
|
||||
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;
|
||||
@@ -641,6 +710,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; }
|
||||
|
||||
public byte GetHonoredFactionCount() { return _honoredFactionCount; }
|
||||
|
||||
@@ -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 */;
|
||||
Reference in New Issue
Block a user