diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/game/BattleGround.cpp | 91 | ||||
-rw-r--r-- | src/game/BattleGround.h | 2 | ||||
-rw-r--r-- | src/scripts/world/npcs_special.cpp | 71 |
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(); } |