2010-10-07 15:35:36 +02:00
/*
2020-01-02 06:44:10 +01:00
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
2010-10-07 15:35:36 +02:00
*
* 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
2009-03-26 14:03:55 -06:00
#include "ReputationMgr.h"
2017-05-18 23:52:58 +02:00
#include "CharacterPackets.h"
#include "DatabaseEnv.h"
2017-06-04 01:00:45 +02:00
#include "DB2Stores.h"
2017-05-18 23:52:58 +02:00
#include "Log.h"
2010-07-27 04:31:27 +02:00
#include "ObjectMgr.h"
2017-05-18 23:52:58 +02:00
#include "Player.h"
#include "ReputationPackets.h"
#include "ScriptMgr.h"
#include "World.h"
2012-11-20 16:01:31 +01:00
#include "WorldSession.h"
2009-10-17 15:51:44 -07:00
2021-06-04 19:27:26 +02:00
std :: set < int32 > const ReputationMgr :: ReputationRankThresholds =
{
- 42000 ,
// Hated
- 6000 ,
// Hostile
- 3000 ,
// Unfriendly
0 ,
// Neutral
3000 ,
// Friendly
9000 ,
// Honored
21000 ,
// Revered
42000
// Exalted
};
const int32 ReputationMgr :: Reputation_Cap = 42000 ;
2015-03-28 16:27:50 +01:00
const int32 ReputationMgr :: Reputation_Bottom = - 42000 ;
2021-06-04 19:27:26 +02:00
template < typename T , typename F >
static int32 ReputationToRankHelper ( std :: set < T > const & thresholds , int32 standing , F thresholdExtractor )
2009-03-26 14:03:55 -06:00
{
2021-06-04 19:27:26 +02:00
auto itr = thresholds . begin ();
auto end = thresholds . end ();
int32 rank = - 1 ;
while ( itr != end && standing >= thresholdExtractor ( * itr ))
2009-03-26 14:03:55 -06:00
{
2021-06-04 19:27:26 +02:00
++ rank ;
++ itr ;
2009-03-26 14:03:55 -06:00
}
2021-06-04 19:27:26 +02:00
return rank ;
}
ReputationRank ReputationMgr :: ReputationToRank ( FactionEntry const * factionEntry , int32 standing )
{
int32 rank = MIN_REPUTATION_RANK ;
if ( std :: set < FriendshipRepReactionEntry const *> const * friendshipReactions = sDB2Manager . GetFriendshipRepReactions ( factionEntry -> FriendshipRepID ))
rank = ReputationToRankHelper ( * friendshipReactions , standing , []( FriendshipRepReactionEntry const * frr ) { return frr -> ReactionThreshold ; });
else
rank = ReputationToRankHelper ( ReputationRankThresholds , standing , []( int32 threshold ) { return threshold ; });
return ReputationRank ( rank );
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2016-07-20 13:27:04 +02:00
FactionState const * ReputationMgr :: GetState ( FactionEntry const * factionEntry ) const
{
2020-08-14 17:06:03 +02:00
return factionEntry -> CanHaveReputation () ? GetState ( factionEntry -> ReputationIndex ) : nullptr ;
2016-07-20 13:27:04 +02: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 );
2015-02-17 21:08:28 +01:00
return false ;
2011-09-15 17:44:03 +02:00
}
return IsAtWar ( factionEntry );
}
bool ReputationMgr :: IsAtWar ( FactionEntry const * factionEntry ) const
{
if ( ! factionEntry )
return false ;
if ( FactionState const * factionState = GetState ( factionEntry ))
2021-06-05 23:00:06 +02:00
return factionState -> Flags . HasFlag ( ReputationFlags :: AtWar );
2011-09-15 17:44:03 +02:00
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
{
2021-06-04 19:27:26 +02:00
int32 dataIndex = GetFactionDataIndexForRaceAndClass ( factionEntry );
if ( dataIndex < 0 )
2009-03-26 14:03:55 -06:00
return 0 ;
2009-10-17 15:51:44 -07:00
2021-06-04 19:27:26 +02:00
return factionEntry -> ReputationBase [ dataIndex ];
}
2011-04-20 08:22:50 +02:00
2021-06-04 19:27:26 +02:00
int32 ReputationMgr :: GetMinReputation ( FactionEntry const * factionEntry ) const
{
if ( std :: set < FriendshipRepReactionEntry const *> const * friendshipReactions = sDB2Manager . GetFriendshipRepReactions ( factionEntry -> FriendshipRepID ))
return ( * friendshipReactions -> begin ()) -> ReactionThreshold ;
2009-10-17 15:51:44 -07:00
2021-06-04 19:27:26 +02:00
return * ReputationRankThresholds . begin ();
}
int32 ReputationMgr :: GetMaxReputation ( FactionEntry const * factionEntry ) const
{
2021-06-06 00:11:06 +02:00
if ( ParagonReputationEntry const * paragonReputation = sDB2Manager . GetParagonReputation ( factionEntry -> ID ))
{
// has reward quest, cap is just before threshold for another quest reward
// for example: if current reputation is 12345 and questa are given every 10000 and player has unclaimed reward
// then cap will be 19999
// otherwise cap is one theshold level larger
// if current reputation is 12345 and questa are given every 10000 and player does NOT have unclaimed reward
// then cap will be 29999
int32 reputation = GetReputation ( factionEntry );
int32 cap = reputation + paragonReputation -> LevelThreshold - reputation % paragonReputation -> LevelThreshold - 1 ;
if ( _player -> GetQuestStatus ( paragonReputation -> QuestID ) == QUEST_STATUS_NONE )
cap += paragonReputation -> LevelThreshold ;
return cap ;
}
2021-06-04 19:27:26 +02:00
if ( std :: set < FriendshipRepReactionEntry const *> const * friendshipReactions = sDB2Manager . GetFriendshipRepReactions ( factionEntry -> FriendshipRepID ))
return ( * friendshipReactions -> rbegin ()) -> ReactionThreshold ;
int32 dataIndex = GetFactionDataIndexForRaceAndClass ( factionEntry );
2021-06-06 00:11:06 +02:00
if ( dataIndex >= 0 )
2021-06-04 19:27:26 +02:00
return factionEntry -> ReputationMax [ dataIndex ];
return * ReputationRankThresholds . rbegin ();
2009-03-26 14:03:55 -06:00
}
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 );
2021-06-04 19:27:26 +02:00
return ReputationToRank ( factionEntry , reputation );
2009-03-26 14:03:55 -06:00
}
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 );
2021-06-04 19:27:26 +02:00
return ReputationToRank ( factionEntry , reputation );
}
std :: string ReputationMgr :: GetReputationRankName ( FactionEntry const * factionEntry ) const
{
ReputationRank rank = GetRank ( factionEntry );
if ( ! factionEntry -> FriendshipRepID )
return sObjectMgr -> GetTrinityString ( ReputationRankStrIndex [ GetRank ( factionEntry )], _player -> GetSession () -> GetSessionDbcLocale ());
if ( std :: set < FriendshipRepReactionEntry const *> const * friendshipReactions = sDB2Manager . GetFriendshipRepReactions ( factionEntry -> FriendshipRepID ))
{
auto itr = friendshipReactions -> begin ();
std :: advance ( itr , uint32 ( rank ));
return ( * itr ) -> Reaction [ _player -> GetSession () -> GetSessionDbcLocale ()];
}
return "" ;
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2016-07-20 13:27:04 +02:00
ReputationRank const * ReputationMgr :: GetForcedRankIfAny ( FactionTemplateEntry const * factionTemplateEntry ) const
{
return GetForcedRankIfAny ( factionTemplateEntry -> Faction );
}
2021-06-06 00:11:06 +02:00
int32 ReputationMgr :: GetParagonLevel ( uint32 paragonFactionId ) const
{
return GetParagonLevel ( sFactionStore . LookupEntry ( paragonFactionId ));
}
int32 ReputationMgr :: GetParagonLevel ( FactionEntry const * paragonFactionEntry ) const
{
if ( ! paragonFactionEntry )
return 0 ;
if ( ParagonReputationEntry const * paragonReputation = sDB2Manager . GetParagonReputation ( paragonFactionEntry -> ID ))
return GetReputation ( paragonFactionEntry ) / paragonReputation -> LevelThreshold ;
return 0 ;
}
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
2021-06-05 23:00:06 +02:00
ReputationFlags ReputationMgr :: GetDefaultStateFlags ( FactionEntry const * factionEntry ) const
2009-03-26 14:03:55 -06:00
{
2021-06-06 00:11:06 +02:00
ReputationFlags flags = [ & ]()
{
int32 dataIndex = GetFactionDataIndexForRaceAndClass ( factionEntry );
if ( dataIndex < 0 )
return ReputationFlags :: None ;
return static_cast < ReputationFlags > ( factionEntry -> ReputationFlags [ dataIndex ]);
}();
if ( sDB2Manager . GetParagonReputation ( factionEntry -> ID ))
flags |= ReputationFlags :: ShowPropagated ;
2009-10-17 15:51:44 -07:00
2021-06-06 00:11:06 +02:00
return flags ;
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 :: SendForceReactions ()
{
2015-04-09 00:05:31 +02:00
WorldPackets :: Reputation :: SetForcedReactions setForcedReactions ;
setForcedReactions . Reactions . resize ( _forcedReactions . size ());
std :: size_t i = 0 ;
2012-02-14 12:46:26 -05:00
for ( ForcedReactions :: const_iterator itr = _forcedReactions . begin (); itr != _forcedReactions . end (); ++ itr )
2009-03-26 14:03:55 -06:00
{
2015-04-09 00:05:31 +02:00
WorldPackets :: Reputation :: ForcedReaction & forcedReaction = setForcedReactions . Reactions [ i ++ ];
forcedReaction . Faction = int32 ( itr -> first );
forcedReaction . Reaction = int32 ( itr -> second );
2009-03-26 14:03:55 -06:00
}
2015-04-09 00:05:31 +02:00
_player -> SendDirectMessage ( setForcedReactions . Write ());
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
{
2016-03-07 23:26:54 +01:00
WorldPackets :: Reputation :: SetFactionStanding setFactionStanding ;
setFactionStanding . ReferAFriendBonus = 0.0f ;
setFactionStanding . BonusFromAchievementSystem = 0.0f ;
2017-06-15 04:19:12 +02:00
if ( faction )
setFactionStanding . Faction . emplace_back ( int32 ( faction -> ReputationListID ), faction -> Standing );
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 ;
2017-06-15 04:19:12 +02:00
if ( ! faction || itr -> second . ReputationListID != faction -> ReputationListID )
2016-03-07 23:26:54 +01:00
setFactionStanding . Faction . emplace_back ( int32 ( itr -> second . ReputationListID ), itr -> second . Standing );
2010-07-26 17:58:25 -06:00
}
2009-03-26 14:03:55 -06:00
}
2010-11-24 13:41:20 +01:00
2016-03-07 23:26:54 +01:00
setFactionStanding . ShowVisual = _sendFactionIncreased ;
_player -> SendDirectMessage ( setFactionStanding . Write ());
_sendFactionIncreased = false ; // Reset
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 ()
{
2014-11-17 18:21:41 +01:00
WorldPackets :: Reputation :: InitializeFactions initFactions ;
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
{
2021-06-05 23:00:06 +02:00
initFactions . FactionFlags [ itr -> first ] = itr -> second . Flags . AsUnderlyingType ();
2014-11-17 18:21:41 +01:00
initFactions . FactionStandings [ itr -> first ] = itr -> second . Standing ;
/// @todo faction bonus
2011-04-20 08:22:50 +02:00
itr -> second . needSend = false ;
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2014-11-17 18:21:41 +01:00
_player -> SendDirectMessage ( initFactions . Write ());
2009-03-26 14:03:55 -06:00
}
2009-10-17 15:51:44 -07:00
2015-04-22 23:26:31 +02:00
void ReputationMgr :: SendVisible ( FactionState const * faction , bool visible ) const
2009-03-26 14:03:55 -06:00
{
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
2014-08-31 21:57:51 +01:00
// make faction visible/not visible in reputation list at client
2015-04-22 23:26:31 +02:00
WorldPackets :: Character :: SetFactionVisible packet ( visible );
packet . FactionIndex = faction -> ReputationListID ;
_player -> SendDirectMessage ( packet . Write ());
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
2016-04-25 22:03:34 +02:00
for ( FactionEntry const * factionEntry : sFactionStore )
2009-03-26 14:03:55 -06:00
{
2016-04-25 22:03:34 +02:00
if ( factionEntry -> CanHaveReputation ())
2009-03-26 14:03:55 -06:00
{
FactionState newFaction ;
newFaction . ID = factionEntry -> ID ;
2014-11-08 19:26:20 +02:00
newFaction . ReputationListID = factionEntry -> ReputationIndex ;
2009-03-26 14:03:55 -06:00
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
2021-06-05 23:00:06 +02:00
if ( newFaction . Flags . HasFlag ( ReputationFlags :: Visible ))
2012-02-14 12:46:26 -05:00
++ _visibleFactionCount ;
2009-10-17 15:51:44 -07:00
2021-06-04 19:27:26 +02:00
if ( ! factionEntry -> FriendshipRepID )
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
2017-03-02 00:10:15 +01:00
bool ReputationMgr :: SetReputation ( FactionEntry const * factionEntry , int32 standing , bool incremental , bool spillOverOnly , bool noSpillover )
2009-03-26 14:03:55 -06:00
{
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 ;
2016-11-14 16:35:01 +01:00
if ( ! noSpillover )
2009-10-13 16:13:33 -07:00
{
2016-11-14 16:35:01 +01:00
// if spillover definition exists in DB, override DBC
2020-09-04 13:38:24 +02:00
if ( RepSpilloverTemplate const * repTemplate = sObjectMgr -> GetRepSpilloverTemplate ( factionEntry -> ID ))
2010-07-26 17:58:25 -06:00
{
2016-11-14 16:35:01 +01:00
for ( uint32 i = 0 ; i < MAX_SPILLOVER_FACTIONS ; ++ i )
2010-07-26 17:58:25 -06:00
{
2016-11-14 16:35:01 +01:00
if ( repTemplate -> faction [ i ])
2010-07-26 17:58:25 -06:00
{
2016-11-14 16:35:01 +01:00
if ( _player -> GetReputationRank ( repTemplate -> faction [ i ]) <= ReputationRank ( repTemplate -> faction_rank [ i ]))
{
// bonuses are already given, so just modify standing by rate
int32 spilloverRep = int32 ( standing * repTemplate -> faction_rate [ i ]);
SetOneFactionReputation ( sFactionStore . AssertEntry ( repTemplate -> faction [ i ]), spilloverRep , incremental );
}
2010-07-26 17:58:25 -06:00
}
}
}
2016-11-14 16:35:01 +01:00
else
2009-10-10 22:59:25 +02:00
{
2016-11-14 16:35:01 +01:00
float spillOverRepOut = float ( standing );
// check for sub-factions that receive spillover
std :: vector < uint32 > const * flist = sDB2Manager . GetFactionTeamList ( factionEntry -> ID );
// if has no sub-factions, check for factions with same parent
2018-03-12 18:20:26 +01:00
if ( ! flist && factionEntry -> ParentFactionID && factionEntry -> ParentFactionMod [ 1 ] != 0.0f )
2009-10-10 22:59:25 +02:00
{
2018-03-12 18:20:26 +01:00
spillOverRepOut *= factionEntry -> ParentFactionMod [ 1 ];
2016-11-14 16:35:01 +01:00
if ( FactionEntry const * parent = sFactionStore . LookupEntry ( factionEntry -> ParentFactionID ))
2010-11-24 13:41:20 +01:00
{
2016-11-14 16:35:01 +01:00
FactionStateList :: iterator parentState = _factions . find ( parent -> ReputationIndex );
// some team factions have own reputation standing, in this case do not spill to other sub-factions
2021-06-05 23:00:06 +02:00
if ( parentState != _factions . end () && parentState -> second . Flags . HasFlag ( ReputationFlags :: HeaderShowsBar ))
2016-11-14 16:35:01 +01:00
{
SetOneFactionReputation ( parent , int32 ( spillOverRepOut ), incremental );
}
else // spill to "sister" factions
{
flist = sDB2Manager . GetFactionTeamList ( factionEntry -> ParentFactionID );
}
2010-07-26 17:58:25 -06:00
}
2009-10-10 22:59:25 +02:00
}
2016-11-14 16:35:01 +01:00
if ( flist )
2010-11-24 13:41:20 +01:00
{
2016-11-14 16:35:01 +01:00
// Spillover to affiliated factions
for ( std :: vector < uint32 >:: const_iterator itr = flist -> begin (); itr != flist -> end (); ++ itr )
2010-11-24 13:41:20 +01:00
{
2016-11-14 16:35:01 +01:00
if ( FactionEntry const * factionEntryCalc = sFactionStore . LookupEntry ( * itr ))
{
2018-03-12 18:20:26 +01:00
if ( factionEntryCalc == factionEntry || GetRank ( factionEntryCalc ) > ReputationRank ( factionEntryCalc -> ParentFactionCap [ 0 ]))
2016-11-14 16:35:01 +01:00
continue ;
2018-03-12 18:20:26 +01:00
int32 spilloverRep = int32 ( spillOverRepOut * factionEntryCalc -> ParentFactionMod [ 0 ]);
2016-11-14 16:35:01 +01:00
if ( spilloverRep != 0 || ! incremental )
res = SetOneFactionReputation ( factionEntryCalc , spilloverRep , incremental );
}
2010-11-24 13:41:20 +01:00
}
}
}
}
2012-05-30 08:01:02 +02:00
2010-11-24 13:41:20 +01:00
// spillover done, update faction itself
2014-11-08 19:26:20 +02:00
FactionStateList :: iterator faction = _factions . find ( factionEntry -> ReputationIndex );
2012-02-14 12:46:26 -05:00
if ( faction != _factions . end ())
2010-11-24 13:41:20 +01:00
{
2021-06-06 00:11:06 +02:00
FactionEntry const * primaryFactionToModify = factionEntry ;
if ( incremental && standing > 0 && CanGainParagonReputationForFaction ( factionEntry ))
{
primaryFactionToModify = sFactionStore . AssertEntry ( factionEntry -> ParagonFactionID );
faction = _factions . find ( primaryFactionToModify -> ReputationIndex );
}
if ( faction != _factions . end ())
{
// if we update spillover only, do not update main reputation (rank exceeds creature reward rate)
if ( ! spillOverOnly )
res = SetOneFactionReputation ( primaryFactionToModify , standing , incremental );
2017-03-02 00:10:15 +01:00
2021-06-06 00:11:06 +02:00
// 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 )
{
2014-11-08 19:26:20 +02:00
FactionStateList :: iterator itr = _factions . find ( factionEntry -> ReputationIndex );
2012-02-14 12:46:26 -05:00
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
2021-06-04 19:27:26 +02:00
if ( standing > GetMaxReputation ( factionEntry ))
standing = GetMaxReputation ( factionEntry );
else if ( standing < GetMinReputation ( factionEntry ))
standing = GetMinReputation ( factionEntry );
2009-10-17 15:51:44 -07:00
2021-06-04 19:27:26 +02:00
ReputationRank old_rank = ReputationToRank ( factionEntry , itr -> second . Standing + BaseRep );
ReputationRank new_rank = ReputationToRank ( factionEntry , standing );
2009-10-17 15:51:44 -07:00
2021-06-06 00:11:06 +02:00
int32 oldStanding = itr -> second . Standing + BaseRep ;
2021-05-09 20:21:32 +02:00
int32 newStanding = standing - BaseRep ;
_player -> ReputationChanged ( factionEntry , newStanding - itr -> second . Standing );
itr -> second . Standing = newStanding ;
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 ;
2021-06-06 00:11:06 +02:00
ParagonReputationEntry const * paragonReputation = sDB2Manager . GetParagonReputation ( factionEntry -> ID );
if ( paragonReputation )
{
int32 oldParagonLevel = oldStanding / paragonReputation -> LevelThreshold ;
int32 newParagonLevel = standing / paragonReputation -> LevelThreshold ;
if ( oldParagonLevel != newParagonLevel )
if ( Quest const * paragonRewardQuest = sObjectMgr -> GetQuestTemplate ( paragonReputation -> QuestID ))
_player -> AddQuestAndCheckCompletion ( paragonRewardQuest , nullptr );
}
if ( ! factionEntry -> FriendshipRepID && ! paragonReputation )
2021-06-04 19:27:26 +02:00
UpdateRankCounters ( old_rank , new_rank );
2009-10-17 15:51:44 -07:00
2016-05-07 01:16:29 +02:00
_player -> UpdateCriteria ( CRITERIA_TYPE_KNOWN_FACTIONS , factionEntry -> ID );
_player -> UpdateCriteria ( CRITERIA_TYPE_GAIN_REPUTATION , factionEntry -> ID );
_player -> UpdateCriteria ( CRITERIA_TYPE_GAIN_EXALTED_REPUTATION , factionEntry -> ID );
_player -> UpdateCriteria ( CRITERIA_TYPE_GAIN_REVERED_REPUTATION , factionEntry -> ID );
_player -> UpdateCriteria ( 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
2014-11-08 19:26:20 +02:00
void ReputationMgr :: SetVisible ( FactionTemplateEntry const * factionTemplateEntry )
2009-03-26 14:03:55 -06:00
{
2014-11-08 19:26:20 +02:00
if ( ! factionTemplateEntry -> Faction )
2009-03-26 14:03:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2014-11-08 19:26:20 +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
2020-03-30 19:06:11 +02:00
if ( ! ( factionEntry -> ReputationRaceMask [ 1 ]. HasRace ( _player -> getRace ()) && factionEntry -> ReputationBase [ 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
{
2014-12-29 01:00:16 +01:00
if ( ! factionEntry -> CanHaveReputation ())
2009-03-26 14:03:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2014-11-08 19:26:20 +02:00
FactionStateList :: iterator itr = _factions . find ( factionEntry -> ReputationIndex );
2012-02-14 12:46:26 -05:00
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
2021-06-05 23:00:06 +02:00
if ( faction -> Flags . HasFlag ( ReputationFlags :: Hidden ))
return ;
if ( faction -> Flags . HasFlag ( ReputationFlags :: Header ) && ! faction -> Flags . HasFlag ( ReputationFlags :: HeaderShowsBar ))
2009-03-26 14:03:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2021-06-06 00:11:06 +02:00
if ( sDB2Manager . GetParagonReputation ( faction -> ID ))
return ;
2009-03-26 14:03:55 -06:00
// already set
2021-06-05 23:00:06 +02:00
if ( faction -> Flags . HasFlag ( ReputationFlags :: Visible ))
2009-03-26 14:03:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2021-06-05 23:00:06 +02:00
faction -> Flags |= ReputationFlags :: 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
2021-06-05 23:00:06 +02:00
if ( itr -> second . Flags . HasFlag ( ReputationFlags :: Hidden | ReputationFlags :: Header ))
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
{
2017-11-25 19:35:44 +01:00
// Do not allow to declare war to our own faction. But allow for rival factions (eg Aldor vs Scryer).
2021-06-05 23:00:06 +02:00
if ( atWar && faction -> Flags . HasFlag ( ReputationFlags :: Peaceful ))
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
2021-06-05 23:00:06 +02:00
if ( faction -> Flags . HasFlag ( ReputationFlags :: AtWar ) == 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 )
2021-06-05 23:00:06 +02:00
faction -> Flags |= ReputationFlags :: AtWar ;
2009-03-26 14:03:55 -06:00
else
2021-06-05 23:00:06 +02:00
faction -> Flags &= ~ ReputationFlags :: AtWar ;
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
2021-06-05 23:00:06 +02:00
if ( faction -> Flags . HasFlag ( ReputationFlags :: Hidden | ReputationFlags :: Header ) || ! faction -> Flags . HasFlag ( ReputationFlags :: 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
2021-06-05 23:00:06 +02:00
if ( faction -> Flags . HasFlag ( ReputationFlags :: Inactive ) == 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 )
2021-06-05 23:00:06 +02:00
faction -> Flags |= ReputationFlags :: Inactive ;
2009-03-26 14:03:55 -06:00
else
2021-06-05 23:00:06 +02:00
faction -> Flags &= ~ ReputationFlags :: 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 ());
2014-12-29 01:00:16 +01:00
if ( factionEntry && factionEntry -> CanHaveReputation ())
2009-03-26 14:03:55 -06:00
{
2014-11-08 19:26:20 +02:00
FactionState * faction = & _factions [ factionEntry -> ReputationIndex ];
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
2021-06-04 19:27:26 +02:00
if ( ! factionEntry -> FriendshipRepID )
{
int32 BaseRep = GetBaseReputation ( factionEntry );
ReputationRank old_rank = ReputationToRank ( factionEntry , BaseRep );
ReputationRank new_rank = ReputationToRank ( factionEntry , BaseRep + faction -> Standing );
UpdateRankCounters ( old_rank , new_rank );
}
2009-10-17 15:51:44 -07:00
2021-06-05 23:00:06 +02:00
EnumFlag < ReputationFlags > dbFactionFlags = static_cast < ReputationFlags > ( fields [ 2 ]. GetUInt16 ());
2009-10-17 15:51:44 -07:00
2021-06-05 23:00:06 +02:00
if ( dbFactionFlags . HasFlag ( ReputationFlags :: Visible ))
SetVisible ( faction ); // have internal checks for forced invisibility
2009-10-17 15:51:44 -07:00
2021-06-05 23:00:06 +02:00
if ( dbFactionFlags . HasFlag ( ReputationFlags :: Inactive ))
SetInactive ( faction , true ); // have internal checks for visibility requirement
2009-10-17 15:51:44 -07:00
2021-06-05 23:00:06 +02:00
if ( dbFactionFlags . HasFlag ( ReputationFlags :: AtWar )) // DB at war
SetAtWar ( faction , true ); // have internal checks for ReputationFlags::Peaceful
else // DB not at war
2009-03-26 14:03:55 -06:00
{
// allow remove if visible (and then not FACTION_FLAG_INVISIBLE_FORCED or FACTION_FLAG_HIDDEN)
2021-06-05 23:00:06 +02:00
if ( faction -> Flags . HasFlag ( ReputationFlags :: Visible ))
SetAtWar ( faction , false ); // have internal checks for ReputationFlags::Peaceful
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
2019-07-27 10:52:33 +02:00
void ReputationMgr :: SaveToDB ( CharacterDatabaseTransaction & 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
{
2019-07-27 01:00:37 +02:00
CharacterDatabasePreparedStatement * stmt = CharacterDatabase . GetPreparedStatement ( CHAR_DEL_CHAR_REPUTATION_BY_FACTION );
2014-10-23 23:04:16 +02:00
stmt -> setUInt64 ( 0 , _player -> GetGUID (). GetCounter ());
2012-05-30 08:01:02 +02:00
stmt -> setUInt16 ( 1 , uint16 ( itr -> second . ID ));
trans -> Append ( stmt );
stmt = CharacterDatabase . GetPreparedStatement ( CHAR_INS_CHAR_REPUTATION_BY_FACTION );
2014-10-23 23:04:16 +02:00
stmt -> setUInt64 ( 0 , _player -> GetGUID (). GetCounter ());
2012-05-30 08:01:02 +02:00
stmt -> setUInt16 ( 1 , uint16 ( itr -> second . ID ));
stmt -> setInt32 ( 2 , itr -> second . Standing );
2021-06-05 23:00:06 +02:00
stmt -> setUInt16 ( 3 , itr -> second . Flags . AsUnderlyingType ());
2012-05-30 08:01:02 +02:00
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
}
2021-06-04 19:27:26 +02:00
int32 ReputationMgr :: GetFactionDataIndexForRaceAndClass ( FactionEntry const * factionEntry ) const
{
if ( ! factionEntry )
return - 1 ;
uint8 race = _player -> getRace ();
uint32 classMask = _player -> getClassMask ();
for ( int32 i = 0 ; i < 4 ; i ++ )
{
if (( factionEntry -> ReputationRaceMask [ i ]. HasRace ( race ) || ( ! factionEntry -> ReputationRaceMask [ i ] && factionEntry -> ReputationClassMask [ i ] != 0 ))
&& ( factionEntry -> ReputationClassMask [ i ] & classMask || factionEntry -> ReputationClassMask [ i ] == 0 ))
return i ;
}
return - 1 ;
}
2021-06-06 00:11:06 +02:00
bool ReputationMgr :: CanGainParagonReputationForFaction ( FactionEntry const * factionEntry ) const
{
if ( ! sFactionStore . LookupEntry ( factionEntry -> ParagonFactionID ))
return false ;
if ( GetRank ( factionEntry ) != REP_EXALTED )
return false ;
ParagonReputationEntry const * paragonReputation = sDB2Manager . GetParagonReputation ( factionEntry -> ParagonFactionID );
if ( ! paragonReputation )
return false ;
Quest const * quest = sObjectMgr -> GetQuestTemplate ( paragonReputation -> QuestID );
if ( ! quest )
return false ;
return _player -> getLevel () >= _player -> GetQuestMinLevel ( quest );
}