aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/game/BattleGround.cpp91
-rw-r--r--src/game/BattleGround.h2
-rw-r--r--src/scripts/world/npcs_special.cpp71
3 files changed, 161 insertions, 3 deletions
diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp
index 2eac1e5c758..522acf003ef 100644
--- a/src/game/BattleGround.cpp
+++ b/src/game/BattleGround.cpp
@@ -1809,7 +1809,7 @@ void BattleGround::HandleKillPlayer(Player *player, Player *killer)
// add +1 deaths
UpdatePlayerScore(player, SCORE_DEATHS, 1);
-
+ RewardXPAtKill(killer, player);
// add +1 kills to group and +1 killing_blows to killer
if (killer)
{
@@ -1948,3 +1948,92 @@ void BattleGround::SetBracket(PvPDifficultyEntry const* bracketEntry)
m_BracketId = bracketEntry->GetBracketId();
SetLevelRange(bracketEntry->minLevel,bracketEntry->maxLevel);
}
+
+void BattleGround::RewardXPAtKill(Player* plr, Unit* victim)
+{
+ if (!plr || !victim)
+ return;
+
+ uint32 xp = 0;
+ uint32 count = 0;
+ uint32 sum_level = 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
+ {
+ 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)
+ itr_xp = uint32(itr_xp*(1.0f + (*i)->GetAmount() / 100.0f));
+
+ 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)
+ xp = uint32(xp*(1.0f + (*i)->GetAmount() / 100.0f));
+
+ plr->GiveXP(xp, victim);
+
+ if (Pet* pet = plr->GetPet())
+ pet->GivePetXP(xp);
+ }
+} \ No newline at end of file
diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h
index ed3e8f2a87e..eb19b025579 100644
--- a/src/game/BattleGround.h
+++ b/src/game/BattleGround.h
@@ -547,6 +547,8 @@ class BattleGround
/* virtual score-array - get's used in bg-subclasses */
int32 m_TeamScores[BG_TEAMS_COUNT];
+ void RewardXPAtKill(Player* plr, Unit* victim);
+
protected:
//this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends BattleGround
void EndNow();
diff --git a/src/scripts/world/npcs_special.cpp b/src/scripts/world/npcs_special.cpp
index c9b48cb293e..cfd1b7698fc 100644
--- a/src/scripts/world/npcs_special.cpp
+++ b/src/scripts/world/npcs_special.cpp
@@ -2063,6 +2063,10 @@ bool GossipSelect_npc_wormhole(Player* pPlayer, Creature* /*pCreature*/, uint32
return true;
}
+/*######
+## npc_pet_trainer
+######*/
+
enum ePetTrainer
{
TEXT_ISHUNTER = 5838,
@@ -2377,7 +2381,64 @@ bool GossipSelect_npc_tabard_vendor(Player* pPlayer, Creature* pCreature, uint32
break;
}
return true;
-}
+}
+
+/*######
+## npc_experience
+######*/
+
+#define EXP_COST 100000//10 00 00 copper (10golds)
+#define GOSSIP_TEXT_EXP 14736
+#define GOSSIP_XP_OFF "I no longer wish to gain experience."
+#define GOSSIP_XP_ON "I wish to start gaining experience again."
+
+
+bool GossipHello_npc_experience(Player* pPlayer, Creature* pCreature)
+{
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_XP_OFF, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_XP_ON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_EXP, pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_experience(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction)
+{
+ bool noXPGain = pPlayer->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN);
+ bool doSwitch = false;
+
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF + 1://xp off
+ {
+ if (!noXPGain)//does gain xp
+ doSwitch = true;//switch to don't gain xp
+ }
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 2://xp on
+ {
+ if (noXPGain)//doesn't gain xp
+ doSwitch = true;//switch to gain xp
+ }
+ break;
+ }
+ if (doSwitch)
+ {
+ if (pPlayer->GetMoney() < EXP_COST)
+ pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0);
+ else if (noXPGain)
+ {
+ pPlayer->ModifyMoney(-EXP_COST);
+ pPlayer->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN);
+ }
+ else if (!noXPGain)
+ {
+ pPlayer->ModifyMoney(-EXP_COST);
+ pPlayer->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN);
+ }
+ }
+ pPlayer->PlayerTalkClass->CloseGossip();
+ return true;
+}
void AddSC_npcs_special()
{
@@ -2528,6 +2589,12 @@ void AddSC_npcs_special()
newscript->Name = "npc_tabard_vendor";
newscript->pGossipHello = &GossipHello_npc_tabard_vendor;
newscript->pGossipSelect = &GossipSelect_npc_tabard_vendor;
- newscript->RegisterSelf();
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_experience";
+ newscript->pGossipHello = &GossipHello_npc_experience;
+ newscript->pGossipSelect = &GossipSelect_npc_experience;
+ newscript->RegisterSelf();
}