diff options
author | megamage <none@none> | 2009-03-26 14:03:55 -0600 |
---|---|---|
committer | megamage <none@none> | 2009-03-26 14:03:55 -0600 |
commit | b78f837425ebfe842dfba545f608f08dcbab3ee7 (patch) | |
tree | 43ec8b635c43339c95742cc439b2a2f43a8d86cf | |
parent | 1ac13728a70fccf9180a7065b04c9dd9c83a9498 (diff) |
[7547] Improvments in reputation achievements implememtaion. Author: VladimirMangos
* Speedup achievement checks at reputation updates.
* Implement
- ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION
- ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION
- ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS
--HG--
branch : trunk
-rw-r--r-- | src/game/AchievementMgr.cpp | 28 | ||||
-rw-r--r-- | src/game/ReputationMgr.cpp | 475 | ||||
-rw-r--r-- | src/game/ReputationMgr.h | 146 |
3 files changed, 634 insertions, 15 deletions
diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 2d99944e8ad..dfd63f4b37d 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -762,18 +762,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui } case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION: { - // skip faction check only at loading - if (miscvalue1 && GetPlayer()->GetReputationRank(miscvalue1) < REP_EXALTED) - continue; - - uint32 counter = 0; - FactionStateList const& factionStateList = GetPlayer()->GetReputationMgr().GetStateList(); - for (FactionStateList::const_iterator iter = factionStateList.begin(); iter!= factionStateList.end(); ++iter) - if(FactionEntry const *factionEntry = sFactionStore.LookupEntry(iter->second.ID)) - if(ReputationMgr::ReputationToRank(iter->second.Standing + GetPlayer()->GetReputationMgr().GetBaseReputation(factionEntry)) >= REP_EXALTED) - ++counter; - - SetCriteriaProgress(achievementCriteria, counter); + SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetExaltedFactionCount()); break; } case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP: @@ -866,6 +855,15 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui SetCriteriaProgress(achievementCriteria, spellCount); break; } + case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION: + SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetReveredFactionCount()); + break; + case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION: + SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetHonoredFactionCount()); + break; + case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS: + SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetVisibleFactionCount()); + break; case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: { if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID) @@ -930,9 +928,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION: case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED: - case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION: - case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION: - case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS: case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM: case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM: case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED: @@ -1067,6 +1062,9 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD: + case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION: + case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION: + case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_ARMOR: diff --git a/src/game/ReputationMgr.cpp b/src/game/ReputationMgr.cpp new file mode 100644 index 00000000000..0ff70201015 --- /dev/null +++ b/src/game/ReputationMgr.cpp @@ -0,0 +1,475 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ReputationMgr.h" +#include "Database/DBCStores.h" +#include "Player.h" +#include "WorldPacket.h" + +const int32 ReputationMgr::PointsInRank[MAX_REPUTATION_RANK] = {36000, 3000, 3000, 3000, 6000, 12000, 21000, 1000}; + +ReputationRank ReputationMgr::ReputationToRank(int32 standing) +{ + int32 limit = Reputation_Cap + 1; + for (int i = MAX_REPUTATION_RANK-1; i >= MIN_REPUTATION_RANK; --i) + { + limit -= PointsInRank[i]; + if (standing >= limit ) + return ReputationRank(i); + } + return MIN_REPUTATION_RANK; +} + +int32 ReputationMgr::GetReputation(uint32 faction_id) const +{ + FactionEntry const *factionEntry = sFactionStore.LookupEntry(faction_id); + + if (!factionEntry) + { + sLog.outError("ReputationMgr::GetReputation: Can't get reputation of %s for unknown faction (faction id) #%u.",m_player->GetName(), faction_id); + return 0; + } + + return GetReputation(factionEntry); +} + +int32 ReputationMgr::GetBaseReputation(FactionEntry const* factionEntry) const +{ + if (!factionEntry) + return 0; + + uint32 raceMask = m_player->getRaceMask(); + uint32 classMask = m_player->getClassMask(); + for (int i=0; i < 4; i++) + { + if( (factionEntry->BaseRepRaceMask[i] & raceMask) && + (factionEntry->BaseRepClassMask[i]==0 || + (factionEntry->BaseRepClassMask[i] & classMask) ) ) + return factionEntry->BaseRepValue[i]; + } + + // in faction.dbc exist factions with (RepListId >=0, listed in character reputation list) with all BaseRepRaceMask[i]==0 + return 0; +} + +int32 ReputationMgr::GetReputation(FactionEntry const* factionEntry) const +{ + // Faction without recorded reputation. Just ignore. + if(!factionEntry) + return 0; + + if(FactionState const* state = GetState(factionEntry)) + return GetBaseReputation(factionEntry) + state->Standing; + + return 0; +} + +ReputationRank ReputationMgr::GetRank(FactionEntry const* factionEntry) const +{ + int32 reputation = GetReputation(factionEntry); + return ReputationToRank(reputation); +} + +ReputationRank ReputationMgr::GetBaseRank(FactionEntry const* factionEntry) const +{ + int32 reputation = GetBaseReputation(factionEntry); + return ReputationToRank(reputation); +} + +void ReputationMgr::ApplyForceReaction( uint32 faction_id,ReputationRank rank,bool apply ) +{ + if(apply) + m_forcedReactions[faction_id] = rank; + else + m_forcedReactions.erase(faction_id); +} + +uint32 ReputationMgr::GetDefaultStateFlags(FactionEntry const* factionEntry) const +{ + if (!factionEntry) + return 0; + + uint32 raceMask = m_player->getRaceMask(); + uint32 classMask = m_player->getClassMask(); + for (int i=0; i < 4; i++) + { + if( (factionEntry->BaseRepRaceMask[i] & raceMask) && + (factionEntry->BaseRepClassMask[i]==0 || + (factionEntry->BaseRepClassMask[i] & classMask) ) ) + return factionEntry->ReputationFlags[i]; + } + return 0; +} + +void ReputationMgr::SendForceReactions() +{ + WorldPacket data; + data.Initialize(SMSG_SET_FORCED_REACTIONS, 4+m_forcedReactions.size()*(4+4)); + data << uint32(m_forcedReactions.size()); + for(ForcedReactions::const_iterator itr = m_forcedReactions.begin(); itr != m_forcedReactions.end(); ++itr) + { + data << uint32(itr->first); // faction_id (Faction.dbc) + data << uint32(itr->second); // reputation rank + } + m_player->SendDirectMessage(&data); +} + +void ReputationMgr::SendState(FactionState const* faction) const +{ + if(faction->Flags & FACTION_FLAG_VISIBLE) //If faction is visible then update it + { + WorldPacket data(SMSG_SET_FACTION_STANDING, (16)); // last check 2.4.0 + data << (float) 0; // unk 2.4.0 + data << (uint8) 0; // wotlk 8634 + data << (uint32) 1; // count + // for + data << (uint32) faction->ReputationListID; + data << (uint32) faction->Standing; + // end for + m_player->SendDirectMessage(&data); + } +} + +void ReputationMgr::SendInitialReputations() +{ + WorldPacket data(SMSG_INITIALIZE_FACTIONS, (4+128*5)); + data << uint32 (0x00000080); + + RepListID a = 0; + + for (FactionStateList::const_iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr) + { + // fill in absent fields + for (; a != itr->first; a++) + { + data << uint8 (0x00); + data << uint32 (0x00000000); + } + + // fill in encountered data + data << uint8 (itr->second.Flags); + data << uint32 (itr->second.Standing); + + ++a; + } + + // fill in absent fields + for (; a != 128; a++) + { + data << uint8 (0x00); + data << uint32 (0x00000000); + } + + m_player->SendDirectMessage(&data); +} + +void ReputationMgr::SendStates() const +{ + for(FactionStateList::const_iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr) + SendState(&(itr->second)); +} + +void ReputationMgr::SendVisible(FactionState const* faction) const +{ + if(m_player->GetSession()->PlayerLoading()) + return; + + // make faction visible in reputation list at client + WorldPacket data(SMSG_SET_FACTION_VISIBLE, 4); + data << faction->ReputationListID; + m_player->SendDirectMessage(&data); +} + +void ReputationMgr::Initilize() +{ + m_factions.clear(); + m_visibleFactionCount = 0; + m_honoredFactionCount = 0; + m_reveredFactionCount = 0; + m_exaltedFactionCount = 0; + + for(unsigned int i = 1; i < sFactionStore.GetNumRows(); i++) + { + FactionEntry const *factionEntry = sFactionStore.LookupEntry(i); + + if( factionEntry && (factionEntry->reputationListID >= 0)) + { + FactionState newFaction; + newFaction.ID = factionEntry->ID; + newFaction.ReputationListID = factionEntry->reputationListID; + newFaction.Standing = 0; + newFaction.Flags = GetDefaultStateFlags(factionEntry); + newFaction.Changed = true; + + if( newFaction.Flags & FACTION_FLAG_VISIBLE ) + ++m_visibleFactionCount; + + UpdateRankCounters(REP_HOSTILE,GetBaseRank(factionEntry)); + + m_factions[newFaction.ReputationListID] = newFaction; + } + } +} + +bool ReputationMgr::SetReputation(FactionEntry const* factionEntry, int32 standing, bool incremental) +{ + SimpleFactionsList const* flist = GetFactionTeamList(factionEntry->ID); + if (flist) + { + bool res = false; + for (SimpleFactionsList::const_iterator itr = flist->begin();itr != flist->end();++itr) + { + FactionEntry const *factionEntryCalc = sFactionStore.LookupEntry(*itr); + if(factionEntryCalc) + res = SetOneFactionReputation(factionEntryCalc, standing, incremental); + } + return res; + } + else + return SetOneFactionReputation(factionEntry, standing, incremental); +} + +bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing, bool incremental) +{ + FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID); + if (itr != m_factions.end()) + { + int32 BaseRep = GetBaseReputation(factionEntry); + + if(incremental) + standing += itr->second.Standing + BaseRep; + + if (standing > Reputation_Cap) + standing = Reputation_Cap; + else if (standing < Reputation_Bottom) + standing = Reputation_Bottom; + + ReputationRank old_rank = ReputationToRank(itr->second.Standing + BaseRep); + ReputationRank new_rank = ReputationToRank(standing); + + itr->second.Standing = standing - BaseRep; + itr->second.Changed = true; + + SetVisible(&itr->second); + + if(new_rank <= REP_HOSTILE) + SetAtWar(&itr->second,true); + + SendState(&itr->second); + + UpdateRankCounters(old_rank, new_rank); + + m_player->ReputationChanged(factionEntry); + m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS, factionEntry->ID); + m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION, factionEntry->ID); + m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION,factionEntry->ID); + m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION,factionEntry->ID); + m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION,factionEntry->ID); + + return true; + } + return false; +} + +void ReputationMgr::SetVisible(FactionTemplateEntry const*factionTemplateEntry) +{ + if(!factionTemplateEntry->faction) + return; + + if(FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionTemplateEntry->faction)) + SetVisible(factionEntry); +} + +void ReputationMgr::SetVisible(FactionEntry const *factionEntry) +{ + if(factionEntry->reputationListID < 0) + return; + + FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID); + if (itr == m_factions.end()) + return; + + SetVisible(&itr->second); +} + +void ReputationMgr::SetVisible(FactionState* faction) +{ + // always invisible or hidden faction can't be make visible + if(faction->Flags & (FACTION_FLAG_INVISIBLE_FORCED|FACTION_FLAG_HIDDEN)) + return; + + // already set + if(faction->Flags & FACTION_FLAG_VISIBLE) + return; + + faction->Flags |= FACTION_FLAG_VISIBLE; + faction->Changed = true; + + ++m_visibleFactionCount; + + SendVisible(faction); +} + +void ReputationMgr::SetAtWar( RepListID repListID, bool on ) +{ + FactionStateList::iterator itr = m_factions.find(repListID); + if (itr == m_factions.end()) + return; + + // always invisible or hidden faction can't change war state + if(itr->second.Flags & (FACTION_FLAG_INVISIBLE_FORCED|FACTION_FLAG_HIDDEN) ) + return; + + SetAtWar(&itr->second,on); +} + +void ReputationMgr::SetAtWar(FactionState* faction, bool atWar) +{ + // not allow declare war to own faction + if(atWar && (faction->Flags & FACTION_FLAG_PEACE_FORCED) ) + return; + + // already set + if(((faction->Flags & FACTION_FLAG_AT_WAR) != 0) == atWar) + return; + + if( atWar ) + faction->Flags |= FACTION_FLAG_AT_WAR; + else + faction->Flags &= ~FACTION_FLAG_AT_WAR; + + faction->Changed = true; +} + +void ReputationMgr::SetInactive( RepListID repListID, bool on ) +{ + FactionStateList::iterator itr = m_factions.find(repListID); + if (itr == m_factions.end()) + return; + + SetInactive(&itr->second,on); +} + +void ReputationMgr::SetInactive(FactionState* faction, bool inactive) +{ + // always invisible or hidden faction can't be inactive + if(inactive && ((faction->Flags & (FACTION_FLAG_INVISIBLE_FORCED|FACTION_FLAG_HIDDEN)) || !(faction->Flags & FACTION_FLAG_VISIBLE) ) ) + return; + + // already set + if(((faction->Flags & FACTION_FLAG_INACTIVE) != 0) == inactive) + return; + + if(inactive) + faction->Flags |= FACTION_FLAG_INACTIVE; + else + faction->Flags &= ~FACTION_FLAG_INACTIVE; + + faction->Changed = true; +} + +void ReputationMgr::LoadFromDB(QueryResult *result) +{ + // Set initial reputations (so everything is nifty before DB data load) + Initilize(); + + //QueryResult *result = CharacterDatabase.PQuery("SELECT faction,standing,flags FROM character_reputation WHERE guid = '%u'",GetGUIDLow()); + + if(result) + { + do + { + Field *fields = result->Fetch(); + + FactionEntry const *factionEntry = sFactionStore.LookupEntry(fields[0].GetUInt32()); + if( factionEntry && (factionEntry->reputationListID >= 0)) + { + FactionState* faction = &m_factions[factionEntry->reputationListID]; + + // update standing to current + faction->Standing = int32(fields[1].GetUInt32()); + + // update counters + int32 BaseRep = GetBaseReputation(factionEntry); + ReputationRank old_rank = ReputationToRank(BaseRep); + ReputationRank new_rank = ReputationToRank(BaseRep + faction->Standing); + UpdateRankCounters(old_rank,new_rank); + + uint32 dbFactionFlags = fields[2].GetUInt32(); + + if( dbFactionFlags & FACTION_FLAG_VISIBLE ) + SetVisible(faction); // have internal checks for forced invisibility + + if( dbFactionFlags & FACTION_FLAG_INACTIVE) + SetInactive(faction,true); // have internal checks for visibility requirement + + if( dbFactionFlags & FACTION_FLAG_AT_WAR ) // DB at war + SetAtWar(faction,true); // have internal checks for FACTION_FLAG_PEACE_FORCED + else // DB not at war + { + // allow remove if visible (and then not FACTION_FLAG_INVISIBLE_FORCED or FACTION_FLAG_HIDDEN) + if( faction->Flags & FACTION_FLAG_VISIBLE ) + SetAtWar(faction,false); // have internal checks for FACTION_FLAG_PEACE_FORCED + } + + // set atWar for hostile + if(GetRank(factionEntry) <= REP_HOSTILE) + SetAtWar(faction,true); + + // reset changed flag if values similar to saved in DB + if(faction->Flags==dbFactionFlags) + faction->Changed = false; + } + } + while( result->NextRow() ); + + delete result; + } +} + +void ReputationMgr::SaveToDB() +{ + CharacterDatabase.BeginTransaction(); + for(FactionStateList::iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr) + { + if (itr->second.Changed) + { + CharacterDatabase.PExecute("DELETE FROM character_reputation WHERE guid = '%u' AND faction='%u'", m_player->GetGUIDLow(), itr->second.ID); + CharacterDatabase.PExecute("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; + } + } + CharacterDatabase.CommitTransaction(); +} + +void ReputationMgr::UpdateRankCounters( ReputationRank old_rank, ReputationRank new_rank ) +{ + if(old_rank >= REP_EXALTED) + --m_exaltedFactionCount; + if(old_rank >= REP_REVERED) + --m_reveredFactionCount; + if(old_rank >= REP_HONORED) + --m_honoredFactionCount; + + if(new_rank >= REP_EXALTED) + ++m_exaltedFactionCount; + if(new_rank >= REP_REVERED) + ++m_reveredFactionCount; + if(new_rank >= REP_HONORED) + ++m_honoredFactionCount; +}
\ No newline at end of file diff --git a/src/game/ReputationMgr.h b/src/game/ReputationMgr.h new file mode 100644 index 00000000000..cb4c85fd5be --- /dev/null +++ b/src/game/ReputationMgr.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MANGOS_REPUTATION_MGR_H +#define __MANGOS_REPUTATION_MGR_H + +#include "Common.h" +#include "SharedDefines.h" +#include "Database/DBCStructure.h" +#include <map> + +enum FactionFlags +{ + FACTION_FLAG_VISIBLE = 0x01, // makes visible in client (set or can be set at interaction with target of this faction) + FACTION_FLAG_AT_WAR = 0x02, // enable AtWar-button in client. player controlled (except opposition team always war state), Flag only set on initial creation + FACTION_FLAG_HIDDEN = 0x04, // hidden faction from reputation pane in client (player can gain reputation, but this update not sent to client) + 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 +}; + +typedef uint32 RepListID; +struct FactionState +{ + uint32 ID; + RepListID ReputationListID; + uint32 Flags; + int32 Standing; + bool Changed; +}; + +typedef std::map<RepListID,FactionState> FactionStateList; +typedef std::pair<FactionStateList::const_iterator,FactionStateList::const_iterator> FactionStateListPair; + +typedef std::map<uint32,ReputationRank> ForcedReactions; + +class Player; +class QueryResult; + +class ReputationMgr +{ + public: // constructors and global modifiers + explicit ReputationMgr(Player* owner) : m_player(owner), + m_visibleFactionCount(0), m_honoredFactionCount(0), m_reveredFactionCount(0), m_exaltedFactionCount(0) {} + ~ReputationMgr() {} + + void SaveToDB(); + void LoadFromDB(QueryResult *result); + public: // statics + static const int32 PointsInRank[MAX_REPUTATION_RANK]; + static const int32 Reputation_Cap = 42999; + static const int32 Reputation_Bottom = -42000; + + static ReputationRank ReputationToRank(int32 standing); + public: // accessors + uint8 GetVisibleFactionCount() const { return m_visibleFactionCount; } + uint8 GetHonoredFactionCount() const { return m_honoredFactionCount; } + uint8 GetReveredFactionCount() const { return m_reveredFactionCount; } + uint8 GetExaltedFactionCount() const { return m_exaltedFactionCount; } + + FactionStateList const& GetStateList() const { return m_factions; } + + FactionState const* GetState(FactionEntry const* factionEntry) const + { + return factionEntry->reputationListID >= 0 ? GetState(factionEntry->reputationListID) : NULL; + } + + FactionState const* GetState(RepListID id) const + { + FactionStateList::const_iterator repItr = m_factions.find (id); + return repItr != m_factions.end() ? &repItr->second : NULL; + } + + int32 GetReputation(uint32 faction_id) const; + int32 GetReputation(FactionEntry const* factionEntry) const; + int32 GetBaseReputation(FactionEntry const* factionEntry) const; + + ReputationRank GetRank(FactionEntry const* factionEntry) const; + ReputationRank GetBaseRank(FactionEntry const* factionEntry) const; + + ReputationRank const* GetForcedRankIfAny(FactionTemplateEntry const* factionTemplateEntry) const + { + ForcedReactions::const_iterator forceItr = m_forcedReactions.find(factionTemplateEntry->faction); + return forceItr != m_forcedReactions.end() ? &forceItr->second : NULL; + } + + public: // modifiers + bool SetReputation(FactionEntry const* factionEntry, int32 standing) + { + return SetReputation(factionEntry, standing, false); + } + bool ModifyReputation(FactionEntry const* factionEntry, int32 standing) + { + return SetReputation(factionEntry, standing, true); + } + + void SetVisible(FactionTemplateEntry const* factionTemplateEntry); + void SetVisible(FactionEntry const* factionEntry); + void SetAtWar(RepListID repListID, bool on); + void SetInactive(RepListID repListID, bool on); + + void ApplyForceReaction(uint32 faction_id,ReputationRank rank,bool apply); + + public: // senders + void SendInitialReputations(); + void SendForceReactions(); + void SendState(FactionState const* faction) const; + void SendStates() const; + + private: // internal helper functions + void Initilize(); + uint32 GetDefaultStateFlags(const FactionEntry *factionEntry) const; + bool SetReputation(FactionEntry const* factionEntry, int32 standing, bool incremental); + bool SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing, bool incremental); + void SetVisible(FactionState* faction); + void SetAtWar(FactionState* faction, bool atWar); + void SetInactive(FactionState* faction, bool inactive); + void SendVisible(FactionState const* faction) const; + void UpdateRankCounters( ReputationRank old_rank, ReputationRank new_rank ); + private: + Player* m_player; + FactionStateList m_factions; + ForcedReactions m_forcedReactions; + uint8 m_visibleFactionCount :8; + uint8 m_honoredFactionCount :8; + uint8 m_reveredFactionCount :8; + uint8 m_exaltedFactionCount :8; +}; + +#endif |