From 873a1df5967c51c205838108cb37c485b1420fce Mon Sep 17 00:00:00 2001 From: hondacrx Date: Tue, 24 Jan 2023 23:35:51 -0500 Subject: [PATCH] Core/Reputation: Implemented renown reputation (Dragonflight) Port From (https://github.com/TrinityCore/TrinityCore/commit/d64d84dfa68da4ff83f0b88ad4e88dccc5ace623) --- Source/Game/Chat/Commands/ModifyCommands.cs | 2 +- Source/Game/Entities/Player/Player.Items.cs | 8 +- Source/Game/Entities/Player/Player.PvP.cs | 2 +- Source/Game/Entities/Player/Player.Quest.cs | 6 +- Source/Game/Entities/Player/Player.Talents.cs | 2 +- Source/Game/Entities/Player/Player.cs | 17 +- Source/Game/Garrisons/Garrisons.cs | 4 +- Source/Game/Handlers/QuestHandler.cs | 2 +- Source/Game/Reputation/ReputationManager.cs | 163 +++++++++++++++--- Source/Game/Spells/Spell.cs | 2 +- Source/Game/Spells/SpellEffects.cs | 2 +- 11 files changed, 166 insertions(+), 44 deletions(-) diff --git a/Source/Game/Chat/Commands/ModifyCommands.cs b/Source/Game/Chat/Commands/ModifyCommands.cs index e23858dfc..bacde1897 100644 --- a/Source/Game/Chat/Commands/ModifyCommands.cs +++ b/Source/Game/Chat/Commands/ModifyCommands.cs @@ -651,7 +651,7 @@ namespace Game.Chat if (amount == 0) return false; - target.ModifyCurrency((CurrencyTypes)currencyId, (int)amount, true, true); + target.ModifyCurrency(currencyId, (int)amount, true, true); return true; } diff --git a/Source/Game/Entities/Player/Player.Items.cs b/Source/Game/Entities/Player/Player.Items.cs index 42487942d..009474f3f 100644 --- a/Source/Game/Entities/Player/Player.Items.cs +++ b/Source/Game/Entities/Player/Player.Items.cs @@ -122,7 +122,7 @@ namespace Game.Entities uint count = iece.CurrencyCount[i]; uint currencyid = iece.CurrencyID[i]; if (count != 0 && currencyid != 0) - ModifyCurrency((CurrencyTypes)currencyid, (int)count, true, true); + ModifyCurrency(currencyid, (int)count, true, true); } // Grant back money @@ -2452,7 +2452,7 @@ namespace Game.Entities continue; if (iece.CurrencyID[i] != 0) - ModifyCurrency((CurrencyTypes)iece.CurrencyID[i], -(int)(iece.CurrencyCount[i] * stacks), true, true); + ModifyCurrency(iece.CurrencyID[i], -(int)(iece.CurrencyCount[i] * stacks), true, true); } } @@ -3178,7 +3178,7 @@ namespace Game.Entities return false; } - ModifyCurrency((CurrencyTypes)currency, (int)count, true, true); + ModifyCurrency(currency, (int)count, true, true); if (iece != null) { for (byte i = 0; i < ItemConst.MaxItemExtCostItems; ++i) @@ -3197,7 +3197,7 @@ namespace Game.Entities if (iece.Flags.HasAnyFlag((byte)((uint)ItemExtendedCostFlags.RequireSeasonEarned1 << i))) continue; - ModifyCurrency((CurrencyTypes)iece.CurrencyID[i], -(int)(iece.CurrencyCount[i] * stacks), false, true); + ModifyCurrency(iece.CurrencyID[i], -(int)(iece.CurrencyCount[i] * stacks), false, true); } } diff --git a/Source/Game/Entities/Player/Player.PvP.cs b/Source/Game/Entities/Player/Player.PvP.cs index d0f31e3d2..179dd3b77 100644 --- a/Source/Game/Entities/Player/Player.PvP.cs +++ b/Source/Game/Entities/Player/Player.PvP.cs @@ -235,7 +235,7 @@ namespace Game.Entities var rewardCurrencyTypes = Global.DB2Mgr.GetRewardPackCurrencyTypesByRewardID(rewardPackEntry.Id); foreach (RewardPackXCurrencyTypeRecord currency in rewardCurrencyTypes) - ModifyCurrency((CurrencyTypes)currency.CurrencyTypeID, currency.Quantity); + ModifyCurrency(currency.CurrencyTypeID, currency.Quantity); var rewardPackXItems = Global.DB2Mgr.GetRewardPackItemsByRewardID(rewardPackEntry.Id); foreach (RewardPackXItemRecord rewardPackXItem in rewardPackXItems) diff --git a/Source/Game/Entities/Player/Player.Quest.cs b/Source/Game/Entities/Player/Player.Quest.cs index 8046f8e24..52475282d 100644 --- a/Source/Game/Entities/Player/Player.Quest.cs +++ b/Source/Game/Entities/Player/Player.Quest.cs @@ -968,7 +968,7 @@ namespace Game.Entities DestroyItemCount((uint)obj.ObjectID, (uint)obj.Amount, true); break; case QuestObjectiveType.Currency: - ModifyCurrency((CurrencyTypes)obj.ObjectID, -obj.Amount, false, true); + ModifyCurrency((uint)obj.ObjectID, -obj.Amount, false, true); break; } } @@ -1036,7 +1036,7 @@ namespace Game.Entities { for (uint i = 0; i < SharedConst.QuestRewardChoicesCount; ++i) if (quest.RewardChoiceItemId[i] != 0 && quest.RewardChoiceItemType[i] == LootItemType.Currency && quest.RewardChoiceItemId[i] == rewardId) - ModifyCurrency((CurrencyTypes)quest.RewardChoiceItemId[i], (int)quest.RewardChoiceItemCount[i]); + ModifyCurrency(quest.RewardChoiceItemId[i], (int)quest.RewardChoiceItemCount[i]); } break; } @@ -1044,7 +1044,7 @@ namespace Game.Entities for (byte i = 0; i < SharedConst.QuestRewardCurrencyCount; ++i) { if (quest.RewardCurrencyId[i] != 0) - ModifyCurrency((CurrencyTypes)quest.RewardCurrencyId[i], (int)quest.RewardCurrencyCount[i]); + ModifyCurrency(quest.RewardCurrencyId[i], (int)quest.RewardCurrencyCount[i]); } uint skill = quest.RewardSkillId; diff --git a/Source/Game/Entities/Player/Player.Talents.cs b/Source/Game/Entities/Player/Player.Talents.cs index de7d77936..97bd9ec08 100644 --- a/Source/Game/Entities/Player/Player.Talents.cs +++ b/Source/Game/Entities/Player/Player.Talents.cs @@ -1043,7 +1043,7 @@ namespace Game.Entities ModifyMoney(-amount); break; case TraitCurrencyType.CurrencyTypesBased: - ModifyCurrency((CurrencyTypes)traitCurrency.CurrencyTypesID, -amount); + ModifyCurrency((uint)traitCurrency.CurrencyTypesID, -amount); break; default: break; diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index e0df7cce7..000bb1f98 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -1098,6 +1098,7 @@ namespace Game.Entities _currencyStorage[(uint)id] = cur; } } + public uint GetCurrency(uint id) { var playerCurrency = _currencyStorage.LookupByKey(id); @@ -1106,7 +1107,8 @@ namespace Game.Entities return playerCurrency.Quantity; } - public void ModifyCurrency(CurrencyTypes id, int count, bool printLog = true, bool ignoreMultipliers = false) + + public void ModifyCurrency(uint id, int count, bool printLog = true, bool ignoreMultipliers = false) { if (count == 0) return; @@ -1127,7 +1129,7 @@ namespace Game.Entities return; } - if (id == CurrencyTypes.Azerite) + if (id == (uint)CurrencyTypes.Azerite) { if (count > 0) { @@ -1151,7 +1153,7 @@ namespace Game.Entities cur.WeeklyQuantity = 0; cur.TrackedQuantity = 0; cur.Flags = 0; - _currencyStorage[(uint)id] = cur; + _currencyStorage[id] = cur; playerCurrency = _currencyStorage.LookupByKey(id); } else @@ -1203,19 +1205,19 @@ namespace Game.Entities if (playerCurrency.state != PlayerCurrencyState.New) playerCurrency.state = PlayerCurrencyState.Changed; - CurrencyChanged((uint)id, count); + CurrencyChanged(id, count); playerCurrency.Quantity = (uint)newTotalCount; playerCurrency.WeeklyQuantity = (uint)newWeekCount; playerCurrency.TrackedQuantity = (uint)newTrackedCount; if (count > 0) - UpdateCriteria(CriteriaType.CurrencyGained, (uint)id, (uint)count); + UpdateCriteria(CriteriaType.CurrencyGained, id, (uint)count); - _currencyStorage[(uint)id] = playerCurrency; + _currencyStorage[id] = playerCurrency; SetCurrency packet = new(); - packet.Type = (uint)id; + packet.Type = id; packet.Quantity = newTotalCount; packet.SuppressChatLog = !printLog; packet.WeeklyQuantity = newWeekCount; @@ -1226,6 +1228,7 @@ namespace Game.Entities SendPacket(packet); } } + public bool HasCurrency(uint id, uint count) { var playerCurrency = _currencyStorage.LookupByKey(id); diff --git a/Source/Game/Garrisons/Garrisons.cs b/Source/Game/Garrisons/Garrisons.cs index 89d78f5e3..accde25b0 100644 --- a/Source/Game/Garrisons/Garrisons.cs +++ b/Source/Game/Garrisons/Garrisons.cs @@ -369,7 +369,7 @@ namespace Game.Garrisons map.AddToMap(go); } - _owner.ModifyCurrency((CurrencyTypes)building.CurrencyTypeID, -building.CurrencyQty, false, true); + _owner.ModifyCurrency(building.CurrencyTypeID, -building.CurrencyQty, false, true); _owner.ModifyMoney(-building.GoldCost * MoneyConstants.Gold, false); if (oldBuildingId != 0) @@ -409,7 +409,7 @@ namespace Game.Garrisons GarrBuildingRecord constructing = CliDB.GarrBuildingStorage.LookupByKey(buildingRemoved.GarrBuildingID); // Refund construction/upgrade cost - _owner.ModifyCurrency((CurrencyTypes)constructing.CurrencyTypeID, constructing.CurrencyQty, false, true); + _owner.ModifyCurrency(constructing.CurrencyTypeID, constructing.CurrencyQty, false, true); _owner.ModifyMoney(constructing.GoldCost * MoneyConstants.Gold, false); if (constructing.UpgradeLevel > 1) diff --git a/Source/Game/Handlers/QuestHandler.cs b/Source/Game/Handlers/QuestHandler.cs index 16a584795..aed69b4ec 100644 --- a/Source/Game/Handlers/QuestHandler.cs +++ b/Source/Game/Handlers/QuestHandler.cs @@ -820,7 +820,7 @@ namespace Game } foreach (PlayerChoiceResponseRewardEntry currency in reward.Currency) - _player.ModifyCurrency((CurrencyTypes)currency.Id, currency.Quantity); + _player.ModifyCurrency(currency.Id, currency.Quantity); foreach (PlayerChoiceResponseRewardEntry faction in reward.Faction) _player.GetReputationMgr().ModifyReputation(CliDB.FactionStorage.LookupByKey(faction.Id), faction.Quantity); diff --git a/Source/Game/Reputation/ReputationManager.cs b/Source/Game/Reputation/ReputationManager.cs index 73a221970..15c5257c5 100644 --- a/Source/Game/Reputation/ReputationManager.cs +++ b/Source/Game/Reputation/ReputationManager.cs @@ -111,11 +111,11 @@ namespace Game 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 + // for example: if current reputation is 12345 and quests 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 + // if current reputation is 12345 and quests are given every 10000 and player does NOT have unclaimed reward // then cap will be 29999 int reputation = GetReputation(factionEntry); @@ -127,6 +127,14 @@ namespace Game return cap; } + if (IsRenownReputation(factionEntry)) + { + // Compared to a paragon reputation, DF renown reputations + // have a maximum value of 2500 which resets with each level of renown acquired. + // We calculate the total reputation necessary to raise the renown to the maximum + return GetRenownMaxLevel(factionEntry) * GetRenownLevelThreshold(factionEntry); + } + var friendshipReactions = Global.DB2Mgr.GetFriendshipRepReactions(factionEntry.FriendshipRepID); if (!friendshipReactions.Empty()) return friendshipReactions.LastOrDefault().ReactionThreshold; @@ -168,6 +176,14 @@ namespace Game return GetForcedRankIfAny(factionTemplateEntry.Faction); } + bool IsParagonReputation(FactionRecord factionEntry) + { + if (Global.DB2Mgr.GetParagonReputation(factionEntry.Id) != null) + return true; + + return false; + } + public int GetParagonLevel(uint paragonFactionId) { return GetParagonLevel(CliDB.FactionStorage.LookupByKey(paragonFactionId)); @@ -184,6 +200,55 @@ namespace Game return 0; } + + bool HasMaximumRenownReputation(FactionRecord factionEntry) + { + if (!IsRenownReputation(factionEntry)) + return false; + + return GetRenownLevel(factionEntry) >= GetRenownMaxLevel(factionEntry); + } + + bool IsRenownReputation(FactionRecord factionEntry) + { + return factionEntry.RenownCurrencyID > 0; + } + + int GetRenownLevel(FactionRecord renownFactionEntry) + { + if (renownFactionEntry == null) + return 0; + + CurrencyTypesRecord currency = CliDB.CurrencyTypesStorage.LookupByKey(renownFactionEntry.RenownCurrencyID); + if (currency != null) + return (int)_player.GetCurrency(currency.Id); + + return 0; + } + + int GetRenownLevelThreshold(FactionRecord renownFactionEntry) + { + if (renownFactionEntry == null || !IsRenownReputation(renownFactionEntry)) + return 0; + + int dataIndex = GetFactionDataIndexForRaceAndClass(renownFactionEntry); + if (dataIndex >= 0) + return renownFactionEntry.ReputationMax[dataIndex]; + + return 0; + } + + int GetRenownMaxLevel(FactionRecord renownFactionEntry) + { + if (renownFactionEntry == null) + return 0; + + CurrencyTypesRecord currency = CliDB.CurrencyTypesStorage.LookupByKey(renownFactionEntry.RenownCurrencyID); + if (currency != null) + return (int)currency.MaxQty; + + return 0; + } public void ApplyForceReaction(uint faction_id, ReputationRank rank, bool apply) { @@ -226,8 +291,11 @@ namespace Game { SetFactionStanding setFactionStanding = new(); setFactionStanding.BonusFromAchievementSystem = 0.0f; + + int standing = faction.VisualStandingIncrease != 0 ? faction.VisualStandingIncrease : faction.Standing; + if (faction != null) - setFactionStanding.Faction.Add(new FactionStandingData((int)faction.ReputationListID, faction.Standing)); + setFactionStanding.Faction.Add(new FactionStandingData((int)faction.ReputationListID, standing)); foreach (var state in _factions.Values) { @@ -235,7 +303,10 @@ namespace Game { state.needSend = false; if (faction == null || state.ReputationListID != faction.ReputationListID) - setFactionStanding.Faction.Add(new FactionStandingData((int)state.ReputationListID, state.Standing)); + { + standing = state.VisualStandingIncrease != 0 ? state.VisualStandingIncrease : state.Standing; + setFactionStanding.Faction.Add(new FactionStandingData((int)state.ReputationListID, standing)); + } } } @@ -288,6 +359,7 @@ namespace Game newFaction.Id = factionEntry.Id; newFaction.ReputationListID = (uint)factionEntry.ReputationIndex; newFaction.Standing = 0; + newFaction.VisualStandingIncrease = 0; newFaction.Flags = GetDefaultStateFlags(factionEntry); newFaction.needSend = true; newFaction.needSave = true; @@ -408,13 +480,22 @@ namespace Game var factionState = _factions.LookupByKey((uint)factionEntry.ReputationIndex); if (factionState != null) { - int BaseRep = GetBaseReputation(factionEntry); + // Ignore renown reputation already raised to the maximum level + if (HasMaximumRenownReputation(factionEntry)) + { + factionState.needSend = false; + factionState.needSave = false; + return false; + } - if (incremental) + int baseRep = GetBaseReputation(factionEntry); + int oldStanding = factionState.Standing + baseRep; + + if (incremental || IsRenownReputation(factionEntry)) { // int32 *= float cause one point loss? standing = (int)(Math.Floor(standing * WorldConfig.GetFloatValue(WorldCfg.RateReputationGain) + 0.5f)); - standing += factionState.Standing + BaseRep; + standing += oldStanding; } if (standing > GetMaxReputation(factionEntry)) @@ -422,13 +503,56 @@ namespace Game else if (standing < GetMinReputation(factionEntry)) standing = GetMinReputation(factionEntry); - ReputationRank old_rank = ReputationToRank(factionEntry, factionState.Standing + BaseRep); - ReputationRank new_rank = ReputationToRank(factionEntry, standing); + // Ignore rank for paragon or renown reputation + if (!IsParagonReputation(factionEntry) && !IsRenownReputation(factionEntry)) + { + ReputationRank oldRank = ReputationToRank(factionEntry, oldStanding); + ReputationRank newRank = ReputationToRank(factionEntry, standing); - int oldStanding = factionState.Standing + BaseRep; - int newStanding = standing - BaseRep; + if (newRank <= ReputationRank.Hostile) + SetAtWar(factionState, true); - _player.ReputationChanged(factionEntry, newStanding - factionState.Standing); + if (newRank > oldRank) + _sendFactionIncreased = true; + + if (factionEntry.FriendshipRepID == 0) + UpdateRankCounters(oldRank, newRank); + } + else + _sendFactionIncreased = true; // TODO: Check Paragon reputation + + // Calculate new standing and reputation change + int newStanding = 0; + int reputationChange = standing - oldStanding; + + if (!IsRenownReputation(factionEntry)) + newStanding = standing - baseRep; + else + { + CurrencyTypesRecord currency = CliDB.CurrencyTypesStorage.LookupByKey(factionEntry.RenownCurrencyID); + if (currency != null) + { + int renownLevelThreshold = GetRenownLevelThreshold(factionEntry); + int oldRenownLevel = GetRenownLevel(factionEntry); + + int totalReputation = (oldRenownLevel * renownLevelThreshold) + (standing - baseRep); + int newRenownLevel = totalReputation / renownLevelThreshold; + newStanding = totalReputation % renownLevelThreshold; + + if (newRenownLevel >= GetRenownMaxLevel(factionEntry)) + { + newStanding = 0; + reputationChange += (GetRenownMaxLevel(factionEntry) * renownLevelThreshold) - totalReputation; + } + + factionState.VisualStandingIncrease = reputationChange; + + if (oldRenownLevel != newRenownLevel) + _player.ModifyCurrency(currency.Id, newRenownLevel - oldRenownLevel, false); + } + } + + _player.ReputationChanged(factionEntry, reputationChange); factionState.Standing = newStanding; factionState.needSend = true; @@ -436,12 +560,6 @@ namespace Game SetVisible(factionState); - if (new_rank <= ReputationRank.Hostile) - SetAtWar(factionState, true); - - if (new_rank > old_rank) - _sendFactionIncreased = true; - ParagonReputationRecord paragonReputation = Global.DB2Mgr.GetParagonReputation(factionEntry.Id); if (paragonReputation != null) { @@ -455,9 +573,6 @@ namespace Game } } - if (factionEntry.FriendshipRepID == 0 && paragonReputation == null) - UpdateRankCounters(old_rank, new_rank); - _player.UpdateCriteria(CriteriaType.TotalFactionsEncountered, factionEntry.Id); _player.UpdateCriteria(CriteriaType.ReputationGained, factionEntry.Id); _player.UpdateCriteria(CriteriaType.TotalExaltedFactions, factionEntry.Id); @@ -700,7 +815,7 @@ namespace Game if (!CliDB.FactionStorage.ContainsKey(factionEntry.ParagonFactionID)) return false; - if (GetRank(factionEntry) != ReputationRank.Exalted) + if (GetRank(factionEntry) != ReputationRank.Exalted && !HasMaximumRenownReputation(factionEntry)) return false; ParagonReputationRecord paragonReputation = Global.DB2Mgr.GetParagonReputation(factionEntry.ParagonFactionID); @@ -803,10 +918,12 @@ namespace Game public uint Id; public uint ReputationListID; public int Standing; + public int VisualStandingIncrease; public ReputationFlags Flags; public bool needSend; public bool needSave; } + public class RepRewardRate { public float questRate; // We allow rate = 0.0 in database. For this case, it means that @@ -817,6 +934,7 @@ namespace Game public float creatureRate; // no reputation are given at all for this faction/rate type. public float spellRate; } + public class ReputationOnKillEntry { public uint RepFaction1; @@ -829,6 +947,7 @@ namespace Game public bool IsTeamAward2; public bool TeamDependent; } + public class RepSpilloverTemplate { public uint[] faction = new uint[5]; diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index 660b48eb0..f676c3435 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -4501,7 +4501,7 @@ namespace Game.Spells } foreach (var reagentsCurrency in m_spellInfo.ReagentsCurrency) - p_caster.ModifyCurrency((CurrencyTypes)reagentsCurrency.CurrencyTypesID, -reagentsCurrency.CurrencyCount, false, true); + p_caster.ModifyCurrency(reagentsCurrency.CurrencyTypesID, -reagentsCurrency.CurrencyCount, false, true); } void HandleThreatSpells() diff --git a/Source/Game/Spells/SpellEffects.cs b/Source/Game/Spells/SpellEffects.cs index 9e19934db..6b708f302 100644 --- a/Source/Game/Spells/SpellEffects.cs +++ b/Source/Game/Spells/SpellEffects.cs @@ -4729,7 +4729,7 @@ namespace Game.Spells if (!CliDB.CurrencyTypesStorage.ContainsKey(effectInfo.MiscValue)) return; - unitTarget.ToPlayer().ModifyCurrency((CurrencyTypes)effectInfo.MiscValue, damage); + unitTarget.ToPlayer().ModifyCurrency((uint)effectInfo.MiscValue, damage); } [SpellEffectHandler(SpellEffectName.CastButton)]