From 7026dc0d1bccc7c9da0216f46c5733557aad30c3 Mon Sep 17 00:00:00 2001 From: Lynx3d Date: Mon, 22 Nov 2010 00:23:03 +0100 Subject: [PATCH] [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 --- src/game/DBCStructure.h | 8 +-- src/game/DBCfmt.h | 2 +- src/game/ReputationMgr.cpp | 125 ++++++++++++++++++++----------------- src/game/ReputationMgr.h | 3 +- src/shared/revision_nr.h | 2 +- 5 files changed, 76 insertions(+), 64 deletions(-) diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index 22993cb3b..2d3fb7848 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -813,10 +813,10 @@ struct FactionEntry int32 BaseRepValue[4]; // 10-13 m_reputationBase uint32 ReputationFlags[4]; // 14-17 m_reputationFlags uint32 team; // 18 m_parentFactionID - //float spilloverRate1; // 19 Members of the team gain (received_rep*rate). If spilloverRate1 is (0.0 || 1.0), spilloverRate2 are used instead... - //float spilloverRate2; // 20 ...but only if spilloverRate2 is not (1.0 || 0.0). Faction must be member of a team before spillover are given. - //uint32 spilloverMaxRank; // 21 The highest rank player will receive spillover at (the cap). Above this rank will not give any spillover for this faction - //uint32 spilloverRank_unk; // 22 + float spilloverRateIn; // 19 Faction gains incoming rep * spilloverRateIn + float spilloverRateOut; // 20 Faction outputs rep * spilloverRateOut as spillover reputation + uint32 spilloverMaxRankIn; // 21 The highest rank the faction will profit from incoming spillover + //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 // 39 string flags //char* description[16]; // 40-55 m_description_lang diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h index 0025c20e6..c26acd8d5 100644 --- a/src/game/DBCfmt.h +++ b/src/game/DBCfmt.h @@ -44,7 +44,7 @@ const char DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii"; const char DurabilityQualityfmt[]="nf"; const char EmotesEntryfmt[]="nxxiiix"; const char EmotesTextEntryfmt[]="nxixxxxxxxxxxxxxxxx"; -const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiixxxxssssssssssssssssxxxxxxxxxxxxxxxxxx"; +const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiiffixssssssssssssssssxxxxxxxxxxxxxxxxxx"; const char FactionTemplateEntryfmt[]="niiiiiiiiiiiii"; const char GameObjectDisplayInfofmt[]="nxxxxxxxxxxxfxxxxxx"; const char GemPropertiesEntryfmt[]="nixxi"; diff --git a/src/game/ReputationMgr.cpp b/src/game/ReputationMgr.cpp index 18b85e82c..ad77c520c 100644 --- a/src/game/ReputationMgr.cpp +++ b/src/game/ReputationMgr.cpp @@ -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(p_count, count); - m_player->SendDirectMessage(&data); } + + data.put(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) diff --git a/src/game/ReputationMgr.h b/src/game/ReputationMgr.h index 1c2172790..6efcf67b4 100644 --- a/src/game/ReputationMgr.h +++ b/src/game/ReputationMgr.h @@ -32,7 +32,8 @@ enum FactionFlags FACTION_FLAG_INVISIBLE_FORCED = 0x08, // always overwrite FACTION_FLAG_VISIBLE and hide faction in rep.list, used for hide opposite team factions FACTION_FLAG_PEACE_FORCED = 0x10, // always overwrite FACTION_FLAG_AT_WAR, used for prevent war with own team factions FACTION_FLAG_INACTIVE = 0x20, // player controlled, state stored in characters.data ( CMSG_SET_FACTION_INACTIVE ) - FACTION_FLAG_RIVAL = 0x40 // flag for the two competing outland factions + FACTION_FLAG_RIVAL = 0x40, // flag for the two competing outland factions + FACTION_FLAG_TEAM_REPUTATION = 0x80 // faction has own reputation standing despite teaming up sub-factions; spillover from subfactions will go this instead of other subfactions }; typedef uint32 RepListID; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 1c5c2e407..c999ca4f8 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "10773" + #define REVISION_NR "10774" #endif // __REVISION_NR_H__