diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 90c48fce6..edc8a708c 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -745,7 +745,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if (miscvalue1 && miscvalue1 != achievementCriteria->gain_reputation.factionID) continue; - int32 reputation = GetPlayer()->GetReputation(achievementCriteria->gain_reputation.factionID); + int32 reputation = GetPlayer()->GetReputationMgr().GetReputation(achievementCriteria->gain_reputation.factionID); if (reputation > 0) SetCriteriaProgress(achievementCriteria, reputation); break; @@ -757,13 +757,12 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; uint32 counter = 0; - FactionStateList const& factionStateList = GetPlayer()->GetFactionStateList(); + FactionStateList const& factionStateList = GetPlayer()->GetReputationMgr().GetStateList(); for (FactionStateList::const_iterator iter = factionStateList.begin(); iter!= factionStateList.end(); ++iter) - { - FactionEntry const *factionEntry = sFactionStore.LookupEntry(iter->second.ID); - if(GetPlayer()->ReputationToRank(iter->second.Standing + GetPlayer()->GetBaseReputation(factionEntry)) >= REP_EXALTED) - ++counter; - } + 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); break; } diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index aff08dc79..b62fd7843 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -585,7 +585,7 @@ void BattleGround::RewardReputationToTeam(uint32 faction_id, uint32 Reputation, if(!team) team = plr->GetTeam(); if(team == TeamID) - plr->ModifyFactionReputation(factionEntry, Reputation); + plr->GetReputationMgr().ModifyReputation(factionEntry, Reputation); } } diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 998620a47..c2c384ac9 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -860,7 +860,7 @@ void WorldSession::HandleSetFactionAtWar( WorldPacket & recv_data ) recv_data >> repListID; recv_data >> flag; - GetPlayer()->SetFactionAtWar(repListID,flag); + GetPlayer()->GetReputationMgr().SetAtWar(repListID,flag); } //I think this function is never used :/ I dunno, but i guess this opcode not exists @@ -888,7 +888,7 @@ void WorldSession::HandleSetFactionCheat( WorldPacket & /*recv_data*/ ) } } */ - GetPlayer()->SendFactionStates(); + GetPlayer()->GetReputationMgr().SendStates(); } void WorldSession::HandleMeetingStoneInfo( WorldPacket & /*recv_data*/ ) @@ -953,7 +953,7 @@ void WorldSession::HandleSetWatchedFactionInactiveOpcode(WorldPacket & recv_data uint8 inactive; recv_data >> replistid >> inactive; - _player->SetFactionInactive(replistid, inactive); + _player->GetReputationMgr().SetInactive(replistid, inactive); } void WorldSession::HandleToggleHelmOpcode( WorldPacket & /*recv_data*/ ) diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 144f529cf..d3a9fcb71 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -893,7 +893,7 @@ bool ChatHandler::HandleLookupFactionCommand(const char* args) FactionEntry const *factionEntry = sFactionStore.LookupEntry (id); if (factionEntry) { - FactionState const* repState = target ? target->GetFactionState(factionEntry) : NULL; + FactionState const* repState = target ? target->GetReputationMgr().GetState(factionEntry) : NULL; int loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale(); std::string name = factionEntry->name[loc]; @@ -929,10 +929,10 @@ bool ChatHandler::HandleLookupFactionCommand(const char* args) if (repState) // and then target!=NULL also { - ReputationRank rank = target->GetReputationRank(factionEntry); + ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry); std::string rankName = GetMangosString(ReputationRankStrIndex[rank]); - ss << " " << rankName << "|h|r (" << target->GetReputation(factionEntry) << ")"; + ss << " " << rankName << "|h|r (" << target->GetReputationMgr().GetReputation(factionEntry) << ")"; if(repState->Flags & FACTION_FLAG_VISIBLE) ss << GetMangosString(LANG_FACTION_VISIBLE); @@ -1019,9 +1019,9 @@ bool ChatHandler::HandleModifyRepCommand(const char * args) if (deltaTxt) { int32 delta = atoi(deltaTxt); - if ((delta < 0) || (delta > Player::ReputationRank_Length[r] -1)) + if ((delta < 0) || (delta > ReputationMgr::PointsInRank[r] -1)) { - PSendSysMessage(LANG_COMMAND_FACTION_DELTA, (Player::ReputationRank_Length[r]-1)); + PSendSysMessage(LANG_COMMAND_FACTION_DELTA, (ReputationMgr::PointsInRank[r]-1)); SetSentErrorMessage(true); return false; } @@ -1029,7 +1029,7 @@ bool ChatHandler::HandleModifyRepCommand(const char * args) } break; } - amount += Player::ReputationRank_Length[r]; + amount += ReputationMgr::PointsInRank[r]; } if (r >= MAX_REPUTATION_RANK) { @@ -1055,8 +1055,9 @@ bool ChatHandler::HandleModifyRepCommand(const char * args) return false; } - target->SetFactionReputation(factionEntry,amount); - PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[m_session->GetSessionDbcLocale()], factionId, GetNameLink(target).c_str(), target->GetReputation(factionEntry)); + target->GetReputationMgr().SetReputation(factionEntry,amount); + PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[m_session->GetSessionDbcLocale()], factionId, + GetNameLink(target).c_str(), target->GetReputationMgr().GetReputation(factionEntry)); return true; } @@ -2297,16 +2298,16 @@ bool ChatHandler::HandlePInfoCommand(const char* args) return false; } - FactionStateList const& targetFSL = target->GetFactionStateList(); + FactionStateList const& targetFSL = target->GetReputationMgr().GetStateList(); for(FactionStateList::const_iterator itr = targetFSL.begin(); itr != targetFSL.end(); ++itr) { FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID); char const* factionName = factionEntry ? factionEntry->name[m_session->GetSessionDbcLocale()] : "#Not found#"; - ReputationRank rank = target->GetReputationRank(factionEntry); + ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry); std::string rankName = GetMangosString(ReputationRankStrIndex[rank]); std::ostringstream ss; ss << itr->second.ID << ": |cffffffff|Hfaction:" << itr->second.ID << "|h[" << factionName << "]|h|r " << rankName << "|h|r (" - << target->GetReputation(factionEntry) << ")"; + << target->GetReputationMgr().GetReputation(factionEntry) << ")"; if(itr->second.Flags & FACTION_FLAG_VISIBLE) ss << GetMangosString(LANG_FACTION_VISIBLE); diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 182f1817d..df24f4eec 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -5015,12 +5015,10 @@ bool ChatHandler::HandleQuestComplete(const char* args) if(uint32 repFaction = pQuest->GetRepObjectiveFaction()) { uint32 repValue = pQuest->GetRepObjectiveValue(); - uint32 curRep = player->GetReputation(repFaction); + uint32 curRep = player->GetReputationMgr().GetReputation(repFaction); if(curRep < repValue) - { - FactionEntry const *factionEntry = sFactionStore.LookupEntry(repFaction); - player->SetFactionReputation(factionEntry,repValue); - } + if(FactionEntry const *factionEntry = sFactionStore.LookupEntry(repFaction)) + player->GetReputationMgr().SetReputation(factionEntry,repValue); } // If the quest requires money diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index f5dea56f0..6d6b4f022 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -406,7 +406,7 @@ void WorldSession::HandleSetTargetOpcode( WorldPacket & recv_data ) return; if(FactionTemplateEntry const* factionTemplateEntry = sFactionTemplateStore.LookupEntry(unit->getFaction())) - _player->SetFactionVisible(factionTemplateEntry); + _player->GetReputationMgr().SetVisible(factionTemplateEntry); } void WorldSession::HandleSetSelectionOpcode( WorldPacket & recv_data ) @@ -424,7 +424,7 @@ void WorldSession::HandleSetSelectionOpcode( WorldPacket & recv_data ) return; if(FactionTemplateEntry const* factionTemplateEntry = sFactionTemplateStore.LookupEntry(unit->getFaction())) - _player->SetFactionVisible(factionTemplateEntry); + _player->GetReputationMgr().SetVisible(factionTemplateEntry); } void WorldSession::HandleStandStateChangeOpcode( WorldPacket & recv_data ) diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index f859ad856..68807c6ba 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -82,7 +82,7 @@ ObjectAccessor::GetNPCIfCanInteractWith(Player const &player, uint64 guid, uint3 if(FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(unit->getFaction())) if(factionTemplate->faction) if(FactionEntry const* faction = sFactionStore.LookupEntry(factionTemplate->faction)) - if(faction->reputationListID >= 0 && player.GetReputationRank(faction) <= REP_UNFRIENDLY) + if(faction->reputationListID >= 0 && player.GetReputationMgr().GetRank(faction) <= REP_UNFRIENDLY) return NULL; // not too far diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 0a556f35d..77f446f93 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -2985,10 +2985,10 @@ void ObjectMgr::LoadQuests() // no changes, quest can't be done for this requirement } - if(qinfo->RequiredMinRepValue && qinfo->RequiredMinRepValue > Player::Reputation_Cap) + if(qinfo->RequiredMinRepValue && qinfo->RequiredMinRepValue > ReputationMgr::Reputation_Cap) { sLog.outErrorDb("Quest %u has `RequiredMinRepValue` = %d but max reputation is %u, quest can't be done.", - qinfo->GetQuestId(),qinfo->RequiredMinRepValue,Player::Reputation_Cap); + qinfo->GetQuestId(),qinfo->RequiredMinRepValue,ReputationMgr::Reputation_Cap); // no changes, quest can't be done for this requirement } @@ -6591,7 +6591,7 @@ bool PlayerCondition::Meets(Player const * player) const case CONDITION_REPUTATION_RANK: { FactionEntry const* faction = sFactionStore.LookupEntry(value1); - return faction && player->GetReputationRank(faction) >= value2; + return faction && player->GetReputationMgr().GetRank(faction) >= value2; } case CONDITION_TEAM: return player->GetTeam() == value1; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 4198ca9c7..ac82c94b6 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -261,11 +261,9 @@ std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi) //== Player ==================================================== -const int32 Player::ReputationRank_Length[MAX_REPUTATION_RANK] = {36000, 3000, 3000, 3000, 6000, 12000, 21000, 1000}; - UpdateMask Player::updateVisualBits; -Player::Player (WorldSession *session): Unit(), m_achievementMgr(this) +Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputationMgr(this) { m_transport = 0; @@ -5603,442 +5601,10 @@ void Player::setFactionForRace(uint8 race) setFaction( getFactionForRace(race) ); } -void Player::UpdateReputation() const -{ - sLog.outDetail( "WORLD: Player::UpdateReputation" ); - - for(FactionStateList::const_iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr) - { - SendFactionState(&(itr->second)); - } -} - -void Player::SendFactionState(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 - GetSession()->SendPacket(&data); - } -} - -void Player::SendFactionStates() const -{ - for(FactionStateList::const_iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr) - SendFactionState(&(itr->second)); -} - -void Player::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); - } - - GetSession()->SendPacket(&data); -} - -void Player::SetFactionAtWar( 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; - - SetFactionAtWar(&itr->second,on); -} - -void Player::SetFactionAtWar(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 Player::SetFactionInactive( RepListID repListID, bool on ) -{ - FactionStateList::iterator itr = m_factions.find(repListID); - if (itr == m_factions.end()) - return; - - SetFactionInactive(&itr->second,on); -} - -void Player::SetFactionInactive(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 Player::SetFactionVisible(FactionTemplateEntry const*factionTemplateEntry) -{ - if(!factionTemplateEntry->faction) - return; - - if(FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionTemplateEntry->faction)) - SetFactionVisible(factionEntry); -} - -void Player::SetFactionVisible(FactionEntry const *factionEntry) -{ - if(factionEntry->reputationListID < 0) - return; - - FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID); - if (itr == m_factions.end()) - return; - - SetFactionVisible(&itr->second); -} - -void Player::SetFactionVisible(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; - - if(!m_session->PlayerLoading()) - { - // make faction visible in reputation list at client - WorldPacket data(SMSG_SET_FACTION_VISIBLE, 4); - data << faction->ReputationListID; - GetSession()->SendPacket(&data); - } -} - -void Player::SetInitialFactions() -{ - 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 = GetDefaultReputationFlags(factionEntry); - newFaction.Changed = true; - - m_factions[newFaction.ReputationListID] = newFaction; - } - } -} - -uint32 Player::GetDefaultReputationFlags(const FactionEntry *factionEntry) const -{ - if (!factionEntry) - return 0; - - uint32 raceMask = getRaceMask(); - uint32 classMask = 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; -} - -int32 Player::GetBaseReputation(const FactionEntry *factionEntry) const -{ - if (!factionEntry) - return 0; - - uint32 raceMask = getRaceMask(); - uint32 classMask = 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 Player::GetReputation(uint32 faction_id) const -{ - FactionEntry const *factionEntry = sFactionStore.LookupEntry(faction_id); - - if (!factionEntry) - { - sLog.outError("Player::GetReputation: Can't get reputation of %s for unknown faction (faction template id) #%u.",GetName(), faction_id); - return 0; - } - - return GetReputation(factionEntry); -} - -int32 Player::GetReputation(const FactionEntry *factionEntry) const -{ - // Faction without recorded reputation. Just ignore. - if(!factionEntry) - return 0; - - FactionStateList::const_iterator itr = m_factions.find(factionEntry->reputationListID); - if (itr != m_factions.end()) - return GetBaseReputation(factionEntry) + itr->second.Standing; - - return 0; -} - ReputationRank Player::GetReputationRank(uint32 faction) const { - FactionEntry const*factionEntry = sFactionStore.LookupEntry(faction); - if(!factionEntry) - return MIN_REPUTATION_RANK; - - return GetReputationRank(factionEntry); -} - -ReputationRank Player::ReputationToRank(int32 standing) const -{ - int32 Limit = Reputation_Cap + 1; - for (int i = MAX_REPUTATION_RANK-1; i >= MIN_REPUTATION_RANK; --i) - { - Limit -= ReputationRank_Length[i]; - if (standing >= Limit ) - return ReputationRank(i); - } - return MIN_REPUTATION_RANK; -} - -ReputationRank Player::GetReputationRank(const FactionEntry *factionEntry) const -{ - int32 Reputation = GetReputation(factionEntry); - return ReputationToRank(Reputation); -} - -ReputationRank Player::GetBaseReputationRank(const FactionEntry *factionEntry) const -{ - int32 Reputation = GetBaseReputation(factionEntry); - return ReputationToRank(Reputation); -} - -bool Player::ModifyFactionReputation(uint32 FactionTemplateId, int32 DeltaReputation) -{ - FactionTemplateEntry const* factionTemplateEntry = sFactionTemplateStore.LookupEntry(FactionTemplateId); - - if(!factionTemplateEntry) - { - sLog.outError("Player::ModifyFactionReputation: Can't update reputation of %s for unknown faction (faction template id) #%u.", GetName(), FactionTemplateId); - return false; - } - - FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionTemplateEntry->faction); - - // Faction without recorded reputation. Just ignore. - if(!factionEntry) - return false; - - return ModifyFactionReputation(factionEntry, DeltaReputation); -} - -bool Player::ModifyFactionReputation(FactionEntry const* factionEntry, int32 standing) -{ - 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 = ModifyOneFactionReputation(factionEntryCalc, standing); - } - return res; - } - else - return ModifyOneFactionReputation(factionEntry, standing); -} - -bool Player::ModifyOneFactionReputation(FactionEntry const* factionEntry, int32 standing) -{ - FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID); - if (itr != m_factions.end()) - { - int32 BaseRep = GetBaseReputation(factionEntry); - int32 new_rep = BaseRep + itr->second.Standing + standing; - - if (new_rep > Reputation_Cap) - new_rep = Reputation_Cap; - else - if (new_rep < Reputation_Bottom) - new_rep = Reputation_Bottom; - - if(ReputationToRank(new_rep) <= REP_HOSTILE) - SetFactionAtWar(&itr->second,true); - - itr->second.Standing = new_rep - BaseRep; - itr->second.Changed = true; - - SetFactionVisible(&itr->second); - - ReputationChanged(factionEntry); - - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION,factionEntry->ID); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION,factionEntry->ID); - - SendFactionState(&(itr->second)); - - return true; - } - return false; -} - -bool Player::SetFactionReputation(uint32 FactionTemplateId, int32 standing) -{ - FactionTemplateEntry const* factionTemplateEntry = sFactionTemplateStore.LookupEntry(FactionTemplateId); - - if(!factionTemplateEntry) - { - sLog.outError("Player::SetFactionReputation: Can't set reputation of %s for unknown faction (faction template id) #%u.", GetName(), FactionTemplateId); - return false; - } - - FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionTemplateEntry->faction); - - // Faction without recorded reputation. Just ignore. - if(!factionEntry) - return false; - - return SetFactionReputation(factionEntry, standing); -} - -bool Player::SetFactionReputation(FactionEntry const* factionEntry, int32 standing) -{ - 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); - } - return res; - } - else - return SetOneFactionReputation(factionEntry, standing); -} - -bool Player::SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing) -{ - FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID); - if (itr != m_factions.end()) - { - if (standing > Reputation_Cap) - standing = Reputation_Cap; - else - if (standing < Reputation_Bottom) - standing = Reputation_Bottom; - - int32 BaseRep = GetBaseReputation(factionEntry); - itr->second.Standing = standing - BaseRep; - itr->second.Changed = true; - - SetFactionVisible(&itr->second); - - if(ReputationToRank(standing) <= REP_HOSTILE) - SetFactionAtWar(&itr->second,true); - - SendFactionState(&(itr->second)); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION,factionEntry->ID); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION,factionEntry->ID); - return true; - } - return false; -} - -void Player::ApplyForceReaction( uint32 faction_id,ReputationRank rank,bool apply ) -{ - if(apply) - m_forcedReactions[faction_id] = rank; - else - m_forcedReactions.erase(faction_id); -} - -void Player::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 - } - SendDirectMessage(&data); + FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction); + return GetReputationMgr().GetRank(factionEntry); } //Calculate total reputation percent player gain with quest/creature level @@ -6077,16 +5643,16 @@ void Player::RewardReputation(Unit *pVictim, float rate) int32 donerep1 = CalculateReputationGain(pVictim->getLevel(),Rep->repvalue1,false); donerep1 = int32(donerep1*rate); FactionEntry const *factionEntry1 = sFactionStore.LookupEntry(Rep->repfaction1); - uint32 current_reputation_rank1 = GetReputationRank(factionEntry1); + uint32 current_reputation_rank1 = GetReputationMgr().GetRank(factionEntry1); if(factionEntry1 && current_reputation_rank1 <= Rep->reputation_max_cap1) - ModifyFactionReputation(factionEntry1, donerep1); + GetReputationMgr().ModifyReputation(factionEntry1, donerep1); // Wiki: Team factions value divided by 2 if(Rep->is_teamaward1) { FactionEntry const *team1_factionEntry = sFactionStore.LookupEntry(factionEntry1->team); if(team1_factionEntry) - ModifyFactionReputation(team1_factionEntry, donerep1 / 2); + GetReputationMgr().ModifyReputation(team1_factionEntry, donerep1 / 2); } } @@ -6095,16 +5661,16 @@ void Player::RewardReputation(Unit *pVictim, float rate) int32 donerep2 = CalculateReputationGain(pVictim->getLevel(),Rep->repvalue2,false); donerep2 = int32(donerep2*rate); FactionEntry const *factionEntry2 = sFactionStore.LookupEntry(Rep->repfaction2); - uint32 current_reputation_rank2 = GetReputationRank(factionEntry2); + uint32 current_reputation_rank2 = GetReputationMgr().GetRank(factionEntry2); if(factionEntry2 && current_reputation_rank2 <= Rep->reputation_max_cap2) - ModifyFactionReputation(factionEntry2, donerep2); + GetReputationMgr().ModifyReputation(factionEntry2, donerep2); // Wiki: Team factions value divided by 2 if(Rep->is_teamaward2) { FactionEntry const *team2_factionEntry = sFactionStore.LookupEntry(factionEntry2->team); if(team2_factionEntry) - ModifyFactionReputation(team2_factionEntry, donerep2 / 2); + GetReputationMgr().ModifyReputation(team2_factionEntry, donerep2 / 2); } } } @@ -6120,7 +5686,7 @@ void Player::RewardReputation(Quest const *pQuest) int32 rep = CalculateReputationGain(GetQuestLevel(pQuest),pQuest->RewRepValue[i],true); FactionEntry const* factionEntry = sFactionStore.LookupEntry(pQuest->RewRepFaction[i]); if(factionEntry) - ModifyFactionReputation(factionEntry, rep); + GetReputationMgr().ModifyReputation(factionEntry, rep); } } @@ -10328,7 +9894,7 @@ uint8 Player::CanUseAmmo( uint32 item ) const } if( pProto->RequiredSpell != 0 && !HasSpell( pProto->RequiredSpell ) ) return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; - /*if( GetReputation() < pProto->RequiredReputation ) + /*if( GetReputationMgr().GetReputation() < pProto->RequiredReputation ) return EQUIP_ERR_CANT_EQUIP_REPUTATION; */ if( getLevel() < pProto->RequiredLevel ) @@ -12517,7 +12083,7 @@ bool Player::CanCompleteQuest( uint32 quest_id ) } uint32 repFacId = qInfo->GetRepObjectiveFaction(); - if ( repFacId && GetReputation(repFacId) < qInfo->GetRepObjectiveValue() ) + if ( repFacId && GetReputationMgr().GetReputation(repFacId) < qInfo->GetRepObjectiveValue() ) return false; return true; @@ -12652,7 +12218,7 @@ void Player::AddQuest( Quest const *pQuest, Object *questGiver ) if( pQuest->GetRepObjectiveFaction() ) if(FactionEntry const* factionEntry = sFactionStore.LookupEntry(pQuest->GetRepObjectiveFaction())) - SetFactionVisible(factionEntry); + GetReputationMgr().SetVisible(factionEntry); uint32 qtime = 0; if( pQuest->HasFlag( QUEST_MANGOS_FLAGS_TIMED ) ) @@ -13145,7 +12711,7 @@ bool Player::SatisfyQuestRace( Quest const* qInfo, bool msg ) bool Player::SatisfyQuestReputation( Quest const* qInfo, bool msg ) { uint32 fIdMin = qInfo->GetRequiredMinRepFaction(); //Min required rep - if(fIdMin && GetReputation(fIdMin) < qInfo->GetRequiredMinRepValue()) + if(fIdMin && GetReputationMgr().GetReputation(fIdMin) < qInfo->GetRequiredMinRepValue()) { if( msg ) SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ ); @@ -13153,7 +12719,7 @@ bool Player::SatisfyQuestReputation( Quest const* qInfo, bool msg ) } uint32 fIdMax = qInfo->GetRequiredMaxRepFaction(); //Max required rep - if(fIdMax && GetReputation(fIdMax) >= qInfo->GetRequiredMaxRepValue()) + if(fIdMax && GetReputationMgr().GetReputation(fIdMax) >= qInfo->GetRequiredMaxRepValue()) { if( msg ) SendCanTakeQuestResponse( INVALIDREASON_DONT_HAVE_REQ ); @@ -13810,13 +13376,13 @@ void Player::ReputationChanged(FactionEntry const* factionEntry ) QuestStatusData& q_status = mQuestStatus[questid]; if( q_status.m_status == QUEST_STATUS_INCOMPLETE ) { - if(GetReputation(factionEntry) >= qInfo->GetRepObjectiveValue()) + if(GetReputationMgr().GetReputation(factionEntry) >= qInfo->GetRepObjectiveValue()) if ( CanCompleteQuest( questid ) ) CompleteQuest( questid ); } else if( q_status.m_status == QUEST_STATUS_COMPLETE ) { - if(GetReputation(factionEntry) < qInfo->GetRepObjectiveValue()) + if(GetReputationMgr().GetReputation(factionEntry) < qInfo->GetRepObjectiveValue()) IncompleteQuest( questid ); } } @@ -14575,7 +14141,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) _LoadTutorials(holder->GetResult(PLAYER_LOGIN_QUERY_LOADTUTORIALS)); // must be before inventory (some items required reputation check) - _LoadReputation(holder->GetResult(PLAYER_LOGIN_QUERY_LOADREPUTATION)); + m_reputationMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADREPUTATION)); _LoadInventory(holder->GetResult(PLAYER_LOGIN_QUERY_LOADINVENTORY), time_diff); @@ -15319,61 +14885,6 @@ void Player::_LoadDailyQuestStatus(QueryResult *result) m_DailyQuestChanged = false; } -void Player::_LoadReputation(QueryResult *result) -{ - m_factions.clear(); - - // Set initial reputations (so everything is nifty before DB data load) - SetInitialFactions(); - - //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()); - - uint32 dbFactionFlags = fields[2].GetUInt32(); - - if( dbFactionFlags & FACTION_FLAG_VISIBLE ) - SetFactionVisible(faction); // have internal checks for forced invisibility - - if( dbFactionFlags & FACTION_FLAG_INACTIVE) - SetFactionInactive(faction,true); // have internal checks for visibility requirement - - if( dbFactionFlags & FACTION_FLAG_AT_WAR ) // DB at war - SetFactionAtWar(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 ) - SetFactionAtWar(faction,false); // have internal checks for FACTION_FLAG_PEACE_FORCED - } - - // set atWar for hostile - if(GetReputationRank(factionEntry) <= REP_HOSTILE) - SetFactionAtWar(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 Player::_LoadSpells(QueryResult *result) { //QueryResult *result = CharacterDatabase.PQuery("SELECT spell,active,disabled FROM character_spell WHERE guid = '%u'",GetGUIDLow()); @@ -15857,7 +15368,8 @@ void Player::SaveToDB() _SaveSpellCooldowns(); _SaveActions(); _SaveAuras(); - _SaveReputation(); + m_achievementMgr.SaveToDB(); + m_reputationMgr.SaveToDB(); CharacterDatabase.CommitTransaction(); @@ -15871,7 +15383,6 @@ void Player::SaveToDB() // save pet (hunter pet level and experience and all type pets health/mana). if(Pet* pet = GetPet()) pet->SavePetToDB(PET_SAVE_AS_CURRENT); - m_achievementMgr.SaveToDB(); } // fast save function for item/money cheating preventing - save only inventory and money state @@ -16135,19 +15646,6 @@ void Player::_SaveDailyQuestStatus() GetGUIDLow(), GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx),uint64(m_lastDailyQuestTime)); } -void Player::_SaveReputation() -{ - 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'", GetGUIDLow(), itr->second.ID); - CharacterDatabase.PExecute("INSERT INTO character_reputation (guid,faction,standing,flags) VALUES ('%u', '%u', '%i', '%u')", GetGUIDLow(), itr->second.ID, itr->second.Standing, itr->second.Flags); - itr->second.Changed = false; - } - } -} - void Player::_SaveSpells() { for (PlayerSpellMap::iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end();) @@ -18322,7 +17820,7 @@ void Player::SendInitialPacketsBeforeAddToMap() GetSession()->SendPacket(&data); SendInitialActionButtons(); - SendInitialReputations(); + m_reputationMgr.SendInitialReputations(); m_achievementMgr.SendAllAchievementData(); // update zone diff --git a/src/game/Player.h b/src/game/Player.h index c306004c9..480ba7c40 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -34,6 +34,7 @@ #include "MapReference.h" #include "Util.h" // for Tokens typedef #include "AchievementMgr.h" +#include "ReputationMgr.h" #include "BattleGround.h" #include @@ -270,31 +271,6 @@ struct Runes } }; -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 FactionStateList; - -typedef std::map ForcedReactions; - typedef std::set GuardianPetList; struct EnchantDuration @@ -1691,49 +1667,11 @@ class MANGOS_DLL_SPEC Player : public Unit bool RewardPlayerAndGroupAtKill(Unit* pVictim); bool isHonorOrXPTarget(Unit* pVictim); - FactionStateList const& GetFactionStateList() { return m_factions; } - FactionState const* GetFactionState(RepListID id) const - { - FactionStateList::const_iterator repItr = m_factions.find (id); - return repItr != m_factions.end() ? &repItr->second : NULL; - } - FactionState const* GetFactionState(FactionEntry const* factionEntry) const - { - return factionEntry->reputationListID >= 0 ? GetFactionState(factionEntry->reputationListID) : NULL; - } - uint32 GetDefaultReputationFlags(const FactionEntry *factionEntry) const; - int32 GetBaseReputation(const FactionEntry *factionEntry) const; - int32 GetReputation(uint32 faction_id) const; - int32 GetReputation(const FactionEntry *factionEntry) const; - ReputationRank GetReputationRank(uint32 faction) const; - ReputationRank GetReputationRank(const FactionEntry *factionEntry) const; - ReputationRank GetBaseReputationRank(const FactionEntry *factionEntry) const; - ReputationRank ReputationToRank(int32 standing) const; - const static int32 ReputationRank_Length[MAX_REPUTATION_RANK]; - const static int32 Reputation_Cap = 42999; - const static int32 Reputation_Bottom = -42000; - bool ModifyFactionReputation(uint32 FactionTemplateId, int32 DeltaReputation); - bool ModifyFactionReputation(FactionEntry const* factionEntry, int32 standing); - bool SetFactionReputation(uint32 FactionTemplateId, int32 standing); - bool SetFactionReputation(FactionEntry const* factionEntry, int32 standing); + ReputationMgr& GetReputationMgr() { return m_reputationMgr; } + ReputationMgr const& GetReputationMgr() const { return m_reputationMgr; } + ReputationRank GetReputationRank(uint32 faction_id) const; void RewardReputation(Unit *pVictim, float rate); void RewardReputation(Quest const *pQuest); - void SetInitialFactions(); - void UpdateReputation() const; - void SendFactionState(FactionState const* faction) const; - void SendInitialReputations(); - void SetFactionAtWar(RepListID repListID, bool atWar); - void SetFactionInactive(RepListID repListID, bool inactive); - void SetFactionVisible(FactionTemplateEntry const* factionTemplateEntry); - void SetFactionVisible(FactionEntry const* factionEntry); - ReputationRank const* GetForcedRankIfAny(FactionTemplateEntry const* factionTemplateEntry) const - { - ForcedReactions::const_iterator forceItr = m_forcedReactions.find(factionTemplateEntry->faction); - return forceItr != m_forcedReactions.end() ? &forceItr->second : NULL; - } - void ApplyForceReaction(uint32 faction_id,ReputationRank rank,bool apply); - void SendForceReactions(); - void SendFactionStates() const; void UpdateSkillsForLevel(); void UpdateSkillsToMaxSkillsForLevel(); // for .levelup @@ -2161,7 +2099,6 @@ class MANGOS_DLL_SPEC Player : public Unit void _LoadQuestStatus(QueryResult *result); void _LoadDailyQuestStatus(QueryResult *result); void _LoadGroup(QueryResult *result); - void _LoadReputation(QueryResult *result); void _LoadSkills(); void _LoadSpells(QueryResult *result); void _LoadTutorials(QueryResult *result); @@ -2180,7 +2117,6 @@ class MANGOS_DLL_SPEC Player : public Unit void _SaveMail(); void _SaveQuestStatus(); void _SaveDailyQuestStatus(); - void _SaveReputation(); void _SaveSpells(); void _SaveTutorials(); @@ -2355,11 +2291,6 @@ class MANGOS_DLL_SPEC Player : public Unit void UpdateKnownCurrencies(uint32 itemId, bool apply); int32 CalculateReputationGain(uint32 creatureOrQuestLevel, int32 rep, bool for_quest); - void SetFactionVisible(FactionState* faction); - void SetFactionAtWar(FactionState* faction, bool atWar); - void SetFactionInactive(FactionState* faction, bool inactive); - bool ModifyOneFactionReputation(FactionEntry const* factionEntry, int32 standing); - bool SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing); void AdjustQuestReqItemCount( Quest const* pQuest, QuestStatusData& questStatusData ); GridReference m_gridRef; @@ -2374,8 +2305,7 @@ class MANGOS_DLL_SPEC Player : public Unit bool m_isInWater; AchievementMgr m_achievementMgr; - FactionStateList m_factions; - ForcedReactions m_forcedReactions; + ReputationMgr m_reputationMgr; }; void AddItemsSetItem(Player*player,Item *item); diff --git a/src/game/ReputationMgr.cpp b/src/game/ReputationMgr.cpp new file mode 100644 index 000000000..5dcf60cca --- /dev/null +++ b/src/game/ReputationMgr.cpp @@ -0,0 +1,551 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * 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; +} + +/* +FactionState const* ReputationMgr::GetState( FactionTemplateEntry const* factionTemplateEntry ) const +{ + if(factionTemplateEntry->faction) + if (FactionEntry const* raw_faction = sFactionStore.LookupEntry(factionTemplateEntry->faction)) + if (raw_faction->reputationListID >=0 ) + return GetState(raw_faction); + + return NULL; +} +*/ +/* +ReputationRank ReputationMgr::GetRank(uint32 faction) const +{ + FactionEntry const*factionEntry = sFactionStore.LookupEntry(faction); + if(!factionEntry) + return MIN_REPUTATION_RANK; + + return GetRank(factionEntry); +} +*/ +/* +ReputationRank const* ReputationMgr::GetRankIfAny(FactionTemplateEntry const* factionTemplateEntry,ReputationRank& rankHolder) const +{ + if (!factionTemplateEntry->faction) + return NULL; + + if (FactionEntry const* raw_faction = sFactionStore.LookupEntry(factionTemplateEntry->faction)) + { + if (raw_faction->reputationListID >=0 ) + { + rankHolder = GetRank(raw_faction); + return &rankHolder; + } + } + + return NULL; +} +*/ + +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(); + + 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; + + m_factions[newFaction.ReputationListID] = newFaction; + } + } +} + +bool ReputationMgr::SetReputation(FactionEntry const* factionEntry, int32 standing) +{ + 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); + } + return res; + } + else + return SetOneFactionReputation(factionEntry, standing); +} + +bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing) +{ + FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID); + if (itr != m_factions.end()) + { + if (standing > Reputation_Cap) + standing = Reputation_Cap; + else + if (standing < Reputation_Bottom) + standing = Reputation_Bottom; + + int32 BaseRep = GetBaseReputation(factionEntry); + itr->second.Standing = standing - BaseRep; + itr->second.Changed = true; + + SetVisible(&itr->second); + + if(ReputationToRank(standing) <= REP_HOSTILE) + SetAtWar(&itr->second,true); + + SendState(&itr->second); + + m_player->ReputationChanged(factionEntry); + m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION,factionEntry->ID); + m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION,factionEntry->ID); + return true; + } + return false; +} + +/* +bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing) +{ + FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID); + if (itr != m_factions.end()) + { + if (standing > Reputation_Cap) + standing = Reputation_Cap; + else + if (standing < Reputation_Bottom) + standing = Reputation_Bottom; + + int32 BaseRep = GetBaseReputation(factionEntry); + itr->second.Standing = standing - BaseRep; + itr->second.Changed = true; + + if(itr->second.SetFactionVisible()) + SendFactionVisible(&itr->second); + + if(ReputationToRank(standing) <= REP_HOSTILE) + itr->second.SetAtWar(true); + + SendState(&(itr->second)); + m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION,factionEntry->ID); + m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION,factionEntry->ID); + return true; + } + return false; +} +*/ + +bool ReputationMgr::ModifyReputation(FactionEntry const* factionEntry, int32 standing) +{ + 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 = ModifyOneFactionReputation(factionEntryCalc, standing); + } + return res; + } + else + return ModifyOneFactionReputation(factionEntry, standing); +} + +bool ReputationMgr::ModifyOneFactionReputation(FactionEntry const* factionEntry, int32 standing) +{ + FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID); + if (itr != m_factions.end()) + { + int32 BaseRep = GetBaseReputation(factionEntry); + int32 new_rep = BaseRep + itr->second.Standing + standing; + + if (new_rep > Reputation_Cap) + new_rep = Reputation_Cap; + else + if (new_rep < Reputation_Bottom) + new_rep = Reputation_Bottom; + + if(ReputationToRank(new_rep) <= REP_HOSTILE) + SetAtWar(&itr->second,true); + + itr->second.Standing = new_rep - BaseRep; + itr->second.Changed = true; + + SetVisible(&itr->second); + SendState(&itr->second); + + m_player->ReputationChanged(factionEntry); + + m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION,factionEntry->ID); + m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_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; + + 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()); + + 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(); +} diff --git a/src/game/ReputationMgr.h b/src/game/ReputationMgr.h new file mode 100644 index 000000000..edc60edfd --- /dev/null +++ b/src/game/ReputationMgr.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * 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 + +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 FactionStateList; +typedef std::pair FactionStateListPair; + +typedef std::map ForcedReactions; + +class Player; +class QueryResult; + +class ReputationMgr +{ + public: // constructors and global modifiers + explicit ReputationMgr(Player* owner) : m_player(owner) {} + ~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 + 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); + bool ModifyReputation(FactionEntry const* factionEntry, int32 standing); + + 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 SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing); + bool ModifyOneFactionReputation(FactionEntry const* factionEntry, int32 standing); + void SetVisible(FactionState* faction); + void SetAtWar(FactionState* faction, bool atWar); + void SetInactive(FactionState* faction, bool inactive); + void SendVisible(FactionState const* faction) const; + private: + Player* m_player; + FactionStateList m_factions; + ForcedReactions m_forcedReactions; +}; + +#endif diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 384715007..7388e793b 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -2917,8 +2917,8 @@ void Aura::HandleForceReaction(bool apply, bool Real) uint32 faction_id = m_modifier.m_miscvalue; uint32 faction_rank = m_modifier.m_amount; - player->ApplyForceReaction(faction_id,ReputationRank(faction_rank),apply); - player->SendForceReactions(); + player->GetReputationMgr().ApplyForceReaction(faction_id,ReputationRank(faction_rank),apply); + player->GetReputationMgr().SendForceReactions(); } void Aura::HandleAuraModSkill(bool apply, bool Real) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index fb7bee81c..127b007af 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -5757,7 +5757,7 @@ void Spell::EffectReputation(uint32 i) if(!factionEntry) return; - _player->ModifyFactionReputation(factionEntry,rep_change); + _player->GetReputationMgr().ModifyReputation(factionEntry,rep_change); } void Spell::EffectQuestComplete(uint32 i) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 5ee3e611b..309b5516d 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -6968,14 +6968,13 @@ bool Unit::IsHostileTo(Unit const* unit) const // forced reaction if(target_faction->faction) { - if(ReputationRank const* force =((Player*)tester)->GetForcedRankIfAny(target_faction)) + if(ReputationRank const* force =((Player*)tester)->GetReputationMgr().GetForcedRankIfAny(target_faction)) return *force <= REP_HOSTILE; // if faction have reputation then hostile state for tester at 100% dependent from at_war state if(FactionEntry const* raw_target_faction = sFactionStore.LookupEntry(target_faction->faction)) - if(raw_target_faction->reputationListID >=0) - if(FactionState const* factionState = ((Player*)tester)->GetFactionState(raw_target_faction)) - return (factionState->Flags & FACTION_FLAG_AT_WAR); + if(FactionState const* factionState = ((Player*)tester)->GetReputationMgr().GetState(raw_target_faction)) + return (factionState->Flags & FACTION_FLAG_AT_WAR); } } // CvP forced reaction and reputation case @@ -6984,13 +6983,13 @@ bool Unit::IsHostileTo(Unit const* unit) const // forced reaction if(tester_faction->faction) { - if(ReputationRank const* force = ((Player*)target)->GetForcedRankIfAny(tester_faction)) + if(ReputationRank const* force = ((Player*)target)->GetReputationMgr().GetForcedRankIfAny(tester_faction)) return *force <= REP_HOSTILE; // apply reputation state FactionEntry const* raw_tester_faction = sFactionStore.LookupEntry(tester_faction->faction); if(raw_tester_faction && raw_tester_faction->reputationListID >=0 ) - return ((Player const*)target)->GetReputationRank(raw_tester_faction) <= REP_HOSTILE; + return ((Player const*)target)->GetReputationMgr().GetRank(raw_tester_faction) <= REP_HOSTILE; } } @@ -7081,14 +7080,13 @@ bool Unit::IsFriendlyTo(Unit const* unit) const // forced reaction if(target_faction->faction) { - if(ReputationRank const* force =((Player*)tester)->GetForcedRankIfAny(target_faction)) + if(ReputationRank const* force =((Player*)tester)->GetReputationMgr().GetForcedRankIfAny(target_faction)) return *force >= REP_FRIENDLY; // if faction have reputation then friendly state for tester at 100% dependent from at_war state if(FactionEntry const* raw_target_faction = sFactionStore.LookupEntry(target_faction->faction)) - if(raw_target_faction->reputationListID >=0) - if(FactionState const* FactionState = ((Player*)tester)->GetFactionState(raw_target_faction)) - return !(FactionState->Flags & FACTION_FLAG_AT_WAR); + if(FactionState const* factionState = ((Player*)tester)->GetReputationMgr().GetState(raw_target_faction)) + return !(factionState->Flags & FACTION_FLAG_AT_WAR); } } // CvP forced reaction and reputation case @@ -7097,13 +7095,13 @@ bool Unit::IsFriendlyTo(Unit const* unit) const // forced reaction if(tester_faction->faction) { - if(ReputationRank const* force =((Player*)target)->GetForcedRankIfAny(tester_faction)) + if(ReputationRank const* force =((Player*)target)->GetReputationMgr().GetForcedRankIfAny(tester_faction)) return *force >= REP_FRIENDLY; // apply reputation state if(FactionEntry const* raw_tester_faction = sFactionStore.LookupEntry(tester_faction->faction)) if(raw_tester_faction->reputationListID >=0 ) - return ((Player const*)target)->GetReputationRank(raw_tester_faction) >= REP_FRIENDLY; + return ((Player const*)target)->GetReputationMgr().GetRank(raw_tester_faction) >= REP_FRIENDLY; } } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 0691f71bc..1835b16ac 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 "7539" + #define REVISION_NR "7540" #endif // __REVISION_NR_H__ diff --git a/win/VC71/game.vcproj b/win/VC71/game.vcproj index 1fac58c4d..c9ade4015 100644 --- a/win/VC71/game.vcproj +++ b/win/VC71/game.vcproj @@ -720,6 +720,12 @@ + + + + diff --git a/win/VC80/game.vcproj b/win/VC80/game.vcproj index 30cce87e4..f0721a841 100644 --- a/win/VC80/game.vcproj +++ b/win/VC80/game.vcproj @@ -1134,6 +1134,14 @@ RelativePath="..\..\src\game\ReactorAI.h" > + + + + diff --git a/win/VC90/game.vcproj b/win/VC90/game.vcproj index e7117d0e7..2ba06dc11 100644 --- a/win/VC90/game.vcproj +++ b/win/VC90/game.vcproj @@ -1136,6 +1136,14 @@ RelativePath="..\..\src\game\ReactorAI.h" > + + + +