Core/Reputation: Implement a more generic solution for reputation spillover (fix by Lynx3d, port by Kaelima)
* Sorts out issues with factions 1037 and 1052 * Give a more correct client output when reputation is assigned to parent faction * reputation_spillover_template can still be used to override spillover from dbc Closes issue 4915. --HG-- branch : trunk
This commit is contained in:
@@ -822,10 +822,10 @@ struct FactionEntry
|
|||||||
int32 BaseRepValue[4]; // 10-13 m_reputationBase
|
int32 BaseRepValue[4]; // 10-13 m_reputationBase
|
||||||
uint32 ReputationFlags[4]; // 14-17 m_reputationFlags
|
uint32 ReputationFlags[4]; // 14-17 m_reputationFlags
|
||||||
uint32 team; // 18 m_parentFactionID
|
uint32 team; // 18 m_parentFactionID
|
||||||
//float unk1; // 19
|
float spilloverRateIn; // 19 Faction gains incoming rep * spilloverRateIn
|
||||||
//float unk2; // 20
|
float spilloverRateOut; // 20 Faction outputs rep * spilloverRateOut as spillover reputation
|
||||||
//uint32 unk3 // 21
|
uint32 spilloverMaxRankIn; // 21 The highest rank the faction will profit from incoming spillover
|
||||||
//uint32 unk4; // 22
|
//uint32 spilloverRank_unk; // 22 It does not seem to be the max standing at which a faction outputs spillover ...so no idea
|
||||||
char* name[16]; // 23-38 m_name_lang
|
char* name[16]; // 23-38 m_name_lang
|
||||||
// 39 string flags
|
// 39 string flags
|
||||||
//char* description[16]; // 40-55 m_description_lang
|
//char* description[16]; // 40-55 m_description_lang
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ const char DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii";
|
|||||||
const char DurabilityQualityfmt[]="nf";
|
const char DurabilityQualityfmt[]="nf";
|
||||||
const char EmotesEntryfmt[]="nxxiiix";
|
const char EmotesEntryfmt[]="nxxiiix";
|
||||||
const char EmotesTextEntryfmt[]="nxixxxxxxxxxxxxxxxx";
|
const char EmotesTextEntryfmt[]="nxixxxxxxxxxxxxxxxx";
|
||||||
const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiixxxxssssssssssssssssxxxxxxxxxxxxxxxxxx";
|
const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiiffixssssssssssssssssxxxxxxxxxxxxxxxxxx";
|
||||||
const char FactionTemplateEntryfmt[]="niiiiiiiiiiiii";
|
const char FactionTemplateEntryfmt[]="niiiiiiiiiiiii";
|
||||||
const char GameObjectDisplayInfofmt[]="nxxxxxxxxxxxffffffx";
|
const char GameObjectDisplayInfofmt[]="nxxxxxxxxxxxffffffx";
|
||||||
const char GemPropertiesEntryfmt[]="nixxi";
|
const char GemPropertiesEntryfmt[]="nixxi";
|
||||||
|
|||||||
@@ -7156,7 +7156,7 @@ void ObjectMgr::LoadReputationSpilloverTemplate()
|
|||||||
bar.step();
|
bar.step();
|
||||||
|
|
||||||
sLog.outString();
|
sLog.outString();
|
||||||
sLog.outErrorDb(">> Loaded `reputation_spillover_template`, table is empty!");
|
sLog.outString(">> Loaded `reputation_spillover_template`, table is empty.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -139,35 +139,36 @@ void ReputationMgr::SendForceReactions()
|
|||||||
m_player->SendDirectMessage(&data);
|
m_player->SendDirectMessage(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReputationMgr::SendState(FactionState const* faction) const
|
void ReputationMgr::SendState(FactionState const* faction)
|
||||||
{
|
{
|
||||||
if (faction->Flags & FACTION_FLAG_VISIBLE) //If faction is visible then update it
|
uint32 count = 1;
|
||||||
|
|
||||||
|
WorldPacket data(SMSG_SET_FACTION_STANDING, (16)); // last check 2.4.0
|
||||||
|
data << (float) 0; // unk 2.4.0
|
||||||
|
data << (uint8) 0; // wotlk 8634
|
||||||
|
|
||||||
|
size_t p_count = data.wpos();
|
||||||
|
data << (uint32) count; // placeholder
|
||||||
|
|
||||||
|
data << (uint32) faction->ReputationListID;
|
||||||
|
data << (uint32) faction->Standing;
|
||||||
|
|
||||||
|
for (FactionStateList::iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr)
|
||||||
{
|
{
|
||||||
uint32 count = 1;
|
if (itr->second.needSend)
|
||||||
|
|
||||||
WorldPacket data(SMSG_SET_FACTION_STANDING, (16)); // last check 2.4.0
|
|
||||||
data << (float) 0; // unk 2.4.0
|
|
||||||
data << (uint8) 0; // wotlk 8634
|
|
||||||
|
|
||||||
size_t p_count = data.wpos();
|
|
||||||
data << (uint32) count; // placeholder
|
|
||||||
|
|
||||||
data << (uint32) faction->ReputationListID;
|
|
||||||
data << (uint32) faction->Standing;
|
|
||||||
|
|
||||||
for(FactionStateList::const_iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr)
|
|
||||||
{
|
{
|
||||||
if (itr->second.Changed && itr->second.ReputationListID != faction->ReputationListID)
|
itr->second.needSend = false;
|
||||||
|
if (itr->second.ReputationListID != faction->ReputationListID)
|
||||||
{
|
{
|
||||||
data << (uint32) itr->second.ReputationListID;
|
data << (uint32) itr->second.ReputationListID;
|
||||||
data << (uint32) itr->second.Standing;
|
data << (uint32) itr->second.Standing;
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data.put<uint32>(p_count, count);
|
|
||||||
m_player->SendDirectMessage(&data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.put<uint32>(p_count, count);
|
||||||
|
m_player->SendDirectMessage(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReputationMgr::SendInitialReputations()
|
void ReputationMgr::SendInitialReputations()
|
||||||
@@ -203,9 +204,9 @@ void ReputationMgr::SendInitialReputations()
|
|||||||
m_player->SendDirectMessage(&data);
|
m_player->SendDirectMessage(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReputationMgr::SendStates() const
|
void ReputationMgr::SendStates()
|
||||||
{
|
{
|
||||||
for (FactionStateList::const_iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr)
|
for (FactionStateList::iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr)
|
||||||
SendState(&(itr->second));
|
SendState(&(itr->second));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,7 +240,8 @@ void ReputationMgr::Initialize()
|
|||||||
newFaction.ReputationListID = factionEntry->reputationListID;
|
newFaction.ReputationListID = factionEntry->reputationListID;
|
||||||
newFaction.Standing = 0;
|
newFaction.Standing = 0;
|
||||||
newFaction.Flags = GetDefaultStateFlags(factionEntry);
|
newFaction.Flags = GetDefaultStateFlags(factionEntry);
|
||||||
newFaction.Changed = true;
|
newFaction.needSend = true;
|
||||||
|
newFaction.needSave = true;
|
||||||
|
|
||||||
if (newFaction.Flags & FACTION_FLAG_VISIBLE)
|
if (newFaction.Flags & FACTION_FLAG_VISIBLE)
|
||||||
++m_visibleFactionCount;
|
++m_visibleFactionCount;
|
||||||
@@ -254,58 +256,71 @@ void ReputationMgr::Initialize()
|
|||||||
bool ReputationMgr::SetReputation(FactionEntry const* factionEntry, int32 standing, bool incremental)
|
bool ReputationMgr::SetReputation(FactionEntry const* factionEntry, int32 standing, bool incremental)
|
||||||
{
|
{
|
||||||
sScriptMgr.OnPlayerReputationChange(m_player, factionEntry->ID, standing, incremental);
|
sScriptMgr.OnPlayerReputationChange(m_player, factionEntry->ID, standing, incremental);
|
||||||
|
bool res = false;
|
||||||
if (SimpleFactionsList const* flist = GetFactionTeamList(factionEntry->ID))
|
// if spillover definition exists in DB, override DBC
|
||||||
|
if (const RepSpilloverTemplate *repTemplate = sObjectMgr.GetRepSpilloverTemplate(factionEntry->ID))
|
||||||
{
|
{
|
||||||
bool res = false;
|
for (uint32 i = 0; i < MAX_SPILLOVER_FACTIONS; ++i)
|
||||||
for (SimpleFactionsList::const_iterator itr = flist->begin();itr != flist->end();++itr)
|
|
||||||
{
|
{
|
||||||
if (FactionEntry const *factionEntryCalc = sFactionStore.LookupEntry(*itr))
|
if (repTemplate->faction[i])
|
||||||
{
|
{
|
||||||
res = SetOneFactionReputation(factionEntryCalc, standing, incremental);
|
if (m_player->GetReputationRank(repTemplate->faction[i]) <= ReputationRank(repTemplate->faction_rank[i]))
|
||||||
|
|
||||||
if (res)
|
|
||||||
{
|
{
|
||||||
FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID);
|
// bonuses are already given, so just modify standing by rate
|
||||||
if (itr != m_factions.end())
|
int32 spilloverRep = standing * repTemplate->faction_rate[i];
|
||||||
SendState(&itr->second);
|
SetOneFactionReputation(sFactionStore.LookupEntry(repTemplate->faction[i]), spilloverRep, incremental);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// update for the actual faction first
|
float spillOverRepOut = standing;
|
||||||
bool res = SetOneFactionReputation(factionEntry, standing, incremental);
|
// check for sub-factions that receive spillover
|
||||||
|
SimpleFactionsList const* flist = GetFactionTeamList(factionEntry->ID);
|
||||||
if (res)
|
// if has no sub-factions, check for factions with same parent
|
||||||
|
if (!flist && factionEntry->team && factionEntry->spilloverRateOut != 0.0f)
|
||||||
{
|
{
|
||||||
// then some spillover calculation here if it exist
|
spillOverRepOut *= factionEntry->spilloverRateOut;
|
||||||
if (RepSpilloverTemplate const * repTemplate = sObjectMgr.GetRepSpilloverTemplate(factionEntry->ID))
|
if (FactionEntry const *parent = sFactionStore.LookupEntry(factionEntry->team))
|
||||||
{
|
{
|
||||||
for (uint32 i = 0; i < MAX_SPILLOVER_FACTIONS; ++i)
|
FactionStateList::iterator parentState = m_factions.find(parent->reputationListID);
|
||||||
|
// some team factions have own reputation standing, in this case do not spill to other sub-factions
|
||||||
|
if (parentState != m_factions.end() && (parentState->second.Flags & FACTION_FLAG_SPECIAL))
|
||||||
{
|
{
|
||||||
if (repTemplate->faction[i])
|
SetOneFactionReputation(parent, int32(spillOverRepOut), incremental);
|
||||||
{
|
}
|
||||||
if (m_player->GetReputationRank(repTemplate->faction[i]) <= ReputationRank(repTemplate->faction_rank[i]))
|
else // spill to "sister" factions
|
||||||
{
|
{
|
||||||
// bonuses are already given, so just modify standing by rate
|
flist = GetFactionTeamList(factionEntry->team);
|
||||||
int32 spilloverRep = int32(standing * repTemplate->faction_rate[i]);
|
}
|
||||||
SetOneFactionReputation(sFactionStore.LookupEntry(repTemplate->faction[i]), spilloverRep, incremental);
|
}
|
||||||
}
|
}
|
||||||
}
|
if (flist)
|
||||||
|
{
|
||||||
|
// Spillover to affiliated factions
|
||||||
|
for (SimpleFactionsList::const_iterator itr = flist->begin(); itr != flist->end(); ++itr)
|
||||||
|
{
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// now we can send it
|
|
||||||
FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID);
|
|
||||||
if (itr != m_factions.end())
|
|
||||||
SendState(&itr->second);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
// spillover done, update faction itself
|
||||||
|
FactionStateList::iterator faction = m_factions.find(factionEntry->reputationListID);
|
||||||
|
if (faction != m_factions.end())
|
||||||
|
{
|
||||||
|
res = SetOneFactionReputation(factionEntry, standing, incremental);
|
||||||
|
// only this faction gets reported to client, even if it has no own visible standing
|
||||||
|
SendState(&faction->second);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing, bool incremental)
|
bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing, bool incremental)
|
||||||
@@ -331,7 +346,8 @@ bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, in
|
|||||||
ReputationRank new_rank = ReputationToRank(standing);
|
ReputationRank new_rank = ReputationToRank(standing);
|
||||||
|
|
||||||
itr->second.Standing = standing - BaseRep;
|
itr->second.Standing = standing - BaseRep;
|
||||||
itr->second.Changed = true;
|
itr->second.needSend = true;
|
||||||
|
itr->second.needSave = true;
|
||||||
|
|
||||||
SetVisible(&itr->second);
|
SetVisible(&itr->second);
|
||||||
|
|
||||||
@@ -387,7 +403,8 @@ void ReputationMgr::SetVisible(FactionState* faction)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
faction->Flags |= FACTION_FLAG_VISIBLE;
|
faction->Flags |= FACTION_FLAG_VISIBLE;
|
||||||
faction->Changed = true;
|
faction->needSend = true;
|
||||||
|
faction->needSave = true;
|
||||||
|
|
||||||
++m_visibleFactionCount;
|
++m_visibleFactionCount;
|
||||||
|
|
||||||
@@ -422,7 +439,8 @@ void ReputationMgr::SetAtWar(FactionState* faction, bool atWar)
|
|||||||
else
|
else
|
||||||
faction->Flags &= ~FACTION_FLAG_AT_WAR;
|
faction->Flags &= ~FACTION_FLAG_AT_WAR;
|
||||||
|
|
||||||
faction->Changed = true;
|
faction->needSend = true;
|
||||||
|
faction->needSave = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReputationMgr::SetInactive(RepListID repListID, bool on)
|
void ReputationMgr::SetInactive(RepListID repListID, bool on)
|
||||||
@@ -449,7 +467,8 @@ void ReputationMgr::SetInactive(FactionState* faction, bool inactive)
|
|||||||
else
|
else
|
||||||
faction->Flags &= ~FACTION_FLAG_INACTIVE;
|
faction->Flags &= ~FACTION_FLAG_INACTIVE;
|
||||||
|
|
||||||
faction->Changed = true;
|
faction->needSend = true;
|
||||||
|
faction->needSave = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReputationMgr::LoadFromDB(PreparedQueryResult result)
|
void ReputationMgr::LoadFromDB(PreparedQueryResult result)
|
||||||
@@ -502,7 +521,10 @@ void ReputationMgr::LoadFromDB(PreparedQueryResult result)
|
|||||||
|
|
||||||
// reset changed flag if values similar to saved in DB
|
// reset changed flag if values similar to saved in DB
|
||||||
if (faction->Flags == dbFactionFlags)
|
if (faction->Flags == dbFactionFlags)
|
||||||
faction->Changed = false;
|
{
|
||||||
|
faction->needSend = false;
|
||||||
|
faction->needSave = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (result->NextRow());
|
while (result->NextRow());
|
||||||
@@ -513,11 +535,11 @@ void ReputationMgr::SaveToDB(SQLTransaction& trans)
|
|||||||
{
|
{
|
||||||
for (FactionStateList::iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr)
|
for (FactionStateList::iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr)
|
||||||
{
|
{
|
||||||
if (itr->second.Changed)
|
if (itr->second.needSave)
|
||||||
{
|
{
|
||||||
trans->PAppend("DELETE FROM character_reputation WHERE guid = '%u' AND faction='%u'", m_player->GetGUIDLow(), itr->second.ID);
|
trans->PAppend("DELETE FROM character_reputation WHERE guid = '%u' AND faction='%u'", m_player->GetGUIDLow(), itr->second.ID);
|
||||||
trans->PAppend("INSERT INTO character_reputation (guid,faction,standing,flags) VALUES ('%u', '%u', '%i', '%u')", m_player->GetGUIDLow(), itr->second.ID, itr->second.Standing, itr->second.Flags);
|
trans->PAppend("INSERT INTO character_reputation (guid,faction,standing,flags) VALUES ('%u', '%u', '%i', '%u')", m_player->GetGUIDLow(), itr->second.ID, itr->second.Standing, itr->second.Flags);
|
||||||
itr->second.Changed = false;
|
itr->second.needSave = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ struct FactionState
|
|||||||
RepListID ReputationListID;
|
RepListID ReputationListID;
|
||||||
uint8 Flags;
|
uint8 Flags;
|
||||||
int32 Standing;
|
int32 Standing;
|
||||||
bool Changed;
|
bool needSend;
|
||||||
|
bool needSave;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::map<RepListID,FactionState> FactionStateList;
|
typedef std::map<RepListID,FactionState> FactionStateList;
|
||||||
@@ -131,8 +132,8 @@ class ReputationMgr
|
|||||||
public: // senders
|
public: // senders
|
||||||
void SendInitialReputations();
|
void SendInitialReputations();
|
||||||
void SendForceReactions();
|
void SendForceReactions();
|
||||||
void SendState(FactionState const* faction) const;
|
void SendState(FactionState const* faction);
|
||||||
void SendStates() const;
|
void SendStates();
|
||||||
|
|
||||||
private: // internal helper functions
|
private: // internal helper functions
|
||||||
void Initialize();
|
void Initialize();
|
||||||
|
|||||||
Reference in New Issue
Block a user