[10774] Implement more generic reputation spillover

* Also fixes factions 1037 and 1052
* More correct client output when reputation assigned to parent faction
* reputation_spillover_template can still be used to override spillover from dbc
This commit is contained in:
Lynx3d 2010-11-22 00:23:03 +01:00
parent 5f4f39851e
commit 7026dc0d1b
5 changed files with 76 additions and 64 deletions

View file

@ -122,33 +122,30 @@ void ReputationMgr::SendForceReactions()
void ReputationMgr::SendState(FactionState const* faction) const
{
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::const_iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr)
{
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::const_iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr)
if (itr->second.Changed && itr->second.ReputationListID != faction->ReputationListID)
{
if (itr->second.Changed && itr->second.ReputationListID != faction->ReputationListID)
{
data << (uint32) itr->second.ReputationListID;
data << (uint32) itr->second.Standing;
++count;
}
data << (uint32) itr->second.ReputationListID;
data << (uint32) itr->second.Standing;
++count;
}
data.put<uint32>(p_count, count);
m_player->SendDirectMessage(&data);
}
data.put<uint32>(p_count, count);
m_player->SendDirectMessage(&data);
}
void ReputationMgr::SendInitialReputations()
@ -228,57 +225,71 @@ void ReputationMgr::Initialize()
bool ReputationMgr::SetReputation(FactionEntry const* factionEntry, int32 standing, bool incremental)
{
if (SimpleFactionsList const* flist = GetFactionTeamList(factionEntry->ID))
bool res = false;
// if spillover definition exists in DB, override DBC
if (const RepSpilloverTemplate *repTemplate = sObjectMgr.GetRepSpilloverTemplate(factionEntry->ID))
{
bool res = false;
for (SimpleFactionsList::const_iterator itr = flist->begin();itr != flist->end();++itr)
for (uint32 i = 0; i < MAX_SPILLOVER_FACTIONS; ++i)
{
if (FactionEntry const *factionEntryCalc = sFactionStore.LookupEntry(*itr))
if (repTemplate->faction[i])
{
res = SetOneFactionReputation(factionEntryCalc, standing, incremental);
if (res)
if (m_player->GetReputationRank(repTemplate->faction[i]) <= ReputationRank(repTemplate->faction_rank[i]))
{
FactionStateList::iterator itrstate = m_factions.find(factionEntryCalc->reputationListID);
if (itrstate != m_factions.end())
SendState(&itrstate->second);
// bonuses are already given, so just modify standing by rate
int32 spilloverRep = standing * repTemplate->faction_rate[i];
SetOneFactionReputation(sFactionStore.LookupEntry(repTemplate->faction[i]), spilloverRep, incremental);
}
}
}
return res;
}
else
{
// update for the actual faction first
bool res = SetOneFactionReputation(factionEntry, standing, incremental);
if (res)
float spillOverRepOut = 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)
{
// then some spillover calculation here if it exist
if (const RepSpilloverTemplate *repTemplate = sObjectMgr.GetRepSpilloverTemplate(factionEntry->ID))
spillOverRepOut *= factionEntry->spilloverRateOut;
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_TEAM_REPUTATION))
{
if (repTemplate->faction[i])
{
if (m_player->GetReputationRank(repTemplate->faction[i]) <= ReputationRank(repTemplate->faction_rank[i]))
{
// bonuses are already given, so just modify standing by rate
int32 spilloverRep = standing * repTemplate->faction_rate[i];
SetOneFactionReputation(sFactionStore.LookupEntry(repTemplate->faction[i]), spilloverRep, incremental);
}
}
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 (FactionEntry const *factionEntryCalc = sFactionStore.LookupEntry(*itr))
{
if (factionEntryCalc == factionEntry || GetRank(factionEntryCalc) > 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)