2 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "ReputationMgr.h"
20 #include "DBCStores.h"
22 #include "WorldPacket.h"
24 const int32
ReputationMgr::PointsInRank
[MAX_REPUTATION_RANK
] = {36000, 3000, 3000, 3000, 6000, 12000, 21000, 1000};
26 ReputationRank
ReputationMgr::ReputationToRank(int32 standing
)
28 int32 limit
= Reputation_Cap
+ 1;
29 for (int i
= MAX_REPUTATION_RANK
-1; i
>= MIN_REPUTATION_RANK
; --i
)
31 limit
-= PointsInRank
[i
];
32 if (standing
>= limit
)
33 return ReputationRank(i
);
35 return MIN_REPUTATION_RANK
;
38 int32
ReputationMgr::GetReputation(uint32 faction_id
) const
40 FactionEntry
const *factionEntry
= sFactionStore
.LookupEntry(faction_id
);
44 sLog
.outError("ReputationMgr::GetReputation: Can't get reputation of %s for unknown faction (faction id) #%u.",m_player
->GetName(), faction_id
);
48 return GetReputation(factionEntry
);
51 int32
ReputationMgr::GetBaseReputation(FactionEntry
const* factionEntry
) const
56 uint32 raceMask
= m_player
->getRaceMask();
57 uint32 classMask
= m_player
->getClassMask();
58 for (int i
=0; i
< 4; i
++)
60 if( (factionEntry
->BaseRepRaceMask
[i
] & raceMask
) &&
61 (factionEntry
->BaseRepClassMask
[i
]==0 ||
62 (factionEntry
->BaseRepClassMask
[i
] & classMask
) ) )
63 return factionEntry
->BaseRepValue
[i
];
66 // in faction.dbc exist factions with (RepListId >=0, listed in character reputation list) with all BaseRepRaceMask[i]==0
70 int32
ReputationMgr::GetReputation(FactionEntry
const* factionEntry
) const
72 // Faction without recorded reputation. Just ignore.
76 if(FactionState
const* state
= GetState(factionEntry
))
77 return GetBaseReputation(factionEntry
) + state
->Standing
;
82 ReputationRank
ReputationMgr::GetRank(FactionEntry
const* factionEntry
) const
84 int32 reputation
= GetReputation(factionEntry
);
85 return ReputationToRank(reputation
);
88 ReputationRank
ReputationMgr::GetBaseRank(FactionEntry
const* factionEntry
) const
90 int32 reputation
= GetBaseReputation(factionEntry
);
91 return ReputationToRank(reputation
);
94 void ReputationMgr::ApplyForceReaction( uint32 faction_id
,ReputationRank rank
,bool apply
)
97 m_forcedReactions
[faction_id
] = rank
;
99 m_forcedReactions
.erase(faction_id
);
102 uint32
ReputationMgr::GetDefaultStateFlags(FactionEntry
const* factionEntry
) const
107 uint32 raceMask
= m_player
->getRaceMask();
108 uint32 classMask
= m_player
->getClassMask();
109 for (int i
=0; i
< 4; i
++)
111 if( (factionEntry
->BaseRepRaceMask
[i
] & raceMask
) &&
112 (factionEntry
->BaseRepClassMask
[i
]==0 ||
113 (factionEntry
->BaseRepClassMask
[i
] & classMask
) ) )
114 return factionEntry
->ReputationFlags
[i
];
119 void ReputationMgr::SendForceReactions()
122 data
.Initialize(SMSG_SET_FORCED_REACTIONS
, 4+m_forcedReactions
.size()*(4+4));
123 data
<< uint32(m_forcedReactions
.size());
124 for(ForcedReactions::const_iterator itr
= m_forcedReactions
.begin(); itr
!= m_forcedReactions
.end(); ++itr
)
126 data
<< uint32(itr
->first
); // faction_id (Faction.dbc)
127 data
<< uint32(itr
->second
); // reputation rank
129 m_player
->SendDirectMessage(&data
);
132 void ReputationMgr::SendState(FactionState
const* faction
) const
134 if(faction
->Flags
& FACTION_FLAG_VISIBLE
) //If faction is visible then update it
136 WorldPacket
data(SMSG_SET_FACTION_STANDING
, (16)); // last check 2.4.0
137 data
<< (float) 0; // unk 2.4.0
138 data
<< (uint8
) 0; // wotlk 8634
139 data
<< (uint32
) 1; // count
141 data
<< (uint32
) faction
->ReputationListID
;
142 data
<< (uint32
) faction
->Standing
;
144 m_player
->SendDirectMessage(&data
);
148 void ReputationMgr::SendInitialReputations()
150 WorldPacket
data(SMSG_INITIALIZE_FACTIONS
, (4+128*5));
151 data
<< uint32 (0x00000080);
155 for (FactionStateList::const_iterator itr
= m_factions
.begin(); itr
!= m_factions
.end(); ++itr
)
157 // fill in absent fields
158 for (; a
!= itr
->first
; a
++)
160 data
<< uint8 (0x00);
161 data
<< uint32 (0x00000000);
164 // fill in encountered data
165 data
<< uint8 (itr
->second
.Flags
);
166 data
<< uint32 (itr
->second
.Standing
);
171 // fill in absent fields
172 for (; a
!= 128; a
++)
174 data
<< uint8 (0x00);
175 data
<< uint32 (0x00000000);
178 m_player
->SendDirectMessage(&data
);
181 void ReputationMgr::SendStates() const
183 for(FactionStateList::const_iterator itr
= m_factions
.begin(); itr
!= m_factions
.end(); ++itr
)
184 SendState(&(itr
->second
));
187 void ReputationMgr::SendVisible(FactionState
const* faction
) const
189 if(m_player
->GetSession()->PlayerLoading())
192 // make faction visible in reputation list at client
193 WorldPacket
data(SMSG_SET_FACTION_VISIBLE
, 4);
194 data
<< faction
->ReputationListID
;
195 m_player
->SendDirectMessage(&data
);
198 void ReputationMgr::Initilize()
201 m_visibleFactionCount
= 0;
202 m_honoredFactionCount
= 0;
203 m_reveredFactionCount
= 0;
204 m_exaltedFactionCount
= 0;
206 for(unsigned int i
= 1; i
< sFactionStore
.GetNumRows(); i
++)
208 FactionEntry
const *factionEntry
= sFactionStore
.LookupEntry(i
);
210 if( factionEntry
&& (factionEntry
->reputationListID
>= 0))
212 FactionState newFaction
;
213 newFaction
.ID
= factionEntry
->ID
;
214 newFaction
.ReputationListID
= factionEntry
->reputationListID
;
215 newFaction
.Standing
= 0;
216 newFaction
.Flags
= GetDefaultStateFlags(factionEntry
);
217 newFaction
.Changed
= true;
219 if( newFaction
.Flags
& FACTION_FLAG_VISIBLE
)
220 ++m_visibleFactionCount
;
222 UpdateRankCounters(REP_HOSTILE
,GetBaseRank(factionEntry
));
224 m_factions
[newFaction
.ReputationListID
] = newFaction
;
229 bool ReputationMgr::SetReputation(FactionEntry
const* factionEntry
, int32 standing
, bool incremental
)
231 SimpleFactionsList
const* flist
= GetFactionTeamList(factionEntry
->ID
);
235 for (SimpleFactionsList::const_iterator itr
= flist
->begin();itr
!= flist
->end();++itr
)
237 FactionEntry
const *factionEntryCalc
= sFactionStore
.LookupEntry(*itr
);
239 res
= SetOneFactionReputation(factionEntryCalc
, standing
, incremental
);
244 return SetOneFactionReputation(factionEntry
, standing
, incremental
);
247 bool ReputationMgr::SetOneFactionReputation(FactionEntry
const* factionEntry
, int32 standing
, bool incremental
)
249 FactionStateList::iterator itr
= m_factions
.find(factionEntry
->reputationListID
);
250 if (itr
!= m_factions
.end())
252 int32 BaseRep
= GetBaseReputation(factionEntry
);
255 standing
+= itr
->second
.Standing
+ BaseRep
;
257 if (standing
> Reputation_Cap
)
258 standing
= Reputation_Cap
;
259 else if (standing
< Reputation_Bottom
)
260 standing
= Reputation_Bottom
;
262 ReputationRank old_rank
= ReputationToRank(itr
->second
.Standing
+ BaseRep
);
263 ReputationRank new_rank
= ReputationToRank(standing
);
265 itr
->second
.Standing
= standing
- BaseRep
;
266 itr
->second
.Changed
= true;
268 SetVisible(&itr
->second
);
270 if(new_rank
<= REP_HOSTILE
)
271 SetAtWar(&itr
->second
,true);
273 SendState(&itr
->second
);
275 UpdateRankCounters(old_rank
, new_rank
);
277 m_player
->ReputationChanged(factionEntry
);
278 m_player
->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS
, factionEntry
->ID
);
279 m_player
->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION
, factionEntry
->ID
);
280 m_player
->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION
,factionEntry
->ID
);
281 m_player
->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION
,factionEntry
->ID
);
282 m_player
->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION
,factionEntry
->ID
);
289 void ReputationMgr::SetVisible(FactionTemplateEntry
const*factionTemplateEntry
)
291 if(!factionTemplateEntry
->faction
)
294 if(FactionEntry
const *factionEntry
= sFactionStore
.LookupEntry(factionTemplateEntry
->faction
))
295 SetVisible(factionEntry
);
298 void ReputationMgr::SetVisible(FactionEntry
const *factionEntry
)
300 if(factionEntry
->reputationListID
< 0)
303 FactionStateList::iterator itr
= m_factions
.find(factionEntry
->reputationListID
);
304 if (itr
== m_factions
.end())
307 SetVisible(&itr
->second
);
310 void ReputationMgr::SetVisible(FactionState
* faction
)
312 // always invisible or hidden faction can't be make visible
313 if(faction
->Flags
& (FACTION_FLAG_INVISIBLE_FORCED
|FACTION_FLAG_HIDDEN
))
317 if(faction
->Flags
& FACTION_FLAG_VISIBLE
)
320 faction
->Flags
|= FACTION_FLAG_VISIBLE
;
321 faction
->Changed
= true;
323 ++m_visibleFactionCount
;
325 SendVisible(faction
);
328 void ReputationMgr::SetAtWar( RepListID repListID
, bool on
)
330 FactionStateList::iterator itr
= m_factions
.find(repListID
);
331 if (itr
== m_factions
.end())
334 // always invisible or hidden faction can't change war state
335 if(itr
->second
.Flags
& (FACTION_FLAG_INVISIBLE_FORCED
|FACTION_FLAG_HIDDEN
) )
338 SetAtWar(&itr
->second
,on
);
341 void ReputationMgr::SetAtWar(FactionState
* faction
, bool atWar
)
343 // not allow declare war to own faction
344 if(atWar
&& (faction
->Flags
& FACTION_FLAG_PEACE_FORCED
) )
348 if(((faction
->Flags
& FACTION_FLAG_AT_WAR
) != 0) == atWar
)
352 faction
->Flags
|= FACTION_FLAG_AT_WAR
;
354 faction
->Flags
&= ~FACTION_FLAG_AT_WAR
;
356 faction
->Changed
= true;
359 void ReputationMgr::SetInactive( RepListID repListID
, bool on
)
361 FactionStateList::iterator itr
= m_factions
.find(repListID
);
362 if (itr
== m_factions
.end())
365 SetInactive(&itr
->second
,on
);
368 void ReputationMgr::SetInactive(FactionState
* faction
, bool inactive
)
370 // always invisible or hidden faction can't be inactive
371 if(inactive
&& ((faction
->Flags
& (FACTION_FLAG_INVISIBLE_FORCED
|FACTION_FLAG_HIDDEN
)) || !(faction
->Flags
& FACTION_FLAG_VISIBLE
) ) )
375 if(((faction
->Flags
& FACTION_FLAG_INACTIVE
) != 0) == inactive
)
379 faction
->Flags
|= FACTION_FLAG_INACTIVE
;
381 faction
->Flags
&= ~FACTION_FLAG_INACTIVE
;
383 faction
->Changed
= true;
386 void ReputationMgr::LoadFromDB(QueryResult
*result
)
388 // Set initial reputations (so everything is nifty before DB data load)
391 //QueryResult *result = CharacterDatabase.PQuery("SELECT faction,standing,flags FROM character_reputation WHERE guid = '%u'",GetGUIDLow());
397 Field
*fields
= result
->Fetch();
399 FactionEntry
const *factionEntry
= sFactionStore
.LookupEntry(fields
[0].GetUInt32());
400 if( factionEntry
&& (factionEntry
->reputationListID
>= 0))
402 FactionState
* faction
= &m_factions
[factionEntry
->reputationListID
];
404 // update standing to current
405 faction
->Standing
= int32(fields
[1].GetUInt32());
408 int32 BaseRep
= GetBaseReputation(factionEntry
);
409 ReputationRank old_rank
= ReputationToRank(BaseRep
);
410 ReputationRank new_rank
= ReputationToRank(BaseRep
+ faction
->Standing
);
411 UpdateRankCounters(old_rank
,new_rank
);
413 uint32 dbFactionFlags
= fields
[2].GetUInt32();
415 if( dbFactionFlags
& FACTION_FLAG_VISIBLE
)
416 SetVisible(faction
); // have internal checks for forced invisibility
418 if( dbFactionFlags
& FACTION_FLAG_INACTIVE
)
419 SetInactive(faction
,true); // have internal checks for visibility requirement
421 if( dbFactionFlags
& FACTION_FLAG_AT_WAR
) // DB at war
422 SetAtWar(faction
,true); // have internal checks for FACTION_FLAG_PEACE_FORCED
423 else // DB not at war
425 // allow remove if visible (and then not FACTION_FLAG_INVISIBLE_FORCED or FACTION_FLAG_HIDDEN)
426 if( faction
->Flags
& FACTION_FLAG_VISIBLE
)
427 SetAtWar(faction
,false); // have internal checks for FACTION_FLAG_PEACE_FORCED
430 // set atWar for hostile
431 if(GetRank(factionEntry
) <= REP_HOSTILE
)
432 SetAtWar(faction
,true);
434 // reset changed flag if values similar to saved in DB
435 if(faction
->Flags
==dbFactionFlags
)
436 faction
->Changed
= false;
439 while( result
->NextRow() );
445 void ReputationMgr::SaveToDB()
447 for(FactionStateList::iterator itr
= m_factions
.begin(); itr
!= m_factions
.end(); ++itr
)
449 if (itr
->second
.Changed
)
451 CharacterDatabase
.PExecute("DELETE FROM character_reputation WHERE guid = '%u' AND faction='%u'", m_player
->GetGUIDLow(), itr
->second
.ID
);
452 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
);
453 itr
->second
.Changed
= false;
458 void ReputationMgr::UpdateRankCounters( ReputationRank old_rank
, ReputationRank new_rank
)
460 if(old_rank
>= REP_EXALTED
)
461 --m_exaltedFactionCount
;
462 if(old_rank
>= REP_REVERED
)
463 --m_reveredFactionCount
;
464 if(old_rank
>= REP_HONORED
)
465 --m_honoredFactionCount
;
467 if(new_rank
>= REP_EXALTED
)
468 ++m_exaltedFactionCount
;
469 if(new_rank
>= REP_REVERED
)
470 ++m_reveredFactionCount
;
471 if(new_rank
>= REP_HONORED
)
472 ++m_honoredFactionCount
;