TrinityCore
ReputationMgr.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "ReputationMgr.h"
19#include "CharacterPackets.h"
20#include "DatabaseEnv.h"
21#include "DB2Stores.h"
22#include "Language.h"
23#include "Log.h"
24#include "ObjectMgr.h"
25#include "Player.h"
26#include "ReputationPackets.h"
27#include "ScriptMgr.h"
28#include "World.h"
29#include "WorldSession.h"
30
32{
35};
36
37std::set<int32> const ReputationMgr::ReputationRankThresholds =
38{
39 -42000,
40 // Hated
41 -6000,
42 // Hostile
43 -3000,
44 // Unfriendly
45 0,
46 // Neutral
47 3000,
48 // Friendly
49 9000,
50 // Honored
51 21000,
52 // Revered
53 42000
54 // Exalted
55};
56
59
60template<typename T, typename F, typename... Rest>
61static int32 ReputationToRankHelper(std::set<T, Rest...> const& thresholds, int32 standing, F thresholdExtractor)
62{
63 auto itr = thresholds.begin();
64 auto end = thresholds.end();
65 int32 rank = -1;
66 while (itr != end && standing >= thresholdExtractor(*itr))
67 {
68 ++rank;
69 ++itr;
70 }
71
72 return rank;
73}
74
76{
78 if (DB2Manager::FriendshipRepReactionSet const* friendshipReactions = sDB2Manager.GetFriendshipRepReactions(factionEntry->FriendshipRepID))
79 rank = ReputationToRankHelper(*friendshipReactions, standing, [](FriendshipRepReactionEntry const* frr) { return frr->ReactionThreshold; });
80 else
81 rank = ReputationToRankHelper(ReputationRankThresholds, standing, [](int32 threshold) { return threshold; });
82
83 return ReputationRank(rank);
84}
85
86FactionState const* ReputationMgr::GetState(FactionEntry const* factionEntry) const
87{
88 return factionEntry->CanHaveReputation() ? GetState(factionEntry->ReputationIndex) : nullptr;
89}
90
91bool ReputationMgr::IsAtWar(uint32 faction_id) const
92{
93 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
94
95 if (!factionEntry)
96 {
97 TC_LOG_ERROR("misc", "ReputationMgr::IsAtWar: Can't get AtWar flag of {} for unknown faction (faction id) #{}.", _player->GetName(), faction_id);
98 return false;
99 }
100
101 return IsAtWar(factionEntry);
102}
103
104bool ReputationMgr::IsAtWar(FactionEntry const* factionEntry) const
105{
106 if (!factionEntry)
107 return false;
108
109 if (FactionState const* factionState = GetState(factionEntry))
110 return factionState->Flags.HasFlag(ReputationFlags::AtWar);
111 return false;
112}
113
115{
116 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
117
118 if (!factionEntry)
119 {
120 TC_LOG_ERROR("misc", "ReputationMgr::GetReputation: Can't get reputation of {} for unknown faction (faction id) #{}.", _player->GetName(), faction_id);
121 return 0;
122 }
123
124 return GetReputation(factionEntry);
125}
126
128{
129 int32 dataIndex = GetFactionDataIndexForRaceAndClass(factionEntry);
130 if (dataIndex < 0)
131 return 0;
132
133 return factionEntry->ReputationBase[dataIndex];
134}
135
137{
138 if (DB2Manager::FriendshipRepReactionSet const* friendshipReactions = sDB2Manager.GetFriendshipRepReactions(factionEntry->FriendshipRepID))
139 return (*friendshipReactions->begin())->ReactionThreshold;
140
141 return *ReputationRankThresholds.begin();
142}
143
145{
146 if (ParagonReputationEntry const* paragonReputation = sDB2Manager.GetParagonReputation(factionEntry->ID))
147 {
148 // has reward quest, cap is just before threshold for another quest reward
149 // for example: if current reputation is 12345 and quests are given every 10000 and player has unclaimed reward
150 // then cap will be 19999
151
152 // otherwise cap is one theshold level larger
153 // if current reputation is 12345 and questa are given every 10000 and player does NOT have unclaimed reward
154 // then cap will be 29999
155
156 int32 reputation = GetReputation(factionEntry);
157 int32 cap = reputation + paragonReputation->LevelThreshold - reputation % paragonReputation->LevelThreshold - 1;
158
159 if (_player->GetQuestStatus(paragonReputation->QuestID) == QUEST_STATUS_NONE)
160 cap += paragonReputation->LevelThreshold;
161
162 return cap;
163 }
164
165 if (IsRenownReputation(factionEntry))
166 {
167 // Compared to a paragon reputation, DF renown reputations
168 // have a maximum value of 2500 which resets with each level of renown acquired.
169 // We calculate the total reputation necessary to raise the renown to the maximum
170 return GetRenownMaxLevel(factionEntry) * GetRenownLevelThreshold(factionEntry);
171 }
172
173 if (DB2Manager::FriendshipRepReactionSet const* friendshipReactions = sDB2Manager.GetFriendshipRepReactions(factionEntry->FriendshipRepID))
174 return (*friendshipReactions->rbegin())->ReactionThreshold;
175
176 int32 dataIndex = GetFactionDataIndexForRaceAndClass(factionEntry);
177 if (dataIndex >= 0)
178 return factionEntry->ReputationMax[dataIndex];
179
180 return *ReputationRankThresholds.rbegin();
181}
182
184{
185 // Faction without recorded reputation. Just ignore.
186 if (!factionEntry)
187 return 0;
188
189 if (FactionState const* state = GetState(factionEntry))
190 return GetBaseReputation(factionEntry) + state->Standing;
191
192 return 0;
193}
194
196{
197 int32 reputation = GetReputation(factionEntry);
198 return ReputationToRank(factionEntry, reputation);
199}
200
202{
203 int32 reputation = GetBaseReputation(factionEntry);
204 return ReputationToRank(factionEntry, reputation);
205}
206
207std::string ReputationMgr::GetReputationRankName(FactionEntry const* factionEntry) const
208{
209 ReputationRank rank = GetRank(factionEntry);
210 if (!factionEntry->FriendshipRepID)
211 return sObjectMgr->GetTrinityString(ReputationRankStrIndex[GetRank(factionEntry)], _player->GetSession()->GetSessionDbcLocale());
212
213 if (DB2Manager::FriendshipRepReactionSet const* friendshipReactions = sDB2Manager.GetFriendshipRepReactions(factionEntry->FriendshipRepID))
214 {
215 auto itr = friendshipReactions->begin();
216 std::advance(itr, uint32(rank));
217 return (*itr)->Reaction[_player->GetSession()->GetSessionDbcLocale()];
218 }
219
220 return "";
221}
222
224{
225 return GetForcedRankIfAny(factionTemplateEntry->Faction);
226}
227
229{
230 if (sDB2Manager.GetParagonReputation(factionEntry->ID))
231 return true;
232
233 return false;
234}
235
237{
238 return GetParagonLevel(sFactionStore.LookupEntry(paragonFactionId));
239}
240
241int32 ReputationMgr::GetParagonLevel(FactionEntry const* paragonFactionEntry) const
242{
243 if (!paragonFactionEntry)
244 return 0;
245
246 if (ParagonReputationEntry const* paragonReputation = sDB2Manager.GetParagonReputation(paragonFactionEntry->ID))
247 return GetReputation(paragonFactionEntry) / paragonReputation->LevelThreshold;
248
249 return 0;
250}
251
253{
254 if (!IsRenownReputation(factionEntry))
255 return false;
256
257 return GetRenownLevel(factionEntry) >= GetRenownMaxLevel(factionEntry);
258}
259
260bool ReputationMgr::IsRenownReputation(FactionEntry const* factionEntry) const
261{
262 return factionEntry->RenownCurrencyID > 0;
263}
264
265int32 ReputationMgr::GetRenownLevel(FactionEntry const* renownFactionEntry) const
266{
267 if (!renownFactionEntry)
268 return 0;
269
270 if (CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(renownFactionEntry->RenownCurrencyID))
271 return _player->GetCurrencyQuantity(currency->ID);
272
273 return 0;
274}
275
277{
278 if (!renownFactionEntry || !IsRenownReputation(renownFactionEntry))
279 return 0;
280
281 int32 dataIndex = GetFactionDataIndexForRaceAndClass(renownFactionEntry);
282 if (dataIndex >= 0)
283 return renownFactionEntry->ReputationMax[dataIndex];
284
285 return 0;
286}
287
289{
290 if (!renownFactionEntry)
291 return 0;
292
293 if (CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(renownFactionEntry->RenownCurrencyID))
294 return _player->GetCurrencyMaxQuantity(currency);
295
296 return 0;
297}
298
300{
301 if (apply)
302 {
303 _forcedReactions[faction_id] = rank;
304 _player->SetVisibleForcedReaction(faction_id, rank);
305 }
306 else
307 {
308 _forcedReactions.erase(faction_id);
310 }
311}
312
314{
315 ReputationFlags flags = [&]()
316 {
317 int32 dataIndex = GetFactionDataIndexForRaceAndClass(factionEntry);
318 if (dataIndex < 0)
320
321 return static_cast<ReputationFlags>(factionEntry->ReputationFlags[dataIndex]);
322 }();
323
324 if (sDB2Manager.GetParagonReputation(factionEntry->ID))
326
327 return flags;
328}
329
331{
333 setFactionStanding.BonusFromAchievementSystem = 0.0f;
334
335 auto getStandingForPacket = [](FactionState const* state)
336 {
337 return state->VisualStandingIncrease ? state->VisualStandingIncrease : state->Standing;
338 };
339
340 if (faction)
341 setFactionStanding.Faction.emplace_back(int32(faction->ReputationListID), getStandingForPacket(faction));
342
343 for (auto& [reputationIndex, state] : _factions)
344 {
345 if (state.needSend)
346 {
347 state.needSend = false;
348 if (!faction || state.ReputationListID != faction->ReputationListID)
349 setFactionStanding.Faction.emplace_back(int32(state.ReputationListID), getStandingForPacket(&state));
350 }
351 }
352
353 setFactionStanding.ShowVisual = _sendFactionIncreased;
354 _player->SendDirectMessage(setFactionStanding.Write());
355
356 _sendFactionIncreased = false; // Reset
357}
358
360{
362
363 for (FactionStateList::iterator itr = _factions.begin(); itr != _factions.end(); ++itr)
364 {
365 WorldPackets::Reputation::FactionData& factionData = initFactions.Factions.emplace_back();
366 factionData.FactionID = itr->second.ID;
367 factionData.Flags = itr->second.Flags.AsUnderlyingType();
368 factionData.Standing = itr->second.Standing;
370 WorldPackets::Reputation::FactionBonusData& bonus = initFactions.Bonuses.emplace_back();
371 bonus.FactionID = itr->second.ID;
372 bonus.FactionHasBonus = false;
373 itr->second.needSend = false;
374 }
375
376 _player->SendDirectMessage(initFactions.Write());
377}
378
379void ReputationMgr::SendVisible(FactionState const* faction, bool visible) const
380{
382 return;
383
384 // make faction visible/not visible in reputation list at client
386 packet.FactionIndex = faction->ReputationListID;
388}
389
391{
392 _factions.clear();
397 _sendFactionIncreased = false;
398
399 for (FactionEntry const* factionEntry : sFactionStore)
400 {
401 if (factionEntry->CanHaveReputation())
402 {
403 FactionState newFaction;
404 newFaction.ID = factionEntry->ID;
405 newFaction.ReputationListID = factionEntry->ReputationIndex;
406 newFaction.Standing = 0;
407 newFaction.VisualStandingIncrease = 0;
408 newFaction.Flags = GetDefaultStateFlags(factionEntry);
409 newFaction.needSend = true;
410 newFaction.needSave = true;
411
412 if (newFaction.Flags.HasFlag(ReputationFlags::Visible))
414
415 if (!factionEntry->FriendshipRepID)
417
418 _factions[newFaction.ReputationListID] = newFaction;
419 }
420 }
421}
422
423bool ReputationMgr::SetReputation(FactionEntry const* factionEntry, int32 standing, bool incremental, bool spillOverOnly, bool noSpillover)
424{
425 sScriptMgr->OnPlayerReputationChange(_player, factionEntry->ID, standing, incremental);
426 bool res = false;
427 if (!noSpillover)
428 {
429 // if spillover definition exists in DB, override DBC
430 if (RepSpilloverTemplate const* repTemplate = sObjectMgr->GetRepSpilloverTemplate(factionEntry->ID))
431 {
432 for (uint32 i = 0; i < MAX_SPILLOVER_FACTIONS; ++i)
433 {
434 if (repTemplate->faction[i])
435 {
436 if (_player->GetReputationRank(repTemplate->faction[i]) <= ReputationRank(repTemplate->faction_rank[i]))
437 {
438 // bonuses are already given, so just modify standing by rate
439 int32 spilloverRep = int32(standing * repTemplate->faction_rate[i]);
440 SetOneFactionReputation(sFactionStore.AssertEntry(repTemplate->faction[i]), spilloverRep, incremental);
441 }
442 }
443 }
444 }
445 else
446 {
447 float spillOverRepOut = float(standing);
448 // check for sub-factions that receive spillover
449 std::vector<uint32> const* flist = sDB2Manager.GetFactionTeamList(factionEntry->ID);
450 // if has no sub-factions, check for factions with same parent
451 if (!flist && factionEntry->ParentFactionID && factionEntry->ParentFactionMod[1] != 0.0f)
452 {
453 spillOverRepOut *= factionEntry->ParentFactionMod[1];
454 if (FactionEntry const* parent = sFactionStore.LookupEntry(factionEntry->ParentFactionID))
455 {
456 FactionStateList::iterator parentState = _factions.find(parent->ReputationIndex);
457 // some team factions have own reputation standing, in this case do not spill to other sub-factions
458 if (parentState != _factions.end() && parentState->second.Flags.HasFlag(ReputationFlags::HeaderShowsBar))
459 {
460 SetOneFactionReputation(parent, int32(spillOverRepOut), incremental);
461 }
462 else // spill to "sister" factions
463 {
464 flist = sDB2Manager.GetFactionTeamList(factionEntry->ParentFactionID);
465 }
466 }
467 }
468 if (flist)
469 {
470 // Spillover to affiliated factions
471 for (std::vector<uint32>::const_iterator itr = flist->begin(); itr != flist->end(); ++itr)
472 {
473 if (FactionEntry const* factionEntryCalc = sFactionStore.LookupEntry(*itr))
474 {
475 if (factionEntryCalc == factionEntry || GetRank(factionEntryCalc) > ReputationRank(factionEntryCalc->ParentFactionCap[0]))
476 continue;
477 int32 spilloverRep = int32(spillOverRepOut * factionEntryCalc->ParentFactionMod[0]);
478 if (spilloverRep != 0 || !incremental)
479 res = SetOneFactionReputation(factionEntryCalc, spilloverRep, incremental);
480 }
481 }
482 }
483 }
484 }
485
486 // spillover done, update faction itself
487 FactionStateList::iterator faction = _factions.find(factionEntry->ReputationIndex);
488 if (faction != _factions.end())
489 {
490 FactionEntry const* primaryFactionToModify = factionEntry;
491 if (incremental && standing > 0 && CanGainParagonReputationForFaction(factionEntry))
492 {
493 primaryFactionToModify = sFactionStore.AssertEntry(factionEntry->ParagonFactionID);
494 faction = _factions.find(primaryFactionToModify->ReputationIndex);
495 }
496
497 if (faction != _factions.end())
498 {
499 // if we update spillover only, do not update main reputation (rank exceeds creature reward rate)
500 if (!spillOverOnly)
501 res = SetOneFactionReputation(primaryFactionToModify, standing, incremental);
502
503 // only this faction gets reported to client, even if it has no own visible standing
504 SendState(&faction->second);
505 }
506 }
507 return res;
508}
509
510bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing, bool incremental)
511{
512 FactionStateList::iterator itr = _factions.find(factionEntry->ReputationIndex);
513 if (itr != _factions.end())
514 {
515 // Ignore renown reputation already raised to the maximum level
516 if (HasMaximumRenownReputation(factionEntry) && standing > 0)
517 {
518 itr->second.needSend = false;
519 itr->second.needSave = false;
520 return false;
521 }
522
523 int32 baseRep = GetBaseReputation(factionEntry);
524 int32 oldStanding = itr->second.Standing + baseRep;
525
526 if (incremental || IsRenownReputation(factionEntry))
527 {
528 // int32 *= float cause one point loss?
529 standing = int32(floor((float)standing * sWorld->getRate(RATE_REPUTATION_GAIN) + 0.5f));
530 standing += oldStanding;
531 }
532
533 if (standing > GetMaxReputation(factionEntry))
534 standing = GetMaxReputation(factionEntry);
535 else if (standing < GetMinReputation(factionEntry))
536 standing = GetMinReputation(factionEntry);
537
538 // Ignore rank for paragon or renown reputation
539 if (!IsParagonReputation(factionEntry) && !IsRenownReputation(factionEntry))
540 {
541 ReputationRank oldRank = ReputationToRank(factionEntry, oldStanding);
542 ReputationRank newRank = ReputationToRank(factionEntry, standing);
543
544 if (newRank <= REP_HOSTILE)
545 SetAtWar(&itr->second, true);
546
547 if (newRank > oldRank)
549
550 if (!factionEntry->FriendshipRepID)
551 UpdateRankCounters(oldRank, newRank);
552 }
553 else
554 _sendFactionIncreased = true; // TODO: Check Paragon reputation
555
556 // Calculate new standing and reputation change
557 int32 newStanding = 0;
558 int32 reputationChange = standing - oldStanding;
559
560 if (!IsRenownReputation(factionEntry))
561 newStanding = standing - baseRep;
562 else
563 {
564 if (CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(factionEntry->RenownCurrencyID))
565 {
566 int32 renownLevelThreshold = GetRenownLevelThreshold(factionEntry);
567 int32 oldRenownLevel = GetRenownLevel(factionEntry);
568
569 int32 totalReputation = (oldRenownLevel * renownLevelThreshold) + (standing - baseRep);
570 int32 newRenownLevel = totalReputation / renownLevelThreshold;
571 newStanding = totalReputation % renownLevelThreshold;
572
573 if (newRenownLevel >= GetRenownMaxLevel(factionEntry))
574 {
575 newStanding = 0;
576 reputationChange += (GetRenownMaxLevel(factionEntry) * renownLevelThreshold) - totalReputation;
577 }
578
579 itr->second.VisualStandingIncrease = reputationChange;
580
581 // If the reputation is decreased by command, we will send CurrencyDestroyReason::Cheat
582 if (oldRenownLevel != newRenownLevel)
583 _player->ModifyCurrency(currency->ID, newRenownLevel - oldRenownLevel, CurrencyGainSource::RenownRepGain, CurrencyDestroyReason::Cheat);
584 }
585 }
586
587 _player->ReputationChanged(factionEntry, reputationChange);
588
589 itr->second.Standing = newStanding;
590 itr->second.needSend = true;
591 itr->second.needSave = true;
592
593 SetVisible(&itr->second);
594
595 ParagonReputationEntry const* paragonReputation = sDB2Manager.GetParagonReputation(factionEntry->ID);
596 if (paragonReputation)
597 {
598 int32 oldParagonLevel = oldStanding / paragonReputation->LevelThreshold;
599 int32 newParagonLevel = standing / paragonReputation->LevelThreshold;
600 if (oldParagonLevel != newParagonLevel)
601 if (Quest const* paragonRewardQuest = sObjectMgr->GetQuestTemplate(paragonReputation->QuestID))
602 _player->AddQuestAndCheckCompletion(paragonRewardQuest, nullptr);
603 }
604
610
611 return true;
612 }
613 return false;
614}
615
616void ReputationMgr::SetVisible(FactionTemplateEntry const* factionTemplateEntry)
617{
618 if (!factionTemplateEntry->Faction)
619 return;
620
621 if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplateEntry->Faction))
622 // Never show factions of the opposing team
623 if (!(factionEntry->ReputationRaceMask[1].HasRace(_player->GetRace()) && factionEntry->ReputationBase[1] == Reputation_Bottom))
624 SetVisible(factionEntry);
625}
626
628{
629 if (!factionEntry->CanHaveReputation())
630 return;
631
632 FactionStateList::iterator itr = _factions.find(factionEntry->ReputationIndex);
633 if (itr == _factions.end())
634 return;
635
636 SetVisible(&itr->second);
637}
638
640{
641 // always invisible or hidden faction can't be make visible
643 return;
644
646 return;
647
648 if (sDB2Manager.GetParagonReputation(faction->ID))
649 return;
650
651 // already set
653 return;
654
656 faction->needSend = true;
657 faction->needSave = true;
658
660
661 SendVisible(faction);
662}
663
664void ReputationMgr::SetAtWar(RepListID repListID, bool on)
665{
666 FactionStateList::iterator itr = _factions.find(repListID);
667 if (itr == _factions.end())
668 return;
669
670 // always invisible or hidden faction can't change war state
671 if (itr->second.Flags.HasFlag(ReputationFlags::Hidden | ReputationFlags::Header))
672 return;
673
674 SetAtWar(&itr->second, on);
675}
676
677void ReputationMgr::SetAtWar(FactionState* faction, bool atWar) const
678{
679 // Do not allow to declare war to our own faction. But allow for rival factions (eg Aldor vs Scryer).
680 if (atWar && faction->Flags.HasFlag(ReputationFlags::Peaceful) && GetRank(sFactionStore.AssertEntry(faction->ID)) > REP_HATED)
681 return;
682
683 // already set
684 if (faction->Flags.HasFlag(ReputationFlags::AtWar) == atWar)
685 return;
686
687 if (atWar)
688 faction->Flags |= ReputationFlags::AtWar;
689 else
690 faction->Flags &= ~ReputationFlags::AtWar;
691
692 faction->needSend = true;
693 faction->needSave = true;
694}
695
696void ReputationMgr::SetInactive(RepListID repListID, bool on)
697{
698 FactionStateList::iterator itr = _factions.find(repListID);
699 if (itr == _factions.end())
700 return;
701
702 SetInactive(&itr->second, on);
703}
704
705void ReputationMgr::SetInactive(FactionState* faction, bool inactive) const
706{
707 // always invisible or hidden faction can't be inactive
709 return;
710
711 // already set
712 if (faction->Flags.HasFlag(ReputationFlags::Inactive) == inactive)
713 return;
714
715 if (inactive)
717 else
719
720 faction->needSend = true;
721 faction->needSave = true;
722}
723
725{
726 // Set initial reputations (so everything is nifty before DB data load)
727 Initialize();
728
729 //QueryResult* result = CharacterDatabase.PQuery("SELECT faction, standing, flags FROM character_reputation WHERE guid = '{}'", GetGUIDLow());
730
731 if (result)
732 {
733 do
734 {
735 Field* fields = result->Fetch();
736
737 FactionEntry const* factionEntry = sFactionStore.LookupEntry(fields[0].GetUInt16());
738 if (factionEntry && factionEntry->CanHaveReputation())
739 {
740 FactionState* faction = &_factions[factionEntry->ReputationIndex];
741
742 // update standing to current
743 faction->Standing = fields[1].GetInt32();
744
745 // update counters
746 if (!factionEntry->FriendshipRepID)
747 {
748 int32 BaseRep = GetBaseReputation(factionEntry);
749 ReputationRank old_rank = ReputationToRank(factionEntry, BaseRep);
750 ReputationRank new_rank = ReputationToRank(factionEntry, BaseRep + faction->Standing);
751 UpdateRankCounters(old_rank, new_rank);
752 }
753
754 EnumFlag<ReputationFlags> dbFactionFlags = static_cast<ReputationFlags>(fields[2].GetUInt16());
755
756 if (dbFactionFlags.HasFlag(ReputationFlags::Visible))
757 SetVisible(faction); // have internal checks for forced invisibility
758
759 if (dbFactionFlags.HasFlag(ReputationFlags::Inactive))
760 SetInactive(faction, true); // have internal checks for visibility requirement
761
762 if (dbFactionFlags.HasFlag(ReputationFlags::AtWar)) // DB at war
763 SetAtWar(faction, true); // have internal checks for ReputationFlags::Peaceful
764 else // DB not at war
765 {
766 // allow remove if visible (and then not FACTION_FLAG_INVISIBLE_FORCED or FACTION_FLAG_HIDDEN)
768 SetAtWar(faction, false); // have internal checks for ReputationFlags::Peaceful
769 }
770
771 // set atWar for hostile
772 if (GetRank(factionEntry) <= REP_HOSTILE)
773 SetAtWar(faction, true);
774
775 // reset changed flag if values similar to saved in DB
776 if (faction->Flags == dbFactionFlags)
777 {
778 faction->needSend = false;
779 faction->needSave = false;
780 }
781 }
782 }
783 while (result->NextRow());
784 }
785}
786
788{
789 for (FactionStateList::iterator itr = _factions.begin(); itr != _factions.end(); ++itr)
790 {
791 if (itr->second.needSave)
792 {
794 stmt->setUInt64(0, _player->GetGUID().GetCounter());
795 stmt->setUInt16(1, uint16(itr->second.ID));
796 trans->Append(stmt);
797
798 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_REPUTATION_BY_FACTION);
799 stmt->setUInt64(0, _player->GetGUID().GetCounter());
800 stmt->setUInt16(1, uint16(itr->second.ID));
801 stmt->setInt32(2, itr->second.Standing);
802 stmt->setUInt16(3, itr->second.Flags.AsUnderlyingType());
803 trans->Append(stmt);
804
805 itr->second.needSave = false;
806 }
807 }
808}
809
811{
812 if (old_rank >= REP_EXALTED)
814 if (old_rank >= REP_REVERED)
816 if (old_rank >= REP_HONORED)
818
819 if (new_rank >= REP_EXALTED)
821 if (new_rank >= REP_REVERED)
823 if (new_rank >= REP_HONORED)
825}
826
828{
829 if (!factionEntry)
830 return -1;
831
832 uint8 race = _player->GetRace();
833 uint32 classMask = _player->GetClassMask();
834 for (int32 i = 0; i < 4; i++)
835 {
836 if ((factionEntry->ReputationRaceMask[i].HasRace(race) || (factionEntry->ReputationRaceMask[i].IsEmpty() && factionEntry->ReputationClassMask[i] != 0))
837 && (factionEntry->ReputationClassMask[i] & classMask || factionEntry->ReputationClassMask[i] == 0))
838
839 return i;
840 }
841
842 return -1;
843}
844
846{
847 if (!sFactionStore.LookupEntry(factionEntry->ParagonFactionID))
848 return false;
849
850 if (GetRank(factionEntry) != REP_EXALTED && !HasMaximumRenownReputation(factionEntry))
851 return false;
852
853 ParagonReputationEntry const* paragonReputation = sDB2Manager.GetParagonReputation(factionEntry->ParagonFactionID);
854 if (!paragonReputation)
855 return false;
856
857 Quest const* quest = sObjectMgr->GetQuestTemplate(paragonReputation->QuestID);
858 if (!quest)
859 return false;
860
861 return _player->GetLevel() >= _player->GetQuestMinLevel(quest);
862}
@ CHAR_INS_CHAR_REPUTATION_BY_FACTION
@ CHAR_DEL_CHAR_REPUTATION_BY_FACTION
DB2Storage< CurrencyTypesEntry > sCurrencyTypesStore("CurrencyTypes.db2", &CurrencyTypesLoadInfo::Instance)
DB2Storage< FactionEntry > sFactionStore("Faction.db2", &FactionLoadInfo::Instance)
#define sDB2Manager
Definition: DB2Stores.h:554
@ TotalFactionsEncountered
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
uint8_t uint8
Definition: Define.h:144
int32_t int32
Definition: Define.h:138
uint16_t uint16
Definition: Define.h:143
uint32_t uint32
Definition: Define.h:142
uint16 flags
Definition: DisableMgr.cpp:49
@ LANG_REP_FRIENDLY
Definition: Language.h:377
@ LANG_REP_HONORED
Definition: Language.h:378
@ LANG_REP_NEUTRAL
Definition: Language.h:376
@ LANG_REP_REVERED
Definition: Language.h:379
@ LANG_REP_HOSTILE
Definition: Language.h:374
@ LANG_REP_HATED
Definition: Language.h:373
@ LANG_REP_EXALTED
Definition: Language.h:380
@ LANG_REP_UNFRIENDLY
Definition: Language.h:375
#define TC_LOG_ERROR(filterType__, message__,...)
Definition: Log.h:188
#define sObjectMgr
Definition: ObjectMgr.h:1979
@ QUEST_STATUS_NONE
Definition: QuestDef.h:145
uint32 const ReputationRankStrIndex[MAX_REPUTATION_RANK]
static int32 ReputationToRankHelper(std::set< T, Rest... > const &thresholds, int32 standing, F thresholdExtractor)
uint32 RepListID
Definition: ReputationMgr.h:51
ReputationFlags
Definition: ReputationMgr.h:34
#define sScriptMgr
Definition: ScriptMgr.h:1418
#define MAX_REPUTATION_RANK
#define MIN_REPUTATION_RANK
ReputationRank
@ REP_HATED
@ REP_EXALTED
@ REP_HONORED
@ REP_REVERED
@ REP_HOSTILE
#define MAX_SPILLOVER_FACTIONS
std::set< FriendshipRepReactionEntry const *, FriendshipRepReactionEntryComparator > FriendshipRepReactionSet
Definition: DB2Stores.h:420
constexpr bool HasFlag(T flag) const
Definition: EnumFlag.h:106
Class used to access individual fields of database query result.
Definition: Field.h:92
uint16 GetUInt16() const
Definition: Field.cpp:45
int32 GetInt32() const
Definition: Field.cpp:69
LowType GetCounter() const
Definition: ObjectGuid.h:295
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:160
void SendDirectMessage(WorldPacket const *data) const
Definition: Player.cpp:6344
void ReputationChanged(FactionEntry const *factionEntry, int32 change)
Definition: Player.cpp:16726
void SetVisibleForcedReaction(uint32 factionId, ReputationRank rank)
Definition: Player.cpp:6620
WorldSession * GetSession() const
Definition: Player.h:2186
void UpdateCriteria(CriteriaType type, uint64 miscValue1=0, uint64 miscValue2=0, uint64 miscValue3=0, WorldObject *ref=nullptr)
Definition: Player.cpp:27000
void AddQuestAndCheckCompletion(Quest const *quest, Object *questGiver)
Definition: Player.cpp:14718
QuestStatus GetQuestStatus(uint32 quest_id) const
Definition: Player.cpp:16010
ReputationRank GetReputationRank(uint32 faction_id) const
Definition: Player.cpp:6525
void RemoveVisibleForcedReaction(uint32 factionId)
Definition: Player.cpp:6636
int32 GetQuestMinLevel(Quest const *quest) const
Definition: Player.cpp:14373
void ModifyCurrency(uint32 id, int32 amount, CurrencyGainSource gainSource=CurrencyGainSource::Cheat, CurrencyDestroyReason destroyReason=CurrencyDestroyReason::Cheat)
Modify currency amount.
Definition: Player.cpp:7165
uint32 GetCurrencyQuantity(uint32 id) const
Definition: Player.cpp:7403
uint32 GetCurrencyMaxQuantity(CurrencyTypesEntry const *currency, bool onLoad=false, bool onUpdateVersion=false) const
Definition: Player.cpp:7439
void setUInt16(uint8 index, uint16 value)
void setUInt64(uint8 index, uint64 value)
void setInt32(uint8 index, int32 value)
bool HasMaximumRenownReputation(FactionEntry const *factionEntry) const
bool IsParagonReputation(FactionEntry const *factionEntry) const
std::string GetReputationRankName(FactionEntry const *factionEntry) const
uint8 _honoredFactionCount
ReputationRank GetBaseRank(FactionEntry const *factionEntry) const
int32 GetFactionDataIndexForRaceAndClass(FactionEntry const *factionEntry) const
int32 GetRenownLevelThreshold(FactionEntry const *renownFactionEntry) const
void SetVisible(FactionTemplateEntry const *factionTemplateEntry)
int32 GetBaseReputation(FactionEntry const *factionEntry) const
int32 GetMaxReputation(FactionEntry const *factionEntry) const
uint8 _visibleFactionCount
ReputationFlags GetDefaultStateFlags(FactionEntry const *factionEntry) const
bool CanGainParagonReputationForFaction(FactionEntry const *factionEntry) const
void SetAtWar(RepListID repListID, bool on)
void SendState(FactionState const *faction)
int32 GetReputation(uint32 faction_id) const
bool SetReputation(FactionEntry const *factionEntry, int32 standing)
int32 GetRenownLevel(FactionEntry const *renownFactionEntry) const
void ApplyForceReaction(uint32 faction_id, ReputationRank rank, bool apply)
ReputationRank GetRank(FactionEntry const *factionEntry) const
int32 GetMinReputation(FactionEntry const *factionEntry) const
void SendInitialReputations()
static ReputationRank ReputationToRank(FactionEntry const *factionEntry, int32 standing)
uint8 _exaltedFactionCount
FactionState const * GetState(FactionEntry const *factionEntry) const
uint8 _reveredFactionCount
FactionStateList _factions
ForcedReactions _forcedReactions
static const int32 Reputation_Bottom
Definition: ReputationMgr.h:80
void SendVisible(FactionState const *faction, bool visible=true) const
bool IsAtWar(uint32 faction_id) const
bool SetOneFactionReputation(FactionEntry const *factionEntry, int32 standing, bool incremental)
Public for chat command needs.
bool _sendFactionIncreased
Play visual effect on next SMSG_SET_FACTION_STANDING sent.
int32 GetParagonLevel(uint32 paragonFactionId) const
int32 GetRenownMaxLevel(FactionEntry const *renownFactionEntry) const
bool IsRenownReputation(FactionEntry const *factionEntry) const
static std::set< int32 > const ReputationRankThresholds
Definition: ReputationMgr.h:78
void UpdateRankCounters(ReputationRank old_rank, ReputationRank new_rank)
static const int32 Reputation_Cap
Definition: ReputationMgr.h:79
Player * _player
void LoadFromDB(PreparedQueryResult result)
ReputationRank const * GetForcedRankIfAny(FactionTemplateEntry const *factionTemplateEntry) const
void SetInactive(RepListID repListID, bool on)
void SaveToDB(CharacterDatabaseTransaction trans)
uint32 GetClassMask() const
Definition: Unit.h:759
uint8 GetLevel() const
Definition: Unit.h:750
uint8 GetRace() const
Definition: Unit.h:754
std::string const & GetName() const
Definition: Object.h:556
std::vector< FactionBonusData > Bonuses
std::vector< FactionStandingData > Faction
LocaleConstant GetSessionDbcLocale() const
bool PlayerLoading() const
Definition: WorldSession.h:982
#define sWorld
Definition: World.h:929
@ RATE_REPUTATION_GAIN
Definition: World.h:489
void apply(T *val)
Definition: ByteConverter.h:41
std::array< int32, 4 > ReputationBase
std::array< int32, 4 > ReputationMax
uint16 ParagonFactionID
uint32 FriendshipRepID
uint16 ParentFactionID
std::array< int16, 4 > ReputationClassMask
bool CanHaveReputation() const
std::array< float, 2 > ParentFactionMod
std::array< uint16, 4 > ReputationFlags
int32 RenownCurrencyID
int16 ReputationIndex
std::array< Trinity::RaceMask< int64 >, 4 > ReputationRaceMask
RepListID ReputationListID
Definition: ReputationMgr.h:55
EnumFlag< ReputationFlags > Flags
Definition: ReputationMgr.h:58
int32 VisualStandingIncrease
Definition: ReputationMgr.h:57