aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/authserver/Main.cpp2
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp2
-rw-r--r--src/server/game/Battlegrounds/ArenaScore.h63
-rw-r--r--src/server/game/Battlegrounds/ArenaTeam.h2
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp131
-rw-r--r--src/server/game/Battlegrounds/Battleground.h104
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.cpp170
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.h1
-rw-r--r--src/server/game/Battlegrounds/BattlegroundScore.h120
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp21
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAB.h39
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp227
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAV.h272
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp13
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundBE.h3
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp3
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp17
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundEY.h33
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp23
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundIC.h40
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp3
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp3
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp3
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp18
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundSA.h47
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp16
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundWS.h39
-rw-r--r--src/server/game/DataStores/DBCEnums.h36
-rw-r--r--src/server/game/DataStores/DBCStores.cpp28
-rw-r--r--src/server/game/DataStores/DBCStores.h5
-rw-r--r--src/server/game/DataStores/DBCStructure.h40
-rw-r--r--src/server/game/DataStores/DBCfmt.h2
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp57
-rw-r--r--src/server/game/Entities/Creature/Creature.h8
-rw-r--r--src/server/game/Entities/Item/ItemPrototype.h2
-rw-r--r--src/server/game/Entities/Player/Player.cpp289
-rw-r--r--src/server/game/Entities/Player/Player.h15
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp28
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp135
-rw-r--r--src/server/game/Globals/ObjectMgr.h4
-rw-r--r--src/server/game/Handlers/BattleGroundHandler.cpp2
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp4
-rw-r--r--src/server/game/Handlers/LootHandler.cpp9
-rw-r--r--src/server/game/Handlers/MailHandler.cpp22
-rw-r--r--src/server/game/Handlers/SkillHandler.cpp3
-rw-r--r--src/server/game/Loot/LootMgr.h3
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rw-r--r--src/server/game/Server/WorldSession.h1
-rw-r--r--src/server/game/Spells/Spell.cpp42
-rw-r--r--src/server/game/Spells/SpellEffects.cpp19
-rw-r--r--src/server/game/Spells/SpellInfo.cpp2
-rw-r--r--src/server/game/Spells/SpellMgr.cpp2
-rw-r--r--src/server/game/World/World.cpp6
-rw-r--r--src/server/game/World/World.h1
-rw-r--r--src/server/scripts/Commands/cs_go.cpp32
-rw-r--r--src/server/scripts/Commands/cs_learn.cpp3
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp8
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp8
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp8
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp256
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp438
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h38
-rw-r--r--src/server/scripts/EasternKingdoms/zone_eversong_woods.cpp18
-rw-r--r--src/server/scripts/Spells/spell_warlock.cpp4
-rw-r--r--src/server/worldserver/worldserver.conf.dist8
-rw-r--r--src/tools/mmaps_generator/MapBuilder.cpp32
-rw-r--r--src/tools/mmaps_generator/MapBuilder.h20
67 files changed, 1652 insertions, 1403 deletions
diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp
index 1fdd01ad968..4e39ae0aca1 100644
--- a/src/server/authserver/Main.cpp
+++ b/src/server/authserver/Main.cpp
@@ -130,7 +130,7 @@ int main(int argc, char** argv)
TC_LOG_INFO("server.authserver", "<Ctrl-C> to stop.\n");
TC_LOG_INFO("server.authserver", "Using configuration file %s.", configFile);
- TC_LOG_WARN("server.authserver", "%s (Library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
+ TC_LOG_INFO("server.authserver", "%s (Library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
// authserver PID file creation
std::string pidFile = sConfigMgr->GetStringDefault("PidFile", "");
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index e36433dd8c0..af47b52f500 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -537,9 +537,9 @@ void SmartAI::JustRespawned()
me->SetVisible(true);
if (me->getFaction() != me->GetCreatureTemplate()->faction)
me->RestoreFaction();
- GetScript()->ProcessEventsFor(SMART_EVENT_RESPAWN);
mJustReset = true;
JustReachedHome();
+ GetScript()->ProcessEventsFor(SMART_EVENT_RESPAWN);
mFollowGuid = 0;//do not reset follower on Reset(), we need it after combat evade
mFollowDist = 0;
mFollowAngle = 0;
diff --git a/src/server/game/Battlegrounds/ArenaScore.h b/src/server/game/Battlegrounds/ArenaScore.h
new file mode 100644
index 00000000000..fdeb13adc3d
--- /dev/null
+++ b/src/server/game/Battlegrounds/ArenaScore.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITY_ARENA_SCORE_H
+#define TRINITY_ARENA_SCORE_H
+
+#include "BattlegroundScore.h"
+#include "SharedDefines.h"
+
+struct ArenaScore : public BattlegroundScore
+{
+ friend class BattlegroundBE;
+ friend class BattlegroundDS;
+ friend class BattlegroundNA;
+ friend class BattlegroundRL;
+ friend class BattlegroundRV;
+
+ protected:
+ ArenaScore(uint64 playerGuid, uint32 team) : BattlegroundScore(playerGuid), TeamId(team == ALLIANCE ? 1 : 0) { }
+
+ void AppendToPacket(WorldPacket& data) final
+ {
+ data << uint64(PlayerGuid);
+
+ data << uint32(KillingBlows);
+ data << uint8(TeamId);
+ data << uint32(DamageDone);
+ data << uint32(HealingDone);
+
+ BuildObjectivesBlock(data);
+ }
+
+ void BuildObjectivesBlock(WorldPacket& data) final
+ {
+ data << uint32(0); // Objectives Count
+ }
+
+ // For Logging purpose
+ std::string ToString() const override
+ {
+ std::ostringstream stream;
+ stream << "Damage done: " << DamageDone << ", Healing done: " << HealingDone << ", Killing blows: " << KillingBlows;
+ return stream.str();
+ }
+
+ uint8 TeamId; // bgTeamId
+};
+
+#endif // TRINITY_ARENA_SCORE_H
diff --git a/src/server/game/Battlegrounds/ArenaTeam.h b/src/server/game/Battlegrounds/ArenaTeam.h
index 85372c35daa..d3b6342b273 100644
--- a/src/server/game/Battlegrounds/ArenaTeam.h
+++ b/src/server/game/Battlegrounds/ArenaTeam.h
@@ -129,7 +129,7 @@ class ArenaTeam
uint8 GetSlot() const { return GetSlotByType(GetType()); }
static uint8 GetSlotByType(uint32 type);
uint64 GetCaptain() const { return CaptainGuid; }
- std::string const& GetName() const { return TeamName; }
+ std::string const& GetName() const { return TeamName; }
const ArenaTeamStats& GetStats() const { return Stats; }
uint32 GetRating() const { return Stats.Rating; }
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index ca48ffb3a14..4e077979b3e 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -16,10 +16,12 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "ArenaScore.h"
#include "ArenaTeam.h"
#include "ArenaTeamMgr.h"
#include "Battleground.h"
#include "BattlegroundMgr.h"
+#include "BattlegroundScore.h"
#include "Creature.h"
#include "CreatureTextMgr.h"
#include "Chat.h"
@@ -165,9 +167,6 @@ Battleground::Battleground()
m_ArenaTeamIds[TEAM_ALLIANCE] = 0;
m_ArenaTeamIds[TEAM_HORDE] = 0;
- m_ArenaTeamRatingChanges[TEAM_ALLIANCE] = 0;
- m_ArenaTeamRatingChanges[TEAM_HORDE] = 0;
-
m_ArenaTeamMMR[TEAM_ALLIANCE] = 0;
m_ArenaTeamMMR[TEAM_HORDE] = 0;
@@ -756,7 +755,7 @@ void Battleground::EndBattleground(uint32 winner)
}
else
{
- SetWinner(3);
+ SetWinner(3); // weird
}
SetStatus(STATUS_WAIT_LEAVE);
@@ -771,49 +770,52 @@ void Battleground::EndBattleground(uint32 winner)
if (winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam)
{
+ loserTeamRating = loserArenaTeam->GetRating();
+ loserMatchmakerRating = GetArenaMatchmakerRating(GetOtherTeam(winner));
+ winnerTeamRating = winnerArenaTeam->GetRating();
+ winnerMatchmakerRating = GetArenaMatchmakerRating(winner);
+
if (winner != WINNER_NONE)
{
- loserTeamRating = loserArenaTeam->GetRating();
- loserMatchmakerRating = GetArenaMatchmakerRating(GetOtherTeam(winner));
- winnerTeamRating = winnerArenaTeam->GetRating();
- winnerMatchmakerRating = GetArenaMatchmakerRating(winner);
winnerMatchmakerChange = winnerArenaTeam->WonAgainst(winnerMatchmakerRating, loserMatchmakerRating, winnerChange);
loserMatchmakerChange = loserArenaTeam->LostAgainst(loserMatchmakerRating, winnerMatchmakerRating, loserChange);
TC_LOG_DEBUG("bg.arena", "match Type: %u --- Winner: old rating: %u, rating gain: %d, old MMR: %u, MMR gain: %d --- Loser: old rating: %u, rating loss: %d, old MMR: %u, MMR loss: %d ---", m_ArenaType, winnerTeamRating, winnerChange, winnerMatchmakerRating,
winnerMatchmakerChange, loserTeamRating, loserChange, loserMatchmakerRating, loserMatchmakerChange);
SetArenaMatchmakerRating(winner, winnerMatchmakerRating + winnerMatchmakerChange);
SetArenaMatchmakerRating(GetOtherTeam(winner), loserMatchmakerRating + loserMatchmakerChange);
- SetArenaTeamRatingChangeForTeam(winner, winnerChange);
- SetArenaTeamRatingChangeForTeam(GetOtherTeam(winner), loserChange);
+
+ // bg team that the client expects is different to TeamId
+ // alliance 1, horde 0
+ uint8 winnerTeam = winner == ALLIANCE ? WINNER_ALLIANCE : WINNER_HORDE;
+ uint8 loserTeam = winner == ALLIANCE ? WINNER_HORDE : WINNER_ALLIANCE;
+
+ _arenaTeamScores[winnerTeam].Assign(winnerChange, winnerMatchmakerRating, winnerArenaTeam->GetName());
+ _arenaTeamScores[loserTeam].Assign(loserChange, loserMatchmakerRating, loserArenaTeam->GetName());
+
TC_LOG_DEBUG("bg.arena", "Arena match Type: %u for Team1Id: %u - Team2Id: %u ended. WinnerTeamId: %u. Winner rating: +%d, Loser rating: %d", m_ArenaType, m_ArenaTeamIds[TEAM_ALLIANCE], m_ArenaTeamIds[TEAM_HORDE], winnerArenaTeam->GetId(), winnerChange, loserChange);
if (sWorld->getBoolConfig(CONFIG_ARENA_LOG_EXTENDED_INFO))
- for (Battleground::BattlegroundScoreMap::const_iterator itr = GetPlayerScoresBegin(); itr != GetPlayerScoresEnd(); ++itr)
- if (Player* player = ObjectAccessor::FindPlayer(itr->first))
+ for (auto const& score : PlayerScores)
+ if (Player* player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(score.first, 0, HIGHGUID_PLAYER)))
{
- TC_LOG_DEBUG("bg.arena", "Statistics match Type: %u for %s (GUID: " UI64FMTD ", Team: %d, IP: %s): %u damage, %u healing, %u killing blows",
- m_ArenaType, player->GetName().c_str(), itr->first, player->GetArenaTeamId(m_ArenaType == 5 ? 2 : m_ArenaType == 3),
- player->GetSession()->GetRemoteAddress().c_str(), itr->second->DamageDone, itr->second->HealingDone,
- itr->second->KillingBlows);
+ TC_LOG_DEBUG("bg.arena", "Statistics match Type: %u for %s (GUID: %u, Team: %d, IP: %s): %s",
+ m_ArenaType, player->GetName().c_str(), score.first, player->GetArenaTeamId(m_ArenaType == 5 ? 2 : m_ArenaType == 3),
+ player->GetSession()->GetRemoteAddress().c_str(), score.second->ToString().c_str());
}
}
// Deduct 16 points from each teams arena-rating if there are no winners after 45+2 minutes
else
{
- SetArenaTeamRatingChangeForTeam(ALLIANCE, ARENA_TIMELIMIT_POINTS_LOSS);
- SetArenaTeamRatingChangeForTeam(HORDE, ARENA_TIMELIMIT_POINTS_LOSS);
+ _arenaTeamScores[WINNER_ALLIANCE].Assign(ARENA_TIMELIMIT_POINTS_LOSS, winnerMatchmakerRating, winnerArenaTeam->GetName());
+ _arenaTeamScores[WINNER_HORDE].Assign(ARENA_TIMELIMIT_POINTS_LOSS, loserMatchmakerRating, loserArenaTeam->GetName());
+
winnerArenaTeam->FinishGame(ARENA_TIMELIMIT_POINTS_LOSS);
loserArenaTeam->FinishGame(ARENA_TIMELIMIT_POINTS_LOSS);
}
}
- else
- {
- SetArenaTeamRatingChangeForTeam(ALLIANCE, 0);
- SetArenaTeamRatingChangeForTeam(HORDE, 0);
- }
}
WorldPacket pvpLogData;
- sBattlegroundMgr->BuildPvpLogDataPacket(&pvpLogData, this);
+ BuildPvPLogDataPacket(pvpLogData);
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
@@ -958,7 +960,7 @@ void Battleground::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
participant = true;
}
- BattlegroundScoreMap::iterator itr2 = PlayerScores.find(guid);
+ BattlegroundScoreMap::iterator itr2 = PlayerScores.find(GUID_LOPART(guid));
if (itr2 != PlayerScores.end())
{
delete itr2->second; // delete player's score
@@ -1099,6 +1101,9 @@ void Battleground::Reset()
delete itr->second;
PlayerScores.clear();
+ for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
+ _arenaTeamScores[i].Reset();
+
ResetBGSubclass();
}
@@ -1349,47 +1354,47 @@ bool Battleground::HasFreeSlots() const
return GetPlayersSize() < GetMaxPlayers();
}
-void Battleground::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor)
+void Battleground::BuildPvPLogDataPacket(WorldPacket& data)
{
- //this procedure is called from virtual function implemented in bg subclass
- BattlegroundScoreMap::const_iterator itr = PlayerScores.find(Source->GetGUID());
- if (itr == PlayerScores.end()) // player not found...
- return;
+ uint8 type = (isArena() ? 1 : 0);
+
+ data.Initialize(MSG_PVP_LOG_DATA, 1 + 1 + 4 + 40 * GetPlayerScoresSize());
+ data << uint8(type); // type (battleground = 0 / arena = 1)
- switch (type)
+ if (type) // arena
{
- case SCORE_KILLING_BLOWS: // Killing blows
- itr->second->KillingBlows += value;
- break;
- case SCORE_DEATHS: // Deaths
- itr->second->Deaths += value;
- break;
- case SCORE_HONORABLE_KILLS: // Honorable kills
- itr->second->HonorableKills += value;
- break;
- case SCORE_BONUS_HONOR: // Honor bonus
- // do not add honor in arenas
- if (isBattleground())
- {
- // reward honor instantly
- if (doAddHonor)
- Source->RewardHonor(NULL, 1, value); // RewardHonor calls UpdatePlayerScore with doAddHonor = false
- else
- itr->second->BonusHonor += value;
- }
- break;
- // used only in EY, but in MSG_PVP_LOG_DATA opcode
- case SCORE_DAMAGE_DONE: // Damage Done
- itr->second->DamageDone += value;
- break;
- case SCORE_HEALING_DONE: // Healing Done
- itr->second->HealingDone += value;
- break;
- default:
- TC_LOG_ERROR("bg.battleground", "Battleground::UpdatePlayerScore: unknown score type (%u) for BG (map: %u, instance id: %u)!",
- type, m_MapId, m_InstanceID);
- break;
+ for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
+ _arenaTeamScores[i].BuildRatingInfoBlock(data);
+
+ for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
+ _arenaTeamScores[i].BuildTeamInfoBlock(data);
}
+
+ if (GetStatus() == STATUS_WAIT_LEAVE)
+ {
+ data << uint8(1); // bg ended
+ data << uint8(GetWinner()); // who win
+ }
+ else
+ data << uint8(0); // bg not ended
+
+ data << uint32(GetPlayerScoresSize());
+ for (auto const& score : PlayerScores)
+ score.second->AppendToPacket(data);
+}
+
+bool Battleground::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
+{
+ BattlegroundScoreMap::const_iterator itr = PlayerScores.find(player->GetGUIDLow());
+ if (itr == PlayerScores.end()) // player not found...
+ return false;
+
+ itr->second->UpdateScore(type, value);
+
+ if (type == SCORE_BONUS_HONOR && doAddHonor && isBattleground())
+ player->RewardHonor(NULL, 1, value); // RewardHonor calls UpdatePlayerScore with doAddHonor = false
+
+ return true;
}
void Battleground::AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid)
@@ -1868,7 +1873,7 @@ void Battleground::PlayerAddedToBGCheckIfBGIsRunning(Player* player)
BlockMovement(player);
- sBattlegroundMgr->BuildPvpLogDataPacket(&data, this);
+ BuildPvPLogDataPacket(data);
player->SendDirectMessage(&data);
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, GetEndTime(), GetStartTime(), GetArenaType(), player->GetBGTeam());
diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h
index 4256e2fc094..2904ec1dc7e 100644
--- a/src/server/game/Battlegrounds/Battleground.h
+++ b/src/server/game/Battlegrounds/Battleground.h
@@ -22,6 +22,7 @@
#include "Common.h"
#include "SharedDefines.h"
#include "DBCEnums.h"
+#include "WorldPacket.h"
class Creature;
class GameObject;
@@ -32,6 +33,7 @@ class WorldObject;
class WorldPacket;
class BattlegroundMap;
+struct BattlegroundScore;
struct Position;
struct PvPDifficultyEntry;
struct WorldSafeLocsEntry;
@@ -171,34 +173,6 @@ struct BattlegroundObjectInfo
uint32 spellid;
};
-enum ScoreType
-{
- SCORE_KILLING_BLOWS = 1,
- SCORE_DEATHS = 2,
- SCORE_HONORABLE_KILLS = 3,
- SCORE_BONUS_HONOR = 4,
- //EY, but in MSG_PVP_LOG_DATA opcode!
- SCORE_DAMAGE_DONE = 5,
- SCORE_HEALING_DONE = 6,
- //WS
- SCORE_FLAG_CAPTURES = 7,
- SCORE_FLAG_RETURNS = 8,
- //AB and IC
- SCORE_BASES_ASSAULTED = 9,
- SCORE_BASES_DEFENDED = 10,
- //AV
- SCORE_GRAVEYARDS_ASSAULTED = 11,
- SCORE_GRAVEYARDS_DEFENDED = 12,
- SCORE_TOWERS_ASSAULTED = 13,
- SCORE_TOWERS_DEFENDED = 14,
- SCORE_MINES_CAPTURED = 15,
- SCORE_LEADERS_KILLED = 16,
- SCORE_SECONDARY_OBJECTIVES = 17,
- //SOTA
- SCORE_DESTROYED_DEMOLISHER = 18,
- SCORE_DESTROYED_WALL = 19
-};
-
enum ArenaType
{
ARENA_TYPE_2v2 = 2,
@@ -239,22 +213,6 @@ enum BattlegroundStartingEventsIds
};
#define BG_STARTING_EVENT_COUNT 4
-struct BattlegroundScore
-{
- BattlegroundScore() : KillingBlows(0), Deaths(0), HonorableKills(0), BonusHonor(0),
- DamageDone(0), HealingDone(0)
- { }
-
- virtual ~BattlegroundScore() { } //virtual destructor is used when deleting score from scores map
-
- uint32 KillingBlows;
- uint32 Deaths;
- uint32 HonorableKills;
- uint32 BonusHonor;
- uint32 DamageDone;
- uint32 HealingDone;
-};
-
enum BGHonorMode
{
BG_NORMAL = 0,
@@ -369,9 +327,7 @@ class Battleground
BattlegroundPlayerMap const& GetPlayers() const { return m_Players; }
uint32 GetPlayersSize() const { return m_Players.size(); }
- typedef std::map<uint64, BattlegroundScore*> BattlegroundScoreMap;
- BattlegroundScoreMap::const_iterator GetPlayerScoresBegin() const { return PlayerScores.begin(); }
- BattlegroundScoreMap::const_iterator GetPlayerScoresEnd() const { return PlayerScores.end(); }
+ typedef std::map<uint32, BattlegroundScore*> BattlegroundScoreMap;
uint32 GetPlayerScoresSize() const { return PlayerScores.size(); }
uint32 GetReviveQueueSize() const { return m_ReviveQueue.size(); }
@@ -443,7 +399,8 @@ class Battleground
Group* GetBgRaid(uint32 TeamID) const { return TeamID == ALLIANCE ? m_BgRaids[TEAM_ALLIANCE] : m_BgRaids[TEAM_HORDE]; }
void SetBgRaid(uint32 TeamID, Group* bg_raid);
- virtual void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true);
+ void BuildPvPLogDataPacket(WorldPacket& data);
+ virtual bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true);
static TeamId GetTeamIndexByTeamId(uint32 Team) { return Team == ALLIANCE ? TEAM_ALLIANCE : TEAM_HORDE; }
uint32 GetPlayersCountByTeam(uint32 Team) const { return m_PlayersCount[GetTeamIndexByTeamId(Team)]; }
@@ -460,12 +417,8 @@ class Battleground
void SetArenaTeamIdForTeam(uint32 Team, uint32 ArenaTeamId) { m_ArenaTeamIds[GetTeamIndexByTeamId(Team)] = ArenaTeamId; }
uint32 GetArenaTeamIdForTeam(uint32 Team) const { return m_ArenaTeamIds[GetTeamIndexByTeamId(Team)]; }
uint32 GetArenaTeamIdByIndex(uint32 index) const { return m_ArenaTeamIds[index]; }
- void SetArenaTeamRatingChangeForTeam(uint32 Team, int32 RatingChange) { m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)] = RatingChange; }
- int32 GetArenaTeamRatingChangeForTeam(uint32 Team) const { return m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)]; }
- int32 GetArenaTeamRatingChangeByIndex(uint32 index) const { return m_ArenaTeamRatingChanges[index]; }
void SetArenaMatchmakerRating(uint32 Team, uint32 MMR){ m_ArenaTeamMMR[GetTeamIndexByTeamId(Team)] = MMR; }
uint32 GetArenaMatchmakerRating(uint32 Team) const { return m_ArenaTeamMMR[GetTeamIndexByTeamId(Team)]; }
- uint32 GetArenaMatchmakerRatingByIndex(uint32 index) const { return m_ArenaTeamMMR[index]; }
void CheckArenaAfterTimerConditions();
void CheckArenaWinConditions();
void UpdateArenaWorldState();
@@ -657,9 +610,54 @@ class Battleground
// Arena team ids by team
uint32 m_ArenaTeamIds[BG_TEAMS_COUNT];
- int32 m_ArenaTeamRatingChanges[BG_TEAMS_COUNT];
uint32 m_ArenaTeamMMR[BG_TEAMS_COUNT];
+ struct ArenaTeamScore
+ {
+ friend class Battleground;
+
+ protected:
+ ArenaTeamScore() : RatingChange(0), MatchmakerRating(0) { }
+
+ virtual ~ArenaTeamScore() { }
+
+ void Assign(int32 ratingChange, uint32 matchMakerRating, std::string const& teamName)
+ {
+ RatingChange = ratingChange;
+ MatchmakerRating = matchMakerRating;
+ TeamName = teamName;
+ }
+
+ void BuildRatingInfoBlock(WorldPacket& data)
+ {
+ uint32 ratingLost = std::abs(std::min(RatingChange, 0));
+ uint32 ratingWon = std::max(RatingChange, 0);
+
+ // should be old rating, new rating, and client will calculate rating change itself
+ data << uint32(ratingLost);
+ data << uint32(ratingWon);
+ data << uint32(MatchmakerRating);
+ }
+
+ void BuildTeamInfoBlock(WorldPacket& data)
+ {
+ data << TeamName;
+ }
+
+ void Reset()
+ {
+ RatingChange = 0;
+ MatchmakerRating = 0;
+ TeamName.clear();
+ }
+
+ int32 RatingChange;
+ uint32 MatchmakerRating;
+ std::string TeamName;
+ };
+
+ ArenaTeamScore _arenaTeamScores[BG_TEAMS_COUNT];
+
// Limits
uint32 m_LevelMin;
uint32 m_LevelMax;
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index ab69c950ff4..ef78594626a 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -216,176 +216,6 @@ void BattlegroundMgr::BuildBattlegroundStatusPacket(WorldPacket* data, Battlegro
}
}
-void BattlegroundMgr::BuildPvpLogDataPacket(WorldPacket* data, Battleground* bg)
-{
- uint8 type = (bg->isArena() ? 1 : 0);
-
- data->Initialize(MSG_PVP_LOG_DATA, (1+1+4+40*bg->GetPlayerScoresSize()));
- *data << uint8(type); // type (battleground=0/arena=1)
-
- if (type) // arena
- {
- // it seems this must be according to BG_WINNER_A/H and _NOT_ TEAM_A/H
- for (int8 i = 1; i >= 0; --i)
- {
- int32 rating_change = bg->GetArenaTeamRatingChangeByIndex(i);
-
- uint32 pointsLost = rating_change < 0 ? -rating_change : 0;
- uint32 pointsGained = rating_change > 0 ? rating_change : 0;
- uint32 MatchmakerRating = bg->GetArenaMatchmakerRatingByIndex(i);
-
- *data << uint32(pointsLost); // Rating Lost
- *data << uint32(pointsGained); // Rating gained
- *data << uint32(MatchmakerRating); // Matchmaking Value
- TC_LOG_DEBUG("bg.battleground", "rating change: %d", rating_change);
- }
- for (int8 i = 1; i >= 0; --i)
- {
- if (ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(bg->GetArenaTeamIdByIndex(i)))
- *data << at->GetName();
- else
- *data << uint8(0);
- }
- }
-
- if (bg->GetStatus() != STATUS_WAIT_LEAVE)
- *data << uint8(0); // bg not ended
- else
- {
- *data << uint8(1); // bg ended
- *data << uint8(bg->GetWinner()); // who win
- }
-
- size_t wpos = data->wpos();
- uint32 scoreCount = 0;
- *data << uint32(scoreCount); // placeholder
-
- Battleground::BattlegroundScoreMap::const_iterator itr2 = bg->GetPlayerScoresBegin();
- for (Battleground::BattlegroundScoreMap::const_iterator itr = itr2; itr != bg->GetPlayerScoresEnd();)
- {
- itr2 = itr++;
- BattlegroundScore* score = itr2->second;
- if (!bg->IsPlayerInBattleground(itr2->first))
- {
- TC_LOG_ERROR("bg.battleground", "Player " UI64FMTD " has scoreboard entry for battleground %u but is not in battleground!", itr->first, bg->GetTypeID(true));
- continue;
- }
-
- *data << uint64(itr2->first);
- *data << uint32(score->KillingBlows);
- if (type == 0)
- {
- *data << uint32(score->HonorableKills);
- *data << uint32(score->Deaths);
- *data << uint32(score->BonusHonor);
- }
- else
- {
- Player* player = ObjectAccessor::FindPlayer(itr2->first);
- uint32 team = bg->GetPlayerTeam(itr2->first);
- if (!team && player)
- team = player->GetBGTeam();
- *data << uint8(team == ALLIANCE ? 1 : 0); // green or yellow
- }
- *data << uint32(score->DamageDone); // damage done
- *data << uint32(score->HealingDone); // healing done
- switch (bg->GetTypeID(true)) // battleground specific things
- {
- case BATTLEGROUND_RB:
- switch (bg->GetMapId())
- {
- case 489:
- *data << uint32(0x00000002); // count of next fields
- *data << uint32(((BattlegroundWGScore*)score)->FlagCaptures); // flag captures
- *data << uint32(((BattlegroundWGScore*)score)->FlagReturns); // flag returns
- break;
- case 566:
- *data << uint32(0x00000001); // count of next fields
- *data << uint32(((BattlegroundEYScore*)score)->FlagCaptures); // flag captures
- break;
- case 529:
- *data << uint32(0x00000002); // count of next fields
- *data << uint32(((BattlegroundABScore*)score)->BasesAssaulted); // bases asssulted
- *data << uint32(((BattlegroundABScore*)score)->BasesDefended); // bases defended
- break;
- case 30:
- *data << uint32(0x00000005); // count of next fields
- *data << uint32(((BattlegroundAVScore*)score)->GraveyardsAssaulted); // GraveyardsAssaulted
- *data << uint32(((BattlegroundAVScore*)score)->GraveyardsDefended); // GraveyardsDefended
- *data << uint32(((BattlegroundAVScore*)score)->TowersAssaulted); // TowersAssaulted
- *data << uint32(((BattlegroundAVScore*)score)->TowersDefended); // TowersDefended
- *data << uint32(((BattlegroundAVScore*)score)->MinesCaptured); // MinesCaptured
- break;
- case 607:
- *data << uint32(0x00000002); // count of next fields
- *data << uint32(((BattlegroundSAScore*)score)->demolishers_destroyed);
- *data << uint32(((BattlegroundSAScore*)score)->gates_destroyed);
- break;
- case 628: // IC
- *data << uint32(0x00000002); // count of next fields
- *data << uint32(((BattlegroundICScore*)score)->BasesAssaulted); // bases asssulted
- *data << uint32(((BattlegroundICScore*)score)->BasesDefended); // bases defended
- default:
- *data << uint32(0);
- break;
- }
- break;
- case BATTLEGROUND_AV:
- *data << uint32(0x00000005); // count of next fields
- *data << uint32(((BattlegroundAVScore*)score)->GraveyardsAssaulted); // GraveyardsAssaulted
- *data << uint32(((BattlegroundAVScore*)score)->GraveyardsDefended); // GraveyardsDefended
- *data << uint32(((BattlegroundAVScore*)score)->TowersAssaulted); // TowersAssaulted
- *data << uint32(((BattlegroundAVScore*)score)->TowersDefended); // TowersDefended
- *data << uint32(((BattlegroundAVScore*)score)->MinesCaptured); // MinesCaptured
- break;
- case BATTLEGROUND_WS:
- *data << uint32(0x00000002); // count of next fields
- *data << uint32(((BattlegroundWGScore*)score)->FlagCaptures); // flag captures
- *data << uint32(((BattlegroundWGScore*)score)->FlagReturns); // flag returns
- break;
- case BATTLEGROUND_AB:
- *data << uint32(0x00000002); // count of next fields
- *data << uint32(((BattlegroundABScore*)score)->BasesAssaulted); // bases assaulted
- *data << uint32(((BattlegroundABScore*)score)->BasesDefended); // bases defended
- break;
- case BATTLEGROUND_EY:
- *data << uint32(0x00000001); // count of next fields
- *data << uint32(((BattlegroundEYScore*)score)->FlagCaptures); // flag captures
- break;
- case BATTLEGROUND_SA:
- *data << uint32(0x00000002); // count of next fields
- *data << uint32(((BattlegroundSAScore*)score)->demolishers_destroyed);
- *data << uint32(((BattlegroundSAScore*)score)->gates_destroyed);
- break;
- case BATTLEGROUND_IC:
- *data << uint32(0x00000002); // count of next fields
- *data << uint32(((BattlegroundICScore*)score)->BasesAssaulted); // bases assaulted
- *data << uint32(((BattlegroundICScore*)score)->BasesDefended); // bases defended
- break;
- case BATTLEGROUND_NA:
- case BATTLEGROUND_BE:
- case BATTLEGROUND_AA:
- case BATTLEGROUND_RL:
- case BATTLEGROUND_DS:
- case BATTLEGROUND_RV:
- *data << uint32(0);
- break;
- default:
- TC_LOG_DEBUG("network", "Unhandled MSG_PVP_LOG_DATA for BG id %u", bg->GetTypeID());
- *data << uint32(0);
- break;
- }
- // should never happen
- if (++scoreCount >= bg->GetMaxPlayers() && itr != bg->GetPlayerScoresEnd())
- {
- TC_LOG_ERROR("bg.battleground", "Battleground %u scoreboard has more entries (%u) than allowed players in this bg (%u)", bg->GetTypeID(true), bg->GetPlayerScoresSize(), bg->GetMaxPlayers());
- break;
- }
- }
-
- data->put(wpos, scoreCount);
-}
-
void BattlegroundMgr::BuildGroupJoinedBattlegroundPacket(WorldPacket* data, GroupJoinBattlegroundResult result)
{
data->Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4);
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h
index 046e2588ad3..d9cedbc4546 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.h
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.h
@@ -82,7 +82,6 @@ class BattlegroundMgr
void BuildBattlegroundListPacket(WorldPacket* data, uint64 guid, Player* player, BattlegroundTypeId bgTypeId, uint8 fromWhere);
void BuildGroupJoinedBattlegroundPacket(WorldPacket* data, GroupJoinBattlegroundResult result);
void BuildUpdateWorldStatePacket(WorldPacket* data, uint32 field, uint32 value);
- void BuildPvpLogDataPacket(WorldPacket* data, Battleground* bg);
void BuildBattlegroundStatusPacket(WorldPacket* data, Battleground* bg, uint8 queueSlot, uint8 statusId, uint32 time1, uint32 time2, uint8 arenaType, uint32 arenaFaction);
void BuildPlaySoundPacket(WorldPacket* data, uint32 soundId);
void SendAreaSpiritHealerQueryOpcode(Player* player, Battleground* bg, uint64 guid);
diff --git a/src/server/game/Battlegrounds/BattlegroundScore.h b/src/server/game/Battlegrounds/BattlegroundScore.h
new file mode 100644
index 00000000000..ae65721b516
--- /dev/null
+++ b/src/server/game/Battlegrounds/BattlegroundScore.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITY_BATTLEGROUND_SCORE_H
+#define TRINITY_BATTLEGROUND_SCORE_H
+
+#include "WorldPacket.h"
+
+enum ScoreType
+{
+ SCORE_KILLING_BLOWS = 1,
+ SCORE_DEATHS = 2,
+ SCORE_HONORABLE_KILLS = 3,
+ SCORE_BONUS_HONOR = 4,
+ SCORE_DAMAGE_DONE = 5,
+ SCORE_HEALING_DONE = 6,
+
+ // WS and EY
+ SCORE_FLAG_CAPTURES = 7,
+ SCORE_FLAG_RETURNS = 8,
+
+ // AB and IC
+ SCORE_BASES_ASSAULTED = 9,
+ SCORE_BASES_DEFENDED = 10,
+
+ // AV
+ SCORE_GRAVEYARDS_ASSAULTED = 11,
+ SCORE_GRAVEYARDS_DEFENDED = 12,
+ SCORE_TOWERS_ASSAULTED = 13,
+ SCORE_TOWERS_DEFENDED = 14,
+ SCORE_MINES_CAPTURED = 15,
+
+ // SOTA
+ SCORE_DESTROYED_DEMOLISHER = 16,
+ SCORE_DESTROYED_WALL = 17
+};
+
+struct BattlegroundScore
+{
+ friend class Battleground;
+
+ protected:
+ BattlegroundScore(uint64 playerGuid) : PlayerGuid(playerGuid), KillingBlows(0), Deaths(0),
+ HonorableKills(0), BonusHonor(0), DamageDone(0), HealingDone(0) { }
+
+ virtual ~BattlegroundScore() { }
+
+ virtual void UpdateScore(uint32 type, uint32 value)
+ {
+ switch (type)
+ {
+ case SCORE_KILLING_BLOWS: // Killing blows
+ KillingBlows += value;
+ break;
+ case SCORE_DEATHS: // Deaths
+ Deaths += value;
+ break;
+ case SCORE_HONORABLE_KILLS: // Honorable kills
+ HonorableKills += value;
+ break;
+ case SCORE_BONUS_HONOR: // Honor bonus
+ BonusHonor += value;
+ break;
+ case SCORE_DAMAGE_DONE: // Damage Done
+ DamageDone += value;
+ break;
+ case SCORE_HEALING_DONE: // Healing Done
+ HealingDone += value;
+ break;
+ default:
+ ASSERT(false && "Not implemented Battleground score type!");
+ break;
+ }
+ }
+
+ virtual void AppendToPacket(WorldPacket& data)
+ {
+ data << uint64(PlayerGuid);
+
+ data << uint32(KillingBlows);
+ data << uint32(HonorableKills);
+ data << uint32(Deaths);
+ data << uint32(BonusHonor);
+ data << uint32(DamageDone);
+ data << uint32(HealingDone);
+
+ BuildObjectivesBlock(data);
+ }
+
+ virtual void BuildObjectivesBlock(WorldPacket& /*data*/) = 0;
+
+ // For Logging purpose
+ virtual std::string ToString() const { return ""; }
+
+ uint64 PlayerGuid;
+
+ // Default score, present in every type
+ uint32 KillingBlows;
+ uint32 Deaths;
+ uint32 HonorableKills;
+ uint32 BonusHonor;
+ uint32 DamageDone;
+ uint32 HealingDone;
+};
+
+#endif // TRINITY_BATTLEGROUND_SCORE_H
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
index 38b0e3e084b..2622ab9501f 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
@@ -224,15 +224,11 @@ void BattlegroundAB::StartingEventOpenDoors()
void BattlegroundAB::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- //create score and add it to map, default values are set in the constructor
- BattlegroundABScore* sc = new BattlegroundABScore;
-
- PlayerScores[player->GetGUID()] = sc;
+ PlayerScores[player->GetGUIDLow()] = new BattlegroundABScore(player->GetGUID());
}
void BattlegroundAB::RemovePlayer(Player* /*player*/, uint64 /*guid*/, uint32 /*team*/)
{
-
}
void BattlegroundAB::HandleAreaTrigger(Player* player, uint32 trigger)
@@ -696,26 +692,23 @@ WorldSafeLocsEntry const* BattlegroundAB::GetClosestGraveYard(Player* player)
return good_entry;
}
-void BattlegroundAB::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor)
+bool BattlegroundAB::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{
- BattlegroundScoreMap::iterator itr = PlayerScores.find(Source->GetGUID());
- if (itr == PlayerScores.end()) // player not found...
- return;
+ if (!Battleground::UpdatePlayerScore(player, type, value, doAddHonor))
+ return false;
switch (type)
{
case SCORE_BASES_ASSAULTED:
- ((BattlegroundABScore*)itr->second)->BasesAssaulted += value;
- Source->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AB_OBJECTIVE_ASSAULT_BASE);
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AB_OBJECTIVE_ASSAULT_BASE);
break;
case SCORE_BASES_DEFENDED:
- ((BattlegroundABScore*)itr->second)->BasesDefended += value;
- Source->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AB_OBJECTIVE_DEFEND_BASE);
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AB_OBJECTIVE_DEFEND_BASE);
break;
default:
- Battleground::UpdatePlayerScore(Source, type, value, doAddHonor);
break;
}
+ return true;
}
bool BattlegroundAB::IsAllNodesControlledByTeam(uint32 team) const
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h
index 9abc7627b24..a6b4be10fdf 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h
@@ -20,6 +20,7 @@
#define __BATTLEGROUNDAB_H
#include "Battleground.h"
+#include "BattlegroundScore.h"
#include "Object.h"
enum BG_AB_WorldStates
@@ -236,12 +237,38 @@ struct BG_AB_BannerTimer
uint8 teamIndex;
};
-struct BattlegroundABScore : public BattlegroundScore
+struct BattlegroundABScore final : public BattlegroundScore
{
- BattlegroundABScore(): BasesAssaulted(0), BasesDefended(0) { }
- ~BattlegroundABScore() { }
- uint32 BasesAssaulted;
- uint32 BasesDefended;
+ friend class BattlegroundAB;
+
+ protected:
+ BattlegroundABScore(uint64 playerGuid) : BattlegroundScore(playerGuid), BasesAssaulted(0), BasesDefended(0) { }
+
+ void UpdateScore(uint32 type, uint32 value) override
+ {
+ switch (type)
+ {
+ case SCORE_BASES_ASSAULTED:
+ BasesAssaulted += value;
+ break;
+ case SCORE_BASES_DEFENDED:
+ BasesDefended += value;
+ break;
+ default:
+ BattlegroundScore::UpdateScore(type, value);
+ break;
+ }
+ }
+
+ void BuildObjectivesBlock(WorldPacket& data) final
+ {
+ data << uint32(2);
+ data << uint32(BasesAssaulted);
+ data << uint32(BasesDefended);
+ }
+
+ uint32 BasesAssaulted;
+ uint32 BasesDefended;
};
class BattlegroundAB : public Battleground
@@ -261,7 +288,7 @@ class BattlegroundAB : public Battleground
WorldSafeLocsEntry const* GetClosestGraveYard(Player* player);
/* Scorekeeping */
- void UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor = true);
+ bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
void FillInitialWorldStates(WorldPacket& data);
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
index 16576aa888e..eafb02f031d 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
@@ -47,7 +47,6 @@ BattlegroundAV::BattlegroundAV()
}
m_Mine_Timer = 0;
- m_MaxLevel = 0;
for (BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i < BG_AV_NODES_MAX; ++i)
InitNode(i, 0, false);
@@ -60,11 +59,6 @@ BattlegroundAV::BattlegroundAV()
BattlegroundAV::~BattlegroundAV() { }
-uint16 BattlegroundAV::GetBonusHonor(uint8 kills) /// @todo move this function to Battleground.cpp (needs to find a way to get m_MaxLevel)
-{
- return Trinity::Honor::hk_honor_at_level(m_MaxLevel, kills);
-}
-
void BattlegroundAV::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
@@ -95,7 +89,7 @@ void BattlegroundAV::HandleKillUnit(Creature* unit, Player* killer)
{
CastSpellOnTeam(23658, HORDE); //this is a spell which finishes a quest where a player has to kill the boss
RewardReputationToTeam(729, BG_AV_REP_BOSS, HORDE);
- RewardHonorToTeam(GetBonusHonor(BG_AV_KILL_BOSS), HORDE);
+ RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_BOSS), HORDE);
EndBattleground(HORDE);
DelCreature(AV_CPLACE_TRIGGER17);
}
@@ -103,7 +97,7 @@ void BattlegroundAV::HandleKillUnit(Creature* unit, Player* killer)
{
CastSpellOnTeam(23658, ALLIANCE); //this is a spell which finishes a quest where a player has to kill the boss
RewardReputationToTeam(730, BG_AV_REP_BOSS, ALLIANCE);
- RewardHonorToTeam(GetBonusHonor(BG_AV_KILL_BOSS), ALLIANCE);
+ RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_BOSS), ALLIANCE);
EndBattleground(ALLIANCE);
DelCreature(AV_CPLACE_TRIGGER19);
}
@@ -116,7 +110,7 @@ void BattlegroundAV::HandleKillUnit(Creature* unit, Player* killer)
}
m_CaptainAlive[0]=false;
RewardReputationToTeam(729, BG_AV_REP_CAPTAIN, HORDE);
- RewardHonorToTeam(GetBonusHonor(BG_AV_KILL_CAPTAIN), HORDE);
+ RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_CAPTAIN), HORDE);
UpdateScore(ALLIANCE, (-1)*BG_AV_RES_CAPTAIN);
//spawn destroyed aura
for (uint8 i=0; i <= 9; i++)
@@ -135,7 +129,7 @@ void BattlegroundAV::HandleKillUnit(Creature* unit, Player* killer)
}
m_CaptainAlive[1]=false;
RewardReputationToTeam(730, BG_AV_REP_CAPTAIN, ALLIANCE);
- RewardHonorToTeam(GetBonusHonor(BG_AV_KILL_CAPTAIN), ALLIANCE);
+ RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_CAPTAIN), ALLIANCE);
UpdateScore(HORDE, (-1)*BG_AV_RES_CAPTAIN);
//spawn destroyed aura
for (uint8 i=0; i <= 9; i++)
@@ -279,33 +273,24 @@ void BattlegroundAV::UpdateScore(uint16 team, int16 points)
Creature* BattlegroundAV::AddAVCreature(uint16 cinfoid, uint16 type)
{
- uint8 level;
bool isStatic = false;
Creature* creature = NULL;
ASSERT(type <= AV_CPLACE_MAX + AV_STATICCPLACE_MAX);
if (type >= AV_CPLACE_MAX) //static
{
type -= AV_CPLACE_MAX;
- cinfoid=uint16(BG_AV_StaticCreaturePos[type][4]);
- creature = AddCreature(BG_AV_StaticCreatureInfo[cinfoid][0],
- (type+AV_CPLACE_MAX),
+ cinfoid = uint16(BG_AV_StaticCreaturePos[type][4]);
+ creature = AddCreature(BG_AV_StaticCreatureInfo[cinfoid],
+ type + AV_CPLACE_MAX,
BG_AV_StaticCreaturePos[type][0],
BG_AV_StaticCreaturePos[type][1],
BG_AV_StaticCreaturePos[type][2],
BG_AV_StaticCreaturePos[type][3]);
- level = (BG_AV_StaticCreatureInfo[cinfoid][2] == BG_AV_StaticCreatureInfo[cinfoid][3])
- ? BG_AV_StaticCreatureInfo[cinfoid][2]
- : urand(BG_AV_StaticCreatureInfo[cinfoid][2], BG_AV_StaticCreatureInfo[cinfoid][3]);
isStatic = true;
}
else
{
- creature = AddCreature(BG_AV_CreatureInfo[cinfoid][0],
- type,
- BG_AV_CreaturePos[type]);
- level = (BG_AV_CreatureInfo[cinfoid][2] == BG_AV_CreatureInfo[cinfoid][3])
- ? BG_AV_CreatureInfo[cinfoid][2]
- : urand(BG_AV_CreatureInfo[cinfoid][2], BG_AV_CreatureInfo[cinfoid][3]);
+ creature = AddCreature(BG_AV_CreatureInfo[cinfoid][0], type, BG_AV_CreaturePos[type]);
}
if (!creature)
return NULL;
@@ -330,10 +315,6 @@ Creature* BattlegroundAV::AddAVCreature(uint16 cinfoid, uint16 type)
//just copied this code from a gm-command
}
- if (level != 0)
- level += m_MaxLevel - 60; //maybe we can do this more generic for custom level-range.. actually it's blizzlike
- creature->SetLevel(level);
-
uint32 triggerSpawnID = 0;
uint32 newFaction = 0;
if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_A_CAPTAIN][0])
@@ -358,9 +339,7 @@ Creature* BattlegroundAV::AddAVCreature(uint16 cinfoid, uint16 type)
}
if (triggerSpawnID && newFaction)
{
- if (Creature* trigger = AddCreature(WORLD_TRIGGER,
- triggerSpawnID,
- BG_AV_CreaturePos[triggerSpawnID]))
+ if (Creature* trigger = AddCreature(WORLD_TRIGGER, triggerSpawnID, BG_AV_CreaturePos[triggerSpawnID]))
{
trigger->setFaction(newFaction);
trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false);
@@ -459,11 +438,7 @@ void BattlegroundAV::StartingEventOpenDoors()
void BattlegroundAV::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- //create score and add it to map, default values are set in constructor
- BattlegroundAVScore* sc = new BattlegroundAVScore;
- PlayerScores[player->GetGUID()] = sc;
- if (m_MaxLevel == 0)
- m_MaxLevel=(player->getLevel()%10 == 0)? player->getLevel() : (player->getLevel()-(player->getLevel()%10))+10; /// @todo just look at the code \^_^/ --but queue-info should provide this information..
+ PlayerScores[player->GetGUIDLow()] = new BattlegroundAVScore(player->GetGUID());
}
void BattlegroundAV::EndBattleground(uint32 winner)
@@ -499,7 +474,7 @@ void BattlegroundAV::EndBattleground(uint32 winner)
if (rep[i] != 0)
RewardReputationToTeam(i == 0 ? 730 : 729, rep[i], i == 0 ? ALLIANCE : HORDE);
if (kills[i] != 0)
- RewardHonorToTeam(GetBonusHonor(kills[i]), i == 0 ? ALLIANCE : HORDE);
+ RewardHonorToTeam(GetBonusHonorFromKill(kills[i]), i == 0 ? ALLIANCE : HORDE);
}
/// @todo add enterevademode for all attacking creatures
@@ -553,43 +528,29 @@ void BattlegroundAV::HandleAreaTrigger(Player* player, uint32 trigger)
}
}
-void BattlegroundAV::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor)
+bool BattlegroundAV::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{
- BattlegroundScoreMap::iterator itr = PlayerScores.find(Source->GetGUID());
- if (itr == PlayerScores.end()) // player not found...
- return;
+ if (!Battleground::UpdatePlayerScore(player, type, value, doAddHonor))
+ return false;
switch (type)
{
case SCORE_GRAVEYARDS_ASSAULTED:
- ((BattlegroundAVScore*)itr->second)->GraveyardsAssaulted += value;
- Source->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_GRAVEYARD);
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_GRAVEYARD);
break;
case SCORE_GRAVEYARDS_DEFENDED:
- ((BattlegroundAVScore*)itr->second)->GraveyardsDefended += value;
- Source->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_GRAVEYARD);
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_GRAVEYARD);
break;
case SCORE_TOWERS_ASSAULTED:
- ((BattlegroundAVScore*)itr->second)->TowersAssaulted += value;
- Source->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_TOWER);
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_TOWER);
break;
case SCORE_TOWERS_DEFENDED:
- ((BattlegroundAVScore*)itr->second)->TowersDefended += value;
- Source->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_TOWER);
- break;
- case SCORE_MINES_CAPTURED:
- ((BattlegroundAVScore*)itr->second)->MinesCaptured += value;
- break;
- case SCORE_LEADERS_KILLED:
- ((BattlegroundAVScore*)itr->second)->LeadersKilled += value;
- break;
- case SCORE_SECONDARY_OBJECTIVES:
- ((BattlegroundAVScore*)itr->second)->SecondaryObjectives += value;
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_TOWER);
break;
default:
- Battleground::UpdatePlayerScore(Source, type, value, doAddHonor);
break;
}
+ return true;
}
void BattlegroundAV::EventPlayerDestroyedPoint(BG_AV_Nodes node)
@@ -617,7 +578,7 @@ void BattlegroundAV::EventPlayerDestroyedPoint(BG_AV_Nodes node)
UpdateScore((owner == ALLIANCE) ? HORDE : ALLIANCE, -1 * BG_AV_RES_TOWER);
RewardReputationToTeam(owner == ALLIANCE ? 730 : 729, BG_AV_REP_TOWER, owner);
- RewardHonorToTeam(GetBonusHonor(BG_AV_KILL_TOWER), owner);
+ RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_TOWER), owner);
SpawnBGObject(BG_AV_OBJECT_TAURA_A_DUNBALDAR_SOUTH+GetTeamIndexByTeamId(owner)+(2*tmp), RESPAWN_ONE_DAY);
SpawnBGObject(BG_AV_OBJECT_TFLAG_A_DUNBALDAR_SOUTH+GetTeamIndexByTeamId(owner)+(2*tmp), RESPAWN_ONE_DAY);
@@ -1222,27 +1183,27 @@ bool BattlegroundAV::SetupBattleground()
if (i <= BG_AV_NODES_FROSTWOLF_HUT)
{
if (!AddObject(i, BG_AV_OBJECTID_BANNER_A_B,
- BG_AV_ObjectPos[i][0], BG_AV_ObjectPos[i][1], BG_AV_ObjectPos[i][2], BG_AV_ObjectPos[i][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i][3]/2), std::cos(BG_AV_ObjectPos[i][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[i],
+ 0, 0, std::sin(BG_AV_ObjectPos[i].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(i+11, BG_AV_OBJECTID_BANNER_CONT_A_B,
- BG_AV_ObjectPos[i][0], BG_AV_ObjectPos[i][1], BG_AV_ObjectPos[i][2], BG_AV_ObjectPos[i][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i][3]/2), std::cos(BG_AV_ObjectPos[i][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[i],
+ 0, 0, std::sin(BG_AV_ObjectPos[i].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(i+33, BG_AV_OBJECTID_BANNER_H_B,
- BG_AV_ObjectPos[i][0], BG_AV_ObjectPos[i][1], BG_AV_ObjectPos[i][2], BG_AV_ObjectPos[i][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i][3]/2), std::cos(BG_AV_ObjectPos[i][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[i],
+ 0, 0, std::sin(BG_AV_ObjectPos[i].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(i+22, BG_AV_OBJECTID_BANNER_CONT_H_B,
- BG_AV_ObjectPos[i][0], BG_AV_ObjectPos[i][1], BG_AV_ObjectPos[i][2], BG_AV_ObjectPos[i][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i][3]/2), std::cos(BG_AV_ObjectPos[i][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[i],
+ 0, 0, std::sin(BG_AV_ObjectPos[i].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i].GetOrientation()/2), RESPAWN_ONE_DAY)
//aura
|| !AddObject(BG_AV_OBJECT_AURA_N_FIRSTAID_STATION+i*3, BG_AV_OBJECTID_AURA_N,
- BG_AV_ObjectPos[i][0], BG_AV_ObjectPos[i][1], BG_AV_ObjectPos[i][2], BG_AV_ObjectPos[i][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i][3]/2), std::cos(BG_AV_ObjectPos[i][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[i],
+ 0, 0, std::sin(BG_AV_ObjectPos[i].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(BG_AV_OBJECT_AURA_A_FIRSTAID_STATION+i*3, BG_AV_OBJECTID_AURA_A,
- BG_AV_ObjectPos[i][0], BG_AV_ObjectPos[i][1], BG_AV_ObjectPos[i][2], BG_AV_ObjectPos[i][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i][3]/2), std::cos(BG_AV_ObjectPos[i][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[i],
+ 0, 0, std::sin(BG_AV_ObjectPos[i].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(BG_AV_OBJECT_AURA_H_FIRSTAID_STATION+i*3, BG_AV_OBJECTID_AURA_H,
- BG_AV_ObjectPos[i][0], BG_AV_ObjectPos[i][1], BG_AV_ObjectPos[i][2], BG_AV_ObjectPos[i][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i][3]/2), std::cos(BG_AV_ObjectPos[i][3]/2), RESPAWN_ONE_DAY))
+ BG_AV_ObjectPos[i],
+ 0, 0, std::sin(BG_AV_ObjectPos[i].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i].GetOrientation()/2), RESPAWN_ONE_DAY))
{
TC_LOG_ERROR("bg.battleground", "BatteGroundAV: Failed to spawn some object Battleground not created!2");
return false;
@@ -1253,23 +1214,23 @@ bool BattlegroundAV::SetupBattleground()
if (i <= BG_AV_NODES_STONEHEART_BUNKER) //alliance towers
{
if (!AddObject(i, BG_AV_OBJECTID_BANNER_A,
- BG_AV_ObjectPos[i][0], BG_AV_ObjectPos[i][1], BG_AV_ObjectPos[i][2], BG_AV_ObjectPos[i][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i][3]/2), std::cos(BG_AV_ObjectPos[i][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[i],
+ 0, 0, std::sin(BG_AV_ObjectPos[i].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(i+22, BG_AV_OBJECTID_BANNER_CONT_H,
- BG_AV_ObjectPos[i][0], BG_AV_ObjectPos[i][1], BG_AV_ObjectPos[i][2], BG_AV_ObjectPos[i][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i][3]/2), std::cos(BG_AV_ObjectPos[i][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[i],
+ 0, 0, std::sin(BG_AV_ObjectPos[i].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(BG_AV_OBJECT_TAURA_A_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)), BG_AV_OBJECTID_AURA_A,
- BG_AV_ObjectPos[i+8][0], BG_AV_ObjectPos[i+8][1], BG_AV_ObjectPos[i+8][2], BG_AV_ObjectPos[i+8][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i+8][3]/2), std::cos(BG_AV_ObjectPos[i+8][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[i+8],
+ 0, 0, std::sin(BG_AV_ObjectPos[i+8].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i+8].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(BG_AV_OBJECT_TAURA_H_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)), BG_AV_OBJECTID_AURA_N,
- BG_AV_ObjectPos[i+8][0], BG_AV_ObjectPos[i+8][1], BG_AV_ObjectPos[i+8][2], BG_AV_ObjectPos[i+8][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i+8][3]/2), std::cos(BG_AV_ObjectPos[i+8][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[i+8],
+ 0, 0, std::sin(BG_AV_ObjectPos[i+8].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i+8].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(BG_AV_OBJECT_TFLAG_A_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)), BG_AV_OBJECTID_TOWER_BANNER_A,
- BG_AV_ObjectPos[i+8][0], BG_AV_ObjectPos[i+8][1], BG_AV_ObjectPos[i+8][2], BG_AV_ObjectPos[i+8][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i+8][3]/2), std::cos(BG_AV_ObjectPos[i+8][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[i+8],
+ 0, 0, std::sin(BG_AV_ObjectPos[i+8].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i+8].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(BG_AV_OBJECT_TFLAG_H_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)), BG_AV_OBJECTID_TOWER_BANNER_PH,
- BG_AV_ObjectPos[i+8][0], BG_AV_ObjectPos[i+8][1], BG_AV_ObjectPos[i+8][2], BG_AV_ObjectPos[i+8][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i+8][3]/2), std::cos(BG_AV_ObjectPos[i+8][3]/2), RESPAWN_ONE_DAY))
+ BG_AV_ObjectPos[i+8],
+ 0, 0, std::sin(BG_AV_ObjectPos[i+8].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i+8].GetOrientation()/2), RESPAWN_ONE_DAY))
{
TC_LOG_ERROR("bg.battleground", "BatteGroundAV: Failed to spawn some object Battleground not created!3");
return false;
@@ -1278,23 +1239,23 @@ bool BattlegroundAV::SetupBattleground()
else //horde towers
{
if (!AddObject(i+7, BG_AV_OBJECTID_BANNER_CONT_A,
- BG_AV_ObjectPos[i][0], BG_AV_ObjectPos[i][1], BG_AV_ObjectPos[i][2], BG_AV_ObjectPos[i][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i][3]/2), std::cos(BG_AV_ObjectPos[i][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[i],
+ 0, 0, std::sin(BG_AV_ObjectPos[i].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(i+29, BG_AV_OBJECTID_BANNER_H,
- BG_AV_ObjectPos[i][0], BG_AV_ObjectPos[i][1], BG_AV_ObjectPos[i][2], BG_AV_ObjectPos[i][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i][3]/2), std::cos(BG_AV_ObjectPos[i][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[i],
+ 0, 0, std::sin(BG_AV_ObjectPos[i].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(BG_AV_OBJECT_TAURA_A_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)), BG_AV_OBJECTID_AURA_N,
- BG_AV_ObjectPos[i+8][0], BG_AV_ObjectPos[i+8][1], BG_AV_ObjectPos[i+8][2], BG_AV_ObjectPos[i+8][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i+8][3]/2), std::cos(BG_AV_ObjectPos[i+8][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[i+8],
+ 0, 0, std::sin(BG_AV_ObjectPos[i+8].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i+8].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(BG_AV_OBJECT_TAURA_H_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)), BG_AV_OBJECTID_AURA_H,
- BG_AV_ObjectPos[i+8][0], BG_AV_ObjectPos[i+8][1], BG_AV_ObjectPos[i+8][2], BG_AV_ObjectPos[i+8][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i+8][3]/2), std::cos(BG_AV_ObjectPos[i+8][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[i+8],
+ 0, 0, std::sin(BG_AV_ObjectPos[i+8].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i+8].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(BG_AV_OBJECT_TFLAG_A_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)), BG_AV_OBJECTID_TOWER_BANNER_PA,
- BG_AV_ObjectPos[i+8][0], BG_AV_ObjectPos[i+8][1], BG_AV_ObjectPos[i+8][2], BG_AV_ObjectPos[i+8][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i+8][3]/2), std::cos(BG_AV_ObjectPos[i+8][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[i+8],
+ 0, 0, std::sin(BG_AV_ObjectPos[i+8].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i+8].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(BG_AV_OBJECT_TFLAG_H_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)), BG_AV_OBJECTID_TOWER_BANNER_H,
- BG_AV_ObjectPos[i+8][0], BG_AV_ObjectPos[i+8][1], BG_AV_ObjectPos[i+8][2], BG_AV_ObjectPos[i+8][3],
- 0, 0, std::sin(BG_AV_ObjectPos[i+8][3]/2), std::cos(BG_AV_ObjectPos[i+8][3]/2), RESPAWN_ONE_DAY))
+ BG_AV_ObjectPos[i+8],
+ 0, 0, std::sin(BG_AV_ObjectPos[i+8].GetOrientation()/2), std::cos(BG_AV_ObjectPos[i+8].GetOrientation()/2), RESPAWN_ONE_DAY))
{
TC_LOG_ERROR("bg.battleground", "BatteGroundAV: Failed to spawn some object Battleground not created!4");
return false;
@@ -1304,14 +1265,11 @@ bool BattlegroundAV::SetupBattleground()
{
if (!AddObject(BG_AV_OBJECT_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j,
BG_AV_OBJECTID_FIRE,
- BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][0],
- BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][1],
- BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][2],
- BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][3],
+ BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j],
0,
0,
- std::sin(BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][3]/2),
- std::cos(BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][3]/2),
+ std::sin(BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j].GetOrientation()/2),
+ std::cos(BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j].GetOrientation()/2),
RESPAWN_ONE_DAY))
{
TC_LOG_ERROR("bg.battleground", "BatteGroundAV: Failed to spawn some object Battleground not created!5.%i", i);
@@ -1328,14 +1286,11 @@ bool BattlegroundAV::SetupBattleground()
{
if (!AddObject(BG_AV_OBJECT_BURN_BUILDING_ALLIANCE+(i*10)+j,
BG_AV_OBJECTID_SMOKE,
- BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][0],
- BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][1],
- BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][2],
- BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3],
+ BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j],
0,
0,
- std::sin(BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3]/2),
- std::cos(BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3]/2),
+ std::sin(BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j].GetOrientation()/2),
+ std::cos(BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j].GetOrientation()/2),
RESPAWN_ONE_DAY))
{
TC_LOG_ERROR("bg.battleground", "BatteGroundAV: Failed to spawn some object Battleground not created!6.%i", i);
@@ -1346,14 +1301,11 @@ bool BattlegroundAV::SetupBattleground()
{
if (!AddObject(BG_AV_OBJECT_BURN_BUILDING_ALLIANCE+(i*10)+j,
BG_AV_OBJECTID_FIRE,
- BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][0],
- BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][1],
- BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][2],
- BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3],
+ BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j],
0,
0,
- std::sin(BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3]/2),
- std::cos(BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3]/2),
+ std::sin(BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j].GetOrientation()/2),
+ std::cos(BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j].GetOrientation()/2),
RESPAWN_ONE_DAY))
{
TC_LOG_ERROR("bg.battleground", "BatteGroundAV: Failed to spawn some object Battleground not created!7.%i", i);
@@ -1366,14 +1318,11 @@ bool BattlegroundAV::SetupBattleground()
{
if (!AddObject(BG_AV_OBJECT_MINE_SUPPLY_N_MIN+i,
BG_AV_OBJECTID_MINE_N,
- BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][0],
- BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][1],
- BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][2],
- BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][3],
+ BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i],
0,
0,
- std::sin(BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][3]/2),
- std::cos(BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][3]/2),
+ std::sin(BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i].GetOrientation()/2),
+ std::cos(BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i].GetOrientation()/2),
RESPAWN_ONE_DAY))
{
TC_LOG_ERROR("bg.battleground", "BatteGroundAV: Failed to spawn some mine supplies Battleground not created!7.5.%i", i);
@@ -1384,14 +1333,11 @@ bool BattlegroundAV::SetupBattleground()
{
if (!AddObject(BG_AV_OBJECT_MINE_SUPPLY_S_MIN+i,
BG_AV_OBJECTID_MINE_S,
- BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][0],
- BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][1],
- BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][2],
- BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][3],
+ BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i],
0,
0,
- std::sin(BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][3]/2),
- std::cos(BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][3]/2),
+ std::sin(BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i].GetOrientation()/2),
+ std::cos(BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i].GetOrientation()/2),
RESPAWN_ONE_DAY))
{
TC_LOG_ERROR("bg.battleground", "BatteGroundAV: Failed to spawn some mine supplies Battleground not created!7.6.%i", i);
@@ -1401,14 +1347,11 @@ bool BattlegroundAV::SetupBattleground()
if (!AddObject(BG_AV_OBJECT_FLAG_N_SNOWFALL_GRAVE,
BG_AV_OBJECTID_BANNER_SNOWFALL_N,
- BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][0],
- BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][1],
- BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][2],
- BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][3],
+ BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE],
0,
0,
- std::sin(BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][3]/2),
- std::cos(BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][3]/2),
+ std::sin(BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE].GetOrientation()/2),
+ std::cos(BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE].GetOrientation()/2),
RESPAWN_ONE_DAY))
{
TC_LOG_ERROR("bg.battleground", "BatteGroundAV: Failed to spawn some object Battleground not created!8");
@@ -1417,17 +1360,17 @@ bool BattlegroundAV::SetupBattleground()
for (uint8 i = 0; i < 4; i++)
{
if (!AddObject(BG_AV_OBJECT_SNOW_EYECANDY_A+i, BG_AV_OBJECTID_SNOWFALL_CANDY_A,
- BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][0], BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][1], BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][2], BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3],
- 0, 0, std::sin(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), std::cos(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i],
+ 0, 0, std::sin(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i].GetOrientation()/2), std::cos(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(BG_AV_OBJECT_SNOW_EYECANDY_PA+i, BG_AV_OBJECTID_SNOWFALL_CANDY_PA,
- BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][0], BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][1], BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][2], BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3],
- 0, 0, std::sin(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), std::cos(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i],
+ 0, 0, std::sin(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i].GetOrientation()/2), std::cos(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(BG_AV_OBJECT_SNOW_EYECANDY_H+i, BG_AV_OBJECTID_SNOWFALL_CANDY_H,
- BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][0], BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][1], BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][2], BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3],
- 0, 0, std::sin(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), std::cos(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), RESPAWN_ONE_DAY)
+ BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i],
+ 0, 0, std::sin(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i].GetOrientation()/2), std::cos(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i].GetOrientation()/2), RESPAWN_ONE_DAY)
|| !AddObject(BG_AV_OBJECT_SNOW_EYECANDY_PH+i, BG_AV_OBJECTID_SNOWFALL_CANDY_PH,
- BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][0], BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][1], BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][2], BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3],
- 0, 0, std::sin(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), std::cos(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), RESPAWN_ONE_DAY))
+ BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i],
+ 0, 0, std::sin(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i].GetOrientation()/2), std::cos(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i].GetOrientation()/2), RESPAWN_ONE_DAY))
{
TC_LOG_ERROR("bg.battleground", "BatteGroundAV: Failed to spawn some object Battleground not created!9.%i", i);
return false;
@@ -1591,8 +1534,6 @@ void BattlegroundAV::DefendNode(BG_AV_Nodes node, uint16 team)
void BattlegroundAV::ResetBGSubclass()
{
- m_MaxLevel=0;
-
for (uint8 i=0; i<2; i++) //forloop for both teams (it just make 0 == alliance and 1 == horde also for both mines 0=north 1=south
{
for (uint8 j=0; j<9; j++)
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h
index 03dd0ffcf5c..feb3c016e55 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h
@@ -20,6 +20,7 @@
#define __BATTLEGROUNDAV_H
#include "Battleground.h"
+#include "BattlegroundScore.h"
#include "Object.h"
#define LANG_BG_AV_A_CAPTAIN_BUFF "Begone. Uncouth scum! The Alliance shall prevail in Alterac Valley!"
@@ -131,10 +132,10 @@ enum BG_AV_ObjectIds
BG_AV_OBJECTID_SNOWFALL_CANDY_PH = 179425,
//banners on top of towers:
- BG_AV_OBJECTID_TOWER_BANNER_A = 178927, //[PH] Alliance A1 Tower Banner BIG
- BG_AV_OBJECTID_TOWER_BANNER_H = 178955, //[PH] Horde H1 Tower Banner BIG
- BG_AV_OBJECTID_TOWER_BANNER_PA = 179446, //[PH] Alliance H1 Tower Pre-Banner BIG
- BG_AV_OBJECTID_TOWER_BANNER_PH = 179436, //[PH] Horde A1 Tower Pre-Banner BIG
+ BG_AV_OBJECTID_TOWER_BANNER_A = 178927, //[PH] Alliance A1 Tower Banner BIG
+ BG_AV_OBJECTID_TOWER_BANNER_H = 178955, //[PH] Horde H1 Tower Banner BIG
+ BG_AV_OBJECTID_TOWER_BANNER_PA = 179446, //[PH] Alliance H1 Tower Pre-Banner BIG
+ BG_AV_OBJECTID_TOWER_BANNER_PH = 179436, //[PH] Horde A1 Tower Pre-Banner BIG
//Auras
BG_AV_OBJECTID_AURA_A = 180421,
@@ -148,11 +149,11 @@ enum BG_AV_ObjectIds
BG_AV_OBJECTID_GATE_H = 180424,
//mine supplies
- BG_AV_OBJECTID_MINE_N = 178785,
- BG_AV_OBJECTID_MINE_S = 178784,
+ BG_AV_OBJECTID_MINE_N = 178785,
+ BG_AV_OBJECTID_MINE_S = 178784,
BG_AV_OBJECTID_FIRE = 179065,
- BG_AV_OBJECTID_SMOKE = 179066
+ BG_AV_OBJECTID_SMOKE = 179066
};
enum BG_AV_Nodes
@@ -306,58 +307,58 @@ enum BG_AV_ObjectTypes
BG_AV_OBJECT_MINE_SUPPLY_S_MIN = 225,
BG_AV_OBJECT_MINE_SUPPLY_S_MAX = 236,
- BG_AV_OBJECT_MAX = 237
+ BG_AV_OBJECT_MAX = 237
};
enum BG_AV_OBJECTS
{
- AV_OPLACE_FIRSTAID_STATION = 0,
- AV_OPLACE_STORMPIKE_GRAVE = 1,
- AV_OPLACE_STONEHEART_GRAVE = 2,
- AV_OPLACE_SNOWFALL_GRAVE = 3,
- AV_OPLACE_ICEBLOOD_GRAVE = 4,
- AV_OPLACE_FROSTWOLF_GRAVE = 5,
- AV_OPLACE_FROSTWOLF_HUT = 6,
- AV_OPLACE_DUNBALDAR_SOUTH = 7,
- AV_OPLACE_DUNBALDAR_NORTH = 8,
- AV_OPLACE_ICEWING_BUNKER = 9,
- AV_OPLACE_STONEHEART_BUNKER = 10,
- AV_OPLACE_ICEBLOOD_TOWER = 11,
- AV_OPLACE_TOWER_POINT = 12,
- AV_OPLACE_FROSTWOLF_ETOWER = 13,
- AV_OPLACE_FROSTWOLF_WTOWER = 14,
- AV_OPLACE_BIGBANNER_DUNBALDAR_SOUTH = 15,
- AV_OPLACE_BIGBANNER_DUNBALDAR_NORTH = 16,
- AV_OPLACE_BIGBANNER_ICEWING_BUNKER = 17,
- AV_OPLACE_BIGBANNER_STONEHEART_BUNKER = 18,
- AV_OPLACE_BIGBANNER_ICEBLOOD_TOWER = 19,
- AV_OPLACE_BIGBANNER_TOWER_POINT = 20,
- AV_OPLACE_BIGBANNER_FROSTWOLF_ETOWER = 21,
- AV_OPLACE_BIGBANNER_FROSTWOLF_WTOWER = 22,
-
- AV_OPLACE_BURN_DUNBALDAR_SOUTH = 23,
- AV_OPLACE_BURN_DUNBALDAR_NORTH = 33,
- AV_OPLACE_BURN_ICEWING_BUNKER = 43,
- AV_OPLACE_BURN_STONEHEART_BUNKER = 53,
- AV_OPLACE_BURN_ICEBLOOD_TOWER = 63,
- AV_OPLACE_BURN_TOWER_POINT = 73,
- AV_OPLACE_BURN_FROSTWOLF_ETOWER = 83,
- AV_OPLACE_BURN_FROSTWOLF_WTOWER = 93,
- AV_OPLACE_BURN_BUILDING_A = 103,
- AV_OPLACE_BURN_BUILDING_H = 113,
- AV_OPLACE_SNOW_1 = 123,
- AV_OPLACE_SNOW_2 = 124,
- AV_OPLACE_SNOW_3 = 125,
- AV_OPLACE_SNOW_4 = 126,
- AV_OPLACE_MINE_SUPPLY_N_MIN = 127,
- AV_OPLACE_MINE_SUPPLY_N_MAX = 136,
- AV_OPLACE_MINE_SUPPLY_S_MIN = 137,
- AV_OPLACE_MINE_SUPPLY_S_MAX = 148,
-
- AV_OPLACE_MAX = 149
+ AV_OPLACE_FIRSTAID_STATION = 0,
+ AV_OPLACE_STORMPIKE_GRAVE = 1,
+ AV_OPLACE_STONEHEART_GRAVE = 2,
+ AV_OPLACE_SNOWFALL_GRAVE = 3,
+ AV_OPLACE_ICEBLOOD_GRAVE = 4,
+ AV_OPLACE_FROSTWOLF_GRAVE = 5,
+ AV_OPLACE_FROSTWOLF_HUT = 6,
+ AV_OPLACE_DUNBALDAR_SOUTH = 7,
+ AV_OPLACE_DUNBALDAR_NORTH = 8,
+ AV_OPLACE_ICEWING_BUNKER = 9,
+ AV_OPLACE_STONEHEART_BUNKER = 10,
+ AV_OPLACE_ICEBLOOD_TOWER = 11,
+ AV_OPLACE_TOWER_POINT = 12,
+ AV_OPLACE_FROSTWOLF_ETOWER = 13,
+ AV_OPLACE_FROSTWOLF_WTOWER = 14,
+ AV_OPLACE_BIGBANNER_DUNBALDAR_SOUTH = 15,
+ AV_OPLACE_BIGBANNER_DUNBALDAR_NORTH = 16,
+ AV_OPLACE_BIGBANNER_ICEWING_BUNKER = 17,
+ AV_OPLACE_BIGBANNER_STONEHEART_BUNKER = 18,
+ AV_OPLACE_BIGBANNER_ICEBLOOD_TOWER = 19,
+ AV_OPLACE_BIGBANNER_TOWER_POINT = 20,
+ AV_OPLACE_BIGBANNER_FROSTWOLF_ETOWER = 21,
+ AV_OPLACE_BIGBANNER_FROSTWOLF_WTOWER = 22,
+
+ AV_OPLACE_BURN_DUNBALDAR_SOUTH = 23,
+ AV_OPLACE_BURN_DUNBALDAR_NORTH = 33,
+ AV_OPLACE_BURN_ICEWING_BUNKER = 43,
+ AV_OPLACE_BURN_STONEHEART_BUNKER = 53,
+ AV_OPLACE_BURN_ICEBLOOD_TOWER = 63,
+ AV_OPLACE_BURN_TOWER_POINT = 73,
+ AV_OPLACE_BURN_FROSTWOLF_ETOWER = 83,
+ AV_OPLACE_BURN_FROSTWOLF_WTOWER = 93,
+ AV_OPLACE_BURN_BUILDING_A = 103,
+ AV_OPLACE_BURN_BUILDING_H = 113,
+ AV_OPLACE_SNOW_1 = 123,
+ AV_OPLACE_SNOW_2 = 124,
+ AV_OPLACE_SNOW_3 = 125,
+ AV_OPLACE_SNOW_4 = 126,
+ AV_OPLACE_MINE_SUPPLY_N_MIN = 127,
+ AV_OPLACE_MINE_SUPPLY_N_MAX = 136,
+ AV_OPLACE_MINE_SUPPLY_S_MIN = 137,
+ AV_OPLACE_MINE_SUPPLY_S_MAX = 148,
+
+ AV_OPLACE_MAX = 149
};
-const float BG_AV_ObjectPos[AV_OPLACE_MAX][4] =
+Position const BG_AV_ObjectPos[AV_OPLACE_MAX] =
{
{638.592f, -32.422f, 46.0608f, -1.62316f }, //firstaid station
{669.007f, -294.078f, 30.2909f, 2.77507f }, //stormpike
@@ -1228,59 +1229,59 @@ const float BG_AV_StaticCreaturePos[AV_STATICCPLACE_MAX][5] =
{-1370.9f, -219.793f, 98.4258f, 5.04381f, 47}, //drek thar
};
-const uint32 BG_AV_StaticCreatureInfo[51][4] =
+const uint32 BG_AV_StaticCreatureInfo[51] =
{
- { 2225, 1215, 55, 55 }, //Zora Guthrek
- { 3343, 1215, 55, 55 }, //Grelkor
- { 3625, 1215, 55, 55 }, //Rarck
- { 4255, 1217, 55, 55 }, //Brogus Thunderbrew
- { 4257, 1217, 55, 55 }, //Lana Thunderbrew
- { 5134, 1217, 55, 55 }, //Jonivera Farmountain
- { 5135, 1217, 55, 55 }, //Svalbrad Farmountain
- { 5139, 1217, 55, 55 }, //Kurdrum Barleybeard
- { 10364, 1215, 55, 55 }, //Yaelika Farclaw
- { 10367, 1215, 55, 55 }, //Shrye Ragefist
- { 10981, 38, 50, 51 }, //Frostwolf
- { 10986, 514, 52, 53 }, //Snowblind Harpy
- { 10990, 1274, 50, 51 }, //Alterac Ram
- { 11675, 514, 53, 53 }, //Snowblind Windcaller
- { 11678, 14, 52, 53 }, //Snowblind Ambusher
- { 11839, 39, 56, 56 }, //Wildpaw Brute
- { 11947, 1214, 61, 61 }, // Captain Galvangar /// @todo: Duplicate ? Check and confirm
- { 11948, 1216, 63, 63 }, //Vanndar Stormpike
- { 11949, 1216, 61, 61 }, //Captain Balinda Stonehearth
- { 11997, 1334, 60, 60 }, //Stormpike Herald
- { 12051, 1214, 57, 57 }, //Frostwolf Legionnaire
- { 12096, 1217, 55, 55 }, //Stormpike Quartermaster
- { 12097, 1215, 55, 55 }, //Frostwolf Quartermaster
- { 12127, 1216, 57, 57 }, //Stormpike Guardsman
- { 13176, 1215, 60, 60 }, //Smith Regzar
- { 13179, 1215, 59, 59 }, //Wing Commander Guse
- { 13216, 1217, 58, 58 }, //Gaelden Hammersmith
- { 13218, 1215, 58, 58 }, //Grunnda Wolfheart
- { 13236, 1214, 60, 60 }, //Primalist Thurloga
- { 13257, 1216, 60, 60 }, //Murgot Deepforge
- { 13284, 1214, 58, 58 }, //Frostwolf Shaman
- { 13438, 1217, 58, 58 }, //Wing Commander Slidore
- { 13442, 1216, 60, 60 }, //Arch Druid Renferal
- { 13443, 1216, 60, 60 }, //Druid of the Grove
- { 13447, 1216, 58, 58 }, //Corporal Noreg Stormpike
- { 13577, 1216, 60, 60 }, //Stormpike Ram Rider Commander
- { 13617, 1216, 60, 60 }, //Stormpike Stable Master
- { 13797, 32, 60, 61 }, //Mountaineer Boombellow
- { 13798, 1214, 60, 61 }, //Jotek
- { 13816, 1216, 61, 61 }, //Prospector Stonehewer
- { 14185, 877, 59, 59 }, //Najak Hexxen
- { 14186, 105, 60, 60 }, //Ravak Grimtotem
- { 14187, 1594, 60, 60 }, //Athramanis
- { 14188, 57, 59, 59 }, //Dirk Swindle
- { 14282, 1214, 53, 54 }, //Frostwolf Bloodhound
- { 14283, 1216, 53, 54 }, //Stormpike Owl
- { 14284, 1216, 61, 61 }, //Stormpike Battleguard
- { 11946, 1214, 63, 63 }, //Drek'Thar /// @todo: Correct the level (Level 80 for boss ?)
- { 11948, 1216, 63, 63 }, //Vanndar Stormpike
- { 11947, 1214, 61, 61 }, //Captain Galvangar
- { 11949, 1216, 61, 61 } //Captain Balinda Stonehearth
+ 2225, // Zora Guthrek
+ 3343, // Grelkor
+ 3625, // Rarck
+ 4255, // Brogus Thunderbrew
+ 4257, // Lana Thunderbrew
+ 5134, // Jonivera Farmountain
+ 5135, // Svalbrad Farmountain
+ 5139, // Kurdrum Barleybeard
+ 10364, // Yaelika Farclaw
+ 10367, // Shrye Ragefist
+ 10981, // Frostwolf
+ 10986, // Snowblind Harpy
+ 10990, // Alterac Ram
+ 11675, // Snowblind Windcaller
+ 11678, // Snowblind Ambusher
+ 11839, // Wildpaw Brute
+ 11947, // Captain Galvangar
+ 11948, // Vanndar Stormpike
+ 11949, // Captain Balinda Stonehearth
+ 11997, // Stormpike Herald
+ 12051, // Frostwolf Legionnaire
+ 12096, // Stormpike Quartermaster
+ 12097, // Frostwolf Quartermaster
+ 12127, // Stormpike Guardsman
+ 13176, // Smith Regzar
+ 13179, // Wing Commander Guse
+ 13216, // Gaelden Hammersmith
+ 13218, // Grunnda Wolfheart
+ 13236, // Primalist Thurloga
+ 13257, // Murgot Deepforge
+ 13284, // Frostwolf Shaman
+ 13438, // Wing Commander Slidore
+ 13442, // Arch Druid Renferal
+ 13443, // Druid of the Grove
+ 13447, // Corporal Noreg Stormpike
+ 13577, // Stormpike Ram Rider Commander
+ 13617, // Stormpike Stable Master
+ 13797, // Mountaineer Boombellow
+ 13798, // Jotek
+ 13816, // Prospector Stonehewer
+ 14185, // Najak Hexxen
+ 14186, // Ravak Grimtotem
+ 14187, // Athramanis
+ 14188, // Dirk Swindle
+ 14282, // Frostwolf Bloodhound
+ 14283, // Stormpike Owl
+ 14284, // Stormpike Battleguard
+ 11946, // Drek'Thar
+ 11948, // Vanndar Stormpike
+ 11947, // Captain Galvangar
+ 11949, // Captain Balinda Stonehearth
};
enum BG_AV_Graveyards
@@ -1525,18 +1526,53 @@ struct BG_AV_NodeInfo
inline BG_AV_Nodes &operator++(BG_AV_Nodes &i){ return i = BG_AV_Nodes(i + 1); }
-struct BattlegroundAVScore : public BattlegroundScore
+struct BattlegroundAVScore final : public BattlegroundScore
{
- BattlegroundAVScore() : GraveyardsAssaulted(0), GraveyardsDefended(0), TowersAssaulted(0),
- TowersDefended(0), MinesCaptured(0), LeadersKilled(0), SecondaryObjectives(0) { }
- ~BattlegroundAVScore() { }
- uint32 GraveyardsAssaulted;
- uint32 GraveyardsDefended;
- uint32 TowersAssaulted;
- uint32 TowersDefended;
- uint32 MinesCaptured;
- uint32 LeadersKilled;
- uint32 SecondaryObjectives;
+ friend class BattlegroundAV;
+
+ protected:
+ BattlegroundAVScore(uint64 playerGuid) : BattlegroundScore(playerGuid), GraveyardsAssaulted(0), GraveyardsDefended(0), TowersAssaulted(0), TowersDefended(0), MinesCaptured(0) { }
+
+ void UpdateScore(uint32 type, uint32 value) override
+ {
+ switch (type)
+ {
+ case SCORE_GRAVEYARDS_ASSAULTED:
+ GraveyardsAssaulted += value;
+ break;
+ case SCORE_GRAVEYARDS_DEFENDED:
+ GraveyardsDefended += value;
+ break;
+ case SCORE_TOWERS_ASSAULTED:
+ TowersAssaulted += value;
+ break;
+ case SCORE_TOWERS_DEFENDED:
+ TowersDefended += value;
+ break;
+ case SCORE_MINES_CAPTURED:
+ MinesCaptured += value;
+ break;
+ default:
+ BattlegroundScore::UpdateScore(type, value);
+ break;
+ }
+ }
+
+ void BuildObjectivesBlock(WorldPacket& data) final
+ {
+ data << uint32(5); // Objectives Count
+ data << uint32(GraveyardsAssaulted);
+ data << uint32(GraveyardsDefended);
+ data << uint32(TowersAssaulted);
+ data << uint32(TowersDefended);
+ data << uint32(MinesCaptured);
+ }
+
+ uint32 GraveyardsAssaulted;
+ uint32 GraveyardsDefended;
+ uint32 TowersAssaulted;
+ uint32 TowersDefended;
+ uint32 MinesCaptured;
};
class BattlegroundAV : public Battleground
@@ -1557,7 +1593,7 @@ class BattlegroundAV : public Battleground
/*general stuff*/
void UpdateScore(uint16 team, int16 points);
- void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true);
+ bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
/*handlestuff*/ //these are functions which get called from extern
void EventPlayerClickedOnFlag(Player* source, GameObject* target_obj);
@@ -1607,7 +1643,6 @@ class BattlegroundAV : public Battleground
/*general */
Creature* AddAVCreature(uint16 cinfoid, uint16 type);
- uint16 GetBonusHonor(uint8 kills); /// @todo: Remove this when the core handles this properly
/*variables */
int32 m_Team_Scores[2];
@@ -1622,7 +1657,6 @@ class BattlegroundAV : public Battleground
uint32 m_CaptainBuffTimer[2];
bool m_CaptainAlive[2];
- uint8 m_MaxLevel; /// @todo: Remove this once battleground->getmaxlevel() returns something usefull/is reworked (?)
bool m_IsInformedNearVictory[2];
};
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp
index c89fc57b8aa..548e0bf463b 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp
@@ -16,6 +16,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "ArenaScore.h"
#include "BattlegroundBE.h"
#include "Language.h"
#include "Object.h"
@@ -64,7 +65,7 @@ void BattlegroundBE::StartingEventOpenDoors()
void BattlegroundBE::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUID()] = new BattlegroundScore;
+ PlayerScores[player->GetGUIDLow()] = new ArenaScore(player->GetGUID(), player->GetBGTeam());
UpdateArenaWorldState();
}
@@ -139,13 +140,3 @@ bool BattlegroundBE::SetupBattleground()
return true;
}
-
-void BattlegroundBE::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor)
-{
- BattlegroundScoreMap::iterator itr = PlayerScores.find(Source->GetGUID());
- if (itr == PlayerScores.end()) // player not found...
- return;
-
- //there is nothing special in this score
- Battleground::UpdatePlayerScore(Source, type, value, doAddHonor);
-}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundBE.h b/src/server/game/Battlegrounds/Zones/BattlegroundBE.h
index be801dfff2b..6fd4dc37fc8 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundBE.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundBE.h
@@ -59,8 +59,5 @@ class BattlegroundBE : public Battleground
void Reset();
void FillInitialWorldStates(WorldPacket &d);
void HandleKillPlayer(Player* player, Player* killer);
-
- /* Scorekeeping */
- void UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor = true);
};
#endif
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp
index 9e9e82b32b8..1d6970f8317 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp
@@ -16,6 +16,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "ArenaScore.h"
#include "BattlegroundDS.h"
#include "Creature.h"
#include "GameObject.h"
@@ -152,7 +153,7 @@ void BattlegroundDS::StartingEventOpenDoors()
void BattlegroundDS::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUID()] = new BattlegroundScore;
+ PlayerScores[player->GetGUIDLow()] = new ArenaScore(player->GetGUID(), player->GetBGTeam());
UpdateArenaWorldState();
}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
index 213a91bea88..ca96140f5da 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
@@ -363,12 +363,9 @@ void BattlegroundEY::UpdatePointsIcons(uint32 Team, uint32 Point)
void BattlegroundEY::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- //create score and add it to map
- BattlegroundEYScore* sc = new BattlegroundEYScore;
+ PlayerScores[player->GetGUIDLow()] = new BattlegroundEYScore(player->GetGUID());
m_PlayersNearPoint[EY_POINTS_MAX].push_back(player->GetGUID());
-
- PlayerScores[player->GetGUID()] = sc;
}
void BattlegroundEY::RemovePlayer(Player* player, uint64 guid, uint32 /*team*/)
@@ -832,22 +829,20 @@ void BattlegroundEY::EventPlayerCapturedFlag(Player* player, uint32 BgObjectType
UpdatePlayerScore(player, SCORE_FLAG_CAPTURES, 1);
}
-void BattlegroundEY::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
+bool BattlegroundEY::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{
- BattlegroundScoreMap::iterator itr = PlayerScores.find(player->GetGUID());
- if (itr == PlayerScores.end()) // player not found
- return;
+ if (!Battleground::UpdatePlayerScore(player, type, value, doAddHonor))
+ return false;
switch (type)
{
- case SCORE_FLAG_CAPTURES: // flags captured
- ((BattlegroundEYScore*)itr->second)->FlagCaptures += value;
+ case SCORE_FLAG_CAPTURES:
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, EY_OBJECTIVE_CAPTURE_FLAG);
break;
default:
- Battleground::UpdatePlayerScore(player, type, value, doAddHonor);
break;
}
+ return true;
}
void BattlegroundEY::FillInitialWorldStates(WorldPacket& data)
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.h b/src/server/game/Battlegrounds/Zones/BattlegroundEY.h
index 9e5088d7ba5..056deb3498b 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.h
@@ -20,6 +20,7 @@
#define __BATTLEGROUNDEY_H
#include "Battleground.h"
+#include "BattlegroundScore.h"
#include "Language.h"
#include "Object.h"
@@ -322,11 +323,33 @@ const BattlegroundEYCapturingPointStruct m_CapturingPointTypes[EY_POINTS_MAX] =
BattlegroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_TAKEN_A_M_TOWER, BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_TAKEN_H_M_TOWER, EY_GRAVEYARD_MAGE_TOWER)
};
-struct BattlegroundEYScore : public BattlegroundScore
+struct BattlegroundEYScore final : public BattlegroundScore
{
- BattlegroundEYScore() : FlagCaptures(0) { }
- ~BattlegroundEYScore() { }
- uint32 FlagCaptures;
+ friend class BattlegroundEY;
+
+ protected:
+ BattlegroundEYScore(uint64 playerGuid) : BattlegroundScore(playerGuid), FlagCaptures(0) { }
+
+ void UpdateScore(uint32 type, uint32 value) override
+ {
+ switch (type)
+ {
+ case SCORE_FLAG_CAPTURES: // Flags captured
+ FlagCaptures += value;
+ break;
+ default:
+ BattlegroundScore::UpdateScore(type, value);
+ break;
+ }
+ }
+
+ void BuildObjectivesBlock(WorldPacket& data) final
+ {
+ data << uint32(1); // Objectives Count
+ data << uint32(FlagCaptures);
+ }
+
+ uint32 FlagCaptures;
};
class BattlegroundEY : public Battleground
@@ -357,7 +380,7 @@ class BattlegroundEY : public Battleground
void Reset();
void UpdateTeamScore(uint32 Team);
void EndBattleground(uint32 winner);
- void UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor = true);
+ bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
void FillInitialWorldStates(WorldPacket& data);
void SetDroppedFlagGUID(uint64 guid, int32 /*TeamID*/ = -1) { m_DroppedFlagGUID = guid;}
uint64 GetDroppedFlagGUID() const { return m_DroppedFlagGUID;}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
index faa71fd2ffa..da0b00af40f 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
@@ -273,7 +273,7 @@ void BattlegroundIC::StartingEventOpenDoors()
void BattlegroundIC::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUID()] = new BattlegroundICScore;
+ PlayerScores[player->GetGUIDLow()] = new BattlegroundICScore(player->GetGUID());
if (nodePoint[NODE_TYPE_QUARRY].nodeState == (player->GetTeamId() == TEAM_ALLIANCE ? NODE_STATE_CONTROLLED_A : NODE_STATE_CONTROLLED_H))
player->CastSpell(player, SPELL_QUARRY, true);
@@ -314,27 +314,6 @@ void BattlegroundIC::HandleAreaTrigger(Player* player, uint32 trigger)
}
}
-void BattlegroundIC::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
-{
- std::map<uint64, BattlegroundScore*>::iterator itr = PlayerScores.find(player->GetGUID());
-
- if (itr == PlayerScores.end()) // player not found...
- return;
-
- switch (type)
- {
- case SCORE_BASES_ASSAULTED:
- ((BattlegroundICScore*)itr->second)->BasesAssaulted += value;
- break;
- case SCORE_BASES_DEFENDED:
- ((BattlegroundICScore*)itr->second)->BasesDefended += value;
- break;
- default:
- Battleground::UpdatePlayerScore(player, type, value, doAddHonor);
- break;
- }
-}
-
void BattlegroundIC::FillInitialWorldStates(WorldPacket& data)
{
data << uint32(BG_IC_ALLIANCE_RENFORT_SET) << uint32(1);
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h
index 091a75e7449..0b317cabef3 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h
@@ -20,6 +20,7 @@
#define __BATTLEGROUNDIC_H
#include "Battleground.h"
+#include "BattlegroundScore.h"
#include "Language.h"
#include "Object.h"
@@ -847,12 +848,38 @@ enum HonorRewards
WINNER_HONOR_AMOUNT = 500
};
-struct BattlegroundICScore : public BattlegroundScore
+struct BattlegroundICScore final : public BattlegroundScore
{
- BattlegroundICScore() : BasesAssaulted(0), BasesDefended(0) { }
- ~BattlegroundICScore() { }
- uint32 BasesAssaulted;
- uint32 BasesDefended;
+ friend class BattlegroundIC;
+
+ protected:
+ BattlegroundICScore(uint64 playerGuid) : BattlegroundScore(playerGuid), BasesAssaulted(0), BasesDefended(0) { }
+
+ void UpdateScore(uint32 type, uint32 value) override
+ {
+ switch (type)
+ {
+ case SCORE_BASES_ASSAULTED:
+ BasesAssaulted += value;
+ break;
+ case SCORE_BASES_DEFENDED:
+ BasesDefended += value;
+ break;
+ default:
+ BattlegroundScore::UpdateScore(type, value);
+ break;
+ }
+ }
+
+ void BuildObjectivesBlock(WorldPacket& data) final
+ {
+ data << uint32(2); // Objectives Count
+ data << uint32(BasesAssaulted);
+ data << uint32(BasesDefended);
+ }
+
+ uint32 BasesAssaulted;
+ uint32 BasesDefended;
};
class BattlegroundIC : public Battleground
@@ -881,8 +908,6 @@ class BattlegroundIC : public Battleground
WorldSafeLocsEntry const* GetClosestGraveYard(Player* player);
/* Scorekeeping */
- void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true);
-
void FillInitialWorldStates(WorldPacket& data);
void DoAction(uint32 action, uint64 var);
@@ -894,6 +919,7 @@ class BattlegroundIC : public Battleground
bool IsAllNodesControlledByTeam(uint32 team) const;
bool IsSpellAllowed(uint32 spellId, Player const* player) const;
+
private:
uint32 closeFortressDoorsTimer;
bool doorsClosed;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp
index 70a940ec853..82fcb2f6f91 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp
@@ -16,6 +16,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "ArenaScore.h"
#include "BattlegroundNA.h"
#include "Language.h"
#include "Object.h"
@@ -61,7 +62,7 @@ void BattlegroundNA::StartingEventOpenDoors()
void BattlegroundNA::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUID()] = new BattlegroundScore;
+ PlayerScores[player->GetGUIDLow()] = new ArenaScore(player->GetGUID(), player->GetBGTeam());
UpdateArenaWorldState();
}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp
index 5f77c57c064..712d9a6e296 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp
@@ -16,6 +16,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "ArenaScore.h"
#include "BattlegroundRL.h"
#include "Language.h"
#include "Object.h"
@@ -61,7 +62,7 @@ void BattlegroundRL::StartingEventOpenDoors()
void BattlegroundRL::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUID()] = new BattlegroundScore;
+ PlayerScores[player->GetGUIDLow()] = new ArenaScore(player->GetGUID(), player->GetBGTeam());
UpdateArenaWorldState();
}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp
index dd61b8b9e6f..1059124d041 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp
@@ -16,6 +16,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "ArenaScore.h"
#include "Battleground.h"
#include "BattlegroundRV.h"
#include "ObjectAccessor.h"
@@ -99,7 +100,7 @@ void BattlegroundRV::StartingEventOpenDoors()
void BattlegroundRV::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- PlayerScores[player->GetGUID()] = new BattlegroundScore;
+ PlayerScores[player->GetGUIDLow()] = new ArenaScore(player->GetGUID(), player->GetBGTeam());
UpdateWorldState(BG_RV_WORLD_STATE_A, GetAlivePlayersCountByTeam(ALLIANCE));
UpdateWorldState(BG_RV_WORLD_STATE_H, GetAlivePlayersCountByTeam(HORDE));
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
index 0966ddd19bd..7e90c0b3db0 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
@@ -454,9 +454,7 @@ void BattlegroundSA::FillInitialWorldStates(WorldPacket& data)
void BattlegroundSA::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- //create score and add it to map, default values are set in constructor
- BattlegroundSAScore* sc = new BattlegroundSAScore;
- PlayerScores[player->GetGUID()] = sc;
+ PlayerScores[player->GetGUIDLow()] = new BattlegroundSAScore(player->GetGUID());
SendTransportInit(player);
@@ -493,20 +491,6 @@ void BattlegroundSA::HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/)
return;
}
-void BattlegroundSA::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor)
-{
- BattlegroundScoreMap::iterator itr = PlayerScores.find(Source->GetGUID());
- if (itr == PlayerScores.end()) // player not found...
- return;
-
- if (type == SCORE_DESTROYED_DEMOLISHER)
- ((BattlegroundSAScore*)itr->second)->demolishers_destroyed += value;
- else if (type == SCORE_DESTROYED_WALL)
- ((BattlegroundSAScore*)itr->second)->gates_destroyed += value;
- else
- Battleground::UpdatePlayerScore(Source, type, value, doAddHonor);
-}
-
void BattlegroundSA::TeleportPlayers()
{
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h
index 880da0735f4..a3947334417 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h
@@ -20,16 +20,9 @@
#define __BATTLEGROUNDSA_H
#include "Battleground.h"
+#include "BattlegroundScore.h"
#include "Object.h"
-struct BattlegroundSAScore : public BattlegroundScore
-{
- BattlegroundSAScore() : demolishers_destroyed(0), gates_destroyed(0) { }
- ~BattlegroundSAScore() { }
- uint8 demolishers_destroyed;
- uint8 gates_destroyed;
-};
-
#define BG_SA_FLAG_AMOUNT 3
#define BG_SA_DEMOLISHER_AMOUNT 4
@@ -249,7 +242,7 @@ uint32 const BG_SA_NpcEntries[BG_SA_MAXNPC] =
NPC_KANRETHAD
};
-Position const BG_SA_NpcSpawnlocs[BG_SA_MAXNPC + BG_SA_DEMOLISHER_AMOUNT] =
+Position const BG_SA_NpcSpawnlocs[BG_SA_MAXNPC] =
{
// Cannons
{ 1436.429f, 110.05f, 41.407f, 5.4f },
@@ -515,6 +508,40 @@ struct BG_SA_RoundScore
uint32 time;
};
+struct BattlegroundSAScore final : public BattlegroundScore
+{
+ friend class BattlegroundSA;
+
+ protected:
+ BattlegroundSAScore(uint64 playerGuid) : BattlegroundScore(playerGuid), DemolishersDestroyed(0), GatesDestroyed(0) { }
+
+ void UpdateScore(uint32 type, uint32 value) override
+ {
+ switch (type)
+ {
+ case SCORE_DESTROYED_DEMOLISHER:
+ DemolishersDestroyed += value;
+ break;
+ case SCORE_DESTROYED_WALL:
+ GatesDestroyed += value;
+ break;
+ default:
+ BattlegroundScore::UpdateScore(type, value);
+ break;
+ }
+ }
+
+ void BuildObjectivesBlock(WorldPacket& data) final
+ {
+ data << uint32(2); // Objectives Count
+ data << uint32(DemolishersDestroyed);
+ data << uint32(GatesDestroyed);
+ }
+
+ uint32 DemolishersDestroyed;
+ uint32 GatesDestroyed;
+};
+
/// Class for manage Strand of Ancient battleground
class BattlegroundSA : public Battleground
{
@@ -568,8 +595,6 @@ class BattlegroundSA : public Battleground
void HandleAreaTrigger(Player* Source, uint32 Trigger);
/* Scorekeeping */
- /// Update score board
- void UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor = true);
// Achievement: Not Even a Scratch
bool CheckAchievementCriteriaMeet(uint32 criteriaId, Player const* source, Unit const* target = NULL, uint32 miscValue = 0) override;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
index fcd55e2e16a..1faa3361975 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
@@ -229,10 +229,7 @@ void BattlegroundWS::StartingEventOpenDoors()
void BattlegroundWS::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
- //create score and add it to map, default values are set in constructor
- BattlegroundWGScore* sc = new BattlegroundWGScore;
-
- PlayerScores[player->GetGUID()] = sc;
+ PlayerScores[player->GetGUIDLow()] = new BattlegroundWGScore(player->GetGUID());
}
void BattlegroundWS::RespawnFlag(uint32 Team, bool captured)
@@ -790,26 +787,23 @@ void BattlegroundWS::HandleKillPlayer(Player* player, Player* killer)
Battleground::HandleKillPlayer(player, killer);
}
-void BattlegroundWS::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
+bool BattlegroundWS::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{
- BattlegroundScoreMap::iterator itr = PlayerScores.find(player->GetGUID());
- if (itr == PlayerScores.end()) // player not found
- return;
+ if (!Battleground::UpdatePlayerScore(player, type, value, doAddHonor))
+ return false;
switch (type)
{
case SCORE_FLAG_CAPTURES: // flags captured
- ((BattlegroundWGScore*)itr->second)->FlagCaptures += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_CAPTURE_FLAG);
break;
case SCORE_FLAG_RETURNS: // flags returned
- ((BattlegroundWGScore*)itr->second)->FlagReturns += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_RETURN_FLAG);
break;
default:
- Battleground::UpdatePlayerScore(player, type, value, doAddHonor);
break;
}
+ return true;
}
WorldSafeLocsEntry const* BattlegroundWS::GetClosestGraveYard(Player* player)
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.h b/src/server/game/Battlegrounds/Zones/BattlegroundWS.h
index c6c25ec52de..3d449580fb9 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.h
@@ -20,6 +20,7 @@
#define __BATTLEGROUNDWS_H
#include "Battleground.h"
+#include "BattlegroundScore.h"
enum BG_WS_TimerOrScore
{
@@ -146,12 +147,38 @@ enum BG_WS_Objectives
#define WS_EVENT_START_BATTLE 8563
-struct BattlegroundWGScore : public BattlegroundScore
+struct BattlegroundWGScore final : public BattlegroundScore
{
- BattlegroundWGScore() : FlagCaptures(0), FlagReturns(0) { }
- ~BattlegroundWGScore() { }
- uint32 FlagCaptures;
- uint32 FlagReturns;
+ friend class BattlegroundWS;
+
+ protected:
+ BattlegroundWGScore(uint64 playerGuid) : BattlegroundScore(playerGuid), FlagCaptures(0), FlagReturns(0) { }
+
+ void UpdateScore(uint32 type, uint32 value) override
+ {
+ switch (type)
+ {
+ case SCORE_FLAG_CAPTURES: // Flags captured
+ FlagCaptures += value;
+ break;
+ case SCORE_FLAG_RETURNS: // Flags returned
+ FlagReturns += value;
+ break;
+ default:
+ BattlegroundScore::UpdateScore(type, value);
+ break;
+ }
+ }
+
+ void BuildObjectivesBlock(WorldPacket& data) final
+ {
+ data << uint32(2); // Objectives Count
+ data << uint32(FlagCaptures);
+ data << uint32(FlagReturns);
+ }
+
+ uint32 FlagCaptures;
+ uint32 FlagReturns;
};
class BattlegroundWS : public Battleground
@@ -197,7 +224,7 @@ class BattlegroundWS : public Battleground
void UpdateFlagState(uint32 team, uint32 value);
void SetLastFlagCapture(uint32 team) { _lastFlagCaptureTeam = team; }
void UpdateTeamScore(uint32 team);
- void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true);
+ bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
void SetDroppedFlagGUID(uint64 guid, int32 team = -1)
{
if (team == TEAM_ALLIANCE || team == TEAM_HORDE)
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index 8e186e9d094..03180b35cb5 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -326,8 +326,8 @@ enum MapFlags
enum AbilytyLearnType
{
- ABILITY_LEARNED_ON_GET_PROFESSION_SKILL = 1,
- ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL = 2
+ SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE = 1, // Spell state will update depending on skill value
+ SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN = 2 // Spell will be learned/removed together with entire skill
};
enum ItemEnchantmentType
@@ -349,21 +349,20 @@ enum ItemLimitCategoryMode
ITEM_LIMIT_CATEGORY_MODE_EQUIP = 1 // limit applied to amount equipped items (including used gems)
};
-enum SpellCategoryFlags
+enum SkillRaceClassInfoFlags
{
- SPELL_CATEGORY_FLAG_COOLDOWN_SCALES_WITH_WEAPON_SPEED = 0x01, // unused
- SPELL_CATEGORY_FLAG_COOLDOWN_STARTS_ON_EVENT = 0x04
+ SKILL_FLAG_NO_SKILLUP_MESSAGE = 0x2,
+ SKILL_FLAG_ALWAYS_MAX_VALUE = 0x10,
+ SKILL_FLAG_UNLEARNABLE = 0x20, // Skill can be unlearned
+ SKILL_FLAG_INCLUDE_IN_SORT = 0x80, // Spells belonging to a skill with this flag will additionally compare skill ids when sorting spellbook in client
+ SKILL_FLAG_NOT_TRAINABLE = 0x100,
+ SKILL_FLAG_MONO_VALUE = 0x400 // Skill always has value 1 - clientside display flag, real value can be different
};
-enum TotemCategoryType
+enum SpellCategoryFlags
{
- TOTEM_CATEGORY_TYPE_KNIFE = 1,
- TOTEM_CATEGORY_TYPE_TOTEM = 2,
- TOTEM_CATEGORY_TYPE_ROD = 3,
- TOTEM_CATEGORY_TYPE_PICK = 21,
- TOTEM_CATEGORY_TYPE_STONE = 22,
- TOTEM_CATEGORY_TYPE_HAMMER = 23,
- TOTEM_CATEGORY_TYPE_SPANNER = 24
+ SPELL_CATEGORY_FLAG_COOLDOWN_SCALES_WITH_WEAPON_SPEED = 0x01, // unused
+ SPELL_CATEGORY_FLAG_COOLDOWN_STARTS_ON_EVENT = 0x04
};
// SummonProperties.dbc, col 1
@@ -398,6 +397,17 @@ enum SummonPropFlags
SUMMON_PROP_FLAG_UNK16 = 0x00008000 // Light/Dark Bullet, Soul/Fiery Consumption, Twisted Visage, Twilight Whelp. Phase related?
};
+enum TotemCategoryType
+{
+ TOTEM_CATEGORY_TYPE_KNIFE = 1,
+ TOTEM_CATEGORY_TYPE_TOTEM = 2,
+ TOTEM_CATEGORY_TYPE_ROD = 3,
+ TOTEM_CATEGORY_TYPE_PICK = 21,
+ TOTEM_CATEGORY_TYPE_STONE = 22,
+ TOTEM_CATEGORY_TYPE_HAMMER = 23,
+ TOTEM_CATEGORY_TYPE_SPANNER = 24
+};
+
enum VehicleSeatFlags
{
VEHICLE_SEAT_FLAG_HAS_LOWER_ANIM_FOR_ENTER = 0x00000001,
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index 44f03b6978d..e960422cbbc 100644
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -151,6 +151,9 @@ DBCStorage <ScalingStatValuesEntry> sScalingStatValuesStore(ScalingStatValuesfmt
DBCStorage <SkillLineEntry> sSkillLineStore(SkillLinefmt);
DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore(SkillLineAbilityfmt);
+DBCStorage <SkillRaceClassInfoEntry> sSkillRaceClassInfoStore(SkillRaceClassInfofmt);
+SkillRaceClassInfoMap SkillRaceClassInfoBySkill;
+DBCStorage <SkillTiersEntry> sSkillTiersStore(SkillTiersfmt);
DBCStorage <SoundEntriesEntry> sSoundEntriesStore(SoundEntriesfmt);
@@ -409,6 +412,13 @@ void LoadDBCStores(const std::string& dataPath)
LoadDBC(availableDbcLocales, bad_dbc_files, sScalingStatValuesStore, dbcPath, "ScalingStatValues.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineStore, dbcPath, "SkillLine.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineAbilityStore, dbcPath, "SkillLineAbility.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSkillRaceClassInfoStore, dbcPath, "SkillRaceClassInfo.dbc");
+ for (uint32 i = 0; i < sSkillRaceClassInfoStore.GetNumRows(); ++i)
+ if (SkillRaceClassInfoEntry const* entry = sSkillRaceClassInfoStore.LookupEntry(i))
+ if (sSkillLineStore.LookupEntry(entry->SkillId))
+ SkillRaceClassInfoBySkill.emplace(entry->SkillId, entry);
+
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSkillTiersStore, dbcPath, "SkillTiers.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sSoundEntriesStore, dbcPath, "SoundEntries.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sSpellStore, dbcPath, "Spell.dbc", &CustomSpellEntryfmt, &CustomSpellEntryIndex);
for (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i)
@@ -440,7 +450,7 @@ void LoadDBCStores(const std::string& dataPath)
if (spellInfo->spellLevel)
continue;
- if (skillLine->learnOnGetSkill != ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL)
+ if (skillLine->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN)
continue;
sPetFamilySpellsStore[i].insert(spellInfo->Id);
@@ -965,3 +975,19 @@ uint32 GetDefaultMapLight(uint32 mapId)
return 0;
}
+
+SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_)
+{
+ SkillRaceClassInfoBounds bounds = SkillRaceClassInfoBySkill.equal_range(skill);
+ for (SkillRaceClassInfoMap::iterator itr = bounds.first; itr != bounds.second; ++itr)
+ {
+ if (itr->second->RaceMask && !(itr->second->RaceMask & (1 << (race - 1))))
+ continue;
+ if (itr->second->ClassMask && !(itr->second->ClassMask & (1 << (class_ - 1))))
+ continue;
+
+ return itr->second;
+ }
+
+ return NULL;
+}
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index fe775dfda19..8b89a86fafe 100644
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -74,6 +74,10 @@ LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty);
uint32 GetDefaultMapLight(uint32 mapId);
+typedef std::unordered_multimap<uint32, SkillRaceClassInfoEntry const*> SkillRaceClassInfoMap;
+typedef std::pair<SkillRaceClassInfoMap::iterator, SkillRaceClassInfoMap::iterator> SkillRaceClassInfoBounds;
+SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_);
+
extern DBCStorage <AchievementEntry> sAchievementStore;
extern DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore;
extern DBCStorage <AreaTableEntry> sAreaStore;// recommend access using functions
@@ -150,6 +154,7 @@ extern DBCStorage <ScalingStatDistributionEntry> sScalingStatDistributionStore;
extern DBCStorage <ScalingStatValuesEntry> sScalingStatValuesStore;
extern DBCStorage <SkillLineEntry> sSkillLineStore;
extern DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore;
+extern DBCStorage <SkillTiersEntry> sSkillTiersStore;
extern DBCStorage <SoundEntriesEntry> sSoundEntriesStore;
extern DBCStorage <SpellCastTimesEntry> sSpellCastTimesStore;
extern DBCStorage <SpellCategoryEntry> sSpellCategoryStore;
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index ec9d2dafbd2..2b01dfd70bc 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -1535,23 +1535,6 @@ struct ScalingStatValuesEntry
// uint32 displayOrder; // 19 m_sortIndex
//};
-//struct SkillRaceClassInfoEntry{
-// uint32 id; // 0 m_ID
-// uint32 skillId; // 1 m_skillID
-// uint32 raceMask; // 2 m_raceMask
-// uint32 classMask; // 3 m_classMask
-// uint32 flags; // 4 m_flags
-// uint32 reqLevel; // 5 m_minLevel
-// uint32 skillTierId; // 6 m_skillTierID
-// uint32 skillCostID; // 7 m_skillCostIndex
-//};
-
-//struct SkillTiersEntry{
-// uint32 id; // 0 m_ID
-// uint32 skillValue[16]; // 1-17 m_cost
-// uint32 maxSkillValue[16]; // 18-32 m_valueMax
-//};
-
struct SkillLineEntry
{
uint32 id; // 0 m_ID
@@ -1578,12 +1561,33 @@ struct SkillLineAbilityEntry
//uint32 classmaskNot; // 6 m_excludeClass
uint32 req_skill_value; // 7 m_minSkillLineRank
uint32 forward_spellid; // 8 m_supercededBySpell
- uint32 learnOnGetSkill; // 9 m_acquireMethod
+ uint32 AutolearnType; // 9 m_acquireMethod
uint32 max_value; // 10 m_trivialSkillLineRankHigh
uint32 min_value; // 11 m_trivialSkillLineRankLow
//uint32 characterPoints[2]; // 12-13 m_characterPoints[2]
};
+struct SkillRaceClassInfoEntry
+{
+ //uint32 Id; // 0
+ uint32 SkillId; // 1
+ uint32 RaceMask; // 2
+ uint32 ClassMask; // 3
+ uint32 Flags; // 4
+ //uint32 MinLevel; // 5
+ uint32 SkillTier; // 6
+ //uint32 SkillCostType; // 7
+};
+
+#define MAX_SKILL_STEP 16
+
+struct SkillTiersEntry
+{
+ uint32 Id; // 0
+ //uint32 StepCost[MAX_SKILL_STEP]; // 1-16
+ uint32 MaxSkill[MAX_SKILL_STEP]; // 17-32
+};
+
struct SoundEntriesEntry
{
uint32 Id; // 0 m_ID
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index 222353467f4..a90cc48c5af 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -98,6 +98,8 @@ char const ScalingStatDistributionfmt[] = "niiiiiiiiiiiiiiiiiiiii";
char const ScalingStatValuesfmt[] = "iniiiiiiiiiiiiiiiiiiiiii";
char const SkillLinefmt[] = "nixssssssssssssssssxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxi";
char const SkillLineAbilityfmt[] = "niiiixxiiiiixx";
+char const SkillRaceClassInfofmt[] = "diiiixix";
+char const SkillTiersfmt[] = "nxxxxxxxxxxxxxxxxiiiiiiiiiiiiiiii";
char const SoundEntriesfmt[] = "nxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char const SpellCastTimefmt[] = "nixx";
char const SpellCategoryfmt[] = "ni";
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index c81ba409495..fd8aaff8159 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -142,8 +142,8 @@ bool ForcedDespawnDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
}
Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapObject(),
-lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLowGUID(0),
-m_PlayerDamageReq(0), m_lootRecipient(0), m_lootRecipientGroup(0), m_corpseRemoveTime(0), m_respawnTime(0),
+m_groupLootTimer(0), lootingGroupLowGUID(0), m_PlayerDamageReq(0),
+m_lootRecipient(0), m_lootRecipientGroup(0), _skinner(0), _pickpocketLootRestore(0), m_corpseRemoveTime(0), m_respawnTime(0),
m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_reactState(REACT_AGGRESSIVE),
m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false),
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
@@ -547,6 +547,15 @@ void Creature::Update(uint32 diff)
if (!IsAlive())
break;
+ time_t now = time(NULL);
+
+ // Check if we should refill the pickpocketing loot
+ if (loot.loot_type == LOOT_PICKPOCKETING && _pickpocketLootRestore && _pickpocketLootRestore <= now)
+ {
+ loot.clear();
+ _pickpocketLootRestore = 0;
+ }
+
if (m_regenTimer > 0)
{
if (diff >= m_regenTimer)
@@ -1463,11 +1472,6 @@ void Creature::setDeathState(DeathState s)
setActive(false);
- if (!IsPet() && GetCreatureTemplate()->SkinLootId)
- if (LootTemplates_Skinning.HaveLootFor(GetCreatureTemplate()->SkinLootId))
- if (hasLootRecipient())
- SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
-
if (HasSearchedAssistance())
{
SetNoSearchAssistance(false);
@@ -1527,9 +1531,8 @@ void Creature::Respawn(bool force)
TC_LOG_DEBUG("entities.unit", "Respawning creature %s (GuidLow: %u, Full GUID: " UI64FMTD " Entry: %u)",
GetName().c_str(), GetGUIDLow(), GetGUID(), GetEntry());
m_respawnTime = 0;
- lootForPickPocketed = false;
- lootForBody = false;
-
+ _pickpocketLootRestore = 0;
+ loot.clear();
if (m_originalEntry != GetEntry())
UpdateEntry(m_originalEntry);
@@ -2268,26 +2271,23 @@ void Creature::GetRespawnPosition(float &x, float &y, float &z, float* ori, floa
void Creature::AllLootRemovedFromCorpse()
{
- if (!HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE))
- {
- time_t now = time(NULL);
- if (m_corpseRemoveTime <= now)
- return;
+ if (loot.loot_type != LOOT_SKINNING && !IsPet() && GetCreatureTemplate()->SkinLootId && hasLootRecipient())
+ if (LootTemplates_Skinning.HaveLootFor(GetCreatureTemplate()->SkinLootId))
+ SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
- float decayRate;
- CreatureTemplate const* cinfo = GetCreatureTemplate();
+ time_t now = time(NULL);
+ if (m_corpseRemoveTime <= now)
+ return;
- decayRate = sWorld->getRate(RATE_CORPSE_DECAY_LOOTED);
- uint32 diff = uint32((m_corpseRemoveTime - now) * decayRate);
+ float decayRate = sWorld->getRate(RATE_CORPSE_DECAY_LOOTED);
- m_respawnTime -= diff;
+ // corpse skinnable, but without skinning flag, and then skinned, corpse will despawn next update
+ if (loot.loot_type == LOOT_SKINNING)
+ m_corpseRemoveTime = time(NULL);
+ else
+ m_corpseRemoveTime = now + m_corpseDelay * decayRate;
- // corpse skinnable, but without skinning flag, and then skinned, corpse will despawn next update
- if (cinfo && cinfo->SkinLootId)
- m_corpseRemoveTime = time(NULL);
- else
- m_corpseRemoveTime -= diff;
- }
+ m_respawnTime = m_corpseRemoveTime + m_respawnDelay;
}
uint8 Creature::getLevelForTarget(WorldObject const* target) const
@@ -2712,3 +2712,8 @@ void Creature::ReleaseFocus(Spell const* focusSpell)
ClearUnitState(UNIT_STATE_ROTATING);
}
+void Creature::StartPickPocketRefillTimer()
+{
+ _pickpocketLootRestore = time(NULL) + sWorld->getIntConfig(CONFIG_CREATURE_PICKPOCKET_REFILL);
+}
+
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 9cc08e3b71d..ca536e44e43 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -551,8 +551,10 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
virtual void DeleteFromDB(); // overriden in Pet
Loot loot;
- bool lootForPickPocketed;
- bool lootForBody;
+ void StartPickPocketRefillTimer();
+ void ResetPickPocketRefillTimer() { _pickpocketLootRestore = 0; }
+ void SetSkinner(uint64 guid) { _skinner = guid; }
+ uint64 GetSkinner() const { return _skinner; } // Returns the player who skinned this creature
Player* GetLootRecipient() const;
Group* GetLootRecipientGroup() const;
bool hasLootRecipient() const { return m_lootRecipient || m_lootRecipientGroup; }
@@ -688,8 +690,10 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
uint64 m_lootRecipient;
uint32 m_lootRecipientGroup;
+ uint64 _skinner;
/// Timers
+ time_t _pickpocketLootRestore;
time_t m_corpseRemoveTime; // (msecs)timer for death or corpse disappearance
time_t m_respawnTime; // (secs) time of next respawn
uint32 m_respawnDelay; // (secs) delay between corpse disappearance and respawning
diff --git a/src/server/game/Entities/Item/ItemPrototype.h b/src/server/game/Entities/Item/ItemPrototype.h
index cc477c5bd37..bdf956f8921 100644
--- a/src/server/game/Entities/Item/ItemPrototype.h
+++ b/src/server/game/Entities/Item/ItemPrototype.h
@@ -734,7 +734,7 @@ struct ItemTemplate
default:
break;
}
- return itemLevel;
+ return std::max<float>(0.f, itemLevel);
}
bool IsPotion() const { return Class == ITEM_CLASS_CONSUMABLE && SubClass == ITEM_SUBCLASS_POTION; }
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index f2823cc1435..6a1c91456e5 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -26,6 +26,7 @@
#include "BattlefieldWG.h"
#include "Battleground.h"
#include "BattlegroundMgr.h"
+#include "BattlegroundScore.h"
#include "CellImpl.h"
#include "Channel.h"
#include "ChannelMgr.h"
@@ -1133,7 +1134,8 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
}
// original spells
- learnDefaultSpells();
+ LearnDefaultSkills();
+ LearnCustomSpells();
// original action bar
for (PlayerCreateInfoActions::const_iterator action_itr = info->action.begin(); action_itr != info->action.end(); ++action_itr)
@@ -2920,11 +2922,10 @@ void Player::UninviteFromGroup()
void Player::RemoveFromGroup(Group* group, uint64 guid, RemoveMethod method /* = GROUP_REMOVEMETHOD_DEFAULT*/, uint64 kicker /* = 0 */, const char* reason /* = NULL */)
{
- if (group)
- {
- group->RemoveMember(guid, method, kicker, reason);
- group = NULL;
- }
+ if (!group)
+ return;
+
+ group->RemoveMember(guid, method, kicker, reason);
}
void Player::SendLogXPGain(uint32 GivenXP, Unit* victim, uint32 BonusXP, bool recruitAFriend, float /*group_rate*/)
@@ -3827,34 +3828,14 @@ bool Player::addSpell(uint32 spellId, bool active, bool learning, bool dependent
if (!pSkill)
continue;
- if (!Has310Flyer(false) && pSkill->id == SKILL_MOUNTS)
+ if (!HasSkill(pSkill->id))
+ LearnDefaultSkill(pSkill->id, 0);
+
+ if (pSkill->id == SKILL_MOUNTS && !Has310Flyer(false))
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED &&
spellInfo->Effects[i].CalcValue() == 310)
SetHas310Flyer(true);
-
- if (HasSkill(pSkill->id))
- continue;
-
- if (_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL ||
- // lockpicking/runeforging special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL
- ((pSkill->id == SKILL_LOCKPICKING || pSkill->id == SKILL_RUNEFORGING) && _spell_idx->second->max_value == 0))
- {
- switch (GetSkillRangeType(pSkill, _spell_idx->second->racemask != 0))
- {
- case SKILL_RANGE_LANGUAGE:
- SetSkill(pSkill->id, GetSkillStep(pSkill->id), 300, 300);
- break;
- case SKILL_RANGE_LEVEL:
- SetSkill(pSkill->id, GetSkillStep(pSkill->id), 1, GetMaxSkillValueForLevel());
- break;
- case SKILL_RANGE_MONO:
- SetSkill(pSkill->id, GetSkillStep(pSkill->id), 1, 1);
- break;
- default:
- break;
- }
- }
}
}
@@ -4079,33 +4060,27 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank)
// not ranked skills
SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spell_id);
- for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx)
+ // most likely will never be used, haven't heard of cases where players unlearn a mount
+ if (Has310Flyer(false) && spellInfo)
{
- SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(_spell_idx->second->skillId);
- if (!pSkill)
- continue;
-
- if ((_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL &&
- pSkill->categoryId != SKILL_CATEGORY_CLASS) ||// not unlearn class skills (spellbook/talent pages)
- // lockpicking/runeforging special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL
- ((pSkill->id == SKILL_LOCKPICKING || pSkill->id == SKILL_RUNEFORGING) && _spell_idx->second->max_value == 0))
+ for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx)
{
- // not reset skills for professions and racial abilities
- if ((pSkill->categoryId == SKILL_CATEGORY_SECONDARY || pSkill->categoryId == SKILL_CATEGORY_PROFESSION) &&
- (IsProfessionSkill(pSkill->id) || _spell_idx->second->racemask != 0))
+ SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(_spell_idx->second->skillId);
+ if (!pSkill)
continue;
- SetSkill(pSkill->id, GetSkillStep(pSkill->id), 0, 0);
- }
-
- // most likely will never be used, haven't heard of cases where players unlearn a mount
- if (Has310Flyer(false) && _spell_idx->second->skillId == SKILL_MOUNTS)
- {
- if (spellInfo)
+ if (_spell_idx->second->skillId == SKILL_MOUNTS)
+ {
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
if (spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED &&
spellInfo->Effects[i].CalcValue() == 310)
+ {
Has310Flyer(true, spell_id); // with true as first argument its also used to set/remove the flag
+ break;
+ }
+ }
+ }
}
}
}
@@ -6080,9 +6055,6 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step)
if (!skill_id)
return false;
- if (skill_id == SKILL_FIST_WEAPONS)
- skill_id = SKILL_UNARMED;
-
SkillStatusMap::iterator itr = mSkillStatus.find(skill_id);
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return false;
@@ -6097,13 +6069,14 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step)
if (value < max)
{
- uint32 new_value = value+step;
+ uint32 new_value = value + step;
if (new_value > max)
new_value = max;
SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(new_value, max));
if (itr->second.uState != SKILL_NEW)
itr->second.uState = SKILL_CHANGED;
+
UpdateSkillEnchantments(skill_id, value, new_value);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, skill_id);
return true;
@@ -6277,9 +6250,25 @@ void Player::UpdateWeaponSkill(WeaponAttackType attType)
Item* tmpitem = GetWeaponForAttack(attType, true);
if (!tmpitem && attType == BASE_ATTACK)
+ {
+ // Keep unarmed & fist weapon skills in sync
UpdateSkill(SKILL_UNARMED, weapon_skill_gain);
+ UpdateSkill(SKILL_FIST_WEAPONS, weapon_skill_gain);
+ }
else if (tmpitem && tmpitem->GetTemplate()->SubClass != ITEM_SUBCLASS_WEAPON_FISHING_POLE)
- UpdateSkill(tmpitem->GetSkill(), weapon_skill_gain);
+ {
+ switch (tmpitem->GetTemplate()->SubClass)
+ {
+ case ITEM_SUBCLASS_WEAPON_FISHING_POLE:
+ break;
+ case ITEM_SUBCLASS_WEAPON_FIST:
+ UpdateSkill(SKILL_UNARMED, weapon_skill_gain);
+ // no break intended
+ default:
+ UpdateSkill(tmpitem->GetSkill(), weapon_skill_gain);
+ break;
+ }
+ }
UpdateAllCritPercentages();
}
@@ -6352,11 +6341,11 @@ void Player::UpdateSkillsForLevel()
continue;
uint32 pskill = itr->first;
- SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(pskill);
- if (!pSkill)
+ SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(pskill, getRace(), getClass());
+ if (!rcEntry)
continue;
- if (GetSkillRangeType(pSkill, false) != SKILL_RANGE_LEVEL)
+ if (GetSkillRangeType(rcEntry) != SKILL_RANGE_LEVEL)
continue;
uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos);
@@ -8970,9 +8959,9 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
if (loot_type == LOOT_PICKPOCKETING)
{
- if (!creature->lootForPickPocketed)
+ if (loot->loot_type != LOOT_PICKPOCKETING)
{
- creature->lootForPickPocketed = true;
+ creature->StartPickPocketRefillTimer();
loot->clear();
if (uint32 lootid = creature->GetCreatureTemplate()->pickpocketLootId)
@@ -8992,12 +8981,9 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
if (!recipient)
return;
- if (!creature->lootForBody)
+ if (loot->loot_type == LOOT_NONE)
{
- creature->lootForBody = true;
-
// for creature, loot is filled when creature is killed.
-
if (Group* group = recipient->GetGroup())
{
switch (group->GetLootMethod())
@@ -9018,11 +9004,17 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
}
}
- // possible only if creature->lootForBody && loot->empty() at spell cast check
- if (loot_type == LOOT_SKINNING)
+ // if loot is already skinning loot then don't do anything else
+ if (loot->loot_type == LOOT_SKINNING)
+ {
+ loot_type = LOOT_SKINNING;
+ permission = creature->GetSkinner() == GetGUID() ? OWNER_PERMISSION : NONE_PERMISSION;
+ }
+ else if (loot_type == LOOT_SKINNING)
{
loot->clear();
loot->FillLoot(creature->GetCreatureTemplate()->SkinLootId, LootTemplates_Skinning, this, true);
+ creature->SetSkinner(GetGUID());
permission = OWNER_PERMISSION;
}
// set group rights only for loot_type != LOOT_SKINNING
@@ -17701,7 +17693,8 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
// after spell and quest load
InitTalentForLevel();
- learnDefaultSpells();
+ LearnDefaultSkills();
+ LearnCustomSpells();
// must be before inventory (some items required reputation check)
m_reputationMgr->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_REPUTATION));
@@ -17831,6 +17824,9 @@ bool Player::isAllowedToLoot(const Creature* creature)
if (loot->isLooted()) // nothing to loot or everything looted.
return false;
+ if (loot->loot_type == LOOT_SKINNING)
+ return creature->GetSkinner() == GetGUID();
+
Group* thisGroup = GetGroup();
if (!thisGroup)
return this == creature->GetLootRecipient();
@@ -23072,15 +23068,19 @@ void Player::resetSpells(bool myClassOnly)
for (PlayerSpellMap::const_iterator iter = smap.begin(); iter != smap.end(); ++iter)
removeSpell(iter->first, false, false); // only iter->first can be accessed, object by iter->second can be deleted already
- learnDefaultSpells();
+ LearnDefaultSkills();
+ LearnCustomSpells();
learnQuestRewardedSpells();
}
-void Player::learnDefaultSpells()
+void Player::LearnCustomSpells()
{
+ if (!sWorld->getBoolConfig(CONFIG_START_ALL_SPELLS))
+ return;
+
// learn default race/class spells
PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass());
- for (PlayerCreateInfoSpells::const_iterator itr = info->spell.begin(); itr != info->spell.end(); ++itr)
+ for (PlayerCreateInfoSpells::const_iterator itr = info->customSpells.begin(); itr != info->customSpells.end(); ++itr)
{
uint32 tspell = *itr;
TC_LOG_DEBUG("entities.player.loading", "PLAYER (Class: %u Race: %u): Adding initial spell, id = %u", uint32(getClass()), uint32(getRace()), tspell);
@@ -23091,6 +23091,63 @@ void Player::learnDefaultSpells()
}
}
+void Player::LearnDefaultSkills()
+{
+ // learn default race/class skills
+ PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass());
+ for (PlayerCreateInfoSkills::const_iterator itr = info->skills.begin(); itr != info->skills.end(); ++itr)
+ {
+ uint32 skillId = itr->SkillId;
+ if (HasSkill(skillId))
+ continue;
+
+ LearnDefaultSkill(skillId, itr->Rank);
+ }
+}
+
+void Player::LearnDefaultSkill(uint32 skillId, uint16 rank)
+{
+ SkillRaceClassInfoEntry const* rcInfo = GetSkillRaceClassInfo(skillId, getRace(), getClass());
+ if (!rcInfo)
+ return;
+
+ TC_LOG_DEBUG("entities.player.loading", "PLAYER (Class: %u Race: %u): Adding initial skill, id = %u", uint32(getClass()), uint32(getRace()), skillId);
+ switch (GetSkillRangeType(rcInfo))
+ {
+ case SKILL_RANGE_LANGUAGE:
+ SetSkill(skillId, 0, 300, 300);
+ break;
+ case SKILL_RANGE_LEVEL:
+ {
+ uint16 skillValue = 0;
+ uint16 maxValue = GetMaxSkillValueForLevel();
+ if (rcInfo->Flags & SKILL_FLAG_ALWAYS_MAX_VALUE)
+ skillValue = maxValue;
+ else
+ skillValue = std::min(std::max<uint16>({ 1, uint16((getLevel() - 1) * 5) }), maxValue);
+
+ SetSkill(skillId, 0, skillValue, maxValue);
+ break;
+ }
+ case SKILL_RANGE_MONO:
+ SetSkill(skillId, 0, 1, 1);
+ break;
+ case SKILL_RANGE_RANK:
+ {
+ if (!rank)
+ break;
+
+ SkillTiersEntry const* tier = sSkillTiersStore.LookupEntry(rcInfo->SkillTier);
+ uint16 maxValue = std::max<uint16>(GetMaxSkillValue(skillId), tier->MaxSkill[std::max<int32>(rank - 1, 0)]);
+ uint16 skillValue = std::min(std::max<uint16>({ uint16(1), uint16((getLevel() - 1) * 5) }), maxValue);
+ SetSkill(skillId, rank, skillValue, maxValue);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
void Player::learnQuestRewardedSpells(Quest const* quest)
{
int32 spell_id = quest->GetRewSpellCast();
@@ -23188,29 +23245,35 @@ void Player::learnSkillRewardedSpells(uint32 skill_id, uint32 skill_value)
{
uint32 raceMask = getRaceMask();
uint32 classMask = getClassMask();
- for (uint32 j=0; j<sSkillLineAbilityStore.GetNumRows(); ++j)
+ for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
{
SkillLineAbilityEntry const* pAbility = sSkillLineAbilityStore.LookupEntry(j);
- if (!pAbility || pAbility->skillId != skill_id || pAbility->learnOnGetSkill != ABILITY_LEARNED_ON_GET_PROFESSION_SKILL)
+ if (!pAbility || pAbility->skillId != skill_id)
continue;
+
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(pAbility->spellId);
+ if (!spellInfo)
+ continue;
+
+ if (pAbility->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE && pAbility->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN)
+ continue;
+
// Check race if set
if (pAbility->racemask && !(pAbility->racemask & raceMask))
continue;
+
// Check class if set
if (pAbility->classmask && !(pAbility->classmask & classMask))
continue;
- if (sSpellMgr->GetSpellInfo(pAbility->spellId))
- {
- // need unlearn spell
- if (skill_value < pAbility->req_skill_value)
- removeSpell(pAbility->spellId);
- // need learn
- else if (!IsInWorld())
- addSpell(pAbility->spellId, true, true, true, false);
- else
- learnSpell(pAbility->spellId, true);
- }
+ // need unlearn spell
+ if (skill_value < pAbility->req_skill_value && pAbility->AutolearnType == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE)
+ removeSpell(pAbility->spellId);
+ // need learn
+ else if (!IsInWorld())
+ addSpell(pAbility->spellId, true, true, true, false);
+ else
+ learnSpell(pAbility->spellId, true);
}
}
@@ -23938,7 +24001,7 @@ bool Player::IsAtRecruitAFriendDistance(WorldObject const* pOther) const
return pOther->GetDistance(player) <= sWorld->getFloatConfig(CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE);
}
-uint32 Player::GetBaseWeaponSkillValue (WeaponAttackType attType) const
+uint32 Player::GetBaseWeaponSkillValue(WeaponAttackType attType) const
{
Item* item = GetWeaponForAttack(attType, true);
@@ -23946,8 +24009,8 @@ uint32 Player::GetBaseWeaponSkillValue (WeaponAttackType attType) const
if (attType != BASE_ATTACK && !item)
return 0;
- // weapon skill or (unarmed for base attack and for fist weapons)
- uint32 skill = (item && item->GetSkill() != SKILL_FIST_WEAPONS) ? item->GetSkill() : uint32(SKILL_UNARMED);
+ // weapon skill or (unarmed for base attack)
+ uint32 skill = item ? item->GetSkill() : uint32(SKILL_UNARMED);
return GetBaseSkillValue(skill);
}
@@ -24901,15 +24964,15 @@ void Player::_LoadSkills(PreparedQueryResult result)
uint16 value = fields[1].GetUInt16();
uint16 max = fields[2].GetUInt16();
- SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(skill);
- if (!pSkill)
+ SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(skill, getRace(), getClass());
+ if (!rcEntry)
{
TC_LOG_ERROR("entities.player", "Character %u has skill %u that does not exist.", GetGUIDLow(), skill);
continue;
}
// set fixed skill ranges
- switch (GetSkillRangeType(pSkill, false))
+ switch (GetSkillRangeType(rcEntry))
{
case SKILL_RANGE_LANGUAGE: // 300..300
value = max = 300;
@@ -24917,9 +24980,12 @@ void Player::_LoadSkills(PreparedQueryResult result)
case SKILL_RANGE_MONO: // 1..1, grey monolite bar
value = max = 1;
break;
+ case SKILL_RANGE_LEVEL:
+ max = GetMaxSkillValueForLevel();
default:
break;
}
+
if (value == 0)
{
TC_LOG_ERROR("entities.player", "Character %u has skill %u with value 0. Will be deleted.", GetGUIDLow(), skill);
@@ -24934,11 +25000,20 @@ void Player::_LoadSkills(PreparedQueryResult result)
continue;
}
- // enable unlearn button for primary professions only
- if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION)
- SetUInt32Value(PLAYER_SKILL_INDEX(count), MAKE_PAIR32(skill, 1));
- else
- SetUInt32Value(PLAYER_SKILL_INDEX(count), MAKE_PAIR32(skill, 0));
+ uint16 skillStep = 0;
+ if (SkillTiersEntry const* skillTier = sSkillTiersStore.LookupEntry(rcEntry->SkillTier))
+ {
+ for (uint32 i = 0; i < MAX_SKILL_STEP; ++i)
+ {
+ if (skillTier->MaxSkill[skillStep] == max)
+ {
+ skillStep = i + 1;
+ break;
+ }
+ }
+ }
+
+ SetUInt32Value(PLAYER_SKILL_INDEX(count), MAKE_PAIR32(skill, skillStep));
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(count), MAKE_SKILL_VALUE(value, max));
SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(count), 0);
@@ -24964,34 +25039,6 @@ void Player::_LoadSkills(PreparedQueryResult result)
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(count), 0);
SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(count), 0);
}
-
- // special settings
- if (getClass() == CLASS_DEATH_KNIGHT)
- {
- uint8 base_level = std::min(getLevel(), uint8(sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL)));
- if (base_level < 1)
- base_level = 1;
- uint16 base_skill = (base_level-1)*5; // 270 at starting level 55
- if (base_skill < 1)
- base_skill = 1; // skill mast be known and then > 0 in any case
-
- if (GetPureSkillValue(SKILL_FIRST_AID) < base_skill)
- SetSkill(SKILL_FIRST_AID, 4 /*artisan*/, base_skill, 300);
- if (GetPureSkillValue(SKILL_AXES) < base_skill)
- SetSkill(SKILL_AXES, 0, base_skill, base_skill);
- if (GetPureSkillValue(SKILL_DEFENSE) < base_skill)
- SetSkill(SKILL_DEFENSE, 0, base_skill, base_skill);
- if (GetPureSkillValue(SKILL_POLEARMS) < base_skill)
- SetSkill(SKILL_POLEARMS, 0, base_skill, base_skill);
- if (GetPureSkillValue(SKILL_SWORDS) < base_skill)
- SetSkill(SKILL_SWORDS, 0, base_skill, base_skill);
- if (GetPureSkillValue(SKILL_2H_AXES) < base_skill)
- SetSkill(SKILL_2H_AXES, 0, base_skill, base_skill);
- if (GetPureSkillValue(SKILL_2H_SWORDS) < base_skill)
- SetSkill(SKILL_2H_SWORDS, 0, base_skill, base_skill);
- if (GetPureSkillValue(SKILL_UNARMED) < base_skill)
- SetSkill(SKILL_UNARMED, 0, base_skill, base_skill);
- }
}
uint32 Player::GetPhaseMaskForSpawn() const
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index fdebbde0ae2..5f500b7f1d8 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -249,6 +249,14 @@ struct PlayerCreateInfoAction
typedef std::list<PlayerCreateInfoAction> PlayerCreateInfoActions;
+struct PlayerCreateInfoSkill
+{
+ uint16 SkillId;
+ uint16 Rank;
+};
+
+typedef std::list<PlayerCreateInfoSkill> PlayerCreateInfoSkills;
+
struct PlayerInfo
{
// existence checked by displayId != 0
@@ -263,8 +271,9 @@ struct PlayerInfo
uint16 displayId_m;
uint16 displayId_f;
PlayerCreateInfoItems item;
- PlayerCreateInfoSpells spell;
+ PlayerCreateInfoSpells customSpells;
PlayerCreateInfoActions action;
+ PlayerCreateInfoSkills skills;
PlayerLevelInfo* levelInfo; //[level-1] 0..MaxPlayerLevel-1
};
@@ -1573,7 +1582,9 @@ class Player : public Unit, public GridObject<Player>
void learnSpell(uint32 spell_id, bool dependent);
void removeSpell(uint32 spell_id, bool disabled = false, bool learn_low_rank = true);
void resetSpells(bool myClassOnly = false);
- void learnDefaultSpells();
+ void LearnCustomSpells();
+ void LearnDefaultSkills();
+ void LearnDefaultSkill(uint32 skillId, uint16 rank);
void learnQuestRewardedSpells();
void learnQuestRewardedSpells(Quest const* quest);
void learnSpellHighRank(uint32 spellid);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 5e12022312d..72c1a071487 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -21,6 +21,7 @@
#include "Battlefield.h"
#include "BattlefieldMgr.h"
#include "Battleground.h"
+#include "BattlegroundScore.h"
#include "CellImpl.h"
#include "ConditionMgr.h"
#include "CreatureAI.h"
@@ -2833,12 +2834,10 @@ uint32 Unit::GetWeaponSkillValue (WeaponAttackType attType, Unit const* target)
if (IsInFeralForm())
return GetMaxSkillValueForLevel(); // always maximized SKILL_FERAL_COMBAT in fact
- // weapon skill or (unarmed for base attack and fist weapons)
- uint32 skill;
- if (item && item->GetSkill() != SKILL_FIST_WEAPONS)
+ // weapon skill or (unarmed for base attack)
+ uint32 skill = SKILL_UNARMED;
+ if (item)
skill = item->GetSkill();
- else
- skill = SKILL_UNARMED;
// in PvP use full skill instead current skill value
value = (target && target->IsControlledByPlayer())
@@ -3845,8 +3844,7 @@ void Unit::RemoveAurasByType(AuraType auraType, uint64 casterGUID, Aura* except,
{
Aura* aura = (*iter)->GetBase();
AuraApplication * aurApp = aura->GetApplicationOfTarget(GetGUID());
- if (!aurApp)
- continue;
+ ASSERT(aurApp);
++iter;
if (aura != except && (!casterGUID || aura->GetCasterGUID() == casterGUID)
@@ -7714,7 +7712,8 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL;
// Try handle unknown trigger spells
- if (sSpellMgr->GetSpellInfo(trigger_spell_id) == NULL)
+ // triggered spells exists only in serverside spell_dbc
+ /// @todo: reverify and move these spells to spellscripts
{
switch (auraSpellInfo->SpellFamilyName)
{
@@ -15271,8 +15270,8 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
if (creature)
{
Loot* loot = &creature->loot;
- if (creature->lootForPickPocketed)
- creature->lootForPickPocketed = false;
+ if (creature->loot.loot_type == LOOT_PICKPOCKETING)
+ creature->ResetPickPocketRefillTimer();
loot->clear();
if (uint32 lootid = creature->GetCreatureTemplate()->lootid)
@@ -15288,7 +15287,7 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
group->SendLooter(creature, NULL);
// Update round robin looter only if the creature had loot
- if (!creature->loot.empty())
+ if (!loot->empty())
group->UpdateLooterGuid(creature);
}
}
@@ -15391,9 +15390,12 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
if (!creature->IsPet())
{
creature->DeleteThreatList();
- CreatureTemplate const* cInfo = creature->GetCreatureTemplate();
- if (cInfo && (cInfo->lootid || cInfo->maxgold > 0))
+
+ // must be after setDeathState which resets dynamic flags
+ if (!creature->loot.isLooted())
creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
+ else
+ creature->AllLootRemovedFromCorpse();
}
// Call KilledUnit for creatures, this needs to be called after the lootable flag is set
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index db97ea270ef..4853c9b3ba5 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -1668,7 +1668,7 @@ void ObjectMgr::LoadCreatures()
}
// Skip spawnMask check for transport maps
- if (!_transportMaps.count(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid])
+ if (!IsTransportMap(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid])
TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u).", guid, data.spawnMask, data.mapid);
bool ok = true;
@@ -2003,7 +2003,7 @@ void ObjectMgr::LoadGameobjects()
data.spawnMask = fields[14].GetUInt8();
- if (!_transportMaps.count(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid])
+ if (!IsTransportMap(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid])
TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: %u Entry: %u) that has wrong spawn mask %u including not supported difficulty modes for map (Id: %u), skip", guid, data.id, data.spawnMask, data.mapid);
data.phaseMask = fields[15].GetUInt32();
@@ -3322,17 +3322,91 @@ void ObjectMgr::LoadPlayerInfo()
}
}
+
+ // Load playercreate skills
+ TC_LOG_INFO("server.loading", "Loading Player Create Skill Data...");
+ {
+ uint32 oldMSTime = getMSTime();
+
+ QueryResult result = WorldDatabase.PQuery("SELECT raceMask, classMask, skill, rank FROM playercreateinfo_skills");
+
+ if (!result)
+ {
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 player create skills. DB table `playercreateinfo_skills` is empty.");
+ }
+ else
+ {
+ uint32 count = 0;
+
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 raceMask = fields[0].GetUInt32();
+ uint32 classMask = fields[1].GetUInt32();
+ PlayerCreateInfoSkill skill;
+ skill.SkillId = fields[2].GetUInt16();
+ skill.Rank = fields[3].GetUInt16();
+
+ if (skill.Rank >= MAX_SKILL_STEP)
+ {
+ TC_LOG_ERROR("sql.sql", "Skill rank value %hu set for skill %hu raceMask %u classMask %u is too high, max allowed value is %d", skill.Rank, skill.SkillId, raceMask, classMask, MAX_SKILL_STEP);
+ continue;
+ }
+
+ if (raceMask != 0 && !(raceMask & RACEMASK_ALL_PLAYABLE))
+ {
+ TC_LOG_ERROR("sql.sql", "Wrong race mask %u in `playercreateinfo_skills` table, ignoring.", raceMask);
+ continue;
+ }
+
+ if (classMask != 0 && !(classMask & CLASSMASK_ALL_PLAYABLE))
+ {
+ TC_LOG_ERROR("sql.sql", "Wrong class mask %u in `playercreateinfo_skills` table, ignoring.", classMask);
+ continue;
+ }
+
+ if (!sSkillLineStore.LookupEntry(skill.SkillId))
+ {
+ TC_LOG_ERROR("sql.sql", "Wrong skill id %u in `playercreateinfo_skills` table, ignoring.", skill.SkillId);
+ continue;
+ }
+
+ for (uint32 raceIndex = RACE_HUMAN; raceIndex < MAX_RACES; ++raceIndex)
+ {
+ if (raceMask == 0 || ((1 << (raceIndex - 1)) & raceMask))
+ {
+ for (uint32 classIndex = CLASS_WARRIOR; classIndex < MAX_CLASSES; ++classIndex)
+ {
+ if (classMask == 0 || ((1 << (classIndex - 1)) & classMask))
+ {
+ if (!GetSkillRaceClassInfo(skill.SkillId, raceIndex, classIndex))
+ continue;
+
+ if (PlayerInfo* info = _playerInfo[raceIndex][classIndex])
+ {
+ info->skills.push_back(skill);
+ ++count;
+ }
+ }
+ }
+ }
+ }
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u player create skills in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ }
+ }
+
// Load playercreate spells
TC_LOG_INFO("server.loading", "Loading Player Create Spell Data...");
{
uint32 oldMSTime = getMSTime();
- std::string tableName = sWorld->getBoolConfig(CONFIG_START_ALL_SPELLS) ? "playercreateinfo_spell_custom" : "playercreateinfo_spell";
- QueryResult result = WorldDatabase.PQuery("SELECT racemask, classmask, Spell FROM %s", tableName.c_str());
+ QueryResult result = WorldDatabase.PQuery("SELECT racemask, classmask, Spell FROM playercreateinfo_spell_custom");
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 player create spells. DB table `%s` is empty.", tableName.c_str());
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 player create spells. DB table `playercreateinfo_spell_custom` is empty.");
}
else
{
@@ -3347,13 +3421,13 @@ void ObjectMgr::LoadPlayerInfo()
if (raceMask != 0 && !(raceMask & RACEMASK_ALL_PLAYABLE))
{
- TC_LOG_ERROR("sql.sql", "Wrong race mask %u in `%s` table, ignoring.", raceMask, tableName.c_str());
+ TC_LOG_ERROR("sql.sql", "Wrong race mask %u in `playercreateinfo_spell_custom` table, ignoring.", raceMask);
continue;
}
if (classMask != 0 && !(classMask & CLASSMASK_ALL_PLAYABLE))
{
- TC_LOG_ERROR("sql.sql", "Wrong class mask %u in `%s` table, ignoring.", classMask, tableName.c_str());
+ TC_LOG_ERROR("sql.sql", "Wrong class mask %u in `playercreateinfo_spell_custom` table, ignoring.", classMask);
continue;
}
@@ -3367,7 +3441,7 @@ void ObjectMgr::LoadPlayerInfo()
{
if (PlayerInfo* info = _playerInfo[raceIndex][classIndex])
{
- info->spell.push_back(spellId);
+ info->customSpells.push_back(spellId);
++count;
}
// We need something better here, the check is not accounting for spells used by multiple races/classes but not all of them.
@@ -3381,7 +3455,7 @@ void ObjectMgr::LoadPlayerInfo()
}
while (result->NextRow());
- TC_LOG_INFO("server.loading", ">> Loaded %u player create spells in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO("server.loading", ">> Loaded %u custom player create spells in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
}
@@ -7808,36 +7882,27 @@ int32 ObjectMgr::GetBaseReputationOf(FactionEntry const* factionEntry, uint8 rac
return 0;
}
-SkillRangeType GetSkillRangeType(SkillLineEntry const* pSkill, bool racial)
+SkillRangeType GetSkillRangeType(SkillRaceClassInfoEntry const* rcEntry)
{
- switch (pSkill->categoryId)
+ SkillLineEntry const* skill = sSkillLineStore.LookupEntry(rcEntry->SkillId);
+ if (!skill)
+ return SKILL_RANGE_NONE;
+
+ if (sSkillTiersStore.LookupEntry(rcEntry->SkillTier))
+ return SKILL_RANGE_RANK;
+
+ if (rcEntry->SkillId == SKILL_RUNEFORGING)
+ return SKILL_RANGE_MONO;
+
+ switch (skill->categoryId)
{
- case SKILL_CATEGORY_LANGUAGES: return SKILL_RANGE_LANGUAGE;
- case SKILL_CATEGORY_WEAPON:
- if (pSkill->id != SKILL_FIST_WEAPONS)
- return SKILL_RANGE_LEVEL;
- else
- return SKILL_RANGE_MONO;
case SKILL_CATEGORY_ARMOR:
- case SKILL_CATEGORY_CLASS:
- if (pSkill->id != SKILL_LOCKPICKING)
- return SKILL_RANGE_MONO;
- else
- return SKILL_RANGE_LEVEL;
- case SKILL_CATEGORY_SECONDARY:
- case SKILL_CATEGORY_PROFESSION:
- // not set skills for professions and racial abilities
- if (IsProfessionSkill(pSkill->id))
- return SKILL_RANGE_RANK;
- else if (racial)
- return SKILL_RANGE_NONE;
- else
- return SKILL_RANGE_MONO;
- default:
- case SKILL_CATEGORY_ATTRIBUTES: //not found in dbc
- case SKILL_CATEGORY_GENERIC: //only GENERIC(DND)
- return SKILL_RANGE_NONE;
+ return SKILL_RANGE_MONO;
+ case SKILL_CATEGORY_LANGUAGES:
+ return SKILL_RANGE_LANGUAGE;
}
+
+ return SKILL_RANGE_LEVEL;
}
void ObjectMgr::LoadGameTele()
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 20941901731..3cf0c103452 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -642,7 +642,7 @@ enum SkillRangeType
SKILL_RANGE_NONE // 0..0 always
};
-SkillRangeType GetSkillRangeType(SkillLineEntry const* pSkill, bool racial);
+SkillRangeType GetSkillRangeType(SkillRaceClassInfoEntry const* rcEntry);
#define MAX_PLAYER_NAME 12 // max allowed by client name length
#define MAX_INTERNAL_PLAYER_NAME 15 // max server internal player name length (> MAX_PLAYER_NAME for support declined names)
@@ -1297,6 +1297,8 @@ class ObjectMgr
void LoadFactionChangeSpells();
void LoadFactionChangeTitles();
+ bool IsTransportMap(uint32 mapId) const { return _transportMaps.count(mapId); }
+
private:
// first free id for selected id type
uint32 _auctionId;
diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp
index 0dfe396b65a..7def6b0f467 100644
--- a/src/server/game/Handlers/BattleGroundHandler.cpp
+++ b/src/server/game/Handlers/BattleGroundHandler.cpp
@@ -309,7 +309,7 @@ void WorldSession::HandlePVPLogDataOpcode(WorldPacket & /*recvData*/)
return;
WorldPacket data;
- sBattlegroundMgr->BuildPvpLogDataPacket(&data, bg);
+ bg->BuildPvPLogDataPacket(data);
SendPacket(&data);
TC_LOG_DEBUG("network", "WORLD: Sent MSG_PVP_LOG_DATA Message");
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index c2f93190a05..9ad382b4686 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -750,9 +750,9 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData)
std::string IP_str = GetRemoteAddress();
TC_LOG_INFO("entities.player.character", "Account: %d, IP: %s deleted character: %s, GUID: %u, Level: %u", accountId, IP_str.c_str(), name.c_str(), GUID_LOPART(guid), level);
-
+
// To prevent hook failure, place hook before removing reference from DB
- sScriptMgr->OnPlayerDelete(guid, initAccountId); // To prevent race conditioning, but as it also makes sense, we hand the accountId over for successful delete.
+ sScriptMgr->OnPlayerDelete(guid, initAccountId); // To prevent race conditioning, but as it also makes sense, we hand the accountId over for successful delete.
// Shouldn't interfere with character deletion though
if (sLog->ShouldLog("entities.player.dump", LOG_LEVEL_INFO)) // optimize GetPlayerDump call
diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp
index 61f0b9afce2..b9c6f349ac3 100644
--- a/src/server/game/Handlers/LootHandler.cpp
+++ b/src/server/game/Handlers/LootHandler.cpp
@@ -81,7 +81,7 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket& recvData)
{
Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid);
- bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->lootForPickPocketed);
+ bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING);
if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE))
{
@@ -148,7 +148,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/)
case HIGHGUID_VEHICLE:
{
Creature* creature = player->GetMap()->GetCreature(guid);
- bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->lootForPickPocketed);
+ bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING);
if (lootAllowed && creature->IsWithinDistInMap(player, INTERACTION_DISTANCE))
{
loot = &creature->loot;
@@ -348,18 +348,19 @@ void WorldSession::DoLootRelease(uint64 lguid)
{
Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid);
- bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->lootForPickPocketed);
+ bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING);
if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE))
return;
loot = &creature->loot;
if (loot->isLooted())
{
+ creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
+
// skip pickpocketing loot for speed, skinning timer reduction is no-op in fact
if (!creature->IsAlive())
creature->AllLootRemovedFromCorpse();
- creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
loot->clear();
}
else
diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp
index 10ef7810d1d..1270f4e6419 100644
--- a/src/server/game/Handlers/MailHandler.cpp
+++ b/src/server/game/Handlers/MailHandler.cpp
@@ -131,6 +131,13 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
uint32 reqmoney = cost + money;
+ // Check for overflow
+ if (reqmoney < money)
+ {
+ player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY);
+ return;
+ }
+
if (!player->HasEnoughMoney(reqmoney) && !player->IsGameMaster())
{
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY);
@@ -315,6 +322,10 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
// If theres is an item, there is a one hour delivery delay if sent to another account's character.
uint32 deliver_delay = needItemDelay ? sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0;
+ // don't ask for COD if there are no items
+ if (items_count == 0)
+ COD = 0;
+
// will delete item or place to receiver mail list
draft
.AddMoney(money)
@@ -338,7 +349,7 @@ void WorldSession::HandleMailMarkAsRead(WorldPacket& recvData)
Player* player = _player;
Mail* m = player->GetMail(mailId);
- if (m)
+ if (m && m->state != MAIL_STATE_DELETED)
{
if (player->unReadMails)
--player->unReadMails;
@@ -462,6 +473,13 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData)
return;
}
+ // verify that the mail has the item to avoid cheaters taking COD items without paying
+ if (std::find_if(m->items.begin(), m->items.end(), [itemId](MailItemInfo info){ return info.item_guid == itemId; }) == m->items.end())
+ {
+ player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_INTERNAL_ERROR);
+ return;
+ }
+
// prevent cheating with skip client money check
if (!player->HasEnoughMoney(m->COD))
{
@@ -710,7 +728,7 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket& recvData)
Player* player = _player;
Mail* m = player->GetMail(mailId);
- if (!m || (m->body.empty() && !m->mailTemplateId) || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL))
+ if (!m || (m->body.empty() && !m->mailTemplateId) || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL) || (m->checked & MAIL_CHECK_MASK_COPIED))
{
player->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_ERR_INTERNAL_ERROR);
return;
diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp
index f90dfef2684..8a94753b692 100644
--- a/src/server/game/Handlers/SkillHandler.cpp
+++ b/src/server/game/Handlers/SkillHandler.cpp
@@ -98,7 +98,8 @@ void WorldSession::HandleUnlearnSkillOpcode(WorldPacket& recvData)
uint32 skillId;
recvData >> skillId;
- if (!IsPrimaryProfessionSkill(skillId))
+ SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(skillId, GetPlayer()->getRace(), GetPlayer()->getClass());
+ if (!rcEntry || !(rcEntry->Flags & SKILL_FLAG_UNLEARNABLE))
return;
GetPlayer()->SetSkill(skillId, 0, 0, 0);
diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h
index 9be745e622d..cb3b9082c20 100644
--- a/src/server/game/Loot/LootMgr.h
+++ b/src/server/game/Loot/LootMgr.h
@@ -76,6 +76,8 @@ enum PermissionTypes
enum LootType
{
+ LOOT_NONE = 0,
+
LOOT_CORPSE = 1,
LOOT_PICKPOCKETING = 2,
LOOT_FISHING = 3,
@@ -341,6 +343,7 @@ struct Loot
gold = 0;
unlootedCount = 0;
roundRobinPlayer = 0;
+ loot_type = LOOT_NONE;
i_LootValidatorRefManager.clearReferences();
}
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 9967b59ecec..77bc76c6dfd 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -2595,7 +2595,7 @@ enum CreatureTypeFlags
CREATURE_TYPEFLAGS_EXOTIC = 0x00010000, // Can be tamed by hunter as exotic pet
CREATURE_TYPEFLAGS_UNK17 = 0x00020000, // ? Related to vehicles/pvp?
CREATURE_TYPEFLAGS_UNK18 = 0x00040000, // ? Related to vehicle/siege weapons?
- CREATURE_TYPEFLAGS_UNK19 = 0x00080000,
+ CREATURE_TYPEFLAGS_PROJECTILE_COLLISION = 0x00080000, // Projectiles can collide with this creature - interacts with TARGET_DEST_TRAJ
CREATURE_TYPEFLAGS_UNK20 = 0x00100000,
CREATURE_TYPEFLAGS_UNK21 = 0x00200000,
CREATURE_TYPEFLAGS_UNK22 = 0x00400000,
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 1240ec545ba..4cb6ec2d7af 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -445,7 +445,6 @@ class WorldSession
void HandleForceSpeedChangeAck(WorldPacket& recvData);
void HandlePingOpcode(WorldPacket& recvPacket);
- void HandleAuthSessionOpcode(WorldPacket& recvPacket);
void HandleRepopRequestOpcode(WorldPacket& recvPacket);
void HandleAutostoreLootItemOpcode(WorldPacket& recvPacket);
void HandleLootMoneyOpcode(WorldPacket& recvPacket);
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 48c2a76578d..0e0443cc675 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -1514,10 +1514,24 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex)
std::list<WorldObject*>::const_iterator itr = targets.begin();
for (; itr != targets.end(); ++itr)
{
+ if (!m_caster->HasInLine(*itr, 5.0f))
+ continue;
+
+ if (m_spellInfo->CheckTarget(m_caster, *itr, true) != SPELL_CAST_OK)
+ continue;
+
if (Unit* unitTarget = (*itr)->ToUnit())
- if (m_caster == *itr || m_caster->IsOnVehicle(unitTarget) || (unitTarget)->GetVehicle())//(*itr)->IsOnVehicle(m_caster))
+ {
+ if (m_caster == *itr || m_caster->IsOnVehicle(unitTarget) || unitTarget->GetVehicle())
continue;
+ if (Creature* creatureTarget = unitTarget->ToCreature())
+ {
+ if (!(creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PROJECTILE_COLLISION))
+ continue;
+ }
+ }
+
const float size = std::max((*itr)->GetObjectSize() * 0.7f, 1.0f); // 1/sqrt(3)
/// @todo all calculation should be based on src instead of m_caster
const float objDist2d = m_targets.GetSrcPos()->GetExactDist2d(*itr) * std::cos(m_targets.GetSrcPos()->GetRelativeAngle(*itr));
@@ -2251,7 +2265,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
m_spellAura = NULL; // Set aura to null for every target-make sure that pointer is not used for unit without aura applied
//Spells with this flag cannot trigger if effect is cast on self
- bool canEffectTrigger = !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_CANT_TRIGGER_PROC) && unitTarget->CanProc() && CanExecuteTriggersOnHit(mask);
+ bool canEffectTrigger = !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_CANT_TRIGGER_PROC) && unitTarget->CanProc() && (CanExecuteTriggersOnHit(mask) || missInfo == SPELL_MISS_IMMUNE || missInfo == SPELL_MISS_IMMUNE2);
Unit* spellHitTarget = NULL;
if (missInfo == SPELL_MISS_NONE) // In case spell hit target, do all effect on that target
@@ -2297,15 +2311,8 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
if (m_damage > 0)
positive = false;
else if (!m_healing)
- {
- for (uint8 i = 0; i< MAX_SPELL_EFFECTS; ++i)
- // If at least one effect negative spell is negative hit
- if (mask & (1<<i) && !m_spellInfo->IsPositiveEffect(i))
- {
- positive = false;
- break;
- }
- }
+ positive = m_spellInfo->IsPositive();
+
switch (m_spellInfo->DmgClass)
{
case SPELL_DAMAGE_CLASS_MAGIC:
@@ -2383,7 +2390,6 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
caster->ToPlayer()->CastItemCombatSpell(unitTarget, m_attackType, procVictim, procEx);
}
-
m_damage = damageInfo.damage;
caster->DealSpellDamage(&damageInfo, true);
@@ -2524,9 +2530,14 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
}
}
+ uint8 aura_effmask = 0;
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ if (effectMask & (1 << i) && m_spellInfo->Effects[i].IsUnitOwnedAuraEffect())
+ aura_effmask |= 1 << i;
+
// Get Data Needed for Diminishing Returns, some effects may have multiple auras, so this must be done on spell hit, not aura add
m_diminishGroup = GetDiminishingReturnsGroupForSpell(m_spellInfo, m_triggeredByAuraSpell);
- if (m_diminishGroup)
+ if (m_diminishGroup && aura_effmask)
{
m_diminishLevel = unit->GetDiminishing(m_diminishGroup);
DiminishingReturnsType type = GetDiminishingReturnsGroupType(m_diminishGroup);
@@ -2537,11 +2548,6 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
unit->IncrDiminishing(m_diminishGroup);
}
- uint8 aura_effmask = 0;
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- if (effectMask & (1 << i) && m_spellInfo->Effects[i].IsUnitOwnedAuraEffect())
- aura_effmask |= 1 << i;
-
if (aura_effmask)
{
// Select rank for aura with level requirements only in specific cases
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 9cf0e1ae45c..0a5d265cbfa 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -654,14 +654,6 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
}
break;
}
- case SPELLFAMILY_MAGE:
- {
- // Deep Freeze should deal damage to permanently stun-immune targets.
- if (m_spellInfo->Id == 71757)
- if (unitTarget->GetTypeId() != TYPEID_UNIT || !(unitTarget->IsImmunedToSpellEffect(sSpellMgr->GetSpellInfo(44572), 0)))
- return;
- break;
- }
}
if (m_originalCaster && damage > 0 && apply_direct_bonus)
@@ -2608,8 +2600,16 @@ void Spell::EffectLearnSkill(SpellEffIndex effIndex)
return;
uint32 skillid = m_spellInfo->Effects[effIndex].MiscValue;
+ SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(skillid, unitTarget->getRace(), unitTarget->getClass());
+ if (!rcEntry)
+ return;
+
+ SkillTiersEntry const* tier = sSkillTiersStore.LookupEntry(rcEntry->SkillTier);
+ if (!tier)
+ return;
+
uint16 skillval = unitTarget->ToPlayer()->GetPureSkillValue(skillid);
- unitTarget->ToPlayer()->SetSkill(skillid, m_spellInfo->Effects[effIndex].CalcValue(), skillval?skillval:1, damage*75);
+ unitTarget->ToPlayer()->SetSkill(skillid, m_spellInfo->Effects[effIndex].CalcValue(), std::max<uint16>(skillval, 1), tier->MaxSkill[damage - 1]);
}
void Spell::EffectAddHonor(SpellEffIndex /*effIndex*/)
@@ -4704,6 +4704,7 @@ void Spell::EffectSkinning(SpellEffIndex /*effIndex*/)
m_caster->ToPlayer()->SendLoot(creature->GetGUID(), LOOT_SKINNING);
creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
+ creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 4d97dc97e5b..8034002a470 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -967,7 +967,7 @@ bool SpellInfo::IsAbilityLearnedWithProfession() const
for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx)
{
SkillLineAbilityEntry const* pAbility = _spell_idx->second;
- if (!pAbility || pAbility->learnOnGetSkill != ABILITY_LEARNED_ON_GET_PROFESSION_SKILL)
+ if (!pAbility || pAbility->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE)
continue;
if (pAbility->req_skill_value > 0)
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 6f56c0ebc40..77450dc859a 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -2382,7 +2382,7 @@ void SpellMgr::LoadPetLevelupSpellMap()
if (skillLine->skillId != creatureFamily->skillLine[j])
continue;
- if (skillLine->learnOnGetSkill != ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL)
+ if (skillLine->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN)
continue;
SpellInfo const* spell = GetSpellInfo(skillLine->spellId);
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index d917030bb19..48dd6565f95 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1046,6 +1046,8 @@ void World::LoadConfigSettings(bool reload)
m_bool_configs[CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN] = sConfigMgr->GetBoolDefault("OffhandCheckAtSpellUnlearn", true);
+ m_int_configs[CONFIG_CREATURE_PICKPOCKET_REFILL] = sConfigMgr->GetIntDefault("Creature.PickPocketRefillDelay", 10 * MINUTE);
+
if (int32 clientCacheId = sConfigMgr->GetIntDefault("ClientCacheVersion", 0))
{
// overwrite DB/old value
@@ -1256,7 +1258,9 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_BIRTHDAY_TIME] = sConfigMgr->GetIntDefault("BirthdayTime", 1222964635);
m_bool_configs[CONFIG_IP_BASED_ACTION_LOGGING] = sConfigMgr->GetBoolDefault("Allow.IP.Based.Action.Logging", false);
-
+
+ m_bool_configs[CONFIG_IP_BASED_LOGIN_LOGGING] = sConfigMgr->GetBoolDefault("Wrong.Password.Login.Logging", false);
+
// call ScriptMgr if we're reloading the configuration
if (reload)
sScriptMgr->OnConfigLoad(reload);
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index cdffbf3ee2a..d14d5adf37a 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -331,6 +331,7 @@ enum WorldIntConfigs
CONFIG_BG_REWARD_LOSER_HONOR_FIRST,
CONFIG_BG_REWARD_LOSER_HONOR_LAST,
CONFIG_BIRTHDAY_TIME,
+ CONFIG_CREATURE_PICKPOCKET_REFILL,
INT_CONFIG_VALUE_COUNT
};
diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp
index 3c1fa973cd8..44ebb1ea4e0 100644
--- a/src/server/scripts/Commands/cs_go.cpp
+++ b/src/server/scripts/Commands/cs_go.cpp
@@ -29,6 +29,7 @@ EndScriptData */
#include "Chat.h"
#include "Language.h"
#include "Player.h"
+#include "Transport.h"
class go_commandscript : public CommandScript
{
@@ -132,21 +133,24 @@ public:
float x = fields[0].GetFloat();
float y = fields[1].GetFloat();
float z = fields[2].GetFloat();
- float ort = fields[3].GetFloat();
- int mapId = fields[4].GetUInt16();
+ float o = fields[3].GetFloat();
+ uint32 mapId = fields[4].GetUInt16();
uint32 guid = fields[5].GetUInt32();
uint32 id = fields[6].GetUInt32();
- // if creature is in same map with caster go at its current location
- if (Creature* creature = sObjectAccessor->GetCreature(*player, MAKE_NEW_GUID(guid, id, HIGHGUID_UNIT)))
+ Transport* transport = NULL;
+
+ if (Creature* creature = ObjectAccessor::GetObjectInWorld(MAKE_NEW_GUID(guid, id, HIGHGUID_UNIT), (Creature*)NULL))
{
x = creature->GetPositionX();
y = creature->GetPositionY();
z = creature->GetPositionZ();
- ort = creature->GetOrientation();
+ o = creature->GetOrientation();
+ mapId = creature->GetMapId();
+ transport = creature->GetTransport();
}
- if (!MapManager::IsValidMapCoord(mapId, x, y, z, ort))
+ if (!MapManager::IsValidMapCoord(mapId, x, y, z, o) || sObjectMgr->IsTransportMap(mapId))
{
handler->PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, mapId);
handler->SetSentErrorMessage(true);
@@ -163,7 +167,11 @@ public:
else
player->SaveRecallPosition();
- player->TeleportTo(mapId, x, y, z, ort);
+ if (player->TeleportTo(mapId, x, y, z, o))
+ {
+ if (transport)
+ transport->AddPassenger(player);
+ }
return true;
}
@@ -274,8 +282,8 @@ public:
if (!guid)
return false;
- float x, y, z, ort;
- int mapId;
+ float x, y, z, o;
+ uint32 mapId;
// by DB guid
if (GameObjectData const* goData = sObjectMgr->GetGOData(guid))
@@ -283,7 +291,7 @@ public:
x = goData->posX;
y = goData->posY;
z = goData->posZ;
- ort = goData->orientation;
+ o = goData->orientation;
mapId = goData->mapid;
}
else
@@ -293,7 +301,7 @@ public:
return false;
}
- if (!MapManager::IsValidMapCoord(mapId, x, y, z, ort))
+ if (!MapManager::IsValidMapCoord(mapId, x, y, z, o) || sObjectMgr->IsTransportMap(mapId))
{
handler->PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, mapId);
handler->SetSentErrorMessage(true);
@@ -310,7 +318,7 @@ public:
else
player->SaveRecallPosition();
- player->TeleportTo(mapId, x, y, z, ort);
+ player->TeleportTo(mapId, x, y, z, o);
return true;
}
diff --git a/src/server/scripts/Commands/cs_learn.cpp b/src/server/scripts/Commands/cs_learn.cpp
index 12721c61936..03d10149ae5 100644
--- a/src/server/scripts/Commands/cs_learn.cpp
+++ b/src/server/scripts/Commands/cs_learn.cpp
@@ -332,7 +332,8 @@ public:
if (!handler->extractPlayerTarget((char*)args, &target))
return false;
- target->learnDefaultSpells();
+ target->LearnDefaultSkills();
+ target->LearnCustomSpells();
target->learnQuestRewardedSpells();
handler->PSendSysMessage(LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST, handler->GetNameLink(target).c_str());
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp
index 3c4b372808b..7944011c7a0 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp
@@ -150,14 +150,14 @@ public:
Phase = 0;
- instance->SetData(DATA_KAELTHAS_EVENT, NOT_STARTED);
+ instance->SetBossState(DATA_KAELTHAS, NOT_STARTED);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
- instance->SetData(DATA_KAELTHAS_EVENT, DONE);
+ instance->SetBossState(DATA_KAELTHAS, DONE);
// Enable the Translocation Orb Exit
if (GameObject* escapeOrb = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_ESCAPE_ORB)))
@@ -172,7 +172,7 @@ public:
void EnterCombat(Unit* /*who*/) override
{
- instance->SetData(DATA_KAELTHAS_EVENT, IN_PROGRESS);
+ instance->SetBossState(DATA_KAELTHAS, IN_PROGRESS);
}
void MoveInLineOfSight(Unit* who) override
@@ -515,7 +515,7 @@ public:
return;
}
//Don't really die in all phases of Kael'Thas
- if (instance->GetData(DATA_KAELTHAS_EVENT) == 0)
+ if (instance->GetBossState(DATA_KAELTHAS) == 0)
{
//prevent death
damage = 0;
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp
index 8dc8ff799ba..2af9d9b1567 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp
@@ -153,7 +153,7 @@ public:
//this mean she at some point evaded
void JustReachedHome() override
{
- instance->SetData(DATA_DELRISSA_EVENT, FAIL);
+ instance->SetBossState(DATA_DELRISSA, FAIL);
}
void EnterCombat(Unit* who) override
@@ -172,7 +172,7 @@ public:
}
}
- instance->SetData(DATA_DELRISSA_EVENT, IN_PROGRESS);
+ instance->SetBossState(DATA_DELRISSA, IN_PROGRESS);
}
void InitializeLackeys()
@@ -240,7 +240,7 @@ public:
Talk(SAY_DEATH);
if (instance->GetData(DATA_DELRISSA_DEATH_COUNT) == MAX_ACTIVE_LACKEY)
- instance->SetData(DATA_DELRISSA_EVENT, DONE);
+ instance->SetBossState(DATA_DELRISSA, DONE);
else
{
if (me->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE))
@@ -434,7 +434,7 @@ struct boss_priestess_lackey_commonAI : public ScriptedAI
if (!pDelrissa->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE))
pDelrissa->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
- instance->SetData(DATA_DELRISSA_EVENT, DONE);
+ instance->SetBossState(DATA_DELRISSA, DONE);
}
}
}
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp
index d77f5db9cea..d6c0f95f967 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp
@@ -119,7 +119,7 @@ public:
}
// Set Inst data for encounter
- instance->SetData(DATA_SELIN_EVENT, NOT_STARTED);
+ instance->SetBossState(DATA_SELIN, NOT_STARTED);
DrainLifeTimer = urand(3000, 7000);
DrainManaTimer = DrainLifeTimer + 5000;
@@ -194,7 +194,7 @@ public:
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
- instance->SetData(DATA_SELIN_EVENT, IN_PROGRESS);
+ instance->SetBossState(DATA_SELIN, IN_PROGRESS);
}
void KilledUnit(Unit* /*victim*/) override
@@ -228,7 +228,7 @@ public:
{
Talk(SAY_DEATH);
- instance->SetData(DATA_SELIN_EVENT, DONE); // Encounter complete!
+ instance->SetBossState(DATA_SELIN, DONE); // Encounter complete!
ShatterRemainingCrystals();
}
@@ -351,7 +351,7 @@ public:
}
}
}
- } else TC_LOG_ERROR("scripts", ERROR_INST_DATA);
+ }
}
};
};
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp
index 58b9ef12095..b9930820303 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -16,13 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_Vexallus
-SD%Complete: 90
-SDComment: Heroic and Normal support. Needs further testing.
-SDCategory: Magister's Terrace
-EndScriptData */
-
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "magisters_terrace.h"
@@ -41,26 +33,22 @@ enum Yells
enum Spells
{
- // Pure energy spell info
- SPELL_ENERGY_BOLT = 46156,
- SPELL_ENERGY_FEEDBACK = 44335,
-
- // Vexallus spell info
SPELL_CHAIN_LIGHTNING = 44318,
- SPELL_H_CHAIN_LIGHTNING = 46380, // heroic spell
SPELL_OVERLOAD = 44353,
SPELL_ARCANE_SHOCK = 44319,
- SPELL_H_ARCANE_SHOCK = 46381, // heroic spell
SPELL_SUMMON_PURE_ENERGY = 44322, // mod scale -10
H_SPELL_SUMMON_PURE_ENERGY1 = 46154, // mod scale -5
H_SPELL_SUMMON_PURE_ENERGY2 = 46159 // mod scale -5
-
};
-enum Creatures
+enum Events
{
- NPC_PURE_ENERGY = 24745,
+ EVENT_ENERGY_BOLT = 1,
+ EVENT_ENERGY_FEEDBACK,
+ EVENT_CHAIN_LIGHTNING,
+ EVENT_OVERLOAD,
+ EVENT_ARCANE_SHOCK
};
enum Misc
@@ -71,170 +59,160 @@ enum Misc
class boss_vexallus : public CreatureScript
{
-public:
- boss_vexallus() : CreatureScript("boss_vexallus") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<boss_vexallusAI>(creature);
- };
-
- struct boss_vexallusAI : public BossAI
- {
- boss_vexallusAI(Creature* creature) : BossAI(creature, DATA_VEXALLUS_EVENT)
- {
- instance = creature->GetInstanceScript();
- }
-
- InstanceScript* instance;
+ public:
+ boss_vexallus() : CreatureScript("boss_vexallus") { }
- uint32 ChainLightningTimer;
- uint32 ArcaneShockTimer;
- uint32 OverloadTimer;
- uint32 IntervalHealthAmount;
- bool Enraged;
-
- void Reset() override
+ struct boss_vexallusAI : public BossAI
{
- summons.DespawnAll();
- ChainLightningTimer = 8000;
- ArcaneShockTimer = 5000;
- OverloadTimer = 1200;
- IntervalHealthAmount = 1;
- Enraged = false;
-
- instance->SetData(DATA_VEXALLUS_EVENT, NOT_STARTED);
- }
+ boss_vexallusAI(Creature* creature) : BossAI(creature, DATA_VEXALLUS)
+ {
+ _intervalHealthAmount = 1;
+ _enraged = false;
+ }
- void KilledUnit(Unit* /*victim*/) override
- {
- Talk(SAY_KILL);
- }
+ void Reset() override
+ {
+ _Reset();
+ _intervalHealthAmount = 1;
+ _enraged = false;
+ }
- void JustDied(Unit* /*killer*/) override
- {
- summons.DespawnAll();
- instance->SetData(DATA_VEXALLUS_EVENT, DONE);
- }
+ void KilledUnit(Unit* /*victim*/) override
+ {
+ Talk(SAY_KILL);
+ }
- void EnterCombat(Unit* /*who*/) override
- {
- Talk(SAY_AGGRO);
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ }
- instance->SetData(DATA_VEXALLUS_EVENT, IN_PROGRESS);
- }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ Talk(SAY_AGGRO);
+ _EnterCombat();
- void JustSummoned(Creature* summoned) override
- {
- if (Unit* temp = SelectTarget(SELECT_TARGET_RANDOM, 0))
- summoned->GetMotionMaster()->MoveFollow(temp, 0, 0);
+ events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 8000);
+ events.ScheduleEvent(EVENT_ARCANE_SHOCK, 5000);
+ }
- //spells are SUMMON_TYPE_GUARDIAN, so using setOwner should be ok
- summoned->CastSpell(summoned, SPELL_ENERGY_BOLT, false, 0, 0, me->GetGUID());
- }
+ void JustSummoned(Creature* summoned) override
+ {
+ if (Unit* temp = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ summoned->GetMotionMaster()->MoveFollow(temp, 0, 0);
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ summons.Summon(summoned);
+ }
- if (!Enraged)
+ void DamageTaken(Unit* /*who*/, uint32& /*damage*/) override
{
- //used for check, when Vexallus cast adds 85%, 70%, 55%, 40%, 25%
- if (!HealthAbovePct(100 - INTERVAL_MODIFIER * IntervalHealthAmount))
+ if (_enraged)
+ return;
+
+ // 85%, 70%, 55%, 40%, 25%
+ if (!HealthAbovePct(100 - INTERVAL_MODIFIER * _intervalHealthAmount))
{
- //increase amount, unless we're at 10%, then we switch and return
- if (IntervalHealthAmount == INTERVAL_SWITCH)
+ // increase amount, unless we're at 10%, then we switch and return
+ if (_intervalHealthAmount == INTERVAL_SWITCH)
{
- Enraged = true;
+ _enraged = true;
+ events.Reset();
+ events.ScheduleEvent(EVENT_OVERLOAD, 1200);
return;
}
else
- ++IntervalHealthAmount;
+ ++_intervalHealthAmount;
Talk(SAY_ENERGY);
Talk(EMOTE_DISCHARGE_ENERGY);
if (IsHeroic())
{
- DoCast(me, H_SPELL_SUMMON_PURE_ENERGY1, false);
- DoCast(me, H_SPELL_SUMMON_PURE_ENERGY2, false);
+ DoCast(me, H_SPELL_SUMMON_PURE_ENERGY1);
+ DoCast(me, H_SPELL_SUMMON_PURE_ENERGY2);
}
else
- DoCast(me, SPELL_SUMMON_PURE_ENERGY, false);
-
- //below are workaround summons, remove when summoning spells w/implicitTarget 73 implemented in the core
- me->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0);
-
- if (IsHeroic())
- me->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0);
+ DoCast(me, SPELL_SUMMON_PURE_ENERGY);
}
+ }
- if (ChainLightningTimer <= diff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_CHAIN_LIGHTNING);
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- ChainLightningTimer = 8000;
- } else ChainLightningTimer -= diff;
+ events.Update(diff);
- if (ArcaneShockTimer <= diff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- if (target)
- DoCast(target, SPELL_ARCANE_SHOCK);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- ArcaneShockTimer = 8000;
- } else ArcaneShockTimer -= diff;
- }
- else
- {
- if (OverloadTimer <= diff)
+ while (uint32 eventId = events.ExecuteEvent())
{
- DoCastVictim(SPELL_OVERLOAD);
+ switch (eventId)
+ {
+ case EVENT_CHAIN_LIGHTNING:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ DoCast(target, SPELL_CHAIN_LIGHTNING);
+ events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 8000);
+ break;
+ case EVENT_ARCANE_SHOCK:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 20.0f, true))
+ DoCast(target, SPELL_ARCANE_SHOCK);
+ events.ScheduleEvent(EVENT_ARCANE_SHOCK, 8000);
+ break;
+ case EVENT_OVERLOAD:
+ DoCastVictim(SPELL_OVERLOAD);
+ events.ScheduleEvent(EVENT_OVERLOAD, 2000);
+ break;
+ default:
+ break;
+ }
+ }
- OverloadTimer = 2000;
- } else OverloadTimer -= diff;
+ DoMeleeAttackIfReady();
}
- DoMeleeAttackIfReady();
- }
- };
+ private:
+ uint32 _intervalHealthAmount;
+ bool _enraged;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_vexallusAI>(creature);
+ };
};
-class npc_pure_energy : public CreatureScript
+enum NpcPureEnergy
{
-public:
- npc_pure_energy() : CreatureScript("npc_pure_energy") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_pure_energyAI(creature);
- };
-
- struct npc_pure_energyAI : public ScriptedAI
- {
- npc_pure_energyAI(Creature* creature) : ScriptedAI(creature)
- {
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
- }
+ SPELL_ENERGY_BOLT = 46156,
+ SPELL_ENERGY_FEEDBACK = 44335,
+ SPELL_PURE_ENERGY_PASSIVE = 44326
+};
- void Reset() override { }
+class npc_pure_energy : public CreatureScript
+{
+ public:
+ npc_pure_energy() : CreatureScript("npc_pure_energy") { }
- void JustDied(Unit* slayer) override
+ struct npc_pure_energyAI : public ScriptedAI
{
- if (Unit* temp = me->GetOwner())
+ npc_pure_energyAI(Creature* creature) : ScriptedAI(creature)
{
- if (temp && temp->IsAlive())
- slayer->CastSpell(slayer, SPELL_ENERGY_FEEDBACK, true, 0, 0, temp->GetGUID());
+ me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
}
- }
- void EnterCombat(Unit* /*who*/) override { }
- void MoveInLineOfSight(Unit* /*who*/) override { }
+ void JustDied(Unit* killer) override
+ {
+ killer->CastSpell(killer, SPELL_ENERGY_FEEDBACK, true);
+ me->RemoveAurasDueToSpell(SPELL_PURE_ENERGY_PASSIVE);
+ }
+ };
- void AttackStart(Unit* /*who*/) override { }
- };
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return new npc_pure_energyAI(creature);
+ };
};
void AddSC_boss_vexallus()
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp
index daea647609d..e0050420a08 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -16,19 +15,10 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Instance_Magisters_Terrace
-SD%Complete: 60
-SDComment: Designed only for Selin Fireheart
-SDCategory: Magister's Terrace
-EndScriptData */
-
#include "ScriptMgr.h"
#include "InstanceScript.h"
#include "magisters_terrace.h"
-#define MAX_ENCOUNTER 4
-
/*
0 - Selin Fireheart
1 - Vexallus
@@ -36,281 +26,239 @@ EndScriptData */
3 - Kael'thas Sunstrider
*/
-enum Creatures
+DoorData const doorData[] =
{
- NPC_SELIN = 24723,
- NPC_DELRISSA = 24560,
- NPC_FELCRYSTALS = 24722
-};
-
-enum GameObjects
-{
- GO_VEXALLUS_DOOR = 187896,
- GO_SELIN_DOOR = 187979,
- GO_SELIN_ENCOUNTER_DOOR = 188065,
- GO_DELRISSA_DOOR = 187770,
- GO_KAEL_DOOR = 188064,
- GO_KAEL_STATUE_1 = 188165,
- GO_KAEL_STATUE_2 = 188166,
- GO_ESCAPE_ORB = 188173
+ { GO_SELIN_DOOR, DATA_SELIN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ { GO_SELIN_ENCOUNTER_DOOR, DATA_SELIN, DOOR_TYPE_ROOM, BOUNDARY_NONE },
+ { GO_VEXALLUS_DOOR, DATA_VEXALLUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ { GO_DELRISSA_DOOR, DATA_DELRISSA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ { GO_KAEL_DOOR, DATA_KAELTHAS, DOOR_TYPE_ROOM, BOUNDARY_NONE },
+ { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
};
class instance_magisters_terrace : public InstanceMapScript
{
-public:
- instance_magisters_terrace() : InstanceMapScript("instance_magisters_terrace", 585) { }
-
- struct instance_magisters_terrace_InstanceMapScript : public InstanceScript
- {
- instance_magisters_terrace_InstanceMapScript(Map* map) : InstanceScript(map) { }
-
- uint32 Encounter[MAX_ENCOUNTER];
- uint32 DelrissaDeathCount;
+ public:
+ instance_magisters_terrace() : InstanceMapScript("instance_magisters_terrace", 585) { }
- std::vector<uint64> FelCrystals;
-
- uint64 SelinGUID;
- uint64 DelrissaGUID;
- uint64 VexallusDoorGUID;
- uint64 SelinDoorGUID;
- uint64 SelinEncounterDoorGUID;
- uint64 DelrissaDoorGUID;
- uint64 KaelDoorGUID;
- uint64 KaelStatue[2];
- uint64 EscapeOrbGUID;
- uint32 StatuesState;
- uint8 felCristalIndex;
-
- void Initialize() override
+ struct instance_magisters_terrace_InstanceMapScript : public InstanceScript
{
- memset(&Encounter, 0, sizeof(Encounter));
-
- FelCrystals.clear();
+ instance_magisters_terrace_InstanceMapScript(Map* map) : InstanceScript(map)
+ {
+ SetBossNumber(EncounterCount);
+ LoadDoorData(doorData);
- DelrissaDeathCount = 0;
+ FelCrystals.clear();
+ DelrissaDeathCount = 0;
- SelinGUID = 0;
- DelrissaGUID = 0;
- VexallusDoorGUID = 0;
- SelinDoorGUID = 0;
- SelinEncounterDoorGUID = 0;
- DelrissaDoorGUID = 0;
- KaelDoorGUID = 0;
- KaelStatue[0] = 0;
- KaelStatue[1] = 0;
- EscapeOrbGUID = 0;
- StatuesState = 0;
- felCristalIndex = 0;
- }
+ SelinGUID = 0;
+ DelrissaGUID = 0;
+ EscapeOrbGUID = 0;
+ FelCristalIndex = 0;
- bool IsEncounterInProgress() const override
- {
- for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
- if (Encounter[i] == IN_PROGRESS)
- return true;
- return false;
- }
+ memset(KaelStatue, 0, 2 * sizeof(uint64));
+ }
- uint32 GetData(uint32 identifier) const
- {
- switch (identifier)
+ uint32 GetData(uint32 type) const override
{
- case DATA_SELIN_EVENT:
- return Encounter[0];
- case DATA_VEXALLUS_EVENT:
- return Encounter[1];
- case DATA_DELRISSA_EVENT:
- return Encounter[2];
- case DATA_KAELTHAS_EVENT:
- return Encounter[3];
- case DATA_DELRISSA_DEATH_COUNT:
- return DelrissaDeathCount;
- case DATA_FEL_CRYSTAL_SIZE:
- return FelCrystals.size();
+ switch (type)
+ {
+ case DATA_DELRISSA_DEATH_COUNT:
+ return DelrissaDeathCount;
+ case DATA_FEL_CRYSTAL_SIZE:
+ return uint32(FelCrystals.size());
+ default:
+ break;
+ }
+ return 0;
}
- return 0;
- }
- void SetData(uint32 identifier, uint32 data)
- {
- switch (identifier)
+ void SetData(uint32 type, uint32 data) override
{
- case DATA_SELIN_EVENT:
- if (data == DONE)
- {
- HandleGameObject(SelinEncounterDoorGUID, true);
- HandleGameObject(SelinDoorGUID, true);
- }
- else if (data == IN_PROGRESS)
- HandleGameObject(SelinEncounterDoorGUID, false);
- else if (data == NOT_STARTED)
- HandleGameObject(SelinEncounterDoorGUID, true);
-
- Encounter[0] = data;
- break;
- case DATA_VEXALLUS_EVENT:
- if (data == DONE)
- HandleGameObject(VexallusDoorGUID, true);
- Encounter[1] = data;
- break;
- case DATA_DELRISSA_EVENT:
- if (data == DONE)
- HandleGameObject(DelrissaDoorGUID, true);
- if (data == IN_PROGRESS)
- DelrissaDeathCount = 0;
- Encounter[2] = data;
- break;
- case DATA_KAELTHAS_EVENT:
- if (data == NOT_STARTED || data == DONE)
- HandleGameObject(KaelDoorGUID, true);
- else if (data == IN_PROGRESS)
- HandleGameObject(KaelDoorGUID, false);
- Encounter[3] = data;
- break;
- case DATA_DELRISSA_DEATH_COUNT:
- if (data == SPECIAL)
- ++DelrissaDeathCount;
- else
- DelrissaDeathCount = 0;
- break;
- case DATA_KAELTHAS_STATUES:
- HandleGameObject(KaelStatue[0], data);
- HandleGameObject(KaelStatue[1], data);
- StatuesState = data;
- break;
+ switch (type)
+ {
+ case DATA_DELRISSA_DEATH_COUNT:
+ if (data == SPECIAL)
+ ++DelrissaDeathCount;
+ else
+ DelrissaDeathCount = 0;
+ break;
+ case DATA_KAELTHAS_STATUES:
+ HandleGameObject(KaelStatue[0], data);
+ HandleGameObject(KaelStatue[1], data);
+ break;
+ default:
+ break;
+ }
}
- SaveToDB();
- }
-
- void OnCreatureCreate(Creature* creature) override
- {
- switch (creature->GetEntry())
+ void OnCreatureCreate(Creature* creature) override
{
- case NPC_SELIN:
- SelinGUID = creature->GetGUID();
- break;
- case NPC_DELRISSA:
- DelrissaGUID = creature->GetGUID();
- break;
- case NPC_FELCRYSTALS:
- FelCrystals.push_back(creature->GetGUID());
- break;
+ switch (creature->GetEntry())
+ {
+ case NPC_SELIN:
+ SelinGUID = creature->GetGUID();
+ break;
+ case NPC_DELRISSA:
+ DelrissaGUID = creature->GetGUID();
+ break;
+ case NPC_FELCRYSTALS:
+ FelCrystals.push_back(creature->GetGUID());
+ break;
+ default:
+ break;
+ }
}
- }
- void OnGameObjectCreate(GameObject* go) override
- {
- switch (go->GetEntry())
+ void OnGameObjectCreate(GameObject* go) override
{
- case GO_VEXALLUS_DOOR:
- VexallusDoorGUID = go->GetGUID();
- break;
- case GO_SELIN_DOOR:
- SelinDoorGUID = go->GetGUID();
- break;
- case GO_SELIN_ENCOUNTER_DOOR:
- SelinEncounterDoorGUID = go->GetGUID();
- break;
- case GO_DELRISSA_DOOR:
- DelrissaDoorGUID = go->GetGUID();
- break;
- case GO_KAEL_DOOR:
- KaelDoorGUID = go->GetGUID();
- break;
- case GO_KAEL_STATUE_1:
- KaelStatue[0] = go->GetGUID();
- break;
- case GO_KAEL_STATUE_2:
- KaelStatue[1] = go->GetGUID();
- break;
- case GO_ESCAPE_ORB:
- EscapeOrbGUID = go->GetGUID();
- break;
+ switch (go->GetEntry())
+ {
+ case GO_VEXALLUS_DOOR:
+ case GO_SELIN_DOOR:
+ case GO_SELIN_ENCOUNTER_DOOR:
+ case GO_DELRISSA_DOOR:
+ case GO_KAEL_DOOR:
+ AddDoor(go, true);
+ break;
+ case GO_KAEL_STATUE_1:
+ KaelStatue[0] = go->GetGUID();
+ break;
+ case GO_KAEL_STATUE_2:
+ KaelStatue[1] = go->GetGUID();
+ break;
+ case GO_ESCAPE_ORB:
+ EscapeOrbGUID = go->GetGUID();
+ break;
+ default:
+ break;
+ }
}
- }
-
- std::string GetSaveData() override
- {
- OUT_SAVE_INST_DATA;
-
- std::ostringstream saveStream;
- saveStream << Encounter[0] << ' ' << Encounter[1] << ' ' << Encounter[2] << ' ' << Encounter[3] << ' ' << StatuesState;
- OUT_SAVE_INST_DATA_COMPLETE;
- return saveStream.str();
- }
+ void OnGameObjectRemove(GameObject* go) override
+ {
+ switch (go->GetEntry())
+ {
+ case GO_VEXALLUS_DOOR:
+ case GO_SELIN_DOOR:
+ case GO_SELIN_ENCOUNTER_DOOR:
+ case GO_DELRISSA_DOOR:
+ case GO_KAEL_DOOR:
+ AddDoor(go, false);
+ break;
+ default:
+ break;
+ }
+ }
- void Load(const char* str) override
- {
- if (!str)
+ bool SetBossState(uint32 type, EncounterState state) override
{
- OUT_LOAD_INST_DATA_FAIL;
- return;
+ if (!InstanceScript::SetBossState(type, state))
+ return false;
+
+ switch (type)
+ {
+ case DATA_DELRISSA:
+ if (type == IN_PROGRESS)
+ DelrissaDeathCount = 0;
+ break;
+ default:
+ break;
+ }
+ return true;
}
- OUT_LOAD_INST_DATA(str);
+ std::string GetSaveData() override
+ {
+ OUT_SAVE_INST_DATA;
- std::istringstream loadStream(str);
+ std::ostringstream saveStream;
+ saveStream << "M T " << GetBossSaveData();
- for (uint32 i = 0; i < MAX_ENCOUNTER; ++i)
- {
- uint32 tmpState;
- loadStream >> tmpState;
- if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
- tmpState = NOT_STARTED;
- SetData(i, tmpState);
+ OUT_SAVE_INST_DATA_COMPLETE;
+ return saveStream.str();
}
- loadStream >> StatuesState;
- SetData(DATA_KAELTHAS_STATUES, StatuesState);
+ void Load(const char* str) override
+ {
+ if (!str)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
- OUT_LOAD_INST_DATA_COMPLETE;
- }
+ OUT_LOAD_INST_DATA(str);
- uint64 GetData64(uint32 identifier) const
- {
- switch (identifier)
- {
- case DATA_SELIN:
- return SelinGUID;
- case DATA_DELRISSA:
- return DelrissaGUID;
- case DATA_VEXALLUS_DOOR:
- return VexallusDoorGUID;
- case DATA_DELRISSA_DOOR:
- return DelrissaDoorGUID;
- case DATA_KAEL_DOOR:
- return KaelDoorGUID;
- case DATA_KAEL_STATUE_LEFT:
- return KaelStatue[0];
- case DATA_KAEL_STATUE_RIGHT:
- return KaelStatue[1];
- case DATA_ESCAPE_ORB:
- return EscapeOrbGUID;
- case DATA_FEL_CRYSTAL:
- if (FelCrystals.size() < felCristalIndex)
+ char dataHead1, dataHead2;
+
+ std::istringstream loadStream(str);
+ loadStream >> dataHead1 >> dataHead2;
+ if (dataHead1 == 'M' && dataHead2 == 'T')
+ {
+ for (uint32 i = 0; i < EncounterCount; ++i)
{
- TC_LOG_ERROR("scripts", "Magisters Terrace: No Fel Crystals loaded in Inst Data");
- return 0;
+ uint32 tmpState;
+ loadStream >> tmpState;
+ if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
+ tmpState = NOT_STARTED;
+ SetBossState(i, EncounterState(tmpState));
}
+ }
+ else
+ OUT_LOAD_INST_DATA_FAIL;
- return FelCrystals.at(felCristalIndex);
+ OUT_LOAD_INST_DATA_COMPLETE;
+ }
+
+ uint64 GetData64(uint32 type) const override
+ {
+ switch (type)
+ {
+ case DATA_SELIN:
+ return SelinGUID;
+ case DATA_DELRISSA:
+ return DelrissaGUID;
+ case DATA_KAEL_STATUE_LEFT:
+ return KaelStatue[0];
+ case DATA_KAEL_STATUE_RIGHT:
+ return KaelStatue[1];
+ case DATA_ESCAPE_ORB:
+ return EscapeOrbGUID;
+ case DATA_FEL_CRYSTAL:
+ if (FelCrystals.size() < FelCristalIndex)
+ {
+ TC_LOG_ERROR("scripts", "Magisters Terrace: No Fel Crystals loaded in Inst Data");
+ return 0;
+ }
+
+ return FelCrystals.at(FelCristalIndex);
+ default:
+ break;
+ }
+ return 0;
}
- return 0;
- }
- void SetData64(uint32 identifier, uint64 value)
+ void SetData64(uint32 type, uint64 value) override
+ {
+ if (type == DATA_FEL_CRYSTAL)
+ FelCristalIndex = value;
+ }
+
+ protected:
+ std::vector<uint64> FelCrystals;
+
+ uint64 SelinGUID;
+ uint64 DelrissaGUID;
+ uint64 KaelStatue[2];
+ uint64 EscapeOrbGUID;
+ uint32 DelrissaDeathCount;
+ uint8 FelCristalIndex;
+ };
+
+ InstanceScript* GetInstanceScript(InstanceMap* map) const override
{
- if (identifier == DATA_FEL_CRYSTAL)
- felCristalIndex = value;
+ return new instance_magisters_terrace_InstanceMapScript(map);
}
- };
-
- InstanceScript* GetInstanceScript(InstanceMap* map) const override
- {
- return new instance_magisters_terrace_InstanceMapScript(map);
- }
};
void AddSC_instance_magisters_terrace()
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h
index ddfaa91bc98..d3517dfccf6 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h
@@ -19,24 +19,17 @@
#ifndef DEF_MAGISTERS_TERRACE_H
#define DEF_MAGISTERS_TERRACE_H
-#define ERROR_INST_DATA "TSCR Error: Instance Data not set properly for Magister's Terrace instance (map 585). Encounters will be buggy."
+uint32 const EncounterCount = 4;
-enum Data
+enum DataTypes
{
- DATA_SELIN_EVENT,
- DATA_VEXALLUS_EVENT,
- DATA_DELRISSA_EVENT,
- DATA_KAELTHAS_EVENT,
-
DATA_SELIN,
- DATA_FEL_CRYSTAL,
- DATA_FEL_CRYSTAL_SIZE,
-
- DATA_VEXALLUS_DOOR,
+ DATA_VEXALLUS,
DATA_DELRISSA,
- DATA_DELRISSA_DOOR,
+ DATA_KAELTHAS,
- DATA_KAEL_DOOR,
+ DATA_FEL_CRYSTAL,
+ DATA_FEL_CRYSTAL_SIZE,
DATA_KAEL_STATUE_LEFT,
DATA_KAEL_STATUE_RIGHT,
@@ -45,4 +38,23 @@ enum Data
DATA_ESCAPE_ORB
};
+enum CreatureIds
+{
+ NPC_SELIN = 24723,
+ NPC_DELRISSA = 24560,
+ NPC_FELCRYSTALS = 24722
+};
+
+enum GameObjectIds
+{
+ GO_VEXALLUS_DOOR = 187896,
+ GO_SELIN_DOOR = 187979,
+ GO_SELIN_ENCOUNTER_DOOR = 188065,
+ GO_DELRISSA_DOOR = 187770,
+ GO_KAEL_DOOR = 188064,
+ GO_KAEL_STATUE_1 = 188165,
+ GO_KAEL_STATUE_2 = 188166,
+ GO_ESCAPE_ORB = 188173
+};
+
#endif
diff --git a/src/server/scripts/EasternKingdoms/zone_eversong_woods.cpp b/src/server/scripts/EasternKingdoms/zone_eversong_woods.cpp
index 8c612a11621..bc4fff4da7b 100644
--- a/src/server/scripts/EasternKingdoms/zone_eversong_woods.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_eversong_woods.cpp
@@ -190,6 +190,9 @@ enum InfusedCrystal
// Quest
QUEST_POWERING_OUR_DEFENSES = 8490,
+ // Quest Credit
+ QUEST_POD_CREDIT = 16364,
+
// Says
EMOTE = 0,
@@ -266,24 +269,17 @@ public:
summoned->AI()->AttackStart(me);
}
- void JustDied(Unit* /*killer*/) override
- {
- if (PlayerGUID && !Completed)
- if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID))
- player->FailQuest(QUEST_POWERING_OUR_DEFENSES);
- }
-
void UpdateAI(uint32 diff) override
{
if (EndTimer < diff && Progress)
{
- Talk(EMOTE);
Completed = true;
if (PlayerGUID)
if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID))
- player->CompleteQuest(QUEST_POWERING_OUR_DEFENSES);
-
- me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ {
+ Talk(EMOTE, player);
+ player->KilledMonsterCredit(QUEST_POD_CREDIT);
+ }
me->RemoveCorpse();
} else EndTimer -= diff;
diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp
index 3f935077b22..4571798506e 100644
--- a/src/server/scripts/Spells/spell_warlock.cpp
+++ b/src/server/scripts/Spells/spell_warlock.cpp
@@ -518,7 +518,7 @@ class spell_warl_haunt : public SpellScriptLoader
{
PrepareSpellScript(spell_warl_haunt_SpellScript);
- void HandleOnHit()
+ void HandleAfterHit()
{
if (Aura* aura = GetHitAura())
if (AuraEffect* aurEff = aura->GetEffect(EFFECT_1))
@@ -527,7 +527,7 @@ class spell_warl_haunt : public SpellScriptLoader
void Register() override
{
- OnHit += SpellHitFn(spell_warl_haunt_SpellScript::HandleOnHit);
+ AfterHit += SpellHitFn(spell_warl_haunt_SpellScript::HandleAfterHit);
}
};
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index f71b7bb8150..90f330bac42 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -1353,6 +1353,14 @@ Rate.Creature.Elite.RAREELITE.HP = 1
Rate.Creature.Elite.WORLDBOSS.HP = 1
#
+# Creature.PickPocketRefillDelay
+# Description: Time in seconds that the server will wait before refilling the pickpocket loot
+# for a creature
+# Default: 600
+
+Creature.PickPocketRefillDelay = 600
+
+#
# ListenRange.Say
# Description: Distance in which players can read say messages from creatures or
# gameobjects.
diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp
index cc24035b05e..131041e0cd2 100644
--- a/src/tools/mmaps_generator/MapBuilder.cpp
+++ b/src/tools/mmaps_generator/MapBuilder.cpp
@@ -77,8 +77,8 @@ namespace MMAP
{
for (TileList::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it)
{
- (*it).second->clear();
- delete (*it).second;
+ (*it).m_tiles->clear();
+ delete (*it).m_tiles;
}
delete m_terrainBuilder;
@@ -97,9 +97,9 @@ namespace MMAP
for (uint32 i = 0; i < files.size(); ++i)
{
mapID = uint32(atoi(files[i].substr(0,3).c_str()));
- if (m_tiles.find(mapID) == m_tiles.end())
+ if (std::find(m_tiles.begin(), m_tiles.end(), mapID) == m_tiles.end())
{
- m_tiles.insert(std::pair<uint32, std::set<uint32>*>(mapID, new std::set<uint32>));
+ m_tiles.emplace_back(MapTiles(mapID, new std::set<uint32>));
count++;
}
}
@@ -109,8 +109,11 @@ namespace MMAP
for (uint32 i = 0; i < files.size(); ++i)
{
mapID = uint32(atoi(files[i].substr(0,3).c_str()));
- m_tiles.insert(std::pair<uint32, std::set<uint32>*>(mapID, new std::set<uint32>));
- count++;
+ if (std::find(m_tiles.begin(), m_tiles.end(), mapID) == m_tiles.end())
+ {
+ m_tiles.emplace_back(MapTiles(mapID, new std::set<uint32>));
+ count++;
+ }
}
printf("found %u.\n", count);
@@ -118,8 +121,8 @@ namespace MMAP
printf("Discovering tiles... ");
for (TileList::iterator itr = m_tiles.begin(); itr != m_tiles.end(); ++itr)
{
- std::set<uint32>* tiles = (*itr).second;
- mapID = (*itr).first;
+ std::set<uint32>* tiles = (*itr).m_tiles;
+ mapID = (*itr).m_mapId;
sprintf(filter, "%03u*.vmtile", mapID);
files.clear();
@@ -153,12 +156,12 @@ namespace MMAP
/**************************************************************************/
std::set<uint32>* MapBuilder::getTileList(uint32 mapID)
{
- TileList::iterator itr = m_tiles.find(mapID);
+ TileList::iterator itr = std::find(m_tiles.begin(), m_tiles.end(), mapID);
if (itr != m_tiles.end())
- return (*itr).second;
+ return (*itr).m_tiles;
std::set<uint32>* tiles = new std::set<uint32>();
- m_tiles.insert(std::pair<uint32, std::set<uint32>*>(mapID, tiles));
+ m_tiles.emplace_back(MapTiles(mapID, tiles));
return tiles;
}
@@ -169,9 +172,14 @@ namespace MMAP
BuilderThreadPool* pool = threads > 0 ? new BuilderThreadPool() : NULL;
+ m_tiles.sort([](MapTiles a, MapTiles b)
+ {
+ return a.m_tiles->size() > b.m_tiles->size();
+ });
+
for (TileList::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it)
{
- uint32 mapID = it->first;
+ uint32 mapID = it->m_mapId;
if (!shouldSkipMap(mapID))
{
if (threads > 0)
diff --git a/src/tools/mmaps_generator/MapBuilder.h b/src/tools/mmaps_generator/MapBuilder.h
index 86a6db2077c..08b87324d01 100644
--- a/src/tools/mmaps_generator/MapBuilder.h
+++ b/src/tools/mmaps_generator/MapBuilder.h
@@ -22,6 +22,7 @@
#include <vector>
#include <set>
#include <map>
+#include <list>
#include "TerrainBuilder.h"
#include "IntermediateValues.h"
@@ -39,7 +40,24 @@ using namespace VMAP;
namespace MMAP
{
- typedef std::map<uint32, std::set<uint32>*> TileList;
+ struct MapTiles
+ {
+ MapTiles() : m_mapId(uint32(-1)), m_tiles(NULL) {}
+
+ MapTiles(uint32 id, std::set<uint32>* tiles) : m_mapId(id), m_tiles(tiles) {}
+ ~MapTiles() {}
+
+ uint32 m_mapId;
+ std::set<uint32>* m_tiles;
+
+ bool operator==(uint32 id)
+ {
+ return m_mapId == id;
+ }
+ };
+
+ typedef std::list<MapTiles> TileList;
+
struct Tile
{
Tile() : chf(NULL), solid(NULL), cset(NULL), pmesh(NULL), dmesh(NULL) {}