2010-10-07 15:35:36 +02:00
/*
2014-01-01 00:07:53 +01:00
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
2010-10-07 15:35:36 +02:00
* 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, see <http://www.gnu.org/licenses/>.
2009-03-26 14:03:55 -06:00
*/
2009-10-17 15:51:44 -07:00
2010-08-21 09:53:04 +02:00
#include "DatabaseEnv.h"
2009-03-26 14:03:55 -06:00
#include "ReputationMgr.h"
2009-03-27 09:58:20 -06:00
#include "DBCStores.h"
2009-03-26 14:03:55 -06:00
#include "Player.h"
#include "WorldPacket.h"
2009-05-29 21:27:28 -05:00
#include "World.h"
2010-07-27 04:31:27 +02:00
#include "ObjectMgr.h"
2010-08-11 22:53:31 -07:00
#include "ScriptMgr.h"
2012-11-20 14:54:33 +01:00
#include "Opcodes.h"
2012-11-20 16:01:31 +01:00
#include "WorldSession.h"
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
const int32 ReputationMgr :: PointsInRank [ MAX_REPUTATION_RANK ] = { 36000 , 3000 , 3000 , 3000 , 6000 , 12000 , 21000 , 1000 };
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
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 ];
2010-04-07 22:59:46 +02:00
if ( standing >= limit )
2009-03-26 14:03:55 -06:00
return ReputationRank ( i );
}
return MIN_REPUTATION_RANK ;
}
2009-10-17 15:51:44 -07:00
2011-09-15 17:44:03 +02:00
bool ReputationMgr :: IsAtWar ( uint32 faction_id ) const
{
FactionEntry const * factionEntry = sFactionStore . LookupEntry ( faction_id );
if ( ! factionEntry )
{
2013-11-08 10:50:51 +01:00
TC_LOG_ERROR ( "misc" , "ReputationMgr::IsAtWar: Can't get AtWar flag of %s for unknown faction (faction id) #%u." , _player -> GetName (). c_str (), faction_id );
2011-09-15 17:44:03 +02:00
return 0 ;
}
return IsAtWar ( factionEntry );
}
bool ReputationMgr :: IsAtWar ( FactionEntry const * factionEntry ) const
{
if ( ! factionEntry )
return false ;
if ( FactionState const * factionState = GetState ( factionEntry ))
return ( factionState -> Flags & FACTION_FLAG_AT_WAR );
return false ;
}
2009-03-26 14:03:55 -06:00
int32 ReputationMgr :: GetReputation ( uint32 faction_id ) const
{
2011-09-15 14:08:17 +02:00
FactionEntry const * factionEntry = sFactionStore . LookupEntry ( faction_id );
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
if ( ! factionEntry )
{
2013-11-08 10:50:51 +01:00
TC_LOG_ERROR ( "misc" , "ReputationMgr::GetReputation: Can't get reputation of %s for unknown faction (faction id) #%u." , _player -> GetName (). c_str (), faction_id );
2009-03-26 14:03:55 -06:00
return 0 ;
}
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
return GetReputation ( factionEntry );
}
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
int32 ReputationMgr :: GetBaseReputation ( FactionEntry const * factionEntry ) const
{
if ( ! factionEntry )
return 0 ;
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
uint32 raceMask = _player -> getRaceMask ();
uint32 classMask = _player -> getClassMask ();
2009-03-26 14:03:55 -06:00
for ( int i = 0 ; i < 4 ; i ++ )
{
2010-04-07 22:59:46 +02:00
if (( factionEntry -> BaseRepRaceMask [ i ] & raceMask ||
2009-10-07 16:09:12 +02:00
( factionEntry -> BaseRepRaceMask [ i ] == 0 &&
2010-04-07 22:59:46 +02:00
factionEntry -> BaseRepClassMask [ i ] != 0 )) &&
2009-10-07 14:29:49 +02:00
( factionEntry -> BaseRepClassMask [ i ] & classMask ||
2011-04-20 08:22:50 +02:00
factionEntry -> BaseRepClassMask [ i ] == 0 ))
2009-03-26 14:03:55 -06:00
return factionEntry -> BaseRepValue [ i ];
}
2009-10-17 15:51:44 -07:00
2010-04-07 23:25:02 +02:00
// in faction.dbc exist factions with (RepListId >=0, listed in character reputation list) with all BaseRepRaceMask[i] == 0
2009-03-26 14:03:55 -06:00
return 0 ;
}
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
int32 ReputationMgr :: GetReputation ( FactionEntry const * factionEntry ) const
{
// Faction without recorded reputation. Just ignore.
2010-04-07 19:14:10 +02:00
if ( ! factionEntry )
2009-03-26 14:03:55 -06:00
return 0 ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( FactionState const * state = GetState ( factionEntry ))
2009-03-26 14:03:55 -06:00
return GetBaseReputation ( factionEntry ) + state -> Standing ;
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
return 0 ;
}
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
ReputationRank ReputationMgr :: GetRank ( FactionEntry const * factionEntry ) const
{
int32 reputation = GetReputation ( factionEntry );
return ReputationToRank ( reputation );
}
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
ReputationRank ReputationMgr :: GetBaseRank ( FactionEntry const * factionEntry ) const
{
int32 reputation = GetBaseReputation ( factionEntry );
return ReputationToRank ( reputation );
}
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
void ReputationMgr :: ApplyForceReaction ( uint32 faction_id , ReputationRank rank , bool apply )
2009-03-26 14:03:55 -06:00
{
2010-04-07 19:14:10 +02:00
if ( apply )
2012-02-14 12:46:26 -05:00
_forcedReactions [ faction_id ] = rank ;
2009-03-26 14:03:55 -06:00
else
2012-02-14 12:46:26 -05:00
_forcedReactions . erase ( faction_id );
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
uint32 ReputationMgr :: GetDefaultStateFlags ( FactionEntry const * factionEntry ) const
{
if ( ! factionEntry )
return 0 ;
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
uint32 raceMask = _player -> getRaceMask ();
uint32 classMask = _player -> getClassMask ();
2009-03-26 14:03:55 -06:00
for ( int i = 0 ; i < 4 ; i ++ )
{
2010-04-07 22:59:46 +02:00
if (( factionEntry -> BaseRepRaceMask [ i ] & raceMask ||
2009-10-11 02:29:52 +02:00
( factionEntry -> BaseRepRaceMask [ i ] == 0 &&
2010-04-07 22:59:46 +02:00
factionEntry -> BaseRepClassMask [ i ] != 0 )) &&
2009-10-11 02:29:52 +02:00
( factionEntry -> BaseRepClassMask [ i ] & classMask ||
2011-04-20 08:22:50 +02:00
factionEntry -> BaseRepClassMask [ i ] == 0 ))
2009-03-26 14:03:55 -06:00
return factionEntry -> ReputationFlags [ i ];
}
return 0 ;
}
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
void ReputationMgr :: SendForceReactions ()
{
WorldPacket data ;
2012-02-14 12:46:26 -05:00
data . Initialize ( SMSG_SET_FORCED_REACTIONS , 4 + _forcedReactions . size () * ( 4 + 4 ));
data << uint32 ( _forcedReactions . size ());
for ( ForcedReactions :: const_iterator itr = _forcedReactions . begin (); itr != _forcedReactions . end (); ++ itr )
2009-03-26 14:03:55 -06:00
{
data << uint32 ( itr -> first ); // faction_id (Faction.dbc)
data << uint32 ( itr -> second ); // reputation rank
}
2012-02-14 12:46:26 -05:00
_player -> SendDirectMessage ( & data );
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2010-11-24 13:41:20 +01:00
void ReputationMgr :: SendState ( FactionState const * faction )
2009-03-26 14:03:55 -06:00
{
2010-11-24 13:41:20 +01:00
uint32 count = 1 ;
2010-07-26 17:58:25 -06:00
2012-05-30 08:01:02 +02:00
WorldPacket data ( SMSG_SET_FACTION_STANDING , 17 );
data << float ( 0 );
data << uint8 ( _sendFactionIncreased );
_sendFactionIncreased = false ; // Reset
2010-07-26 17:58:25 -06:00
2010-11-24 13:41:20 +01:00
size_t p_count = data . wpos ();
2012-05-30 08:01:02 +02:00
data << uint32 ( count );
2010-08-08 19:45:53 +02:00
2012-05-30 08:01:02 +02:00
data << uint32 ( faction -> ReputationListID );
data << uint32 ( faction -> Standing );
2010-07-26 17:58:25 -06:00
2012-02-14 12:46:26 -05:00
for ( FactionStateList :: iterator itr = _factions . begin (); itr != _factions . end (); ++ itr )
2010-11-24 13:41:20 +01:00
{
if ( itr -> second . needSend )
2010-07-26 17:58:25 -06:00
{
2010-11-24 13:41:20 +01:00
itr -> second . needSend = false ;
if ( itr -> second . ReputationListID != faction -> ReputationListID )
2010-07-26 17:58:25 -06:00
{
2012-05-30 08:01:02 +02:00
data << uint32 ( itr -> second . ReputationListID );
data << uint32 ( itr -> second . Standing );
2010-07-26 17:58:25 -06:00
++ count ;
}
}
2009-03-26 14:03:55 -06:00
}
2010-11-24 13:41:20 +01:00
data . put < uint32 > ( p_count , count );
2012-02-14 12:46:26 -05:00
_player -> SendDirectMessage ( & data );
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
void ReputationMgr :: SendInitialReputations ()
{
2012-11-27 15:06:40 +01:00
uint16 count = 256 ;
2012-11-27 13:02:04 +01:00
WorldPacket data ( SMSG_INITIALIZE_FACTIONS , 4 + count * 5 );
data << uint32 ( count );
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
RepListID a = 0 ;
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
for ( FactionStateList :: iterator itr = _factions . begin (); itr != _factions . end (); ++ itr )
2009-03-26 14:03:55 -06:00
{
// fill in absent fields
2012-07-11 23:28:40 +02:00
for (; a != itr -> first ; ++ a )
2009-03-26 14:03:55 -06:00
{
2012-07-11 23:28:40 +02:00
data << uint8 ( 0 );
data << uint32 ( 0 );
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
// fill in encountered data
2012-07-11 23:28:40 +02:00
data << uint8 ( itr -> second . Flags );
data << uint32 ( itr -> second . Standing );
2009-10-17 15:51:44 -07:00
2011-04-20 08:22:50 +02:00
itr -> second . needSend = false ;
2009-03-26 14:03:55 -06:00
++ a ;
}
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
// fill in absent fields
2012-11-27 13:02:04 +01:00
for (; a != count ; ++ a )
2009-03-26 14:03:55 -06:00
{
2012-11-27 13:02:04 +01:00
data << uint8 ( 0 );
data << uint32 ( 0 );
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
_player -> SendDirectMessage ( & data );
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2010-11-24 13:41:20 +01:00
void ReputationMgr :: SendStates ()
2009-03-26 14:03:55 -06:00
{
2012-02-14 12:46:26 -05:00
for ( FactionStateList :: iterator itr = _factions . begin (); itr != _factions . end (); ++ itr )
2009-03-26 14:03:55 -06:00
SendState ( & ( itr -> second ));
}
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
void ReputationMgr :: SendVisible ( FactionState const * faction ) const
{
2012-02-14 12:46:26 -05:00
if ( _player -> GetSession () -> PlayerLoading ())
2009-03-26 14:03:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
// make faction visible in reputation list at client
WorldPacket data ( SMSG_SET_FACTION_VISIBLE , 4 );
data << faction -> ReputationListID ;
2012-02-14 12:46:26 -05:00
_player -> SendDirectMessage ( & data );
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2009-10-11 02:29:52 +02:00
void ReputationMgr :: Initialize ()
2009-03-26 14:03:55 -06:00
{
2012-02-14 12:46:26 -05:00
_factions . clear ();
_visibleFactionCount = 0 ;
_honoredFactionCount = 0 ;
_reveredFactionCount = 0 ;
_exaltedFactionCount = 0 ;
2012-05-30 08:01:02 +02:00
_sendFactionIncreased = false ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( unsigned int i = 1 ; i < sFactionStore . GetNumRows (); i ++ )
2009-03-26 14:03:55 -06:00
{
2011-09-15 14:08:17 +02:00
FactionEntry const * factionEntry = sFactionStore . LookupEntry ( i );
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
if ( factionEntry && ( factionEntry -> reputationListID >= 0 ))
2009-03-26 14:03:55 -06:00
{
FactionState newFaction ;
newFaction . ID = factionEntry -> ID ;
newFaction . ReputationListID = factionEntry -> reputationListID ;
newFaction . Standing = 0 ;
newFaction . Flags = GetDefaultStateFlags ( factionEntry );
2010-11-24 13:41:20 +01:00
newFaction . needSend = true ;
newFaction . needSave = true ;
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
if ( newFaction . Flags & FACTION_FLAG_VISIBLE )
2012-02-14 12:46:26 -05:00
++ _visibleFactionCount ;
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
UpdateRankCounters ( REP_HOSTILE , GetBaseRank ( factionEntry ));
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
_factions [ newFaction . ReputationListID ] = newFaction ;
2009-03-26 14:03:55 -06:00
}
}
}
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
bool ReputationMgr :: SetReputation ( FactionEntry const * factionEntry , int32 standing , bool incremental )
{
2012-02-14 12:46:26 -05:00
sScriptMgr -> OnPlayerReputationChange ( _player , factionEntry -> ID , standing , incremental );
2010-11-24 13:41:20 +01:00
bool res = false ;
// if spillover definition exists in DB, override DBC
2011-09-15 14:08:17 +02:00
if ( const RepSpilloverTemplate * repTemplate = sObjectMgr -> GetRepSpilloverTemplate ( factionEntry -> ID ))
2009-10-13 16:13:33 -07:00
{
2010-11-24 13:41:20 +01:00
for ( uint32 i = 0 ; i < MAX_SPILLOVER_FACTIONS ; ++ i )
2010-07-26 17:58:25 -06:00
{
2010-11-24 13:41:20 +01:00
if ( repTemplate -> faction [ i ])
2010-07-26 17:58:25 -06:00
{
2012-02-14 12:46:26 -05:00
if ( _player -> GetReputationRank ( repTemplate -> faction [ i ]) <= ReputationRank ( repTemplate -> faction_rank [ i ]))
2010-07-26 17:58:25 -06:00
{
2010-11-24 13:41:20 +01:00
// bonuses are already given, so just modify standing by rate
2010-11-29 15:50:38 +06:00
int32 spilloverRep = int32 ( standing * repTemplate -> faction_rate [ i ]);
2010-11-24 13:41:20 +01:00
SetOneFactionReputation ( sFactionStore . LookupEntry ( repTemplate -> faction [ i ]), spilloverRep , incremental );
2010-07-26 17:58:25 -06:00
}
}
}
2009-10-13 16:13:33 -07:00
}
2010-07-26 17:58:25 -06:00
else
2009-03-26 14:03:55 -06:00
{
2010-11-29 15:50:38 +06:00
float spillOverRepOut = float ( standing );
2010-11-24 13:41:20 +01:00
// 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 )
2009-10-10 22:59:25 +02:00
{
2010-11-24 13:41:20 +01:00
spillOverRepOut *= factionEntry -> spilloverRateOut ;
2011-09-15 14:08:17 +02:00
if ( FactionEntry const * parent = sFactionStore . LookupEntry ( factionEntry -> team ))
2009-10-10 22:59:25 +02:00
{
2012-02-14 12:46:26 -05:00
FactionStateList :: iterator parentState = _factions . find ( parent -> reputationListID );
2010-11-24 13:41:20 +01:00
// some team factions have own reputation standing, in this case do not spill to other sub-factions
2012-02-14 12:46:26 -05:00
if ( parentState != _factions . end () && ( parentState -> second . Flags & FACTION_FLAG_SPECIAL ))
2010-11-24 13:41:20 +01:00
{
SetOneFactionReputation ( parent , int32 ( spillOverRepOut ), incremental );
}
else // spill to "sister" factions
2010-07-26 17:58:25 -06:00
{
2010-11-24 13:41:20 +01:00
flist = GetFactionTeamList ( factionEntry -> team );
2010-07-26 17:58:25 -06:00
}
2009-10-10 22:59:25 +02:00
}
2009-03-26 14:03:55 -06:00
}
2010-11-24 13:41:20 +01:00
if ( flist )
{
// Spillover to affiliated factions
for ( SimpleFactionsList :: const_iterator itr = flist -> begin (); itr != flist -> end (); ++ itr )
{
2011-09-15 14:08:17 +02:00
if ( FactionEntry const * factionEntryCalc = sFactionStore . LookupEntry ( * itr ))
2010-11-24 13:41:20 +01:00
{
if ( factionEntryCalc == factionEntry || GetRank ( factionEntryCalc ) > ReputationRank ( factionEntryCalc -> spilloverMaxRankIn ))
continue ;
int32 spilloverRep = int32 ( spillOverRepOut * factionEntryCalc -> spilloverRateIn );
if ( spilloverRep != 0 || ! incremental )
res = SetOneFactionReputation ( factionEntryCalc , spilloverRep , incremental );
}
}
}
}
2012-05-30 08:01:02 +02:00
2010-11-24 13:41:20 +01:00
// spillover done, update faction itself
2012-02-14 12:46:26 -05:00
FactionStateList :: iterator faction = _factions . find ( factionEntry -> reputationListID );
if ( faction != _factions . end ())
2010-11-24 13:41:20 +01:00
{
res = SetOneFactionReputation ( factionEntry , standing , incremental );
// only this faction gets reported to client, even if it has no own visible standing
SendState ( & faction -> second );
2010-07-26 17:58:25 -06:00
}
2010-11-24 13:41:20 +01:00
return res ;
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
bool ReputationMgr :: SetOneFactionReputation ( FactionEntry const * factionEntry , int32 standing , bool incremental )
{
2012-02-14 12:46:26 -05:00
FactionStateList :: iterator itr = _factions . find ( factionEntry -> reputationListID );
if ( itr != _factions . end ())
2009-03-26 14:03:55 -06:00
{
int32 BaseRep = GetBaseReputation ( factionEntry );
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( incremental )
2009-05-29 21:27:28 -05:00
{
2009-06-07 16:23:03 -05:00
// int32 *= float cause one point loss?
2011-10-17 07:38:27 -03:00
standing = int32 ( floor (( float ) standing * sWorld -> getRate ( RATE_REPUTATION_GAIN ) + 0.5f ));
2009-03-26 14:03:55 -06:00
standing += itr -> second . Standing + BaseRep ;
2009-05-29 21:27:28 -05:00
}
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
if ( standing > Reputation_Cap )
standing = Reputation_Cap ;
else if ( standing < Reputation_Bottom )
standing = Reputation_Bottom ;
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
ReputationRank old_rank = ReputationToRank ( itr -> second . Standing + BaseRep );
ReputationRank new_rank = ReputationToRank ( standing );
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
itr -> second . Standing = standing - BaseRep ;
2010-11-24 13:41:20 +01:00
itr -> second . needSend = true ;
itr -> second . needSave = true ;
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
SetVisible ( & itr -> second );
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( new_rank <= REP_HOSTILE )
2011-04-29 20:47:02 +02:00
SetAtWar ( & itr -> second , true );
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
if ( new_rank > old_rank )
_sendFactionIncreased = true ;
2009-03-26 14:03:55 -06:00
UpdateRankCounters ( old_rank , new_rank );
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
_player -> ReputationChanged ( factionEntry );
2012-07-09 11:08:33 +02:00
_player -> UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS , factionEntry -> ID );
_player -> UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION , factionEntry -> ID );
_player -> UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION , factionEntry -> ID );
_player -> UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION , factionEntry -> ID );
_player -> UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION , factionEntry -> ID );
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
return true ;
}
return false ;
}
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
void ReputationMgr :: SetVisible ( FactionTemplateEntry const * factionTemplateEntry )
{
2010-04-07 19:14:10 +02:00
if ( ! factionTemplateEntry -> faction )
2009-03-26 14:03:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
if ( FactionEntry const * factionEntry = sFactionStore . LookupEntry ( factionTemplateEntry -> faction ))
2009-10-11 19:35:54 +02:00
// Never show factions of the opposing team
2012-02-14 12:46:26 -05:00
if ( ! ( factionEntry -> BaseRepRaceMask [ 1 ] & _player -> getRaceMask () && factionEntry -> BaseRepValue [ 1 ] == Reputation_Bottom ))
2009-10-11 19:35:54 +02:00
SetVisible ( factionEntry );
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
void ReputationMgr :: SetVisible ( FactionEntry const * factionEntry )
2009-03-26 14:03:55 -06:00
{
2010-04-07 19:14:10 +02:00
if ( factionEntry -> reputationListID < 0 )
2009-03-26 14:03:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
FactionStateList :: iterator itr = _factions . find ( factionEntry -> reputationListID );
if ( itr == _factions . end ())
2009-03-26 14:03:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
SetVisible ( & itr -> second );
}
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
void ReputationMgr :: SetVisible ( FactionState * faction )
{
// always invisible or hidden faction can't be make visible
2009-10-11 02:29:52 +02:00
// except if faction has FACTION_FLAG_SPECIAL
2010-04-07 22:59:46 +02:00
if ( faction -> Flags & ( FACTION_FLAG_INVISIBLE_FORCED | FACTION_FLAG_HIDDEN ) && ! ( faction -> Flags & FACTION_FLAG_SPECIAL ))
2009-03-26 14:03:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
// already set
2010-04-07 19:14:10 +02:00
if ( faction -> Flags & FACTION_FLAG_VISIBLE )
2009-03-26 14:03:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
faction -> Flags |= FACTION_FLAG_VISIBLE ;
2010-11-24 13:41:20 +01:00
faction -> needSend = true ;
faction -> needSave = true ;
2009-10-17 15:51:44 -07:00
2012-02-14 12:46:26 -05:00
++ _visibleFactionCount ;
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
SendVisible ( faction );
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void ReputationMgr :: SetAtWar ( RepListID repListID , bool on )
2009-03-26 14:03:55 -06:00
{
2012-02-14 12:46:26 -05:00
FactionStateList :: iterator itr = _factions . find ( repListID );
if ( itr == _factions . end ())
2009-03-26 14:03:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
// always invisible or hidden faction can't change war state
2010-04-07 22:59:46 +02:00
if ( itr -> second . Flags & ( FACTION_FLAG_INVISIBLE_FORCED | FACTION_FLAG_HIDDEN ))
2009-03-26 14:03:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
SetAtWar ( & itr -> second , on );
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2010-12-06 02:07:53 +01:00
void ReputationMgr :: SetAtWar ( FactionState * faction , bool atWar ) const
2009-03-26 14:03:55 -06:00
{
// not allow declare war to own faction
2010-04-07 22:59:46 +02:00
if ( atWar && ( faction -> Flags & FACTION_FLAG_PEACE_FORCED ))
2009-03-26 14:03:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
// already set
2010-04-07 19:14:10 +02:00
if ((( faction -> Flags & FACTION_FLAG_AT_WAR ) != 0 ) == atWar )
2009-03-26 14:03:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
if ( atWar )
2009-03-26 14:03:55 -06:00
faction -> Flags |= FACTION_FLAG_AT_WAR ;
else
faction -> Flags &= ~ FACTION_FLAG_AT_WAR ;
2009-10-17 15:51:44 -07:00
2010-11-24 13:41:20 +01:00
faction -> needSend = true ;
faction -> needSave = true ;
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void ReputationMgr :: SetInactive ( RepListID repListID , bool on )
2009-03-26 14:03:55 -06:00
{
2012-02-14 12:46:26 -05:00
FactionStateList :: iterator itr = _factions . find ( repListID );
if ( itr == _factions . end ())
2009-03-26 14:03:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
SetInactive ( & itr -> second , on );
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2010-12-06 02:07:53 +01:00
void ReputationMgr :: SetInactive ( FactionState * faction , bool inactive ) const
2009-03-26 14:03:55 -06:00
{
// always invisible or hidden faction can't be inactive
2010-04-07 22:59:46 +02:00
if ( inactive && (( faction -> Flags & ( FACTION_FLAG_INVISIBLE_FORCED | FACTION_FLAG_HIDDEN )) || ! ( faction -> Flags & FACTION_FLAG_VISIBLE )))
2009-03-26 14:03:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
// already set
2010-04-07 19:14:10 +02:00
if ((( faction -> Flags & FACTION_FLAG_INACTIVE ) != 0 ) == inactive )
2009-03-26 14:03:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( inactive )
2009-03-26 14:03:55 -06:00
faction -> Flags |= FACTION_FLAG_INACTIVE ;
else
faction -> Flags &= ~ FACTION_FLAG_INACTIVE ;
2009-10-17 15:51:44 -07:00
2010-11-24 13:41:20 +01:00
faction -> needSend = true ;
faction -> needSave = true ;
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2010-09-20 18:20:40 +02:00
void ReputationMgr :: LoadFromDB ( PreparedQueryResult result )
2009-03-26 14:03:55 -06:00
{
// Set initial reputations (so everything is nifty before DB data load)
2009-10-11 02:29:52 +02:00
Initialize ();
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
//QueryResult* result = CharacterDatabase.PQuery("SELECT faction, standing, flags FROM character_reputation WHERE guid = '%u'", GetGUIDLow());
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( result )
2009-03-26 14:03:55 -06:00
{
do
{
2010-09-24 22:16:21 +02:00
Field * fields = result -> Fetch ();
2011-09-15 14:08:17 +02:00
FactionEntry const * factionEntry = sFactionStore . LookupEntry ( fields [ 0 ]. GetUInt16 ());
2010-04-07 22:59:46 +02:00
if ( factionEntry && ( factionEntry -> reputationListID >= 0 ))
2009-03-26 14:03:55 -06:00
{
2012-02-14 12:46:26 -05:00
FactionState * faction = & _factions [ factionEntry -> reputationListID ];
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
// update standing to current
2012-05-30 08:01:02 +02:00
faction -> Standing = fields [ 1 ]. GetInt32 ();
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
// update counters
int32 BaseRep = GetBaseReputation ( factionEntry );
ReputationRank old_rank = ReputationToRank ( BaseRep );
ReputationRank new_rank = ReputationToRank ( BaseRep + faction -> Standing );
2010-09-20 18:20:40 +02:00
UpdateRankCounters ( old_rank , new_rank );
2009-10-17 15:51:44 -07:00
2011-01-19 18:40:36 +01:00
uint32 dbFactionFlags = fields [ 2 ]. GetUInt16 ();
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
if ( dbFactionFlags & FACTION_FLAG_VISIBLE )
2009-03-26 14:03:55 -06:00
SetVisible ( faction ); // have internal checks for forced invisibility
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
if ( dbFactionFlags & FACTION_FLAG_INACTIVE )
2011-04-29 20:47:02 +02:00
SetInactive ( faction , true ); // have internal checks for visibility requirement
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
if ( dbFactionFlags & FACTION_FLAG_AT_WAR ) // DB at war
2011-04-29 20:47:02 +02:00
SetAtWar ( faction , true ); // have internal checks for FACTION_FLAG_PEACE_FORCED
2009-03-26 14:03:55 -06:00
else // DB not at war
{
// allow remove if visible (and then not FACTION_FLAG_INVISIBLE_FORCED or FACTION_FLAG_HIDDEN)
2010-04-07 22:59:46 +02:00
if ( faction -> Flags & FACTION_FLAG_VISIBLE )
2011-04-29 20:47:02 +02:00
SetAtWar ( faction , false ); // have internal checks for FACTION_FLAG_PEACE_FORCED
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
// set atWar for hostile
2010-04-07 19:14:10 +02:00
if ( GetRank ( factionEntry ) <= REP_HOSTILE )
2011-04-29 20:47:02 +02:00
SetAtWar ( faction , true );
2009-10-17 15:51:44 -07:00
2009-03-26 14:03:55 -06:00
// reset changed flag if values similar to saved in DB
2010-04-07 23:25:02 +02:00
if ( faction -> Flags == dbFactionFlags )
2010-11-24 13:41:20 +01:00
{
faction -> needSend = false ;
faction -> needSave = false ;
}
2009-03-26 14:03:55 -06:00
}
}
2010-04-07 22:59:46 +02:00
while ( result -> NextRow ());
2009-03-26 14:03:55 -06:00
}
}
2009-10-17 15:51:44 -07:00
2010-08-21 03:19:25 +02:00
void ReputationMgr :: SaveToDB ( SQLTransaction & trans )
2009-03-26 14:03:55 -06:00
{
2012-02-14 12:46:26 -05:00
for ( FactionStateList :: iterator itr = _factions . begin (); itr != _factions . end (); ++ itr )
2009-03-26 14:03:55 -06:00
{
2010-11-24 13:41:20 +01:00
if ( itr -> second . needSave )
2009-03-26 14:03:55 -06:00
{
2012-05-30 08:01:02 +02:00
PreparedStatement * stmt = CharacterDatabase . GetPreparedStatement ( CHAR_DEL_CHAR_REPUTATION_BY_FACTION );
stmt -> setUInt32 ( 0 , _player -> GetGUIDLow ());
stmt -> setUInt16 ( 1 , uint16 ( itr -> second . ID ));
trans -> Append ( stmt );
stmt = CharacterDatabase . GetPreparedStatement ( CHAR_INS_CHAR_REPUTATION_BY_FACTION );
stmt -> setUInt32 ( 0 , _player -> GetGUIDLow ());
stmt -> setUInt16 ( 1 , uint16 ( itr -> second . ID ));
stmt -> setInt32 ( 2 , itr -> second . Standing );
stmt -> setUInt16 ( 3 , uint16 ( itr -> second . Flags ));
trans -> Append ( stmt );
2010-11-24 13:41:20 +01:00
itr -> second . needSave = false ;
2009-03-26 14:03:55 -06:00
}
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void ReputationMgr :: UpdateRankCounters ( ReputationRank old_rank , ReputationRank new_rank )
2009-03-26 14:03:55 -06:00
{
2010-04-07 19:14:10 +02:00
if ( old_rank >= REP_EXALTED )
2012-02-14 12:46:26 -05:00
-- _exaltedFactionCount ;
2010-04-07 19:14:10 +02:00
if ( old_rank >= REP_REVERED )
2012-02-14 12:46:26 -05:00
-- _reveredFactionCount ;
2010-04-07 19:14:10 +02:00
if ( old_rank >= REP_HONORED )
2012-02-14 12:46:26 -05:00
-- _honoredFactionCount ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( new_rank >= REP_EXALTED )
2012-02-14 12:46:26 -05:00
++ _exaltedFactionCount ;
2010-04-07 19:14:10 +02:00
if ( new_rank >= REP_REVERED )
2012-02-14 12:46:26 -05:00
++ _reveredFactionCount ;
2010-04-07 19:14:10 +02:00
if ( new_rank >= REP_HONORED )
2012-02-14 12:46:26 -05:00
++ _honoredFactionCount ;
2009-07-31 11:37:03 +08:00
}