Core/Mechanics: refactor XP (and in fact, honor/reputation/kill credit) rewarding routine and get rid of copy/pasted code.
This commit is contained in:
@@ -1949,91 +1949,8 @@ void Battleground::SetBracket(PvPDifficultyEntry const* bracketEntry)
|
|||||||
SetLevelRange(bracketEntry->minLevel,bracketEntry->maxLevel);
|
SetLevelRange(bracketEntry->minLevel,bracketEntry->maxLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Battleground::RewardXPAtKill(Player* plr, Player* victim)
|
void Battleground::RewardXPAtKill(Player* killer, Player* victim)
|
||||||
{
|
{
|
||||||
if (!sWorld->getBoolConfig(CONFIG_BG_XP_FOR_KILL) || !plr || !victim)
|
if (sWorld->getBoolConfig(CONFIG_BG_XP_FOR_KILL) && killer && victim)
|
||||||
return;
|
killer->RewardPlayerAndGroupAtKill(victim, true);
|
||||||
|
|
||||||
uint32 xp = 0;
|
|
||||||
Player* member_with_max_level = NULL;
|
|
||||||
Player* not_gray_member_with_max_level = NULL;
|
|
||||||
|
|
||||||
if (Group *pGroup = plr->GetGroup())//should be always in a raid group while in any bg
|
|
||||||
{
|
|
||||||
uint32 count = 0;
|
|
||||||
uint32 sum_level = 0;
|
|
||||||
for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
|
|
||||||
{
|
|
||||||
Player* member = itr->getSource();
|
|
||||||
if (!member || !member->isAlive()) // only for alive
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!member->IsAtGroupRewardDistance(victim)) // at req. distance
|
|
||||||
continue;
|
|
||||||
|
|
||||||
++count;
|
|
||||||
sum_level += member->getLevel();
|
|
||||||
if (!member_with_max_level || member_with_max_level->getLevel() < member->getLevel())
|
|
||||||
member_with_max_level = member;
|
|
||||||
|
|
||||||
uint32 gray_level = Trinity::XP::GetGrayLevel(member->getLevel());
|
|
||||||
if (victim->getLevel() > gray_level && (!not_gray_member_with_max_level
|
|
||||||
|| not_gray_member_with_max_level->getLevel() < member->getLevel()))
|
|
||||||
not_gray_member_with_max_level = member;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (member_with_max_level)
|
|
||||||
{
|
|
||||||
xp = !not_gray_member_with_max_level ? 0 : Trinity::XP::Gain(not_gray_member_with_max_level, victim);
|
|
||||||
|
|
||||||
if (!xp)
|
|
||||||
return;
|
|
||||||
|
|
||||||
float group_rate = 1.0f;
|
|
||||||
|
|
||||||
for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
|
|
||||||
{
|
|
||||||
Player* pGroupGuy = itr->getSource();
|
|
||||||
if (!pGroupGuy)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!pGroupGuy->IsAtGroupRewardDistance(victim))
|
|
||||||
continue; // member (alive or dead) or his corpse at req. distance
|
|
||||||
|
|
||||||
float rate = group_rate * float(pGroupGuy->getLevel()) / sum_level;
|
|
||||||
|
|
||||||
// XP updated only for alive group member
|
|
||||||
if (pGroupGuy->isAlive() && not_gray_member_with_max_level && pGroupGuy->getLevel() <= not_gray_member_with_max_level->getLevel())
|
|
||||||
{
|
|
||||||
uint32 itr_xp = (member_with_max_level == not_gray_member_with_max_level) ? uint32(xp * rate) : uint32((xp * rate / 2) + 1);
|
|
||||||
|
|
||||||
// handle SPELL_AURA_MOD_XP_PCT auras
|
|
||||||
Unit::AuraEffectList const& ModXPPctAuras = plr->GetAuraEffectsByType(SPELL_AURA_MOD_XP_PCT);
|
|
||||||
for (Unit::AuraEffectList::const_iterator i = ModXPPctAuras.begin(); i != ModXPPctAuras.end(); ++i)
|
|
||||||
AddPctN(itr_xp, (*i)->GetAmount());
|
|
||||||
|
|
||||||
pGroupGuy->GiveXP(itr_xp, victim);
|
|
||||||
if (Pet* pet = pGroupGuy->GetPet())
|
|
||||||
pet->GivePetXP(itr_xp / 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else//should be always in a raid group while in any BG, but you never know...
|
|
||||||
{
|
|
||||||
xp = Trinity::XP::Gain(plr, victim);
|
|
||||||
|
|
||||||
if (!xp)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// handle SPELL_AURA_MOD_XP_PCT auras
|
|
||||||
Unit::AuraEffectList const& ModXPPctAuras = plr->GetAuraEffectsByType(SPELL_AURA_MOD_XP_PCT);
|
|
||||||
for (Unit::AuraEffectList::const_iterator i = ModXPPctAuras.begin(); i != ModXPPctAuras.end(); ++i)
|
|
||||||
AddPctN(xp, (*i)->GetAmount());
|
|
||||||
|
|
||||||
plr->GiveXP(xp, victim);
|
|
||||||
|
|
||||||
if (Pet* pet = plr->GetPet())
|
|
||||||
pet->GivePetXP(xp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -584,7 +584,7 @@ class Battleground
|
|||||||
/* virtual score-array - get's used in bg-subclasses */
|
/* virtual score-array - get's used in bg-subclasses */
|
||||||
int32 m_TeamScores[BG_TEAMS_COUNT];
|
int32 m_TeamScores[BG_TEAMS_COUNT];
|
||||||
|
|
||||||
void RewardXPAtKill(Player* plr, Player* victim);
|
void RewardXPAtKill(Player* killer, Player* victim);
|
||||||
bool CanAwardArenaPoints() const { return m_LevelMin >= BG_AWARD_ARENA_POINTS_MIN_LEVEL; }
|
bool CanAwardArenaPoints() const { return m_LevelMin >= BG_AWARD_ARENA_POINTS_MIN_LEVEL; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -381,6 +381,229 @@ void TradeData::SetAccepted(bool state, bool crosssend /*= false*/)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// == KillRewarder ====================================================
|
||||||
|
// KillRewarder incapsulates logic of rewarding player upon kill with:
|
||||||
|
// * XP;
|
||||||
|
// * honor;
|
||||||
|
// * reputation;
|
||||||
|
// * kill credit (for quest objectives).
|
||||||
|
// Rewarding is initiated in two cases: when player kills unit in Unit::Kill()
|
||||||
|
// and on battlegrounds in Battleground::RewardXPAtKill().
|
||||||
|
//
|
||||||
|
// Rewarding algorithm is:
|
||||||
|
// 1. Initialize internal variables to default values.
|
||||||
|
// 2. In case when player is in group, initialize variables necessary for group calculations:
|
||||||
|
// 2.1. _count - number of alive group members within reward distance;
|
||||||
|
// 2.2. _sumLevel - sum of levels of alive group members within reward distance;
|
||||||
|
// 2.3. _maxLevel - maximum level of alive group member within reward distance;
|
||||||
|
// 2.4. _maxNotGrayMember - maximum level of alive group member within reward distance,
|
||||||
|
// for whom victim is not gray;
|
||||||
|
// 2.5. _isFullXP - flag identifying that for all group members victim is not gray,
|
||||||
|
// so 100% XP will be rewarded (50% otherwise).
|
||||||
|
// 3. Reward killer (and group, if necessary).
|
||||||
|
// 3.1. If killer is in group, reward group.
|
||||||
|
// 3.1.1. Initialize initial XP amount based on maximum level of group member,
|
||||||
|
// for whom victim is not gray.
|
||||||
|
// 3.1.2. Alter group rate if group is in raid (not for battlegrounds).
|
||||||
|
// 3.1.3. Reward each group member (even dead) within reward distance (see 4. for more details).
|
||||||
|
// 3.2. Reward single killer (not group case).
|
||||||
|
// 3.2.1. Initialize initial XP amount based on killer's level.
|
||||||
|
// 3.2.2. Reward killer (see 4. for more details).
|
||||||
|
// 4. Reward player.
|
||||||
|
// 4.1. Give honor (player must be alive and not on BG).
|
||||||
|
// 4.2. Give XP.
|
||||||
|
// 4.2.1. If player is in group, adjust XP:
|
||||||
|
// * set to 0 if player's level is more than maximum level of not gray member;
|
||||||
|
// * cut XP in half if _isFullXP is false.
|
||||||
|
// 4.2.2. Apply auras modifying rewarded XP.
|
||||||
|
// 4.2.3. Give XP to player.
|
||||||
|
// 4.2.4. If player has pet, reward pet with XP (100% for single player, 50% for group case).
|
||||||
|
// 4.3. Give reputation (player must not be on BG).
|
||||||
|
// 4.4. Give kill credit (player must not be in group, or he must be alive or without corpse).
|
||||||
|
// 5. Credit instance encounter.
|
||||||
|
KillRewarder::KillRewarder(Player* killer, Unit* victim, bool isBattleGround) :
|
||||||
|
// 1. Initialize internal variables to default values.
|
||||||
|
_killer(killer), _victim(victim), _isBattleGround(isBattleGround),
|
||||||
|
_isPvP(victim->isCharmedOwnedByPlayerOrPlayer()), _group(killer->GetGroup()), _groupRate(1.0f),
|
||||||
|
_maxLevel(0), _maxNotGrayMember(NULL), _count(0), _sumLevel(0), _isFullXP(false), _xp(0)
|
||||||
|
{
|
||||||
|
_InitGroupData();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void KillRewarder::_InitGroupData()
|
||||||
|
{
|
||||||
|
if (_group)
|
||||||
|
{
|
||||||
|
// 2. In case when player is in group, initialize variables necessary for group calculations:
|
||||||
|
for (GroupReference *itr = _group->GetFirstMember(); itr != NULL; itr = itr->next())
|
||||||
|
if (Player* member = itr->getSource())
|
||||||
|
if (member->isAlive() && member->IsAtGroupRewardDistance(_victim))
|
||||||
|
{
|
||||||
|
const uint8 lvl = member->getLevel();
|
||||||
|
// 2.1. _count - number of alive group members within reward distance;
|
||||||
|
++_count;
|
||||||
|
// 2.2. _sumLevel - sum of levels of alive group members within reward distance;
|
||||||
|
_sumLevel += lvl;
|
||||||
|
// 2.3. _maxLevel - maximum level of alive group member within reward distance;
|
||||||
|
if (_maxLevel < lvl)
|
||||||
|
_maxLevel = lvl;
|
||||||
|
// 2.4. _maxNotGrayMember - maximum level of alive group member within reward distance,
|
||||||
|
// for whom victim is not gray;
|
||||||
|
uint32 grayLevel = Trinity::XP::GetGrayLevel(lvl);
|
||||||
|
if (_victim->getLevel() > grayLevel && (!_maxNotGrayMember || _maxNotGrayMember->getLevel() < lvl))
|
||||||
|
_maxNotGrayMember = member;
|
||||||
|
}
|
||||||
|
// 2.5. _isFullXP - flag identifying that for all group members victim is not gray,
|
||||||
|
// so 100% XP will be rewarded (50% otherwise).
|
||||||
|
_isFullXP = (_maxLevel == _maxNotGrayMember->getLevel());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void KillRewarder::_InitXP(Player* player)
|
||||||
|
{
|
||||||
|
// Get initial value of XP for kill.
|
||||||
|
// XP is given:
|
||||||
|
// * on battlegrounds;
|
||||||
|
// * otherwise, not in PvP;
|
||||||
|
// * not if killer is on vehicle.
|
||||||
|
if (_isBattleGround || !_isPvP || !_killer->GetVehicle())
|
||||||
|
_xp = Trinity::XP::Gain(player, _victim);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void KillRewarder::_RewardHonor(Player* player)
|
||||||
|
{
|
||||||
|
// Rewarded player must be alive.
|
||||||
|
if (player->isAlive())
|
||||||
|
player->RewardHonor(_victim, _count, -1, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void KillRewarder::_RewardXP(Player* player, float rate)
|
||||||
|
{
|
||||||
|
uint32 xp(_xp);
|
||||||
|
if (_group)
|
||||||
|
// 4.2.1. If player is in group, adjust XP:
|
||||||
|
// * set to 0 if player's level is more than maximum level of not gray member;
|
||||||
|
// * cut XP in half if _isFullXP is false.
|
||||||
|
if (_maxNotGrayMember && player->isAlive() &&
|
||||||
|
_maxNotGrayMember->getLevel() >= player->getLevel())
|
||||||
|
xp = _isFullXP ?
|
||||||
|
uint32(xp * rate) : // Reward FULL XP if all group members are not gray.
|
||||||
|
uint32(xp * rate / 2) + 1; // Reward only HALF of XP if some of group members are gray.
|
||||||
|
else
|
||||||
|
xp = 0;
|
||||||
|
if (xp)
|
||||||
|
{
|
||||||
|
// 4.2.2. Apply auras modifying rewarded XP (SPELL_AURA_MOD_XP_PCT).
|
||||||
|
Unit::AuraEffectList const& auras = player->GetAuraEffectsByType(SPELL_AURA_MOD_XP_PCT);
|
||||||
|
for (Unit::AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
|
||||||
|
AddPctN(xp, (*i)->GetAmount());
|
||||||
|
|
||||||
|
// 4.2.3. Give XP to player.
|
||||||
|
player->GiveXP(xp, _victim, _groupRate);
|
||||||
|
if (Pet* pet = player->GetPet())
|
||||||
|
// 4.2.4. If player has pet, reward pet with XP (100% for single player, 50% for group case).
|
||||||
|
pet->GivePetXP(_group ? xp / 2 : xp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void KillRewarder::_RewardReputation(Player* player, float rate)
|
||||||
|
{
|
||||||
|
// 4.3. Give reputation (player must not be on BG).
|
||||||
|
// Even dead players and corpses are rewarded.
|
||||||
|
player->RewardReputation(_victim, rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void KillRewarder::_RewardKillCredit(Player* player)
|
||||||
|
{
|
||||||
|
// 4.4. Give kill credit (player must not be in group, or he must be alive or without corpse).
|
||||||
|
if (!_group || player->isAlive() || !player->GetCorpse())
|
||||||
|
if (_victim->GetTypeId() == TYPEID_UNIT)
|
||||||
|
player->KilledMonster(_victim->ToCreature()->GetCreatureInfo(), _victim->GetGUID());
|
||||||
|
}
|
||||||
|
|
||||||
|
void KillRewarder::_RewardPlayer(Player* player, bool isDungeon)
|
||||||
|
{
|
||||||
|
// 4. Reward player.
|
||||||
|
if (!_isBattleGround)
|
||||||
|
// 4.1. Give honor (player must be alive and not on BG).
|
||||||
|
_RewardHonor(player);
|
||||||
|
// Give XP only in PvE or in battlegrounds.
|
||||||
|
// Give reputation and kill credit only in PvE.
|
||||||
|
if (!_isPvP || _isBattleGround)
|
||||||
|
{
|
||||||
|
const float rate = _group ?
|
||||||
|
_groupRate * float(player->getLevel()) / _sumLevel : // Group rate depends on summary level.
|
||||||
|
1.0f; // Personal rate is 100%.
|
||||||
|
if (_xp)
|
||||||
|
// 4.2. Give XP.
|
||||||
|
_RewardXP(player, rate);
|
||||||
|
if (!_isBattleGround)
|
||||||
|
{
|
||||||
|
// If killer is in dungeon then all members receive full reputation at kill.
|
||||||
|
_RewardReputation(player, isDungeon ? 1.0f : rate);
|
||||||
|
_RewardKillCredit(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KillRewarder::_RewardGroup()
|
||||||
|
{
|
||||||
|
if (_maxLevel)
|
||||||
|
{
|
||||||
|
if (_maxNotGrayMember)
|
||||||
|
// 3.1.1. Initialize initial XP amount based on maximum level of group member,
|
||||||
|
// for whom victim is not gray.
|
||||||
|
_InitXP(_maxNotGrayMember);
|
||||||
|
// To avoid unnecessary calculations and calls,
|
||||||
|
// proceed only if XP is not ZERO or player is not on battleground
|
||||||
|
// (battleground rewards only XP, that's why).
|
||||||
|
if (!_isBattleGround || _xp)
|
||||||
|
{
|
||||||
|
const bool isDungeon = !_isPvP && sMapStore.LookupEntry(_killer->GetMapId())->IsDungeon();
|
||||||
|
if (!_isBattleGround)
|
||||||
|
{
|
||||||
|
// 3.1.2. Alter group rate if group is in raid (not for battlegrounds).
|
||||||
|
const bool isRaid = !_isPvP && sMapStore.LookupEntry(_killer->GetMapId())->IsRaid() && _group->isRaidGroup();
|
||||||
|
_groupRate = Trinity::XP::xp_in_group_rate(_count, isRaid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.1.3. Reward each group member (even dead or corpse) within reward distance.
|
||||||
|
for (GroupReference *itr = _group->GetFirstMember(); itr != NULL; itr = itr->next())
|
||||||
|
if (Player* member = itr->getSource())
|
||||||
|
if (member->IsAtGroupRewardDistance(_victim))
|
||||||
|
_RewardPlayer(member, isDungeon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KillRewarder::Reward()
|
||||||
|
{
|
||||||
|
// 3. Reward killer (and group, if necessary).
|
||||||
|
if (_group)
|
||||||
|
// 3.1. If killer is in group, reward group.
|
||||||
|
_RewardGroup();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 3.2. Reward single killer (not group case).
|
||||||
|
// 3.2.1. Initialize initial XP amount based on killer's level.
|
||||||
|
_InitXP(_killer);
|
||||||
|
// To avoid unnecessary calculations and calls,
|
||||||
|
// proceed only if XP is not ZERO or player is not on battleground
|
||||||
|
// (battleground rewards only XP, that's why).
|
||||||
|
if (!_isBattleGround || _xp)
|
||||||
|
// 3.2.2. Reward killer.
|
||||||
|
_RewardPlayer(_killer, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Credit instance encounter.
|
||||||
|
if (Creature* victim = _victim->ToCreature())
|
||||||
|
if (victim->IsDungeonBoss())
|
||||||
|
if (InstanceScript* instance = _victim->GetInstanceScript())
|
||||||
|
instance->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, _victim->GetEntry(), _victim);
|
||||||
|
}
|
||||||
|
|
||||||
// == Player ====================================================
|
// == Player ====================================================
|
||||||
|
|
||||||
UpdateMask Player::updateVisualBits;
|
UpdateMask Player::updateVisualBits;
|
||||||
@@ -21969,119 +22192,9 @@ bool Player::GetsRecruitAFriendBonus(bool forXP)
|
|||||||
return recruitAFriend;
|
return recruitAFriend;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::RewardPlayerAndGroupAtKill(Unit* pVictim)
|
void Player::RewardPlayerAndGroupAtKill(Unit* pVictim, bool isBattleGround)
|
||||||
{
|
{
|
||||||
bool PvP = pVictim->isCharmedOwnedByPlayerOrPlayer();
|
KillRewarder(this, pVictim, isBattleGround).Reward();
|
||||||
|
|
||||||
// prepare data for near group iteration (PvP and !PvP cases)
|
|
||||||
uint32 xp = 0;
|
|
||||||
bool honored_kill = false;
|
|
||||||
|
|
||||||
if (Group *pGroup = GetGroup())
|
|
||||||
{
|
|
||||||
uint32 count = 0;
|
|
||||||
uint32 sum_level = 0;
|
|
||||||
Player* member_with_max_level = NULL;
|
|
||||||
Player* not_gray_member_with_max_level = NULL;
|
|
||||||
|
|
||||||
pGroup->GetDataForXPAtKill(pVictim,count,sum_level,member_with_max_level,not_gray_member_with_max_level);
|
|
||||||
|
|
||||||
if (member_with_max_level)
|
|
||||||
{
|
|
||||||
// PvP kills doesn't yield experience
|
|
||||||
// also no XP gained if there is no member below gray level
|
|
||||||
xp = (PvP || !not_gray_member_with_max_level || GetVehicle()) ? 0 : Trinity::XP::Gain(not_gray_member_with_max_level, pVictim);
|
|
||||||
|
|
||||||
/// skip in check PvP case (for speed, not used)
|
|
||||||
bool is_raid = PvP ? false : sMapStore.LookupEntry(GetMapId())->IsRaid() && pGroup->isRaidGroup();
|
|
||||||
bool is_dungeon = PvP ? false : sMapStore.LookupEntry(GetMapId())->IsDungeon();
|
|
||||||
float group_rate = Trinity::XP::xp_in_group_rate(count,is_raid);
|
|
||||||
|
|
||||||
for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
|
|
||||||
{
|
|
||||||
Player* pGroupGuy = itr->getSource();
|
|
||||||
if (!pGroupGuy)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!pGroupGuy->IsAtGroupRewardDistance(pVictim))
|
|
||||||
continue; // member (alive or dead) or his corpse at req. distance
|
|
||||||
|
|
||||||
// honor can be in PvP and !PvP (racial leader) cases (for alive)
|
|
||||||
if (pGroupGuy->isAlive() && pGroupGuy->RewardHonor(pVictim, count, -1, true) && pGroupGuy == this)
|
|
||||||
honored_kill = true;
|
|
||||||
|
|
||||||
// xp and reputation only in !PvP case
|
|
||||||
if (!PvP)
|
|
||||||
{
|
|
||||||
float rate = group_rate * float(pGroupGuy->getLevel()) / sum_level;
|
|
||||||
|
|
||||||
// if is in dungeon then all receive full reputation at kill
|
|
||||||
// rewarded any alive/dead/near_corpse group member
|
|
||||||
pGroupGuy->RewardReputation(pVictim,is_dungeon ? 1.0f : rate);
|
|
||||||
|
|
||||||
// XP updated only for alive group member
|
|
||||||
if (pGroupGuy->isAlive() && not_gray_member_with_max_level &&
|
|
||||||
pGroupGuy->getLevel() <= not_gray_member_with_max_level->getLevel())
|
|
||||||
{
|
|
||||||
uint32 itr_xp = (member_with_max_level == not_gray_member_with_max_level) ? uint32(xp * rate) : uint32((xp * rate / 2) + 1);
|
|
||||||
|
|
||||||
// handle SPELL_AURA_MOD_XP_PCT auras
|
|
||||||
Unit::AuraEffectList const& ModXPPctAuras = GetAuraEffectsByType(SPELL_AURA_MOD_XP_PCT);
|
|
||||||
for (Unit::AuraEffectList::const_iterator i = ModXPPctAuras.begin(); i != ModXPPctAuras.end(); ++i)
|
|
||||||
AddPctN(itr_xp, (*i)->GetAmount());
|
|
||||||
|
|
||||||
pGroupGuy->GiveXP(itr_xp, pVictim, group_rate);
|
|
||||||
if (Pet* pet = pGroupGuy->GetPet())
|
|
||||||
pet->GivePetXP(itr_xp / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// quest objectives updated only for alive group member or dead but with not released body
|
|
||||||
if (pGroupGuy->isAlive()|| !pGroupGuy->GetCorpse())
|
|
||||||
{
|
|
||||||
// normal creature (not pet/etc) can be only in !PvP case
|
|
||||||
if (pVictim->GetTypeId() == TYPEID_UNIT)
|
|
||||||
pGroupGuy->KilledMonster(pVictim->ToCreature()->GetCreatureInfo(), pVictim->GetGUID());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // if (!pGroup)
|
|
||||||
{
|
|
||||||
xp = (PvP || GetVehicle()) ? 0 : Trinity::XP::Gain(this, pVictim);
|
|
||||||
|
|
||||||
// honor can be in PvP and !PvP (racial leader) cases
|
|
||||||
if (RewardHonor(pVictim, 1, -1, true))
|
|
||||||
honored_kill = true;
|
|
||||||
|
|
||||||
// xp and reputation only in !PvP case
|
|
||||||
if (!PvP)
|
|
||||||
{
|
|
||||||
RewardReputation(pVictim,1);
|
|
||||||
|
|
||||||
// handle SPELL_AURA_MOD_XP_PCT auras
|
|
||||||
Unit::AuraEffectList const& ModXPPctAuras = GetAuraEffectsByType(SPELL_AURA_MOD_XP_PCT);
|
|
||||||
for (Unit::AuraEffectList::const_iterator i = ModXPPctAuras.begin(); i != ModXPPctAuras.end(); ++i)
|
|
||||||
AddPctN(xp, (*i)->GetAmount());
|
|
||||||
|
|
||||||
GiveXP(xp, pVictim);
|
|
||||||
|
|
||||||
if (Pet* pet = GetPet())
|
|
||||||
pet->GivePetXP(xp);
|
|
||||||
|
|
||||||
// normal creature (not pet/etc) can be only in !PvP case
|
|
||||||
if (pVictim->GetTypeId() == TYPEID_UNIT)
|
|
||||||
KilledMonster(pVictim->ToCreature()->GetCreatureInfo(), pVictim->GetGUID());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Credit encounter in instance
|
|
||||||
if (Creature* victim = pVictim->ToCreature())
|
|
||||||
if (victim->IsDungeonBoss())
|
|
||||||
if (InstanceScript* instance = pVictim->GetInstanceScript())
|
|
||||||
instance->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, pVictim->GetEntry(), pVictim);
|
|
||||||
|
|
||||||
return xp || honored_kill;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::RewardPlayerAndGroupAtEvent(uint32 creature_id, WorldObject* pRewardSource)
|
void Player::RewardPlayerAndGroupAtEvent(uint32 creature_id, WorldObject* pRewardSource)
|
||||||
|
|||||||
@@ -988,6 +988,41 @@ class TradeData
|
|||||||
uint64 m_items[TRADE_SLOT_COUNT]; // traded itmes from m_player side including non-traded slot
|
uint64 m_items[TRADE_SLOT_COUNT]; // traded itmes from m_player side including non-traded slot
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class KillRewarder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KillRewarder(Player* killer, Unit* victim, bool isBattleGround);
|
||||||
|
|
||||||
|
void Reward();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _InitXP(Player* player);
|
||||||
|
void _InitGroupData();
|
||||||
|
|
||||||
|
void _RewardHonor(Player* player);
|
||||||
|
void _RewardXP(Player* player, float rate);
|
||||||
|
void _RewardReputation(Player* player, float rate);
|
||||||
|
void _RewardKillCredit(Player* player);
|
||||||
|
void _RewardPlayer(Player* player, bool isDungeon);
|
||||||
|
void _RewardGroup();
|
||||||
|
|
||||||
|
Player* _killer;
|
||||||
|
Unit* _victim;
|
||||||
|
bool _isBattleGround;
|
||||||
|
|
||||||
|
bool _isPvP;
|
||||||
|
|
||||||
|
Group* _group;
|
||||||
|
float _groupRate;
|
||||||
|
uint8 _maxLevel;
|
||||||
|
Player* _maxNotGrayMember;
|
||||||
|
uint32 _count;
|
||||||
|
uint32 _sumLevel;
|
||||||
|
bool _isFullXP;
|
||||||
|
|
||||||
|
uint32 _xp;
|
||||||
|
};
|
||||||
|
|
||||||
class Player : public Unit, public GridObject<Player>
|
class Player : public Unit, public GridObject<Player>
|
||||||
{
|
{
|
||||||
friend class WorldSession;
|
friend class WorldSession;
|
||||||
@@ -1935,8 +1970,8 @@ class Player : public Unit, public GridObject<Player>
|
|||||||
|
|
||||||
bool IsAtGroupRewardDistance(WorldObject const* pRewardSource) const;
|
bool IsAtGroupRewardDistance(WorldObject const* pRewardSource) const;
|
||||||
bool IsAtRecruitAFriendDistance(WorldObject const* pOther) const;
|
bool IsAtRecruitAFriendDistance(WorldObject const* pOther) const;
|
||||||
bool RewardPlayerAndGroupAtKill(Unit* pVictim);
|
void RewardPlayerAndGroupAtKill(Unit* pVictim, bool isBattleGround);
|
||||||
void RewardPlayerAndGroupAtEvent(uint32 creature_id,WorldObject* pRewardSource);
|
void RewardPlayerAndGroupAtEvent(uint32 creature_id, WorldObject* pRewardSource);
|
||||||
bool isHonorOrXPTarget(Unit* pVictim);
|
bool isHonorOrXPTarget(Unit* pVictim);
|
||||||
|
|
||||||
bool GetsRecruitAFriendBonus(bool forXP);
|
bool GetsRecruitAFriendBonus(bool forXP);
|
||||||
|
|||||||
@@ -15057,7 +15057,7 @@ void Unit::Kill(Unit *pVictim, bool durabilityLoss)
|
|||||||
loot->generateMoneyLoot(creature->GetCreatureInfo()->mingold,creature->GetCreatureInfo()->maxgold);
|
loot->generateMoneyLoot(creature->GetCreatureInfo()->mingold,creature->GetCreatureInfo()->maxgold);
|
||||||
}
|
}
|
||||||
|
|
||||||
player->RewardPlayerAndGroupAtKill(pVictim);
|
player->RewardPlayerAndGroupAtKill(pVictim, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do KILL and KILLED procs. KILL proc is called only for the unit who landed the killing blow (and its owner - for pets and totems) regardless of who tapped the victim
|
// Do KILL and KILLED procs. KILL proc is called only for the unit who landed the killing blow (and its owner - for pets and totems) regardless of who tapped the victim
|
||||||
|
|||||||
@@ -1161,28 +1161,6 @@ void Group::SetTargetIcon(uint8 id, uint64 whoGuid, uint64 targetGuid)
|
|||||||
BroadcastPacket(&data, true);
|
BroadcastPacket(&data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Group::GetDataForXPAtKill(Unit const* victim, uint32& count,uint32& sum_level, Player* & member_with_max_level, Player* & not_gray_member_with_max_level)
|
|
||||||
{
|
|
||||||
for (GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
|
|
||||||
{
|
|
||||||
Player* member = itr->getSource();
|
|
||||||
if (!member || !member->isAlive()) // only for alive
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!member->IsAtGroupRewardDistance(victim)) // at req. distance
|
|
||||||
continue;
|
|
||||||
|
|
||||||
++count;
|
|
||||||
sum_level += member->getLevel();
|
|
||||||
if (!member_with_max_level || member_with_max_level->getLevel() < member->getLevel())
|
|
||||||
member_with_max_level = member;
|
|
||||||
|
|
||||||
uint32 gray_level = Trinity::XP::GetGrayLevel(member->getLevel());
|
|
||||||
if (victim->getLevel() > gray_level && (!not_gray_member_with_max_level || not_gray_member_with_max_level->getLevel() < member->getLevel()))
|
|
||||||
not_gray_member_with_max_level = member;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Group::SendTargetIconList(WorldSession *session)
|
void Group::SendTargetIconList(WorldSession *session)
|
||||||
{
|
{
|
||||||
if (!session)
|
if (!session)
|
||||||
|
|||||||
@@ -232,7 +232,6 @@ class Group
|
|||||||
MemberSlotList const& GetMemberSlots() const;
|
MemberSlotList const& GetMemberSlots() const;
|
||||||
GroupReference* GetFirstMember();
|
GroupReference* GetFirstMember();
|
||||||
uint32 GetMembersCount() const;
|
uint32 GetMembersCount() const;
|
||||||
void GetDataForXPAtKill(Unit const* victim, uint32& count,uint32& sum_level, Player* & member_with_max_level, Player* & not_gray_member_with_max_level);
|
|
||||||
uint8 GetMemberGroup(uint64 guid) const;
|
uint8 GetMemberGroup(uint64 guid) const;
|
||||||
|
|
||||||
void ConvertToLFG();
|
void ConvertToLFG();
|
||||||
|
|||||||
Reference in New Issue
Block a user