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, " +
|
PrepareStatement(HotfixStatements.SEL_OVERRIDE_SPELL_DATA, "SELECT ID, Spells1, Spells2, Spells3, Spells4, Spells5, Spells6, Spells7, Spells8, Spells9, " +
|
||||||
"Spells10, PlayerActionBarFileDataID, Flags FROM override_spell_data");
|
"Spells10, PlayerActionBarFileDataID, Flags FROM override_spell_data");
|
||||||
|
|
||||||
|
// ParagonReputation.db2
|
||||||
|
PrepareStatement(HotfixStatements.SEL_PARAGON_REPUTATION, "SELECT ID, FactionID, LevelThreshold, QuestID FROM paragon_reputation");
|
||||||
|
|
||||||
// Phase.db2
|
// Phase.db2
|
||||||
PrepareStatement(HotfixStatements.SEL_PHASE, "SELECT ID, Flags FROM phase");
|
PrepareStatement(HotfixStatements.SEL_PHASE, "SELECT ID, Flags FROM phase");
|
||||||
|
|
||||||
@@ -1586,6 +1589,8 @@ namespace Framework.Database
|
|||||||
|
|
||||||
SEL_OVERRIDE_SPELL_DATA,
|
SEL_OVERRIDE_SPELL_DATA,
|
||||||
|
|
||||||
|
SEL_PARAGON_REPUTATION,
|
||||||
|
|
||||||
SEL_PHASE,
|
SEL_PHASE,
|
||||||
|
|
||||||
SEL_PHASE_X_PHASE_GROUP,
|
SEL_PHASE_X_PHASE_GROUP,
|
||||||
|
|||||||
@@ -1152,8 +1152,7 @@ namespace Game
|
|||||||
}
|
}
|
||||||
case ConditionTypes.ReputationRank:
|
case ConditionTypes.ReputationRank:
|
||||||
{
|
{
|
||||||
FactionRecord factionEntry = CliDB.FactionStorage.LookupByKey(cond.ConditionValue1);
|
if (!CliDB.FactionStorage.ContainsKey(cond.ConditionValue1))
|
||||||
if (factionEntry == null)
|
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.Sql, "{0} has non existing faction ({1}), skipped.", cond.ToString(true), cond.ConditionValue1);
|
Log.outError(LogFilter.Sql, "{0} has non existing faction ({1}), skipped.", cond.ToString(true), cond.ConditionValue1);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -227,6 +227,7 @@ namespace Game.DataStorage
|
|||||||
NamesReservedLocaleStorage = ReadDB2<NamesReservedLocaleRecord>("NamesReservedLocale.db2", HotfixStatements.SEL_NAMES_RESERVED_LOCALE);
|
NamesReservedLocaleStorage = ReadDB2<NamesReservedLocaleRecord>("NamesReservedLocale.db2", HotfixStatements.SEL_NAMES_RESERVED_LOCALE);
|
||||||
NumTalentsAtLevelStorage = ReadDB2<NumTalentsAtLevelRecord>("NumTalentsAtLevel.db2", HotfixStatements.SEL_NUM_TALENTS_AT_LEVEL);
|
NumTalentsAtLevelStorage = ReadDB2<NumTalentsAtLevelRecord>("NumTalentsAtLevel.db2", HotfixStatements.SEL_NUM_TALENTS_AT_LEVEL);
|
||||||
OverrideSpellDataStorage = ReadDB2<OverrideSpellDataRecord>("OverrideSpellData.db2", HotfixStatements.SEL_OVERRIDE_SPELL_DATA);
|
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);
|
PhaseStorage = ReadDB2<PhaseRecord>("Phase.db2", HotfixStatements.SEL_PHASE);
|
||||||
PhaseXPhaseGroupStorage = ReadDB2<PhaseXPhaseGroupRecord>("PhaseXPhaseGroup.db2", HotfixStatements.SEL_PHASE_X_PHASE_GROUP);
|
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);
|
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<NamesReservedLocaleRecord> NamesReservedLocaleStorage;
|
||||||
public static DB6Storage<NumTalentsAtLevelRecord> NumTalentsAtLevelStorage;
|
public static DB6Storage<NumTalentsAtLevelRecord> NumTalentsAtLevelStorage;
|
||||||
public static DB6Storage<OverrideSpellDataRecord> OverrideSpellDataStorage;
|
public static DB6Storage<OverrideSpellDataRecord> OverrideSpellDataStorage;
|
||||||
|
public static DB6Storage<ParagonReputationRecord> ParagonReputationStorage;
|
||||||
public static DB6Storage<PhaseRecord> PhaseStorage;
|
public static DB6Storage<PhaseRecord> PhaseStorage;
|
||||||
public static DB6Storage<PhaseXPhaseGroupRecord> PhaseXPhaseGroupStorage;
|
public static DB6Storage<PhaseXPhaseGroupRecord> PhaseXPhaseGroupStorage;
|
||||||
public static DB6Storage<PlayerConditionRecord> PlayerConditionStorage;
|
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)
|
foreach (var group in CliDB.PhaseXPhaseGroupStorage.Values)
|
||||||
{
|
{
|
||||||
PhaseRecord phase = CliDB.PhaseStorage.LookupByKey(group.PhaseId);
|
PhaseRecord phase = CliDB.PhaseStorage.LookupByKey(group.PhaseId);
|
||||||
@@ -1722,6 +1726,11 @@ namespace Game.DataStorage
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ParagonReputationRecord GetParagonReputation(uint factionId)
|
||||||
|
{
|
||||||
|
return _paragonReputations.LookupByKey(factionId);
|
||||||
|
}
|
||||||
|
|
||||||
public PvpDifficultyRecord GetBattlegroundBracketByLevel(uint mapid, uint level)
|
public PvpDifficultyRecord GetBattlegroundBracketByLevel(uint mapid, uint level)
|
||||||
{
|
{
|
||||||
PvpDifficultyRecord maxEntry = null; // used for level > max listed level case
|
PvpDifficultyRecord maxEntry = null; // used for level > max listed level case
|
||||||
@@ -2275,6 +2284,7 @@ namespace Game.DataStorage
|
|||||||
MultiMap<uint, MountXDisplayRecord> _mountDisplays = new();
|
MultiMap<uint, MountXDisplayRecord> _mountDisplays = new();
|
||||||
Dictionary<uint, List<NameGenRecord>[]> _nameGenData = new();
|
Dictionary<uint, List<NameGenRecord>[]> _nameGenData = new();
|
||||||
List<string>[] _nameValidators = new List<string>[(int)Locale.Total + 1];
|
List<string>[] _nameValidators = new List<string>[(int)Locale.Total + 1];
|
||||||
|
Dictionary<uint, ParagonReputationRecord> _paragonReputations = new();
|
||||||
MultiMap<uint, uint> _phasesByGroup = new();
|
MultiMap<uint, uint> _phasesByGroup = new();
|
||||||
Dictionary<PowerType, PowerTypeRecord> _powerTypes = new();
|
Dictionary<PowerType, PowerTypeRecord> _powerTypes = new();
|
||||||
Dictionary<uint, byte> _pvpItemBonus = new();
|
Dictionary<uint, byte> _pvpItemBonus = new();
|
||||||
|
|||||||
@@ -19,6 +19,14 @@ using Framework.Constants;
|
|||||||
|
|
||||||
namespace Game.DataStorage
|
namespace Game.DataStorage
|
||||||
{
|
{
|
||||||
|
public sealed class ParagonReputationRecord
|
||||||
|
{
|
||||||
|
public uint Id;
|
||||||
|
public uint FactionID;
|
||||||
|
public int LevelThreshold;
|
||||||
|
public int QuestID;
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class PhaseRecord
|
public sealed class PhaseRecord
|
||||||
{
|
{
|
||||||
public uint Id;
|
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));
|
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} quests definitions in {1} ms", _questTemplates.Count, Time.GetMSTimeDiffToNow(oldMSTime));
|
||||||
}
|
}
|
||||||
public void LoadQuestStartersAndEnders()
|
public void LoadQuestStartersAndEnders()
|
||||||
|
|||||||
@@ -121,12 +121,32 @@ namespace Game
|
|||||||
|
|
||||||
int GetMaxReputation(FactionRecord factionEntry)
|
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);
|
var friendshipReactions = Global.DB2Mgr.GetFriendshipRepReactions(factionEntry.FriendshipRepID);
|
||||||
if (!friendshipReactions.Empty())
|
if (!friendshipReactions.Empty())
|
||||||
return friendshipReactions.LastOrDefault().ReactionThreshold;
|
return friendshipReactions.LastOrDefault().ReactionThreshold;
|
||||||
|
|
||||||
int dataIndex = GetFactionDataIndexForRaceAndClass(factionEntry);
|
int dataIndex = GetFactionDataIndexForRaceAndClass(factionEntry);
|
||||||
if (dataIndex >= 0 && factionEntry.ReputationMax[dataIndex] != 0)
|
if (dataIndex >= 0)
|
||||||
return factionEntry.ReputationMax[dataIndex];
|
return factionEntry.ReputationMax[dataIndex];
|
||||||
|
|
||||||
return ReputationRankThresholds.LastOrDefault();
|
return ReputationRankThresholds.LastOrDefault();
|
||||||
@@ -162,6 +182,23 @@ namespace Game
|
|||||||
return GetForcedRankIfAny(factionTemplateEntry.Faction);
|
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)
|
public void ApplyForceReaction(uint faction_id, ReputationRank rank, bool apply)
|
||||||
{
|
{
|
||||||
if (apply)
|
if (apply)
|
||||||
@@ -172,11 +209,16 @@ namespace Game
|
|||||||
|
|
||||||
ReputationFlags GetDefaultStateFlags(FactionRecord factionEntry)
|
ReputationFlags GetDefaultStateFlags(FactionRecord factionEntry)
|
||||||
{
|
{
|
||||||
int dataIndex = GetFactionDataIndexForRaceAndClass(factionEntry);
|
ReputationFlags flags = ReputationFlags.None;
|
||||||
if (dataIndex < 0)
|
|
||||||
return 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()
|
public void SendForceReactions()
|
||||||
@@ -356,12 +398,22 @@ namespace Game
|
|||||||
var faction = _factions.LookupByKey(factionEntry.ReputationIndex);
|
var faction = _factions.LookupByKey(factionEntry.ReputationIndex);
|
||||||
if (faction != null)
|
if (faction != null)
|
||||||
{
|
{
|
||||||
// if we update spillover only, do not update main reputation (rank exceeds creature reward rate)
|
FactionRecord primaryFactionToModify = factionEntry;
|
||||||
if (!spillOverOnly)
|
if (incremental && standing > 0 && CanGainParagonReputationForFaction(factionEntry))
|
||||||
res = SetOneFactionReputation(factionEntry, standing, incremental);
|
{
|
||||||
|
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
|
if (faction != null)
|
||||||
SendState(faction);
|
{
|
||||||
|
// 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;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -388,6 +440,7 @@ namespace Game
|
|||||||
ReputationRank old_rank = ReputationToRank(factionEntry, factionState.Standing + BaseRep);
|
ReputationRank old_rank = ReputationToRank(factionEntry, factionState.Standing + BaseRep);
|
||||||
ReputationRank new_rank = ReputationToRank(factionEntry, standing);
|
ReputationRank new_rank = ReputationToRank(factionEntry, standing);
|
||||||
|
|
||||||
|
int oldStanding = factionState.Standing + BaseRep;
|
||||||
int newStanding = standing - BaseRep;
|
int newStanding = standing - BaseRep;
|
||||||
|
|
||||||
_player.ReputationChanged(factionEntry, newStanding - factionState.Standing);
|
_player.ReputationChanged(factionEntry, newStanding - factionState.Standing);
|
||||||
@@ -404,7 +457,20 @@ namespace Game
|
|||||||
if (new_rank > old_rank)
|
if (new_rank > old_rank)
|
||||||
_sendFactionIncreased = true;
|
_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);
|
UpdateRankCounters(old_rank, new_rank);
|
||||||
|
|
||||||
_player.UpdateCriteria(CriteriaTypes.KnownFactions, factionEntry.Id);
|
_player.UpdateCriteria(CriteriaTypes.KnownFactions, factionEntry.Id);
|
||||||
@@ -451,6 +517,9 @@ namespace Game
|
|||||||
if (faction.Flags.HasFlag(ReputationFlags.Header) && !faction.Flags.HasFlag(ReputationFlags.HeaderShowsBar))
|
if (faction.Flags.HasFlag(ReputationFlags.Header) && !faction.Flags.HasFlag(ReputationFlags.HeaderShowsBar))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (Global.DB2Mgr.GetParagonReputation(faction.Id) != null)
|
||||||
|
return;
|
||||||
|
|
||||||
// already set
|
// already set
|
||||||
if (faction.Flags.HasFlag(ReputationFlags.Visible))
|
if (faction.Flags.HasFlag(ReputationFlags.Visible))
|
||||||
return;
|
return;
|
||||||
@@ -640,6 +709,25 @@ namespace Game
|
|||||||
|
|
||||||
return -1;
|
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 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 */;
|
||||||
Reference in New Issue
Block a user