fix(Core/Quests): implement QUEST_SPECIAL_FLAGS_NO_REP_SPILLOVER (#9661)

Fixes #9552
This commit is contained in:
UltraNix
2021-12-17 18:06:15 +01:00
committed by GitHub
parent ef8faa0904
commit 0dd59e66d3
5 changed files with 66 additions and 56 deletions

View File

@@ -5848,7 +5848,7 @@ void Player::RewardReputation(Quest const* quest)
}
if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(quest->RewardFactionId[i]))
GetReputationMgr().ModifyReputation(factionEntry, rep);
GetReputationMgr().ModifyReputation(factionEntry, rep, false, quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_NO_REP_SPILLOVER));
}
}

View File

@@ -155,23 +155,25 @@ enum QuestFlags
enum QuestSpecialFlags
{
QUEST_SPECIAL_FLAGS_NONE = 0x000,
QUEST_SPECIAL_FLAGS_NONE = 0x000,
// Trinity flags for set SpecialFlags in DB if required but used only at server
QUEST_SPECIAL_FLAGS_REPEATABLE = 0x001, // Set by 1 in SpecialFlags from DB
QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT = 0x002, // Set by 2 in SpecialFlags from DB (if required area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `FECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script)
QUEST_SPECIAL_FLAGS_AUTO_ACCEPT = 0x004, // Set by 4 in SpecialFlags in DB if the quest is to be auto-accepted.
QUEST_SPECIAL_FLAGS_DF_QUEST = 0x008, // Set by 8 in SpecialFlags in DB if the quest is used by Dungeon Finder.
QUEST_SPECIAL_FLAGS_MONTHLY = 0x010, // Set by 16 in SpecialFlags in DB if the quest is reset at the begining of the month
QUEST_SPECIAL_FLAGS_CAST = 0x020, // Set by 32 in SpecialFlags in DB if the quest requires RequiredOrNpcGo killcredit but NOT kill (a spell cast)
QUEST_SPECIAL_FLAGS_REPEATABLE = 0x001, // Set by 1 in SpecialFlags from DB
QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT = 0x002, // Set by 2 in SpecialFlags from DB (if required area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `FECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script)
QUEST_SPECIAL_FLAGS_AUTO_ACCEPT = 0x004, // Set by 4 in SpecialFlags in DB if the quest is to be auto-accepted.
QUEST_SPECIAL_FLAGS_DF_QUEST = 0x008, // Set by 8 in SpecialFlags in DB if the quest is used by Dungeon Finder.
QUEST_SPECIAL_FLAGS_MONTHLY = 0x010, // Set by 16 in SpecialFlags in DB if the quest is reset at the begining of the month
QUEST_SPECIAL_FLAGS_CAST = 0x020, // Set by 32 in SpecialFlags in DB if the quest requires RequiredOrNpcGo killcredit but NOT kill (a spell cast)
QUEST_SPECIAL_FLAGS_NO_REP_SPILLOVER = 0x040, // Set by 64 in SpecialFlags in DB if the quest does not share rewarded reputation with other allied factions
// room for more custom flags
QUEST_SPECIAL_FLAGS_DB_ALLOWED = QUEST_SPECIAL_FLAGS_REPEATABLE | QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT | QUEST_SPECIAL_FLAGS_AUTO_ACCEPT | QUEST_SPECIAL_FLAGS_DF_QUEST | QUEST_SPECIAL_FLAGS_MONTHLY | QUEST_SPECIAL_FLAGS_CAST,
QUEST_SPECIAL_FLAGS_DB_ALLOWED = QUEST_SPECIAL_FLAGS_REPEATABLE | QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT | QUEST_SPECIAL_FLAGS_AUTO_ACCEPT |
QUEST_SPECIAL_FLAGS_DF_QUEST | QUEST_SPECIAL_FLAGS_MONTHLY | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_NO_REP_SPILLOVER,
QUEST_SPECIAL_FLAGS_DELIVER = 0x080, // Internal flag computed only
QUEST_SPECIAL_FLAGS_SPEAKTO = 0x100, // Internal flag computed only
QUEST_SPECIAL_FLAGS_KILL = 0x200, // Internal flag computed only
QUEST_SPECIAL_FLAGS_TIMED = 0x400, // Internal flag computed only
QUEST_SPECIAL_FLAGS_PLAYER_KILL = 0x800 // Internal flag computed only
QUEST_SPECIAL_FLAGS_DELIVER = 0x080, // Internal flag computed only
QUEST_SPECIAL_FLAGS_SPEAKTO = 0x100, // Internal flag computed only
QUEST_SPECIAL_FLAGS_KILL = 0x200, // Internal flag computed only
QUEST_SPECIAL_FLAGS_TIMED = 0x400, // Internal flag computed only
QUEST_SPECIAL_FLAGS_PLAYER_KILL = 0x800 // Internal flag computed only
};
struct QuestLocale

View File

@@ -282,60 +282,64 @@ void ReputationMgr::Initialize()
}
}
bool ReputationMgr::SetReputation(FactionEntry const* factionEntry, int32 standing, bool incremental, bool spillOverOnly)
bool ReputationMgr::SetReputation(FactionEntry const* factionEntry, int32 standing, bool incremental, bool spillOverOnly, bool noSpillOver)
{
bool res = false;
// if spillover definition exists in DB, override DBC
if (const RepSpilloverTemplate* repTemplate = sObjectMgr->GetRepSpilloverTemplate(factionEntry->ID))
if (!noSpillOver)
{
for (uint32 i = 0; i < MAX_SPILLOVER_FACTIONS; ++i)
// if spillover definition exists in DB, override DBC
if (const RepSpilloverTemplate* repTemplate = sObjectMgr->GetRepSpilloverTemplate(factionEntry->ID))
{
if (repTemplate->faction[i])
for (uint32 i = 0; i < MAX_SPILLOVER_FACTIONS; ++i)
{
if (_player->GetReputationRank(repTemplate->faction[i]) <= ReputationRank(repTemplate->faction_rank[i]))
if (repTemplate->faction[i])
{
// bonuses are already given, so just modify standing by rate
int32 spilloverRep = int32(standing * repTemplate->faction_rate[i]);
SetOneFactionReputation(sFactionStore.LookupEntry(repTemplate->faction[i]), spilloverRep, incremental);
if (_player->GetReputationRank(repTemplate->faction[i]) <= ReputationRank(repTemplate->faction_rank[i]))
{
// bonuses are already given, so just modify standing by rate
int32 spilloverRep = int32(standing * repTemplate->faction_rate[i]);
SetOneFactionReputation(sFactionStore.LookupEntry(repTemplate->faction[i]), spilloverRep, incremental);
}
}
}
}
}
else
{
float spillOverRepOut = float(standing);
// check for sub-factions that receive spillover
SimpleFactionsList const* flist = GetFactionTeamList(factionEntry->ID);
// if has no sub-factions, check for factions with same parent
if (!flist && factionEntry->team && factionEntry->spilloverRateOut != 0.0f)
else
{
spillOverRepOut *= factionEntry->spilloverRateOut;
if (FactionEntry const* parent = sFactionStore.LookupEntry(factionEntry->team))
float spillOverRepOut = float(standing);
// check for sub-factions that receive spillover
SimpleFactionsList const* flist = GetFactionTeamList(factionEntry->ID);
// if has no sub-factions, check for factions with same parent
if (!flist && factionEntry->team && factionEntry->spilloverRateOut != 0.0f)
{
FactionStateList::iterator parentState = _factions.find(parent->reputationListID);
// some team factions have own reputation standing, in this case do not spill to other sub-factions
if (parentState != _factions.end() && (parentState->second.Flags & FACTION_FLAG_SPECIAL))
spillOverRepOut *= factionEntry->spilloverRateOut;
if (FactionEntry const* parent = sFactionStore.LookupEntry(factionEntry->team))
{
SetOneFactionReputation(parent, int32(spillOverRepOut), incremental);
}
else // spill to "sister" factions
{
flist = GetFactionTeamList(factionEntry->team);
FactionStateList::iterator parentState = _factions.find(parent->reputationListID);
// some team factions have own reputation standing, in this case do not spill to other sub-factions
if (parentState != _factions.end() && (parentState->second.Flags & FACTION_FLAG_SPECIAL))
{
SetOneFactionReputation(parent, int32(spillOverRepOut), incremental);
}
else // spill to "sister" factions
{
flist = GetFactionTeamList(factionEntry->team);
}
}
}
}
if (flist)
{
// Spillover to affiliated factions
for (SimpleFactionsList::const_iterator itr = flist->begin(); itr != flist->end(); ++itr)
if (flist)
{
if (FactionEntry const* factionEntryCalc = sFactionStore.LookupEntry(*itr))
// Spillover to affiliated factions
for (SimpleFactionsList::const_iterator itr = flist->begin(); itr != flist->end(); ++itr)
{
if (factionEntryCalc == factionEntry || GetRank(factionEntryCalc) > ReputationRank(factionEntryCalc->spilloverMaxRankIn))
continue;
int32 spilloverRep = int32(spillOverRepOut * factionEntryCalc->spilloverRateIn);
if (spilloverRep != 0 || !incremental)
res = SetOneFactionReputation(factionEntryCalc, spilloverRep, incremental);
if (FactionEntry const* factionEntryCalc = sFactionStore.LookupEntry(*itr))
{
if (factionEntryCalc == factionEntry || GetRank(factionEntryCalc) > ReputationRank(factionEntryCalc->spilloverMaxRankIn))
continue;
int32 spilloverRep = int32(spillOverRepOut * factionEntryCalc->spilloverRateIn);
if (spilloverRep != 0 || !incremental)
res = SetOneFactionReputation(factionEntryCalc, spilloverRep, incremental);
}
}
}
}

View File

@@ -110,11 +110,11 @@ public: // accessors
public: // modifiers
bool SetReputation(FactionEntry const* factionEntry, int32 standing)
{
return SetReputation(factionEntry, standing, false, false);
return SetReputation(factionEntry, standing, false, false, false);
}
bool ModifyReputation(FactionEntry const* factionEntry, int32 standing, bool spillOverOnly = false)
bool ModifyReputation(FactionEntry const* factionEntry, int32 standing, bool spillOverOnly = false, bool noSpillOver = false)
{
return SetReputation(factionEntry, standing, true, spillOverOnly);
return SetReputation(factionEntry, standing, true, spillOverOnly, noSpillOver);
}
void SetVisible(FactionTemplateEntry const* factionTemplateEntry);
@@ -136,7 +136,7 @@ public: // senders
private: // internal helper functions
void Initialize();
uint32 GetDefaultStateFlags(FactionEntry const* factionEntry) const;
bool SetReputation(FactionEntry const* factionEntry, int32 standing, bool incremental, bool spillOverOnly);
bool SetReputation(FactionEntry const* factionEntry, int32 standing, bool incremental, bool spillOverOnly, bool noSpillOver = false);
void SetVisible(FactionState* faction);
void SetAtWar(FactionState* faction, bool atWar) const;
void SetInactive(FactionState* faction, bool inactive) const;