aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/hotfixes/master/2021_06_04_00_hotfixes.sql88
-rw-r--r--src/server/database/Database/Implementation/HotfixDatabase.cpp14
-rw-r--r--src/server/database/Database/Implementation/HotfixDatabase.h8
-rw-r--r--src/server/game/DataStores/DB2LoadInfo.h35
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp18
-rw-r--r--src/server/game/DataStores/DB2Stores.h4
-rw-r--r--src/server/game/DataStores/DB2Structure.h21
-rw-r--r--src/server/game/DataStores/DBCEnums.h11
-rw-r--r--src/server/game/Entities/Player/Player.cpp6
-rw-r--r--src/server/game/Reputation/ReputationMgr.cpp171
-rw-r--r--src/server/game/Reputation/ReputationMgr.h13
-rw-r--r--src/server/scripts/Commands/cs_character.cpp3
-rw-r--r--src/server/scripts/Commands/cs_lookup.cpp3
-rw-r--r--src/server/scripts/Commands/cs_modify.cpp78
14 files changed, 378 insertions, 95 deletions
diff --git a/sql/updates/hotfixes/master/2021_06_04_00_hotfixes.sql b/sql/updates/hotfixes/master/2021_06_04_00_hotfixes.sql
new file mode 100644
index 00000000000..e02eac85190
--- /dev/null
+++ b/sql/updates/hotfixes/master/2021_06_04_00_hotfixes.sql
@@ -0,0 +1,88 @@
+--
+-- Table structure for table `friendship_rep_reaction`
+--
+DROP TABLE IF EXISTS `friendship_rep_reaction`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `friendship_rep_reaction` (
+ `ID` int(10) unsigned NOT NULL DEFAULT '0',
+ `Reaction` text,
+ `FriendshipRepID` int(10) unsigned NOT NULL DEFAULT '0',
+ `ReactionThreshold` smallint(5) unsigned 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 */;
+
+--
+-- Table structure for table `friendship_rep_reaction_locale`
+--
+DROP TABLE IF EXISTS `friendship_rep_reaction_locale`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `friendship_rep_reaction_locale` (
+ `ID` int(10) unsigned NOT NULL DEFAULT '0',
+ `locale` varchar(4) NOT NULL,
+ `Reaction_lang` text,
+ `VerifiedBuild` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`ID`,`locale`,`VerifiedBuild`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
+/*!50500 PARTITION BY LIST COLUMNS(locale)
+(PARTITION deDE VALUES IN ('deDE') ENGINE = InnoDB,
+ PARTITION esES VALUES IN ('esES') ENGINE = InnoDB,
+ PARTITION esMX VALUES IN ('esMX') ENGINE = InnoDB,
+ PARTITION frFR VALUES IN ('frFR') ENGINE = InnoDB,
+ PARTITION itIT VALUES IN ('itIT') ENGINE = InnoDB,
+ PARTITION koKR VALUES IN ('koKR') ENGINE = InnoDB,
+ PARTITION ptBR VALUES IN ('ptBR') ENGINE = InnoDB,
+ PARTITION ruRU VALUES IN ('ruRU') ENGINE = InnoDB,
+ PARTITION zhCN VALUES IN ('zhCN') ENGINE = InnoDB,
+ PARTITION zhTW VALUES IN ('zhTW') ENGINE = InnoDB) */;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `friendship_reputation`
+--
+DROP TABLE IF EXISTS `friendship_reputation`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `friendship_reputation` (
+ `Description` text,
+ `StandingModified` text,
+ `StandingChanged` text,
+ `ID` int(10) unsigned NOT NULL DEFAULT '0',
+ `FactionID` int(11) NOT NULL DEFAULT '0',
+ `TextureFileID` int(11) NOT NULL DEFAULT '0',
+ `Flags` 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 */;
+
+--
+-- Table structure for table `friendship_reputation_locale`
+--
+DROP TABLE IF EXISTS `friendship_reputation_locale`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `friendship_reputation_locale` (
+ `ID` int(10) unsigned NOT NULL DEFAULT '0',
+ `locale` varchar(4) NOT NULL,
+ `Description_lang` text,
+ `StandingModified_lang` text,
+ `StandingChanged_lang` text,
+ `VerifiedBuild` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`ID`,`locale`,`VerifiedBuild`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
+/*!50500 PARTITION BY LIST COLUMNS(locale)
+(PARTITION deDE VALUES IN ('deDE') ENGINE = InnoDB,
+ PARTITION esES VALUES IN ('esES') ENGINE = InnoDB,
+ PARTITION esMX VALUES IN ('esMX') ENGINE = InnoDB,
+ PARTITION frFR VALUES IN ('frFR') ENGINE = InnoDB,
+ PARTITION itIT VALUES IN ('itIT') ENGINE = InnoDB,
+ PARTITION koKR VALUES IN ('koKR') ENGINE = InnoDB,
+ PARTITION ptBR VALUES IN ('ptBR') ENGINE = InnoDB,
+ PARTITION ruRU VALUES IN ('ruRU') ENGINE = InnoDB,
+ PARTITION zhCN VALUES IN ('zhCN') ENGINE = InnoDB,
+ PARTITION zhTW VALUES IN ('zhTW') ENGINE = InnoDB) */;
+/*!40101 SET character_set_client = @saved_cs_client */;
diff --git a/src/server/database/Database/Implementation/HotfixDatabase.cpp b/src/server/database/Database/Implementation/HotfixDatabase.cpp
index 1eba397e46e..eae49d12b2e 100644
--- a/src/server/database/Database/Implementation/HotfixDatabase.cpp
+++ b/src/server/database/Database/Implementation/HotfixDatabase.cpp
@@ -566,6 +566,20 @@ void HotfixDatabaseConnection::DoPrepareStatements()
"Enemies4, Friend1, Friend2, Friend3, Friend4 FROM faction_template WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
PREPARE_MAX_ID_STMT(HOTFIX_SEL_FACTION_TEMPLATE, "SELECT MAX(ID) + 1 FROM faction_template", CONNECTION_SYNCH);
+ // FriendshipRepReaction.db2
+ PrepareStatement(HOTFIX_SEL_FRIENDSHIP_REP_REACTION, "SELECT ID, Reaction, FriendshipRepID, ReactionThreshold FROM friendship_rep_reaction"
+ " WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
+ PREPARE_MAX_ID_STMT(HOTFIX_SEL_FRIENDSHIP_REP_REACTION, "SELECT MAX(ID) + 1 FROM friendship_rep_reaction", CONNECTION_SYNCH);
+ PREPARE_LOCALE_STMT(HOTFIX_SEL_FRIENDSHIP_REP_REACTION, "SELECT ID, Reaction_lang FROM friendship_rep_reaction_locale"
+ " WHERE (`VerifiedBuild` > 0) = ? AND locale = ?", CONNECTION_SYNCH);
+
+ // FriendshipReputation.db2
+ PrepareStatement(HOTFIX_SEL_FRIENDSHIP_REPUTATION, "SELECT Description, StandingModified, StandingChanged, ID, FactionID, TextureFileID, Flags"
+ " FROM friendship_reputation WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
+ PREPARE_MAX_ID_STMT(HOTFIX_SEL_FRIENDSHIP_REPUTATION, "SELECT MAX(ID) + 1 FROM friendship_reputation", CONNECTION_SYNCH);
+ PREPARE_LOCALE_STMT(HOTFIX_SEL_FRIENDSHIP_REPUTATION, "SELECT ID, Description_lang, StandingModified_lang, StandingChanged_lang"
+ " FROM friendship_reputation_locale WHERE (`VerifiedBuild` > 0) = ? AND locale = ?", CONNECTION_SYNCH);
+
// GameobjectDisplayInfo.db2
PrepareStatement(HOTFIX_SEL_GAMEOBJECT_DISPLAY_INFO, "SELECT ID, GeoBoxMinX, GeoBoxMinY, GeoBoxMinZ, GeoBoxMaxX, GeoBoxMaxY, GeoBoxMaxZ, "
"FileDataID, ObjectEffectPackageID, OverrideLootEffectScale, OverrideNameScale FROM gameobject_display_info WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
diff --git a/src/server/database/Database/Implementation/HotfixDatabase.h b/src/server/database/Database/Implementation/HotfixDatabase.h
index 4acb89a35bf..8d88f734343 100644
--- a/src/server/database/Database/Implementation/HotfixDatabase.h
+++ b/src/server/database/Database/Implementation/HotfixDatabase.h
@@ -327,6 +327,14 @@ enum HotfixDatabaseStatements : uint32
HOTFIX_SEL_FACTION_TEMPLATE,
HOTFIX_SEL_FACTION_TEMPLATE_MAX_ID,
+ HOTFIX_SEL_FRIENDSHIP_REP_REACTION,
+ HOTFIX_SEL_FRIENDSHIP_REP_REACTION_MAX_ID,
+ HOTFIX_SEL_FRIENDSHIP_REP_REACTION_LOCALE,
+
+ HOTFIX_SEL_FRIENDSHIP_REPUTATION,
+ HOTFIX_SEL_FRIENDSHIP_REPUTATION_MAX_ID,
+ HOTFIX_SEL_FRIENDSHIP_REPUTATION_LOCALE,
+
HOTFIX_SEL_GAMEOBJECT_DISPLAY_INFO,
HOTFIX_SEL_GAMEOBJECT_DISPLAY_INFO_MAX_ID,
diff --git a/src/server/game/DataStores/DB2LoadInfo.h b/src/server/game/DataStores/DB2LoadInfo.h
index 9f55b36f2fe..516842ab861 100644
--- a/src/server/game/DataStores/DB2LoadInfo.h
+++ b/src/server/game/DataStores/DB2LoadInfo.h
@@ -1998,6 +1998,41 @@ struct FactionTemplateLoadInfo
}
};
+struct FriendshipRepReactionLoadInfo
+{
+ static DB2LoadInfo const* Instance()
+ {
+ static DB2FieldMeta const fields[] =
+ {
+ { false, FT_INT, "ID" },
+ { false, FT_STRING, "Reaction" },
+ { false, FT_INT, "FriendshipRepID" },
+ { false, FT_SHORT, "ReactionThreshold" },
+ };
+ static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, FriendshipRepReactionMeta::Instance(), HOTFIX_SEL_FRIENDSHIP_REP_REACTION);
+ return &loadInfo;
+ }
+};
+
+struct FriendshipReputationLoadInfo
+{
+ static DB2LoadInfo const* Instance()
+ {
+ static DB2FieldMeta const fields[] =
+ {
+ { false, FT_STRING, "Description" },
+ { false, FT_STRING, "StandingModified" },
+ { false, FT_STRING, "StandingChanged" },
+ { false, FT_INT, "ID" },
+ { true, FT_INT, "FactionID" },
+ { true, FT_INT, "TextureFileID" },
+ { true, FT_INT, "Flags" },
+ };
+ static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, FriendshipReputationMeta::Instance(), HOTFIX_SEL_FRIENDSHIP_REPUTATION);
+ return &loadInfo;
+ }
+};
+
struct GameobjectDisplayInfoLoadInfo
{
static DB2LoadInfo const* Instance()
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index 865afd679d4..bd8bba408b8 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -130,6 +130,8 @@ DB2Storage<ExpectedStatEntry> sExpectedStatStore("ExpectedStat
DB2Storage<ExpectedStatModEntry> sExpectedStatModStore("ExpectedStatMod.db2", ExpectedStatModLoadInfo::Instance());
DB2Storage<FactionEntry> sFactionStore("Faction.db2", FactionLoadInfo::Instance());
DB2Storage<FactionTemplateEntry> sFactionTemplateStore("FactionTemplate.db2", FactionTemplateLoadInfo::Instance());
+DB2Storage<FriendshipRepReactionEntry> sFriendshipRepReactionStore("FriendshipRepReaction.db2", FriendshipRepReactionLoadInfo::Instance());
+DB2Storage<FriendshipReputationEntry> sFriendshipReputationStore("FriendshipReputation.db2", FriendshipReputationLoadInfo::Instance());
DB2Storage<GameObjectDisplayInfoEntry> sGameObjectDisplayInfoStore("GameObjectDisplayInfo.db2", GameobjectDisplayInfoLoadInfo::Instance());
DB2Storage<GameObjectsEntry> sGameObjectsStore("GameObjects.db2", GameobjectsLoadInfo::Instance());
DB2Storage<GarrAbilityEntry> sGarrAbilityStore("GarrAbility.db2", GarrAbilityLoadInfo::Instance());
@@ -411,6 +413,7 @@ namespace
std::unordered_map<std::pair<uint32 /*level*/, int32 /*expansion*/>, ExpectedStatEntry const*> _expectedStatsByLevel;
std::unordered_map<uint32 /*contentTuningId*/, std::vector<ExpectedStatModEntry const*>> _expectedStatModsByContentTuning;
FactionTeamContainer _factionTeams;
+ std::unordered_map<uint32, std::set<FriendshipRepReactionEntry const*>> _friendshipRepReactions;
HeirloomItemsContainer _heirlooms;
GlyphBindableSpellsContainer _glyphBindableSpells;
GlyphRequiredSpecsContainer _glyphRequiredSpecs;
@@ -669,6 +672,8 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul
LOAD_DB2(sExpectedStatModStore);
LOAD_DB2(sFactionStore);
LOAD_DB2(sFactionTemplateStore);
+ LOAD_DB2(sFriendshipRepReactionStore);
+ LOAD_DB2(sFriendshipReputationStore);
LOAD_DB2(sGameObjectsStore);
LOAD_DB2(sGameObjectDisplayInfoStore);
LOAD_DB2(sGarrAbilityStore);
@@ -1077,6 +1082,9 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul
if (faction->ParentFactionID)
_factionTeams[faction->ParentFactionID].push_back(faction->ID);
+ for (FriendshipRepReactionEntry const* friendshipRepReaction : sFriendshipRepReactionStore)
+ _friendshipRepReactions[friendshipRepReaction->FriendshipRepID].insert(friendshipRepReaction);
+
for (GameObjectDisplayInfoEntry const* gameObjectDisplayInfo : sGameObjectDisplayInfoStore)
{
if (gameObjectDisplayInfo->GeoBoxMax.X < gameObjectDisplayInfo->GeoBoxMin.X)
@@ -2219,6 +2227,11 @@ std::vector<uint32> const* DB2Manager::GetFactionTeamList(uint32 faction) const
return Trinity::Containers::MapGetValuePtr(_factionTeams, faction);
}
+std::set<FriendshipRepReactionEntry const*> const* DB2Manager::GetFriendshipRepReactions(uint32 friendshipRepID) const
+{
+ return Trinity::Containers::MapGetValuePtr(_friendshipRepReactions, friendshipRepID);
+}
+
uint32 DB2Manager::GetGlobalCurveId(GlobalCurve globalCurveType) const
{
for (GlobalCurveEntry const* globalCurveEntry : sGlobalCurveStore)
@@ -3222,6 +3235,11 @@ bool ItemLevelSelectorQualityEntryComparator::Compare(ItemLevelSelectorQualityEn
return left->Quality < right->Quality;
}
+bool DB2Manager::FriendshipRepReactionEntryComparator::Compare(FriendshipRepReactionEntry const* left, FriendshipRepReactionEntry const* right)
+{
+ return left->ReactionThreshold < right->ReactionThreshold;
+}
+
bool DB2Manager::MountTypeXCapabilityEntryComparator::Compare(MountTypeXCapabilityEntry const* left, MountTypeXCapabilityEntry const* right)
{
if (left->MountTypeID == right->MountTypeID)
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index c39479ee847..640fe011a3d 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -100,6 +100,8 @@ TC_GAME_API extern DB2Storage<EmotesEntry> sEmotesStore
TC_GAME_API extern DB2Storage<EmotesTextEntry> sEmotesTextStore;
TC_GAME_API extern DB2Storage<FactionEntry> sFactionStore;
TC_GAME_API extern DB2Storage<FactionTemplateEntry> sFactionTemplateStore;
+TC_GAME_API extern DB2Storage<FriendshipRepReactionEntry> sFriendshipRepReactionStore;
+TC_GAME_API extern DB2Storage<FriendshipReputationEntry> sFriendshipReputationStore;
TC_GAME_API extern DB2Storage<GameObjectDisplayInfoEntry> sGameObjectDisplayInfoStore;
TC_GAME_API extern DB2Storage<GameObjectsEntry> sGameObjectsStore;
TC_GAME_API extern DB2Storage<GarrAbilityEntry> sGarrAbilityStore;
@@ -278,6 +280,7 @@ TC_GAME_API extern TaxiPathNodesByPath sTaxiPathNod
class TC_GAME_API DB2Manager
{
public:
+ DEFINE_DB2_SET_COMPARATOR(FriendshipRepReactionEntry)
DEFINE_DB2_SET_COMPARATOR(MountTypeXCapabilityEntry)
struct HotfixRecord
@@ -357,6 +360,7 @@ public:
EmotesTextSoundEntry const* GetTextSoundEmoteFor(uint32 emote, uint8 race, uint8 gender, uint8 class_) const;
float EvaluateExpectedStat(ExpectedStatType stat, uint32 level, int32 expansion, uint32 contentTuningId, Classes unitClass) const;
std::vector<uint32> const* GetFactionTeamList(uint32 faction) const;
+ std::set<FriendshipRepReactionEntry const*> const* GetFriendshipRepReactions(uint32 friendshipRepID) const;
uint32 GetGlobalCurveId(GlobalCurve globalCurveType) const;
std::vector<uint32> const* GetGlyphBindableSpells(uint32 glyphPropertiesId) const;
std::vector<uint32> const* GetGlyphRequiredSpecs(uint32 glyphPropertiesId) const;
diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h
index dcc563884b2..101a5db0656 100644
--- a/src/server/game/DataStores/DB2Structure.h
+++ b/src/server/game/DataStores/DB2Structure.h
@@ -1401,6 +1401,27 @@ struct FactionTemplateEntry
bool IsContestedGuardFaction() const { return (Flags & FACTION_TEMPLATE_FLAG_CONTESTED_GUARD) != 0; }
};
+struct FriendshipRepReactionEntry
+{
+ uint32 ID;
+ LocalizedString Reaction;
+ uint32 FriendshipRepID;
+ uint16 ReactionThreshold;
+};
+
+struct FriendshipReputationEntry
+{
+ LocalizedString Description;
+ LocalizedString StandingModified;
+ LocalizedString StandingChanged;
+ uint32 ID;
+ int32 FactionID;
+ int32 TextureFileID;
+ int32 Flags;
+
+ EnumFlag<FriendshipReputationFlags> GetFlags() const { return static_cast<FriendshipReputationFlags>(Flags); }
+};
+
struct GameObjectDisplayInfoEntry
{
uint32 ID;
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index eae6227809c..875576fe4c5 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -997,6 +997,17 @@ enum FactionMasks
// if none flags set then non-aggressive creature
};
+enum class FriendshipReputationFlags : int32
+{
+ NoFXOnReactionChange = 0x01,
+ NoLogTextOnRepGain = 0x02,
+ NoLogTextOnReactionChange = 0x04,
+ ShowRepGainandReactionChangeForHiddenFaction = 0x08,
+ NoRepGainModifiers = 0x10
+};
+
+DEFINE_ENUM_FLAG(FriendshipReputationFlags);
+
enum class GlobalCurve : int32
{
CritDiminishing = 0,
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 7db8a4f6172..b128fcfd70f 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -6271,6 +6271,12 @@ ReputationRank Player::GetReputationRank(uint32 faction) const
// Calculate total reputation percent player gain with quest/creature level
int32 Player::CalculateReputationGain(ReputationSource source, uint32 creatureOrQuestLevel, int32 rep, int32 faction, bool noQuestBonus)
{
+ bool noBonuses = false;
+ if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction))
+ if (FriendshipReputationEntry const* friendshipReputation = sFriendshipReputationStore.LookupEntry(factionEntry->FriendshipRepID))
+ if (friendshipReputation->GetFlags().HasFlag(FriendshipReputationFlags::NoRepGainModifiers))
+ noBonuses = true;
+
float percent = 100.0f;
float repMod = noQuestBonus ? 0.0f : float(GetTotalAuraModifier(SPELL_AURA_MOD_REPUTATION_GAIN));
diff --git a/src/server/game/Reputation/ReputationMgr.cpp b/src/server/game/Reputation/ReputationMgr.cpp
index ebad1e1b632..5e6baf43bf7 100644
--- a/src/server/game/Reputation/ReputationMgr.cpp
+++ b/src/server/game/Reputation/ReputationMgr.cpp
@@ -27,21 +27,53 @@
#include "World.h"
#include "WorldSession.h"
-const int32 ReputationMgr::PointsInRank[MAX_REPUTATION_RANK] = {36000, 3000, 3000, 3000, 6000, 12000, 21000, 1000};
-
-const int32 ReputationMgr::Reputation_Cap = 42999;
+std::set<int32> const ReputationMgr::ReputationRankThresholds =
+{
+ -42000,
+ // Hated
+ -6000,
+ // Hostile
+ -3000,
+ // Unfriendly
+ 0,
+ // Neutral
+ 3000,
+ // Friendly
+ 9000,
+ // Honored
+ 21000,
+ // Revered
+ 42000
+ // Exalted
+};
+
+const int32 ReputationMgr::Reputation_Cap = 42000;
const int32 ReputationMgr::Reputation_Bottom = -42000;
-ReputationRank ReputationMgr::ReputationToRank(int32 standing)
+template<typename T, typename F>
+static int32 ReputationToRankHelper(std::set<T> const& thresholds, int32 standing, F thresholdExtractor)
{
- int32 limit = Reputation_Cap + 1;
- for (int i = MAX_REPUTATION_RANK-1; i >= MIN_REPUTATION_RANK; --i)
+ auto itr = thresholds.begin();
+ auto end = thresholds.end();
+ int32 rank = -1;
+ while (itr != end && standing >= thresholdExtractor(*itr))
{
- limit -= PointsInRank[i];
- if (standing >= limit)
- return ReputationRank(i);
+ ++rank;
+ ++itr;
}
- return MIN_REPUTATION_RANK;
+
+ return rank;
+}
+
+ReputationRank ReputationMgr::ReputationToRank(FactionEntry const* factionEntry, int32 standing)
+{
+ int32 rank = MIN_REPUTATION_RANK;
+ if (std::set<FriendshipRepReactionEntry const*> const* friendshipReactions = sDB2Manager.GetFriendshipRepReactions(factionEntry->FriendshipRepID))
+ rank = ReputationToRankHelper(*friendshipReactions, standing, [](FriendshipRepReactionEntry const* frr) { return frr->ReactionThreshold; });
+ else
+ rank = ReputationToRankHelper(ReputationRankThresholds, standing, [](int32 threshold) { return threshold; });
+
+ return ReputationRank(rank);
}
FactionState const* ReputationMgr::GetState(FactionEntry const* factionEntry) const
@@ -87,24 +119,31 @@ int32 ReputationMgr::GetReputation(uint32 faction_id) const
int32 ReputationMgr::GetBaseReputation(FactionEntry const* factionEntry) const
{
- if (!factionEntry)
+ int32 dataIndex = GetFactionDataIndexForRaceAndClass(factionEntry);
+ if (dataIndex < 0)
return 0;
- uint8 race = _player->getRace();
- uint32 classMask = _player->getClassMask();
- for (int i=0; i < 4; i++)
- {
- if ((factionEntry->ReputationRaceMask[i].HasRace(race) ||
- (!factionEntry->ReputationRaceMask[i] &&
- factionEntry->ReputationClassMask[i] != 0)) &&
- (factionEntry->ReputationClassMask[i] & classMask ||
- factionEntry->ReputationClassMask[i] == 0))
+ return factionEntry->ReputationBase[dataIndex];
+}
- return factionEntry->ReputationBase[i];
- }
+int32 ReputationMgr::GetMinReputation(FactionEntry const* factionEntry) const
+{
+ if (std::set<FriendshipRepReactionEntry const*> const* friendshipReactions = sDB2Manager.GetFriendshipRepReactions(factionEntry->FriendshipRepID))
+ return (*friendshipReactions->begin())->ReactionThreshold;
- // in faction.dbc exist factions with (RepListId >=0, listed in character reputation list) with all BaseRepRaceMask[i] == 0
- return 0;
+ return *ReputationRankThresholds.begin();
+}
+
+int32 ReputationMgr::GetMaxReputation(FactionEntry const* factionEntry) const
+{
+ if (std::set<FriendshipRepReactionEntry const*> const* friendshipReactions = sDB2Manager.GetFriendshipRepReactions(factionEntry->FriendshipRepID))
+ return (*friendshipReactions->rbegin())->ReactionThreshold;
+
+ int32 dataIndex = GetFactionDataIndexForRaceAndClass(factionEntry);
+ if (dataIndex >= 0 && factionEntry->ReputationMax[dataIndex])
+ return factionEntry->ReputationMax[dataIndex];
+
+ return *ReputationRankThresholds.rbegin();
}
int32 ReputationMgr::GetReputation(FactionEntry const* factionEntry) const
@@ -122,13 +161,29 @@ int32 ReputationMgr::GetReputation(FactionEntry const* factionEntry) const
ReputationRank ReputationMgr::GetRank(FactionEntry const* factionEntry) const
{
int32 reputation = GetReputation(factionEntry);
- return ReputationToRank(reputation);
+ return ReputationToRank(factionEntry, reputation);
}
ReputationRank ReputationMgr::GetBaseRank(FactionEntry const* factionEntry) const
{
int32 reputation = GetBaseReputation(factionEntry);
- return ReputationToRank(reputation);
+ return ReputationToRank(factionEntry, reputation);
+}
+
+std::string ReputationMgr::GetReputationRankName(FactionEntry const* factionEntry) const
+{
+ ReputationRank rank = GetRank(factionEntry);
+ if (!factionEntry->FriendshipRepID)
+ return sObjectMgr->GetTrinityString(ReputationRankStrIndex[GetRank(factionEntry)], _player->GetSession()->GetSessionDbcLocale());
+
+ if (std::set<FriendshipRepReactionEntry const*> const* friendshipReactions = sDB2Manager.GetFriendshipRepReactions(factionEntry->FriendshipRepID))
+ {
+ auto itr = friendshipReactions->begin();
+ std::advance(itr, uint32(rank));
+ return (*itr)->Reaction[_player->GetSession()->GetSessionDbcLocale()];
+ }
+
+ return "";
}
ReputationRank const* ReputationMgr::GetForcedRankIfAny(FactionTemplateEntry const* factionTemplateEntry) const
@@ -146,22 +201,11 @@ void ReputationMgr::ApplyForceReaction(uint32 faction_id, ReputationRank rank, b
uint32 ReputationMgr::GetDefaultStateFlags(FactionEntry const* factionEntry) const
{
- if (!factionEntry)
+ int32 dataIndex = GetFactionDataIndexForRaceAndClass(factionEntry);
+ if (dataIndex < 0)
return 0;
- uint8 race = _player->getRace();
- uint32 classMask = _player->getClassMask();
- for (int i=0; i < 4; i++)
- {
- if ((factionEntry->ReputationRaceMask[i].HasRace(race) ||
- (!factionEntry->ReputationRaceMask[i] &&
- factionEntry->ReputationClassMask[i] != 0)) &&
- (factionEntry->ReputationClassMask[i] & classMask ||
- factionEntry->ReputationClassMask[i] == 0))
-
- return factionEntry->ReputationFlags[i];
- }
- return 0;
+ return factionEntry->ReputationFlags[dataIndex];
}
void ReputationMgr::SendForceReactions()
@@ -255,7 +299,8 @@ void ReputationMgr::Initialize()
if (newFaction.Flags & FACTION_FLAG_VISIBLE)
++_visibleFactionCount;
- UpdateRankCounters(REP_HOSTILE, GetBaseRank(factionEntry));
+ if (!factionEntry->FriendshipRepID)
+ UpdateRankCounters(REP_HOSTILE, GetBaseRank(factionEntry));
_factions[newFaction.ReputationListID] = newFaction;
}
@@ -353,13 +398,13 @@ bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, in
standing += itr->second.Standing + BaseRep;
}
- if (standing > Reputation_Cap)
- standing = Reputation_Cap;
- else if (standing < Reputation_Bottom)
- standing = Reputation_Bottom;
+ if (standing > GetMaxReputation(factionEntry))
+ standing = GetMaxReputation(factionEntry);
+ else if (standing < GetMinReputation(factionEntry))
+ standing = GetMinReputation(factionEntry);
- ReputationRank old_rank = ReputationToRank(itr->second.Standing + BaseRep);
- ReputationRank new_rank = ReputationToRank(standing);
+ ReputationRank old_rank = ReputationToRank(factionEntry, itr->second.Standing + BaseRep);
+ ReputationRank new_rank = ReputationToRank(factionEntry, standing);
int32 newStanding = standing - BaseRep;
@@ -377,7 +422,8 @@ bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, in
if (new_rank > old_rank)
_sendFactionIncreased = true;
- UpdateRankCounters(old_rank, new_rank);
+ if (!factionEntry->FriendshipRepID)
+ UpdateRankCounters(old_rank, new_rank);
_player->UpdateCriteria(CRITERIA_TYPE_KNOWN_FACTIONS, factionEntry->ID);
_player->UpdateCriteria(CRITERIA_TYPE_GAIN_REPUTATION, factionEntry->ID);
@@ -515,10 +561,13 @@ void ReputationMgr::LoadFromDB(PreparedQueryResult result)
faction->Standing = fields[1].GetInt32();
// update counters
- int32 BaseRep = GetBaseReputation(factionEntry);
- ReputationRank old_rank = ReputationToRank(BaseRep);
- ReputationRank new_rank = ReputationToRank(BaseRep + faction->Standing);
- UpdateRankCounters(old_rank, new_rank);
+ if (!factionEntry->FriendshipRepID)
+ {
+ int32 BaseRep = GetBaseReputation(factionEntry);
+ ReputationRank old_rank = ReputationToRank(factionEntry, BaseRep);
+ ReputationRank new_rank = ReputationToRank(factionEntry, BaseRep + faction->Standing);
+ UpdateRankCounters(old_rank, new_rank);
+ }
uint32 dbFactionFlags = fields[2].GetUInt16();
@@ -592,3 +641,21 @@ void ReputationMgr::UpdateRankCounters(ReputationRank old_rank, ReputationRank n
if (new_rank >= REP_HONORED)
++_honoredFactionCount;
}
+
+int32 ReputationMgr::GetFactionDataIndexForRaceAndClass(FactionEntry const* factionEntry) const
+{
+ if (!factionEntry)
+ return -1;
+
+ uint8 race = _player->getRace();
+ uint32 classMask = _player->getClassMask();
+ for (int32 i = 0; i < 4; i++)
+ {
+ if ((factionEntry->ReputationRaceMask[i].HasRace(race) || (!factionEntry->ReputationRaceMask[i] && factionEntry->ReputationClassMask[i] != 0))
+ && (factionEntry->ReputationClassMask[i] & classMask || factionEntry->ReputationClassMask[i] == 0))
+
+ return i;
+ }
+
+ return -1;
+}
diff --git a/src/server/game/Reputation/ReputationMgr.h b/src/server/game/Reputation/ReputationMgr.h
index 92eb851f539..68ca9af0054 100644
--- a/src/server/game/Reputation/ReputationMgr.h
+++ b/src/server/game/Reputation/ReputationMgr.h
@@ -72,11 +72,11 @@ class TC_GAME_API ReputationMgr
void SaveToDB(CharacterDatabaseTransaction& trans);
void LoadFromDB(PreparedQueryResult result);
public: // statics
- static const int32 PointsInRank[MAX_REPUTATION_RANK];
+ static std::set<int32> const ReputationRankThresholds;
static const int32 Reputation_Cap;
static const int32 Reputation_Bottom;
- static ReputationRank ReputationToRank(int32 standing);
+ static ReputationRank ReputationToRank(FactionEntry const* factionEntry, int32 standing);
public: // accessors
uint8 GetVisibleFactionCount() const { return _visibleFactionCount; }
uint8 GetHonoredFactionCount() const { return _honoredFactionCount; }
@@ -99,13 +99,12 @@ class TC_GAME_API ReputationMgr
int32 GetReputation(uint32 faction_id) const;
int32 GetReputation(FactionEntry const* factionEntry) const;
int32 GetBaseReputation(FactionEntry const* factionEntry) const;
+ int32 GetMinReputation(FactionEntry const* factionEntry) const;
+ int32 GetMaxReputation(FactionEntry const* factionEntry) const;
ReputationRank GetRank(FactionEntry const* factionEntry) const;
ReputationRank GetBaseRank(FactionEntry const* factionEntry) const;
- uint32 GetReputationRankStrIndex(FactionEntry const* factionEntry) const
- {
- return ReputationRankStrIndex[GetRank(factionEntry)];
- };
+ std::string GetReputationRankName(FactionEntry const* factionEntry) const;;
ReputationRank const* GetForcedRankIfAny(FactionTemplateEntry const* factionTemplateEntry) const;
@@ -149,6 +148,8 @@ class TC_GAME_API ReputationMgr
void SetInactive(FactionState* faction, bool inactive) const;
void SendVisible(FactionState const* faction, bool visible = true) const;
void UpdateRankCounters(ReputationRank old_rank, ReputationRank new_rank);
+ int32 GetFactionDataIndexForRaceAndClass(FactionEntry const* factionEntry) const;
+
private:
Player* _player;
FactionStateList _factions;
diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp
index 833eec17be0..480ea9aae00 100644
--- a/src/server/scripts/Commands/cs_character.cpp
+++ b/src/server/scripts/Commands/cs_character.cpp
@@ -648,8 +648,7 @@ public:
FactionState const& faction = itr->second;
FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction.ID);
char const* factionName = factionEntry ? factionEntry->Name[loc] : "#Not found#";
- ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry);
- std::string rankName = handler->GetTrinityString(ReputationRankStrIndex[rank]);
+ std::string rankName = target->GetReputationMgr().GetReputationRankName(factionEntry);
std::ostringstream ss;
if (handler->GetSession())
ss << faction.ID << " - |cffffffff|Hfaction:" << faction.ID << "|h[" << factionName << ' ' << localeNames[loc] << "]|h|r";
diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp
index 8b45a06e9cc..8b74175c628 100644
--- a/src/server/scripts/Commands/cs_lookup.cpp
+++ b/src/server/scripts/Commands/cs_lookup.cpp
@@ -360,8 +360,7 @@ public:
if (factionState) // and then target != NULL also
{
- uint32 index = target->GetReputationMgr().GetReputationRankStrIndex(factionEntry);
- std::string rankName = handler->GetTrinityString(index);
+ std::string rankName = target->GetReputationMgr().GetReputationRankName(factionEntry);
ss << ' ' << rankName << "|h|r (" << target->GetReputationMgr().GetReputation(factionEntry) << ')';
diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp
index b7b8a33fa31..a0eaa8aea32 100644
--- a/src/server/scripts/Commands/cs_modify.cpp
+++ b/src/server/scripts/Commands/cs_modify.cpp
@@ -684,18 +684,39 @@ public:
if (!factionId || !rankTxt)
return false;
+ FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionId);
+
+ if (!factionEntry)
+ {
+ handler->PSendSysMessage(LANG_COMMAND_FACTION_UNKNOWN, factionId);
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
+
+ if (factionEntry->ReputationIndex < 0)
+ {
+ handler->PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->Name[handler->GetSessionDbcLocale()], factionId);
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
+
amount = atoi(rankTxt);
+ // try to find rank by name
if ((amount == 0) && (rankTxt[0] != '-') && !isdigit(rankTxt[0]))
{
std::string rankStr = rankTxt;
std::wstring wrankStr;
if (!Utf8toWStr(rankStr, wrankStr))
return false;
+
wstrToLower(wrankStr);
- int r = 0;
- amount = -42000;
- for (; r < MAX_REPUTATION_RANK; ++r)
+ auto rankThresholdItr = ReputationMgr::ReputationRankThresholds.begin();
+ auto end = ReputationMgr::ReputationRankThresholds.end();
+
+ int32 r = 0;
+
+ for (; rankThresholdItr != end; ++rankThresholdItr, ++r)
{
std::string rank = handler->GetTrinityString(ReputationRankStrIndex[r]);
if (rank.empty())
@@ -708,45 +729,36 @@ public:
wstrToLower(wrank);
if (wrank.substr(0, wrankStr.size()) == wrankStr)
- {
- char *deltaTxt = strtok(nullptr, " ");
- if (deltaTxt)
- {
- int32 delta = atoi(deltaTxt);
- if ((delta < 0) || (delta > ReputationMgr::PointsInRank[r] -1))
- {
- handler->PSendSysMessage(LANG_COMMAND_FACTION_DELTA, (ReputationMgr::PointsInRank[r]-1));
- handler->SetSentErrorMessage(true);
- return false;
- }
- amount += delta;
- }
break;
- }
- amount += ReputationMgr::PointsInRank[r];
}
- if (r >= MAX_REPUTATION_RANK)
+
+ if (rankThresholdItr == end)
{
handler->PSendSysMessage(LANG_COMMAND_FACTION_INVPARAM, rankTxt);
handler->SetSentErrorMessage(true);
return false;
}
- }
- FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionId);
-
- if (!factionEntry)
- {
- handler->PSendSysMessage(LANG_COMMAND_FACTION_UNKNOWN, factionId);
- handler->SetSentErrorMessage(true);
- return false;
- }
+ amount = *rankThresholdItr;
- if (factionEntry->ReputationIndex < 0)
- {
- handler->PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->Name[handler->GetSessionDbcLocale()], factionId);
- handler->SetSentErrorMessage(true);
- return false;
+ char *deltaTxt = strtok(nullptr, " ");
+ if (deltaTxt)
+ {
+ int32 toNextRank = 0;
+ auto nextThresholdItr = rankThresholdItr;
+ ++nextThresholdItr;
+ if (nextThresholdItr != end)
+ toNextRank = *nextThresholdItr - *rankThresholdItr;
+
+ int32 delta = atoi(deltaTxt);
+ if (delta < 0 || delta >= toNextRank)
+ {
+ handler->PSendSysMessage(LANG_COMMAND_FACTION_DELTA, std::max(0, toNextRank - 1));
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
+ amount += delta;
+ }
}
target->GetReputationMgr().SetOneFactionReputation(factionEntry, amount, false);