TrinityCore
Loading...
Searching...
No Matches
KillRewarder.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "KillRewarder.h"
19#include "SpellAuraEffects.h"
20#include "Creature.h"
21#include "Formulas.h"
22#include "Group.h"
23#include "Guild.h"
24#include "GuildMgr.h"
25#include "InstanceScript.h"
26#include "Pet.h"
27#include "Player.h"
28
29 // == KillRewarder ====================================================
30 // KillRewarder encapsulates logic of rewarding player upon kill with:
31 // * XP;
32 // * honor;
33 // * reputation;
34 // * kill credit (for quest objectives).
35 // Rewarding is initiated in two cases: when player kills unit in Unit::Kill()
36 // and on battlegrounds in Battleground::RewardXPAtKill().
37 //
38 // Rewarding algorithm is:
39 // 1. Initialize internal variables to default values.
40 // 2. In case when player is in group, initialize variables necessary for group calculations:
41 // 2.1. _count - number of alive group members within reward distance;
42 // 2.2. _sumLevel - sum of levels of alive group members within reward distance;
43 // 2.3. _maxLevel - maximum level of alive group member within reward distance;
44 // 2.4. _maxNotGrayMember - maximum level of alive group member within reward distance,
45 // for whom victim is not gray;
46 // 2.5. _isFullXP - flag identifying that for all group members victim is not gray,
47 // so 100% XP will be rewarded (50% otherwise).
48 // 3. Reward killer (and group, if necessary).
49 // 3.1. If killer is in group, reward group.
50 // 3.1.1. Initialize initial XP amount based on maximum level of group member,
51 // for whom victim is not gray.
52 // 3.1.2. Alter group rate if group is in raid (not for battlegrounds).
53 // 3.1.3. Reward each group member (even dead) within reward distance (see 4. for more details).
54 // 3.2. Reward single killer (not group case).
55 // 3.2.1. Initialize initial XP amount based on killer's level.
56 // 3.2.2. Reward killer (see 4. for more details).
57 // 4. Reward player.
58 // 4.1. Give honor (player must be alive and not on BG).
59 // 4.2. Give XP.
60 // 4.2.1. If player is in group, adjust XP:
61 // * set to 0 if player's level is more than maximum level of not gray member;
62 // * cut XP in half if _isFullXP is false.
63 // 4.2.2. Apply auras modifying rewarded XP.
64 // 4.2.3. Give XP to player.
65 // 4.2.4. If player has pet, reward pet with XP (100% for single player, 50% for group case).
66 // 4.3. Give reputation (player must not be on BG).
67 // 4.4. Give kill credit (player must not be in group, or he must be alive or without corpse).
68 // 5. Credit instance encounter.
69
70KillRewarder::KillRewarder(Player* killer, Unit* victim, bool isBattleGround) :
71 // 1. Initialize internal variables to default values.
72 _killer(killer), _victim(victim), _group(killer->GetGroup()),
73 _groupRate(1.0f), _maxNotGrayMember(nullptr), _count(0), _sumLevel(0), _xp(0),
74 _isFullXP(false), _maxLevel(0), _isBattleGround(isBattleGround), _isPvP(false)
75{
76 // mark the credit as pvp if victim is player
77 if (victim->GetTypeId() == TYPEID_PLAYER)
78 _isPvP = true;
79 // or if its owned by player and its not a vehicle
80 else if (victim->GetCharmerOrOwnerGUID().IsPlayer())
81 _isPvP = !victim->IsVehicle();
82
84}
85
87{
88 if (_group)
89 {
90 // 2. In case when player is in group, initialize variables necessary for group calculations:
91 for (GroupReference* itr = _group->GetFirstMember(); itr != nullptr; itr = itr->next())
92 if (Player* member = itr->GetSource())
93 if (_killer == member || (member->IsAtGroupRewardDistance(_victim) && member->IsAlive()))
94 {
95 const uint8 lvl = member->GetLevel();
96 // 2.1. _count - number of alive group members within reward distance;
97 ++_count;
98 // 2.2. _sumLevel - sum of levels of alive group members within reward distance;
99 _sumLevel += lvl;
100 // 2.3. _maxLevel - maximum level of alive group member within reward distance;
101 if (_maxLevel < lvl)
102 _maxLevel = lvl;
103 // 2.4. _maxNotGrayMember - maximum level of alive group member within reward distance,
104 // for whom victim is not gray;
105 uint32 grayLevel = Trinity::XP::GetGrayLevel(lvl);
106 if (_victim->GetLevel() > grayLevel && (!_maxNotGrayMember || _maxNotGrayMember->GetLevel() < lvl))
107 _maxNotGrayMember = member;
108 }
109 // 2.5. _isFullXP - flag identifying that for all group members victim is not gray,
110 // so 100% XP will be rewarded (50% otherwise).
112 }
113 else
114 _count = 1;
115}
116
117inline void KillRewarder::_InitXP(Player* player)
118{
119 // Get initial value of XP for kill.
120 // XP is given:
121 // * on battlegrounds;
122 // * otherwise, not in PvP;
123 // * not if killer is on vehicle.
124 if (_isBattleGround || (!_isPvP && !_killer->GetVehicle()))
126}
127
129{
130 // Rewarded player must be alive.
131 if (player->IsAlive())
132 player->RewardHonor(_victim, _count, -1, true);
133}
134
135inline void KillRewarder::_RewardXP(Player* player, float rate)
136{
137 uint32 xp(_xp);
138 if (_group)
139 {
140 // 4.2.1. If player is in group, adjust XP:
141 // * set to 0 if player's level is more than maximum level of not gray member;
142 // * cut XP in half if _isFullXP is false.
143 if (_maxNotGrayMember && player->IsAlive() &&
144 _maxNotGrayMember->GetLevel() >= player->GetLevel())
145 xp = _isFullXP ?
146 uint32(xp * rate) : // Reward FULL XP if all group members are not gray.
147 uint32(xp * rate / 2) + 1; // Reward only HALF of XP if some of group members are gray.
148 else
149 xp = 0;
150 }
151 if (xp)
152 {
153 // 4.2.2. Apply auras modifying rewarded XP (SPELL_AURA_MOD_XP_PCT).
155
156 // 4.2.3. Give XP to player.
157 player->GiveXP(xp, _victim, _groupRate);
158 if (Pet* pet = player->GetPet())
159 // 4.2.4. If player has pet, reward pet with XP (100% for single player, 50% for group case).
160 pet->GivePetXP(_group ? xp / 2 : xp);
161 }
162}
163
164inline void KillRewarder::_RewardReputation(Player* player, float rate)
165{
166 // 4.3. Give reputation (player must not be on BG).
167 // Even dead players and corpses are rewarded.
168 player->RewardReputation(_victim, rate);
169}
170
172{
173 // 4.4. Give kill credit (player must not be in group, or he must be alive or without corpse).
174 if (!_group || player->IsAlive() || !player->GetCorpse())
175 if (Creature* target = _victim->ToCreature())
176 {
177 player->KilledMonster(target->GetCreatureTemplate(), target->GetGUID());
178 player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE, target->GetCreatureType(), 1, target);
179 }
180}
181
182void KillRewarder::_RewardPlayer(Player* player, bool isDungeon)
183{
184 // 4. Reward player.
185 if (!_isBattleGround)
186 {
187 // 4.1. Give honor (player must be alive and not on BG).
188 _RewardHonor(player);
189 // 4.1.1 Send player killcredit for quests with PlayerSlain
191 player->KilledPlayerCredit();
192 }
193 // Give XP only in PvE or in battlegrounds.
194 // Give reputation and kill credit only in PvE.
195 if (!_isPvP || _isBattleGround)
196 {
197 float const rate = _group ?
198 _groupRate * float(player->GetLevel()) / _sumLevel : // Group rate depends on summary level.
199 1.0f; // Personal rate is 100%.
200 if (_xp)
201 // 4.2. Give XP.
202 _RewardXP(player, rate);
203 if (!_isBattleGround)
204 {
205 // If killer is in dungeon then all members receive full reputation at kill.
206 _RewardReputation(player, isDungeon ? 1.0f : rate);
207 _RewardKillCredit(player);
208 }
209 }
210}
211
213{
214 if (_maxLevel)
215 {
217 // 3.1.1. Initialize initial XP amount based on maximum level of group member,
218 // for whom victim is not gray.
220 // To avoid unnecessary calculations and calls,
221 // proceed only if XP is not ZERO or player is not on battleground
222 // (battleground rewards only XP, that's why).
223 if (!_isBattleGround || _xp)
224 {
225 bool const isDungeon = !_isPvP && sMapStore.LookupEntry(_killer->GetMapId())->IsDungeon();
226 if (!_isBattleGround)
227 {
228 // 3.1.2. Alter group rate if group is in raid (not for battlegrounds).
229 bool const isRaid = !_isPvP && sMapStore.LookupEntry(_killer->GetMapId())->IsRaid() && _group->isRaidGroup();
231 }
232
233 // 3.1.3. Reward each group member (even dead or corpse) within reward distance.
234 for (GroupReference* itr = _group->GetFirstMember(); itr != nullptr; itr = itr->next())
235 {
236 if (Player* member = itr->GetSource())
237 {
238 // Killer may not be at reward distance, check directly
239 if (_killer == member || member->IsAtGroupRewardDistance(_victim))
240 {
241 _RewardPlayer(member, isDungeon);
242 }
243 }
244 }
245 }
246 }
247}
248
250{
251 // 3. Reward killer (and group, if necessary).
252 if (_group)
253 // 3.1. If killer is in group, reward group.
254 _RewardGroup();
255 else
256 {
257 // 3.2. Reward single killer (not group case).
258 // 3.2.1. Initialize initial XP amount based on killer's level.
260 // To avoid unnecessary calculations and calls,
261 // proceed only if XP is not ZERO or player is not on battleground
262 // (battleground rewards only XP, that's why).
263 if (!_isBattleGround || _xp)
264 // 3.2.2. Reward killer.
265 _RewardPlayer(_killer, false);
266 }
267
268 // 5. Credit instance encounter.
269 if (Creature* victim = _victim->ToCreature())
270 if (victim->IsDungeonBoss())
271 if (InstanceScript* instance = _victim->GetInstanceScript())
272 instance->UpdateEncounterStateForKilledCreature(_victim->GetEntry(), _victim);
273}
@ ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE
Definition DBCEnums.h:201
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
uint8_t uint8
Definition Define.h:135
uint32_t uint32
Definition Define.h:133
@ TYPEID_PLAYER
Definition ObjectGuid.h:39
@ SPELL_AURA_MOD_XP_PCT
GroupReference * GetFirstMember()
Definition Group.h:247
bool isRaidGroup() const
Definition Group.cpp:2448
void _RewardHonor(Player *player)
void _RewardPlayer(Player *player, bool isDungeon)
void _InitXP(Player *player)
void _RewardReputation(Player *player, float rate)
uint32 _sumLevel
Player * _maxNotGrayMember
Player * _killer
bool _isBattleGround
Group * _group
void _RewardXP(Player *player, float rate)
void _InitGroupData()
KillRewarder(Player *killer, Unit *victim, bool isBattleGround)
void _RewardKillCredit(Player *player)
bool IsPlayer() const
Definition ObjectGuid.h:179
static Creature * ToCreature(Object *o)
Definition Object.h:186
TypeID GetTypeId() const
Definition Object.h:93
uint32 GetEntry() const
Definition Object.h:81
Definition Pet.h:40
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1=0, uint32 miscValue2=0, WorldObject *ref=nullptr)
Definition Player.cpp:24940
void GiveXP(uint32 xp, Unit *victim, float group_rate=1.0f)
Definition Player.cpp:2353
Pet * GetPet() const
Definition Player.cpp:20286
bool IsAtGroupRewardDistance(WorldObject const *pRewardSource) const
Definition Player.cpp:23664
void KilledMonster(CreatureTemplate const *cInfo, ObjectGuid guid)
Definition Player.cpp:16128
Corpse * GetCorpse() const
Definition Player.cpp:4544
void RewardReputation(Unit *victim, float rate)
Definition Player.cpp:6390
bool RewardHonor(Unit *victim, uint32 groupsize, int32 honor=-1, bool pvptoken=false)
Definition Player.cpp:6524
void KilledPlayerCredit(uint16 count=1)
Definition Player.cpp:16202
Definition Unit.h:769
bool IsVehicle() const
Definition Unit.h:887
Vehicle * GetVehicle() const
Definition Unit.h:1737
bool IsAlive() const
Definition Unit.h:1234
ObjectGuid GetCharmerOrOwnerGUID() const override
Definition Unit.h:1260
float GetTotalAuraMultiplier(AuraType auraType) const
Definition Unit.cpp:4797
uint8 GetLevel() const
Definition Unit.h:889
uint32 GetMapId() const
Definition Position.h:193
InstanceScript * GetInstanceScript() const
Definition Object.cpp:1087
uint32 Gain(Player *player, Unit *u, bool isBattleGround=false)
Definition Formulas.h:171
float xp_in_group_rate(uint32 count, bool isRaid)
Definition Formulas.h:207
uint8 GetGrayLevel(uint8 pl_level)
Definition Formulas.h:49