Core/Reputation: Implemented "friendship reputation"

This commit is contained in:
Shauren
2021-06-04 19:27:26 +02:00
parent ad683a356a
commit 80a6347b7a
14 changed files with 393 additions and 110 deletions

View File

@@ -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 */;

View File

@@ -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);

View File

@@ -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,

View File

@@ -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()

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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));

View File

@@ -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};
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 = 42999;
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;
}

View File

@@ -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;

View File

@@ -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";

View File

@@ -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) << ')';

View File

@@ -684,55 +684,6 @@ public:
if (!factionId || !rankTxt)
return false;
amount = atoi(rankTxt);
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)
{
std::string rank = handler->GetTrinityString(ReputationRankStrIndex[r]);
if (rank.empty())
continue;
std::wstring wrank;
if (!Utf8toWStr(rank, wrank))
continue;
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)
{
handler->PSendSysMessage(LANG_COMMAND_FACTION_INVPARAM, rankTxt);
handler->SetSentErrorMessage(true);
return false;
}
}
FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionId);
if (!factionEntry)
@@ -749,6 +700,67 @@ public:
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);
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())
continue;
std::wstring wrank;
if (!Utf8toWStr(rank, wrank))
continue;
wstrToLower(wrank);
if (wrank.substr(0, wrankStr.size()) == wrankStr)
break;
}
if (rankThresholdItr == end)
{
handler->PSendSysMessage(LANG_COMMAND_FACTION_INVPARAM, rankTxt);
handler->SetSentErrorMessage(true);
return false;
}
amount = *rankThresholdItr;
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);
target->GetReputationMgr().SendState(target->GetReputationMgr().GetState(factionEntry));
handler->PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->Name[handler->GetSessionDbcLocale()], factionId,