aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/Battlegrounds/Battleground.cpp22
-rwxr-xr-xsrc/server/game/Battlegrounds/BattlegroundMgr.cpp14
-rwxr-xr-xsrc/server/game/Battlegrounds/BattlegroundQueue.cpp2
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp7
-rwxr-xr-xsrc/server/game/Handlers/BattleGroundHandler.cpp159
-rwxr-xr-xsrc/server/game/Handlers/MiscHandler.cpp38
-rwxr-xr-xsrc/server/game/Miscellaneous/Language.h4
-rw-r--r--src/server/game/Movement/Spline/MoveSpline.cpp2
-rwxr-xr-xsrc/server/game/Server/WorldSocket.cpp11
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp3
-rwxr-xr-xsrc/server/game/Texts/CreatureTextMgr.cpp53
-rw-r--r--src/server/game/Warden/Warden.cpp21
-rw-r--r--src/server/game/Warden/WardenMac.cpp19
-rw-r--r--src/server/scripts/Commands/cs_lookup.cpp97
-rw-r--r--src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp187
-rw-r--r--src/server/scripts/World/boss_emerald_dragons.cpp310
-rw-r--r--src/server/scripts/World/npc_taxi.cpp8
17 files changed, 524 insertions, 433 deletions
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 50f8554d5db..d00bbcf098d 100755
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -642,7 +642,12 @@ void Battleground::SendPacketToTeam(uint32 TeamID, WorldPacket* packet, Player*
for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
if (Player* player = _GetPlayerForTeam(TeamID, itr, "SendPacketToTeam"))
if (self || sender != player)
- player->GetSession()->SendPacket(packet);
+ {
+ WorldSession* session = player->GetSession();
+ sLog->outDebug(LOG_FILTER_BATTLEGROUND, "%s %s - SendPacketToTeam %u, Player: %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str(),
+ session->GetPlayerInfo().c_str(), TeamID, sender ? sender->GetName().c_str() : "null");
+ session->SendPacket(packet);
+ }
}
void Battleground::PlaySoundToAll(uint32 SoundID)
@@ -1064,7 +1069,7 @@ void Battleground::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
if (Transport)
player->TeleportToBGEntryPoint();
- sLog->outInfo(LOG_FILTER_BATTLEGROUND, "BATTLEGROUND: Removed player %s from Battleground.", player->GetName().c_str());
+ sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Removed player %s from Battleground.", player->GetName().c_str());
}
//battleground object will be deleted next Battleground::Update() call
@@ -1078,9 +1083,6 @@ void Battleground::Reset()
SetStartTime(0);
SetEndTime(0);
SetLastResurrectTime(0);
- SetArenaType(0);
- SetRated(false);
-
m_Events = 0;
if (m_InvitedAlliance > 0 || m_InvitedHorde > 0)
@@ -1177,10 +1179,9 @@ void Battleground::AddPlayer(Player* player)
player->ResetAllPowers();
}
- WorldPacket teammate;
- teammate.Initialize(SMSG_ARENA_OPPONENT_UPDATE, 8);
- teammate << uint64(player->GetGUID());
- SendPacketToTeam(team, &teammate, player, false);
+ WorldPacket data(SMSG_ARENA_OPPONENT_UPDATE, 8);
+ data << uint64(player->GetGUID());
+ SendPacketToTeam(team, &data, player, false);
}
else
{
@@ -1203,9 +1204,6 @@ void Battleground::AddPlayer(Player* player)
// setup BG group membership
PlayerAddedToBGCheckIfBGIsRunning(player);
AddOrSetPlayerToCorrectBgGroup(player, team);
-
- // Log
- sLog->outInfo(LOG_FILTER_BATTLEGROUND, "BATTLEGROUND: Player %s joined the battle.", player->GetName().c_str());
}
// this method adds player to his team's bg group, or sets his correct group if player is already in bg group
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index bfa3b955427..6d472faf9c6 100755
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -131,7 +131,7 @@ void BattlegroundMgr::Update(uint32 diff)
if (m_NextRatedArenaUpdate < diff)
{
// forced update for rated arenas (scan all, but skipped non rated)
- sLog->outDebug(LOG_FILTER_BATTLEGROUND, "BattlegroundMgr: UPDATING ARENA QUEUES");
+ sLog->outTrace(LOG_FILTER_ARENAS, "BattlegroundMgr: UPDATING ARENA QUEUES");
for (int qtype = BATTLEGROUND_QUEUE_2v2; qtype <= BATTLEGROUND_QUEUE_5v5; ++qtype)
for (int bracket = BG_BRACKET_ID_FIRST; bracket < MAX_BATTLEGROUND_BRACKETS; ++bracket)
m_BattlegroundQueues[qtype].BattlegroundQueueUpdate(diff,
@@ -904,25 +904,25 @@ BattlegroundQueueTypeId BattlegroundMgr::BGQueueTypeId(BattlegroundTypeId bgType
{
switch (bgTypeId)
{
- case BATTLEGROUND_WS:
- return BATTLEGROUND_QUEUE_WS;
case BATTLEGROUND_AB:
return BATTLEGROUND_QUEUE_AB;
case BATTLEGROUND_AV:
return BATTLEGROUND_QUEUE_AV;
case BATTLEGROUND_EY:
return BATTLEGROUND_QUEUE_EY;
- case BATTLEGROUND_SA:
- return BATTLEGROUND_QUEUE_SA;
case BATTLEGROUND_IC:
return BATTLEGROUND_QUEUE_IC;
case BATTLEGROUND_RB:
return BATTLEGROUND_QUEUE_RB;
+ case BATTLEGROUND_SA:
+ return BATTLEGROUND_QUEUE_SA;
+ case BATTLEGROUND_WS:
+ return BATTLEGROUND_QUEUE_WS;
case BATTLEGROUND_AA:
- case BATTLEGROUND_NA:
- case BATTLEGROUND_RL:
case BATTLEGROUND_BE:
case BATTLEGROUND_DS:
+ case BATTLEGROUND_NA:
+ case BATTLEGROUND_RL:
case BATTLEGROUND_RV:
switch (arenaType)
{
diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
index 922cccb9186..012d970901d 100755
--- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
@@ -475,7 +475,7 @@ bool BattlegroundQueue::InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg,
uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId);
- sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: invited player %s (%u) to BG instance %u queueindex %u bgtype %u, I can't help it if they don't press the enter battle button.",
+ sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: invited player %s (%u) to BG instance %u queueindex %u bgtype %u",
player->GetName().c_str(), player->GetGUIDLow(), bg->GetInstanceID(), queueSlot, bg->GetTypeID());
// send status packet
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index f8de93afc6d..c886c046427 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -1328,7 +1328,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
// If this is a creature and it attacks from behind it has a probability to daze it's victim
if ((damageInfo->hitOutCome == MELEE_HIT_CRIT || damageInfo->hitOutCome == MELEE_HIT_CRUSHING || damageInfo->hitOutCome == MELEE_HIT_NORMAL || damageInfo->hitOutCome == MELEE_HIT_GLANCING) &&
GetTypeId() != TYPEID_PLAYER && !ToCreature()->IsControlledByPlayer() && !victim->HasInArc(M_PI, this)
- && (victim->GetTypeId() == TYPEID_PLAYER || !victim->ToCreature()->isWorldBoss()))
+ && (victim->GetTypeId() == TYPEID_PLAYER || !victim->ToCreature()->isWorldBoss())&& !victim->IsVehicle())
{
// -probability is between 0% and 40%
// 20% base chance
@@ -1341,7 +1341,10 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
uint32 VictimDefense=victim->GetDefenseSkillValue();
uint32 AttackerMeleeSkill=GetUnitMeleeSkill();
- Probability *= AttackerMeleeSkill/(float)VictimDefense;
+ Probability *= AttackerMeleeSkill/(float)VictimDefense*0.16;
+
+ if (Probability < 0)
+ Probability = 0;
if (Probability > 40.0f)
Probability = 40.0f;
diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp
index 3a359704916..0a076dfaa34 100755
--- a/src/server/game/Handlers/BattleGroundHandler.cpp
+++ b/src/server/game/Handlers/BattleGroundHandler.cpp
@@ -342,8 +342,6 @@ void WorldSession::HandleBattlefieldListOpcode(WorldPacket &recvData)
void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
{
- sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message");
-
uint8 type; // arenatype if arena
uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1
uint32 bgTypeId_; // type id from dbc
@@ -351,16 +349,17 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
uint8 action; // enter battle 0x1, leave queue 0x0
recvData >> type >> unk2 >> bgTypeId_ >> unk >> action;
-
if (!sBattlemasterListStore.LookupEntry(bgTypeId_))
{
- sLog->outDebug(LOG_FILTER_BATTLEGROUND, "BattlegroundHandler: invalid bgtype (%u) with player (Name: %s, GUID: %u) received.", bgTypeId_, _player->GetName().c_str(), _player->GetGUIDLow());
+ sLog->outDebug(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Invalid BgType!",
+ GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action);
return;
}
if (!_player->InBattlegroundQueue())
{
- sLog->outDebug(LOG_FILTER_BATTLEGROUND, "BattlegroundHandler: Invalid CMSG_BATTLEFIELD_PORT received from player (Name: %s, GUID: %u), he is not in bg_queue.", _player->GetName().c_str(), _player->GetGUIDLow());
+ sLog->outDebug(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Player not in queue!",
+ GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action);
return;
}
@@ -372,27 +371,39 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
GroupQueueInfo ginfo;
if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo))
{
- sLog->outError(LOG_FILTER_NETWORKIO, "BattlegroundHandler: itrplayerstatus not found.");
+ sLog->outDebug(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Player not in queue (No player Group Info)!",
+ GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action);
return;
}
// if action == 1, then instanceId is required
if (!ginfo.IsInvitedToBGInstanceGUID && action == 1)
{
- sLog->outError(LOG_FILTER_NETWORKIO, "BattlegroundHandler: instance not found.");
+ sLog->outDebug(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Player is not invited to any bg!",
+ GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action);
return;
}
Battleground* bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
-
- // bg template might and must be used in case of leaving queue, when instance is not created yet
- if (!bg && action == 0)
- bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId);
if (!bg)
{
- sLog->outError(LOG_FILTER_NETWORKIO, "BattlegroundHandler: bg_template not found for type id %u.", bgTypeId);
- return;
+ if (action)
+ {
+ sLog->outDebug(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Cant find BG with id %u!",
+ GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action, ginfo.IsInvitedToBGInstanceGUID);
+ return;
+ }
+
+ bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId);
+ if (!bg)
+ {
+ sLog->outError(LOG_FILTER_NETWORKIO, "BattlegroundHandler: bg_template not found for type id %u.", bgTypeId);
+ return;
+ }
}
+ sLog->outDebug(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u.",
+ GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action);
+
// expected bracket entry
PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel());
if (!bracketEntry)
@@ -409,86 +420,82 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data2, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
_player->GetSession()->SendPacket(&data2);
action = 0;
- sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName().c_str(), _player->GetGUIDLow());
+ sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName().c_str(), _player->GetGUIDLow());
}
//if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue
if (_player->getLevel() > bg->GetMaxLevel())
{
- sLog->outError(LOG_FILTER_NETWORKIO, "Battleground: Player %s (%u) has level (%u) higher than maxlevel (%u) of battleground (%u)! Do not port him to battleground!",
+ sLog->outError(LOG_FILTER_NETWORKIO, "Player %s (%u) has level (%u) higher than maxlevel (%u) of battleground (%u)! Do not port him to battleground!",
_player->GetName().c_str(), _player->GetGUIDLow(), _player->getLevel(), bg->GetMaxLevel(), bg->GetTypeID());
action = 0;
}
}
uint32 queueSlot = _player->GetBattlegroundQueueIndex(bgQueueTypeId);
WorldPacket data;
- switch (action)
+ if (action)
{
- case 1: // port to battleground
- if (!_player->IsInvitedForBattlegroundQueueType(bgQueueTypeId))
- return; // cheating?
+ if (!_player->IsInvitedForBattlegroundQueueType(bgQueueTypeId))
+ return; // cheating?
- if (!_player->InBattleground())
- _player->SetBattlegroundEntryPoint();
+ if (!_player->InBattleground())
+ _player->SetBattlegroundEntryPoint();
- // resurrect the player
- if (!_player->isAlive())
- {
- _player->ResurrectPlayer(1.0f);
- _player->SpawnCorpseBones();
- }
- // stop taxi flight at port
- if (_player->isInFlight())
- {
- _player->GetMotionMaster()->MovementExpired();
- _player->CleanupAfterTaxiFlight();
- }
+ // resurrect the player
+ if (!_player->isAlive())
+ {
+ _player->ResurrectPlayer(1.0f);
+ _player->SpawnCorpseBones();
+ }
+ // stop taxi flight at port
+ if (_player->isInFlight())
+ {
+ _player->GetMotionMaster()->MovementExpired();
+ _player->CleanupAfterTaxiFlight();
+ }
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType());
- _player->GetSession()->SendPacket(&data);
- // remove battleground queue status from BGmgr
- bgQueue.RemovePlayer(_player->GetGUID(), false);
- // this is still needed here if battleground "jumping" shouldn't add deserter debuff
- // also this is required to prevent stuck at old battleground after SetBattlegroundId set to new
- if (Battleground* currentBg = _player->GetBattleground())
- currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true);
-
- // set the destination instance id
- _player->SetBattlegroundId(bg->GetInstanceID(), bgTypeId);
- // set the destination team
- _player->SetBGTeam(ginfo.Team);
- // bg->HandleBeforeTeleportToBattleground(_player);
- sBattlegroundMgr->SendToBattleground(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
- // add only in HandleMoveWorldPortAck()
- // bg->AddPlayer(_player, team);
- sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.", _player->GetName().c_str(), _player->GetGUIDLow(), bg->GetInstanceID(), bg->GetTypeID(), bgQueueTypeId);
- break;
- case 0: // leave queue
- if (bg->isArena() && bg->GetStatus() > STATUS_WAIT_QUEUE)
- return;
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType());
+ _player->GetSession()->SendPacket(&data);
+ // remove battleground queue status from BGmgr
+ bgQueue.RemovePlayer(_player->GetGUID(), false);
+ // this is still needed here if battleground "jumping" shouldn't add deserter debuff
+ // also this is required to prevent stuck at old battleground after SetBattlegroundId set to new
+ if (Battleground* currentBg = _player->GetBattleground())
+ currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true);
+
+ // set the destination instance id
+ _player->SetBattlegroundId(bg->GetInstanceID(), bgTypeId);
+ // set the destination team
+ _player->SetBGTeam(ginfo.Team);
+ // bg->HandleBeforeTeleportToBattleground(_player);
+ sBattlegroundMgr->SendToBattleground(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
+ // add only in HandleMoveWorldPortAck()
+ // bg->AddPlayer(_player, team);
+ sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.", _player->GetName().c_str(), _player->GetGUIDLow(), bg->GetInstanceID(), bg->GetTypeID(), bgQueueTypeId);
+ }
+ else // leave queue
+ {
+ if (bg->isArena() && bg->GetStatus() > STATUS_WAIT_QUEUE)
+ return;
- // if player leaves rated arena match before match start, it is counted as he played but he lost
- if (ginfo.IsRated && ginfo.IsInvitedToBGInstanceGUID)
+ // if player leaves rated arena match before match start, it is counted as he played but he lost
+ if (ginfo.IsRated && ginfo.IsInvitedToBGInstanceGUID)
+ {
+ ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(ginfo.Team);
+ if (at)
{
- ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(ginfo.Team);
- if (at)
- {
- sLog->outDebug(LOG_FILTER_BATTLEGROUND, "UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player->GetGUID()), ginfo.OpponentsTeamRating);
- at->MemberLost(_player, ginfo.OpponentsMatchmakerRating);
- at->SaveToDB();
- }
+ sLog->outDebug(LOG_FILTER_BATTLEGROUND, "UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player->GetGUID()), ginfo.OpponentsTeamRating);
+ at->MemberLost(_player, ginfo.OpponentsMatchmakerRating);
+ at->SaveToDB();
}
- _player->RemoveBattlegroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
- sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0);
- bgQueue.RemovePlayer(_player->GetGUID(), true);
- // player left queue, we should update it - do not update Arena Queue
- if (!ginfo.ArenaType)
- sBattlegroundMgr->ScheduleQueueUpdate(ginfo.ArenaMatchmakerRating, ginfo.ArenaType, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId());
- SendPacket(&data);
- sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName().c_str(), _player->GetGUIDLow(), bg->GetTypeID(), bgQueueTypeId);
- break;
- default:
- sLog->outError(LOG_FILTER_NETWORKIO, "Battleground port: unknown action %u", action);
- break;
+ }
+ _player->RemoveBattlegroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
+ sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0);
+ bgQueue.RemovePlayer(_player->GetGUID(), true);
+ // player left queue, we should update it - do not update Arena Queue
+ if (!ginfo.ArenaType)
+ sBattlegroundMgr->ScheduleQueueUpdate(ginfo.ArenaMatchmakerRating, ginfo.ArenaType, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId());
+ SendPacket(&data);
+ sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName().c_str(), _player->GetGUIDLow(), bg->GetTypeID(), bgQueueTypeId);
}
}
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 8928a7c15a1..2ac0e7df808 100755
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -1382,25 +1382,21 @@ void WorldSession::HandleFarSightOpcode(WorldPacket& recvData)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_FAR_SIGHT");
- uint8 apply;
+ bool apply;
recvData >> apply;
- switch (apply)
+ if (apply)
{
- case 0:
- sLog->outDebug(LOG_FILTER_NETWORKIO, "Player %u set vision to self", _player->GetGUIDLow());
- _player->SetSeer(_player);
- break;
- case 1:
- sLog->outDebug(LOG_FILTER_NETWORKIO, "Added FarSight " UI64FMTD " to player %u", _player->GetUInt64Value(PLAYER_FARSIGHT), _player->GetGUIDLow());
- if (WorldObject* target = _player->GetViewpoint())
- _player->SetSeer(target);
- else
- sLog->outError(LOG_FILTER_NETWORKIO, "Player %s requests non-existing seer " UI64FMTD, _player->GetName().c_str(), _player->GetUInt64Value(PLAYER_FARSIGHT));
- break;
- default:
- sLog->outDebug(LOG_FILTER_NETWORKIO, "Unhandled mode in CMSG_FAR_SIGHT: %u", apply);
- return;
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "Added FarSight " UI64FMTD " to player %u", _player->GetUInt64Value(PLAYER_FARSIGHT), _player->GetGUIDLow());
+ if (WorldObject* target = _player->GetViewpoint())
+ _player->SetSeer(target);
+ else
+ sLog->outError(LOG_FILTER_NETWORKIO, "Player %s requests non-existing seer " UI64FMTD, _player->GetName().c_str(), _player->GetUInt64Value(PLAYER_FARSIGHT));
+ }
+ else
+ {
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "Player %u set vision to self", _player->GetGUIDLow());
+ _player->SetSeer(_player);
}
GetPlayer()->UpdateVisibilityForPlayer();
@@ -1467,7 +1463,7 @@ void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket& recvData)
if (mode >= MAX_DUNGEON_DIFFICULTY)
{
- sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::HandleSetDungeonDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUIDLow(), mode);
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSession::HandleSetDungeonDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUIDLow(), mode);
return;
}
@@ -1478,7 +1474,7 @@ void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket& recvData)
Map* map = _player->FindMap();
if (map && map->IsDungeon())
{
- sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::HandleSetDungeonDifficultyOpcode: player (Name: %s, GUID: %u) tried to reset the instance while player is inside!",
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSession::HandleSetDungeonDifficultyOpcode: player (Name: %s, GUID: %u) tried to reset the instance while player is inside!",
_player->GetName().c_str(), _player->GetGUIDLow());
return;
}
@@ -1499,7 +1495,7 @@ void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket& recvData)
if (groupGuy->GetMap()->IsNonRaidDungeon())
{
- sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::HandleSetDungeonDifficultyOpcode: player %d tried to reset the instance while group member (Name: %s, GUID: %u) is inside!",
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSession::HandleSetDungeonDifficultyOpcode: player %d tried to reset the instance while group member (Name: %s, GUID: %u) is inside!",
_player->GetGUIDLow(), groupGuy->GetName().c_str(), groupGuy->GetGUIDLow());
return;
}
@@ -1534,7 +1530,7 @@ void WorldSession::HandleSetRaidDifficultyOpcode(WorldPacket& recvData)
Map* map = _player->FindMap();
if (map && map->IsDungeon())
{
- sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow());
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow());
return;
}
@@ -1557,7 +1553,7 @@ void WorldSession::HandleSetRaidDifficultyOpcode(WorldPacket& recvData)
if (groupGuy->GetMap()->IsRaid())
{
- sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow());
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow());
return;
}
}
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index 07bfd284a7d..5321202b256 100755
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -950,8 +950,8 @@ enum TrinityStrings
LANG_BATTLEGROUND = 5015,
LANG_ARENA = 5016,
LANG_RAID = 5017,
- LANG_HEROIC = 5018,
- LANG_MOUNTABLE = 5019,
+ //= 5018,
+ //= 5019,
LANG_NPCINFO_PHASEMASK = 5020,
LANG_NPCINFO_ARMOR = 5021,
LANG_CHANNEL_ENABLE_OWNERSHIP = 5022,
diff --git a/src/server/game/Movement/Spline/MoveSpline.cpp b/src/server/game/Movement/Spline/MoveSpline.cpp
index 7160f64c0fb..1821a78d993 100644
--- a/src/server/game/Movement/Spline/MoveSpline.cpp
+++ b/src/server/game/Movement/Spline/MoveSpline.cpp
@@ -201,7 +201,7 @@ bool MoveSplineInitArgs::Validate(Unit* unit) const
#define CHECK(exp) \
if (!(exp))\
{\
- sLog->outError(LOG_FILTER_GENERAL, "MoveSplineInitArgs::Validate: expression '%s' failed for GUID: %u", #exp, unit->GetTypeId() == TYPEID_PLAYER ? unit->GetGUIDLow() : unit->ToCreature()->GetDBTableGUIDLow());\
+ sLog->outError(LOG_FILTER_GENERAL, "MoveSplineInitArgs::Validate: expression '%s' failed for GUID: %u Entry: %u", #exp, unit->GetTypeId() == TYPEID_PLAYER ? unit->GetGUIDLow() : unit->ToCreature()->GetDBTableGUIDLow(), unit->GetEntry());\
return false;\
}
CHECK(path.size() > 1);
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index ee54c8d662c..377f0cb3a1f 100755
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -857,6 +857,17 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
uint32 recruiter = fields[9].GetUInt32();
std::string os = fields[10].GetString();
+ // Must be done before WorldSession is created
+ if (sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED) && os != "Win" && os != "OSX")
+ {
+ packet.Initialize(SMSG_AUTH_RESPONSE, 1);
+ packet << uint8(AUTH_REJECT);
+ SendPacket(packet);
+
+ sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: Client %s attempted to log in using invalid client OS (%s).", GetRemoteAddress().c_str(), os.c_str());
+ return -1;
+ }
+
// Checks gmlevel per Realm
stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_GMLEVEL_BY_REALMID);
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 86fc27af1f2..b27ae461323 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -5436,6 +5436,9 @@ SpellCastResult Spell::CheckCast(bool strict)
if (target->GetCharmerGUID())
return SPELL_FAILED_CHARMED;
+
+ if (target->GetOwner() && target->GetOwner()->GetTypeId() == TYPEID_PLAYER)
+ return SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED;
int32 damage = CalculateDamage(i, target);
if (damage && int32(target->getLevel()) > damage)
diff --git a/src/server/game/Texts/CreatureTextMgr.cpp b/src/server/game/Texts/CreatureTextMgr.cpp
index d50757868ed..89b75fd1695 100755
--- a/src/server/game/Texts/CreatureTextMgr.cpp
+++ b/src/server/game/Texts/CreatureTextMgr.cpp
@@ -65,6 +65,47 @@ class CreatureTextBuilder
uint64 _targetGUID;
};
+class PlayerTextBuilder
+{
+ public:
+ PlayerTextBuilder(WorldObject* obj, WorldObject* speaker, ChatMsg msgtype, uint8 textGroup, uint32 id, uint32 language, uint64 targetGUID)
+ : _source(obj), _talker(speaker), _msgType(msgtype), _textGroup(textGroup), _textId(id), _language(language), _targetGUID(targetGUID)
+ {
+ }
+
+ size_t operator()(WorldPacket* data, LocaleConstant locale) const
+ {
+ std::string const& text = sCreatureTextMgr->GetLocalizedChatString(_source->GetEntry(), _textGroup, _textId, locale);
+
+ *data << uint8(_msgType);
+ *data << uint32(_language);
+ *data << uint64(_talker->GetGUID());
+ *data << uint32(1); // 2.1.0
+ *data << uint32(_talker->GetName().size() + 1);
+ *data << _talker->GetName();
+ size_t whisperGUIDpos = data->wpos();
+ *data << uint64(_targetGUID); // Unit Target
+ if (_targetGUID && !IS_PLAYER_GUID(_targetGUID))
+ {
+ *data << uint32(1); // target name length
+ *data << uint8(0); // target name
+ }
+ *data << uint32(text.length() + 1);
+ *data << text;
+ *data << uint8(0); // ChatTag
+
+ return whisperGUIDpos;
+ }
+
+ WorldObject* _source;
+ WorldObject* _talker;
+ ChatMsg _msgType;
+ uint8 _textGroup;
+ uint32 _textId;
+ uint32 _language;
+ uint64 _targetGUID;
+};
+
void CreatureTextMgr::LoadCreatureTexts()
{
uint32 oldMSTime = getMSTime();
@@ -261,8 +302,16 @@ uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, uint64 whisp
if (iter->emote)
SendEmote(finalSource, iter->emote);
- CreatureTextBuilder builder(finalSource, finalType, iter->group, iter->id, finalLang, whisperGuid);
- SendChatPacket(finalSource, builder, finalType, whisperGuid, range, team, gmOnly);
+ if (srcPlr)
+ {
+ PlayerTextBuilder builder(source, finalSource, finalType, iter->group, iter->id, finalLang, whisperGuid);
+ SendChatPacket(finalSource, builder, finalType, whisperGuid, range, team, gmOnly);
+ }
+ else
+ {
+ CreatureTextBuilder builder(finalSource, finalType, iter->group, iter->id, finalLang, whisperGuid);
+ SendChatPacket(finalSource, builder, finalType, whisperGuid, range, team, gmOnly);
+ }
if (isEqualChanced || (!isEqualChanced && totalChance == 100.0f))
SetRepeatId(source, textGroup, iter->id);
diff --git a/src/server/game/Warden/Warden.cpp b/src/server/game/Warden/Warden.cpp
index ce64dbd1a94..06f8454fda7 100644
--- a/src/server/game/Warden/Warden.cpp
+++ b/src/server/game/Warden/Warden.cpp
@@ -151,13 +151,28 @@ bool Warden::IsValidCheckSum(uint32 checksum, const uint8* data, const uint16 le
}
}
+struct keyData {
+ union
+ {
+ struct
+ {
+ uint8 bytes[20];
+ } bytes;
+
+ struct
+ {
+ uint32 ints[5];
+ } ints;
+ };
+};
+
uint32 Warden::BuildChecksum(const uint8* data, uint32 length)
{
- uint8 hash[20];
- SHA1(data, length, hash);
+ keyData hash;
+ SHA1(data, length, hash.bytes.bytes);
uint32 checkSum = 0;
for (uint8 i = 0; i < 5; ++i)
- checkSum = checkSum ^ *(uint32*)(&hash[0] + i * 4);
+ checkSum = checkSum ^ hash.ints.ints[i];
return checkSum;
}
diff --git a/src/server/game/Warden/WardenMac.cpp b/src/server/game/Warden/WardenMac.cpp
index e08d24ecbcd..c6ce33fe131 100644
--- a/src/server/game/Warden/WardenMac.cpp
+++ b/src/server/game/Warden/WardenMac.cpp
@@ -114,17 +114,32 @@ void WardenMac::RequestHash()
_session->SendPacket(&pkt);
}
+struct keyData {
+ union
+ {
+ struct
+ {
+ uint8 bytes[16];
+ } bytes;
+
+ struct
+ {
+ int ints[4];
+ } ints;
+ };
+};
+
void WardenMac::HandleHashResult(ByteBuffer &buff)
{
// test
int keyIn[4];
- uint8 mod_seed[16] = { 0x4D, 0x80, 0x8D, 0x2C, 0x77, 0xD9, 0x05, 0xC4, 0x1A, 0x63, 0x80, 0xEC, 0x08, 0x58, 0x6A, 0xFE };
+ keyData mod_seed = { { { { 0x4D, 0x80, 0x8D, 0x2C, 0x77, 0xD9, 0x05, 0xC4, 0x1A, 0x63, 0x80, 0xEC, 0x08, 0x58, 0x6A, 0xFE } } } };
for (int i = 0; i < 4; ++i)
{
- keyIn[i] = *(int*)(&mod_seed[0] + i * 4);
+ keyIn[i] = mod_seed.ints.ints[i];
}
int keyOut[4];
diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp
index 8f7e3ed3247..9889b4752c8 100644
--- a/src/server/scripts/Commands/cs_lookup.cpp
+++ b/src/server/scripts/Commands/cs_lookup.cpp
@@ -1156,109 +1156,72 @@ public:
return true;
}
- static bool HandleLookupMapCommand(ChatHandler* /*handler*/, char const* args)
+ static bool HandleLookupMapCommand(ChatHandler* handler, char const* args)
{
if (!*args)
return false;
- /*
+
std::string namePart = args;
std::wstring wNamePart;
- // converting string that we try to find to lower case
if (!Utf8toWStr(namePart, wNamePart))
return false;
wstrToLower(wNamePart);
- bool found = false;
+ uint32 counter = 0;
+ uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS);
+ uint8 locale = handler->GetSession() ? handler->GetSession()->GetSessionDbcLocale() : sWorld->GetDefaultDbcLocale();
// search in Map.dbc
for (uint32 id = 0; id < sMapStore.GetNumRows(); id++)
{
- MapEntry const* MapInfo = sMapStore.LookupEntry(id);
- if (MapInfo)
+ if (MapEntry const* mapInfo = sMapStore.LookupEntry(id))
{
- uint8 locale = handler->GetSession() ? handler->GetSession()->GetSessionDbcLocale() : sWorld->GetDefaultDbcLocale();
-
- std::string name = MapInfo->name[locale];
+ std::string name = mapInfo->name[locale];
if (name.empty())
continue;
- if (!Utf8FitTo(name, wNamePart))
+ if (Utf8FitTo(name, wNamePart) && locale < TOTAL_LOCALES)
{
- locale = LOCALE_enUS;
- for (; locale < TOTAL_LOCALES; locale++)
+ if (maxResults && counter == maxResults)
{
- if (handler->GetSession() && locale == handler->GetSession()->GetSessionDbcLocale())
- continue;
-
- name = MapInfo->name[locale];
- if (name.empty())
- continue;
-
- if (Utf8FitTo(name, wNamePart))
- break;
+ handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults);
+ return true;
}
- }
- if (locale < TOTAL_LOCALES)
- {
- // send map in "id - [name][Continent][Instance/Battleground/Arena][Raid reset time:][Heroic reset time:][Mountable]" format
std::ostringstream ss;
+ ss << id << " - [" << name << ']';
- if (handler->GetSession())
- ss << id << " - |cffffffff|Hmap:" << id << "|h[" << name << ']';
- else // console
- ss << id << " - [" << name << ']';
-
- if (MapInfo->IsContinent())
+ if (mapInfo->IsContinent())
ss << handler->GetTrinityString(LANG_CONTINENT);
- switch (MapInfo->map_type)
+ switch (mapInfo->map_type)
{
- case MAP_INSTANCE: ss << handler->GetTrinityString(LANG_INSTANCE); break;
- case MAP_BATTLEGROUND: ss << handler->GetTrinityString(LANG_BATTLEGROUND); break;
- case MAP_ARENA: ss << handler->GetTrinityString(LANG_ARENA); break;
+ case MAP_INSTANCE:
+ ss << handler->GetTrinityString(LANG_INSTANCE);
+ break;
+ case MAP_RAID:
+ ss << handler->GetTrinityString(LANG_RAID);
+ break;
+ case MAP_BATTLEGROUND:
+ ss << handler->GetTrinityString(LANG_BATTLEGROUND);
+ break;
+ case MAP_ARENA:
+ ss << handler->GetTrinityString(LANG_ARENA);
+ break;
}
- if (MapInfo->IsRaid())
- ss << handler->GetTrinityString(LANG_RAID);
-
- if (MapInfo->SupportsHeroicMode())
- ss << handler->GetTrinityString(LANG_HEROIC);
-
- uint32 ResetTimeRaid = MapInfo->resetTimeRaid;
-
- std::string ResetTimeRaidStr;
- if (ResetTimeRaid)
- ResetTimeRaidStr = secsToTimeString(ResetTimeRaid, true, false);
-
- uint32 ResetTimeHeroic = MapInfo->resetTimeHeroic;
- std::string ResetTimeHeroicStr;
- if (ResetTimeHeroic)
- ResetTimeHeroicStr = secsToTimeString(ResetTimeHeroic, true, false);
-
- if (MapInfo->IsMountAllowed())
- ss << handler->GetTrinityString(LANG_MOUNTABLE);
-
- if (ResetTimeRaid && !ResetTimeHeroic)
- handler->PSendSysMessage(ss.str().c_str(), ResetTimeRaidStr.c_str());
- else if (!ResetTimeRaid && ResetTimeHeroic)
- handler->PSendSysMessage(ss.str().c_str(), ResetTimeHeroicStr.c_str());
- else if (ResetTimeRaid && ResetTimeHeroic)
- handler->PSendSysMessage(ss.str().c_str(), ResetTimeRaidStr.c_str(), ResetTimeHeroicStr.c_str());
- else
- handler->SendSysMessage(ss.str().c_str());
+ handler->SendSysMessage(ss.str().c_str());
- if (!found)
- found = true;
+ ++counter;
}
}
}
- if (!found)
+ if (!counter)
handler->SendSysMessage(LANG_COMMAND_NOMAPFOUND);
- */
+
return true;
}
diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp b/src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp
index b2b4083f9c6..cef95b607c7 100644
--- a/src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp
+++ b/src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp
@@ -24,8 +24,8 @@ enum Spells
SPELL_CLEAVE = 40504,
SPELL_DEMORALIZING_SHOUT = 23511,
SPELL_ENRAGE = 8599,
- SPELL_WHIRLWIND1 = 15589,
- SPELL_WHIRLWIND2 = 13736,
+ SPELL_WHIRLWIND = 13736,
+
SPELL_NORTH_MARSHAL = 45828,
SPELL_SOUTH_MARSHAL = 45829,
SPELL_STONEHEARTH_MARSHAL = 45830,
@@ -48,38 +48,55 @@ enum Creatures
NPC_WEST_FROSTWOLF_WARMASTER = 14777
};
+enum Events
+{
+ EVENT_CHARGE_TARGET = 1,
+ EVENT_CLEAVE = 2,
+ EVENT_DEMORALIZING_SHOUT = 3,
+ EVENT_WHIRLWIND = 4,
+ EVENT_ENRAGE = 5,
+ EVENT_CHECK_RESET = 6
+};
+
+struct SpellPair
+{
+ uint32 npcEntry;
+ uint32 spellId;
+};
+
+uint8 const MAX_SPELL_PAIRS = 8;
+SpellPair const _auraPairs[MAX_SPELL_PAIRS] =
+{
+ { NPC_NORTH_MARSHAL, SPELL_NORTH_MARSHAL },
+ { NPC_SOUTH_MARSHAL, SPELL_SOUTH_MARSHAL },
+ { NPC_STONEHEARTH_MARSHAL, SPELL_STONEHEARTH_MARSHAL },
+ { NPC_ICEWING_MARSHAL, SPELL_ICEWING_MARSHAL },
+ { NPC_EAST_FROSTWOLF_WARMASTER, SPELL_EAST_FROSTWOLF_WARMASTER },
+ { NPC_WEST_FROSTWOLF_WARMASTER, SPELL_WEST_FROSTWOLF_WARMASTER },
+ { NPC_TOWER_POINT_WARMASTER, SPELL_TOWER_POINT_WARMASTER },
+ { NPC_ICEBLOOD_WARMASTER, SPELL_ICEBLOOD_WARMASTER }
+};
+
class mob_av_marshal_or_warmaster : public CreatureScript
{
public:
-
- mob_av_marshal_or_warmaster()
- : CreatureScript("mob_av_marshal_or_warmaster") {}
+ mob_av_marshal_or_warmaster() : CreatureScript("mob_av_marshal_or_warmaster") { }
struct mob_av_marshal_or_warmasterAI : public ScriptedAI
{
- mob_av_marshal_or_warmasterAI(Creature* creature) : ScriptedAI(creature) {}
-
- uint32 ChargeTimer;
- uint32 CleaveTimer;
- uint32 DemoralizingShoutTimer;
- uint32 Whirlwind1Timer;
- uint32 Whirlwind2Timer;
- uint32 EnrageTimer;
- uint32 ResetTimer;
-
- bool bHasAura;
+ mob_av_marshal_or_warmasterAI(Creature* creature) : ScriptedAI(creature) { }
void Reset()
{
- ChargeTimer = urand(2 * IN_MILLISECONDS, 12 * IN_MILLISECONDS);
- CleaveTimer = urand(1 * IN_MILLISECONDS, 11 * IN_MILLISECONDS);
- DemoralizingShoutTimer = urand(2 * IN_MILLISECONDS, 2 * IN_MILLISECONDS);
- Whirlwind1Timer = urand(1 * IN_MILLISECONDS, 12 * IN_MILLISECONDS);
- Whirlwind2Timer = urand(5 * IN_MILLISECONDS, 20 * IN_MILLISECONDS);
- EnrageTimer = urand(5 * IN_MILLISECONDS, 20 * IN_MILLISECONDS);
- ResetTimer = 5 * IN_MILLISECONDS;
-
- bHasAura = false;
+ events.Reset();
+ events.ScheduleEvent(EVENT_CHARGE_TARGET, urand(2 * IN_MILLISECONDS, 12 * IN_MILLISECONDS));
+ events.ScheduleEvent(EVENT_CLEAVE, urand(1 * IN_MILLISECONDS, 11 * IN_MILLISECONDS));
+ events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, 2000);
+ events.ScheduleEvent(EVENT_WHIRLWIND, urand(5 * IN_MILLISECONDS, 20 * IN_MILLISECONDS));
+ events.ScheduleEvent(EVENT_ENRAGE, urand(5 * IN_MILLISECONDS, 20 * IN_MILLISECONDS));
+ events.ScheduleEvent(EVENT_CHECK_RESET, 5000);
+
+ _hasAura = false;
}
void JustRespawned()
@@ -87,90 +104,70 @@ class mob_av_marshal_or_warmaster : public CreatureScript
Reset();
}
- void UpdateAI(const uint32 diff)
+ void UpdateAI(uint32 const diff)
{
- if (!bHasAura)
+ // I have a feeling this isn't blizzlike, but owell, I'm only passing by and cleaning up.
+ if (!_hasAura)
{
- switch (me->GetEntry())
- {
- case NPC_NORTH_MARSHAL:
- DoCast(me, SPELL_NORTH_MARSHAL);
- break;
- case NPC_SOUTH_MARSHAL:
- DoCast(me, SPELL_SOUTH_MARSHAL);
- break;
- case NPC_STONEHEARTH_MARSHAL:
- DoCast(me, SPELL_STONEHEARTH_MARSHAL);
- break;
- case NPC_ICEWING_MARSHAL:
- DoCast(me, SPELL_ICEWING_MARSHAL);
- break;
- case NPC_EAST_FROSTWOLF_WARMASTER:
- DoCast(me, SPELL_EAST_FROSTWOLF_WARMASTER);
- break;
- case NPC_WEST_FROSTWOLF_WARMASTER:
- DoCast(me, SPELL_WEST_FROSTWOLF_WARMASTER);
- break;
- case NPC_ICEBLOOD_WARMASTER:
- DoCast(me, SPELL_ICEBLOOD_WARMASTER);
- break;
- case NPC_TOWER_POINT_WARMASTER:
- DoCast(me, SPELL_TOWER_POINT_WARMASTER);
- break;
- }
+ for (uint8 i = 0; i < MAX_SPELL_PAIRS; ++i)
+ if (_auraPairs[i].npcEntry == me->GetEntry())
+ DoCast(me, _auraPairs[i].spellId);
- bHasAura = true;
+ _hasAura = true;
}
if (!UpdateVictim())
return;
- if (ChargeTimer <= diff)
- {
- DoCast(me->getVictim(), SPELL_CHARGE);
- ChargeTimer = urand(10 * IN_MILLISECONDS, 25 * IN_MILLISECONDS);
- } else ChargeTimer -= diff;
-
- if (CleaveTimer <= diff)
- {
- DoCast(me->getVictim(), SPELL_CLEAVE);
- CleaveTimer = urand(10 * IN_MILLISECONDS, 16 * IN_MILLISECONDS);
- } else CleaveTimer -= diff;
-
- if (DemoralizingShoutTimer <= diff)
- {
- DoCast(me->getVictim(), SPELL_DEMORALIZING_SHOUT);
- DemoralizingShoutTimer = urand(10 * IN_MILLISECONDS, 15 * IN_MILLISECONDS);
- } else DemoralizingShoutTimer -= diff;
+ events.Update(diff);
- if (Whirlwind1Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_WHIRLWIND1);
- Whirlwind1Timer = urand(6 * IN_MILLISECONDS, 20 * IN_MILLISECONDS);
- } else Whirlwind1Timer -= diff;
-
- if (Whirlwind2Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_WHIRLWIND2);
- Whirlwind2Timer = urand(10 * IN_MILLISECONDS, 25 * IN_MILLISECONDS);
- } else Whirlwind2Timer -= diff;
-
- if (EnrageTimer <= diff)
- {
- DoCast(me->getVictim(), SPELL_ENRAGE);
- EnrageTimer = urand(10 * IN_MILLISECONDS, 30 * IN_MILLISECONDS);
- }else EnrageTimer -= diff;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- // check if creature is not outside of building
- if (ResetTimer <= diff)
+ while (uint32 eventId = events.ExecuteEvent())
{
- if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50)
- EnterEvadeMode();
- ResetTimer = 5 * IN_MILLISECONDS;
- } else ResetTimer -= diff;
+ switch (eventId)
+ {
+ case EVENT_CHARGE_TARGET:
+ DoCast(me->getVictim(), SPELL_CHARGE);
+ events.ScheduleEvent(EVENT_CHARGE, urand(10 * IN_MILLISECONDS, 25 * IN_MILLISECONDS));
+ break;
+ case EVENT_CLEAVE:
+ DoCast(me->getVictim(), SPELL_CLEAVE);
+ events.ScheduleEvent(EVENT_CLEAVE, urand(10 * IN_MILLISECONDS, 16 * IN_MILLISECONDS));
+ break;
+ case EVENT_DEMORALIZING_SHOUT:
+ DoCast(me, SPELL_DEMORALIZING_SHOUT);
+ events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, urand(10 * IN_MILLISECONDS, 15 * IN_MILLISECONDS));
+ break;
+ case EVENT_WHIRLWIND:
+ DoCast(me, SPELL_WHIRLWIND);
+ events.ScheduleEvent(EVENT_WHIRLWIND, urand(10 * IN_MILLISECONDS, 25 * IN_MILLISECONDS));
+ break;
+ case EVENT_ENRAGE:
+ DoCast(me, SPELL_ENRAGE);
+ events.ScheduleEvent(EVENT_ENRAGE, urand(10 * IN_MILLISECONDS, 30 * IN_MILLISECONDS));
+ break;
+ case EVENT_CHECK_RESET:
+ {
+ Position const& _homePosition = me->GetHomePosition();
+ if (me->GetDistance2d(_homePosition.GetPositionX(), _homePosition.GetPositionY()) > 50.0f)
+ {
+ EnterEvadeMode();
+ return;
+ }
+ events.ScheduleEvent(EVENT_CHECK_RESET, 5000);
+ break;
+ }
+ }
+ }
DoMeleeAttackIfReady();
}
+
+ private:
+ EventMap events;
+ bool _hasAura;
};
CreatureAI* GetAI(Creature* creature) const
diff --git a/src/server/scripts/World/boss_emerald_dragons.cpp b/src/server/scripts/World/boss_emerald_dragons.cpp
index abb20130ef8..65677959135 100644
--- a/src/server/scripts/World/boss_emerald_dragons.cpp
+++ b/src/server/scripts/World/boss_emerald_dragons.cpp
@@ -22,6 +22,7 @@
#include "SpellScript.h"
#include "Spell.h"
#include "SpellAuraEffects.h"
+#include "PassiveAI.h"
//
// Emerald Dragon NPCs and IDs (kept here for reference)
@@ -91,14 +92,12 @@ struct emerald_dragonAI : public WorldBossAI
{
emerald_dragonAI(Creature* creature) : WorldBossAI(creature)
{
-// me->m_CombatDistance = 12.0f;
-// me->m_SightDistance = 60.0f;
}
void Reset()
{
- _Reset();
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE);
+ WorldBossAI::Reset();
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
me->SetReactState(REACT_AGGRESSIVE);
DoCast(me, SPELL_MARK_OF_NATURE_AURA, true);
events.ScheduleEvent(EVENT_TAIL_SWEEP, 4000);
@@ -109,7 +108,8 @@ struct emerald_dragonAI : public WorldBossAI
// Target killed during encounter, mark them as suspectible for Aura Of Nature
void KilledUnit(Unit* who)
{
- who->CastSpell(who, SPELL_MARK_OF_NATURE, true);
+ if (who->GetTypeId() == TYPEID_PLAYER)
+ who->CastSpell(who, SPELL_MARK_OF_NATURE, true);
}
// Execute and reschedule base events shared between all Emerald Dragons
@@ -216,109 +216,6 @@ class npc_dream_fog : public CreatureScript
};
/*
- * --- Spell: Dream Fog
- */
-
-class DreamFogTargetSelector
-{
- public:
- DreamFogTargetSelector() { }
-
- bool operator()(WorldObject* object) const
- {
- return object->ToUnit() && object->ToUnit()->HasAura(SPELL_SLEEP);
- }
-};
-
-class spell_dream_fog_sleep : public SpellScriptLoader
-{
- public:
- spell_dream_fog_sleep() : SpellScriptLoader("spell_dream_fog_sleep") { }
-
- class spell_dream_fog_sleep_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_dream_fog_sleep_SpellScript);
-
- void FilterTargets(std::list<WorldObject*>& unitList)
- {
- unitList.remove_if(DreamFogTargetSelector());
- }
-
- void Register()
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dream_fog_sleep_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
- }
- };
-
- SpellScript* GetSpellScript() const
- {
- return new spell_dream_fog_sleep_SpellScript();
- }
-};
-
-/*
- * --- Spell: Mark of Nature
- */
-
-class MarkOfNatureTargetSelector
-{
- public:
- MarkOfNatureTargetSelector() { }
-
- bool operator()(WorldObject* object) const
- {
- if (Unit* unit = object->ToUnit())
- // return anyone that isn't tagged or already under the influence of Aura of Nature
- return !(unit->HasAura(SPELL_MARK_OF_NATURE) && !unit->HasAura(SPELL_AURA_OF_NATURE));
- return true;
- }
-};
-
-class spell_mark_of_nature : public SpellScriptLoader
-{
- public:
- spell_mark_of_nature() : SpellScriptLoader("spell_mark_of_nature") { }
-
- class spell_mark_of_nature_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_mark_of_nature_SpellScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/)
- {
- if (!sSpellMgr->GetSpellInfo(SPELL_MARK_OF_NATURE))
- return false;
- if (!sSpellMgr->GetSpellInfo(SPELL_AURA_OF_NATURE))
- return false;
- return true;
- }
-
- void FilterTargets(std::list<WorldObject*>& targets)
- {
- targets.remove_if(MarkOfNatureTargetSelector());
- }
-
- void HandleEffect(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
-
- if (GetHitUnit())
- GetHitUnit()->CastSpell(GetHitUnit(), SPELL_AURA_OF_NATURE, true);
- }
-
- void Register()
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mark_of_nature_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
- OnEffectHitTarget += SpellEffectFn(spell_mark_of_nature_SpellScript::HandleEffect, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
- }
- };
-
- SpellScript* GetSpellScript() const
- {
- return new spell_mark_of_nature_SpellScript();
- }
-};
-
-/*
* ---
* --- Dragonspecific scripts and handling: YSONDRE
* ---
@@ -355,7 +252,6 @@ class boss_ysondre : public CreatureScript
void Reset()
{
_stage = 1;
- _Reset();
emerald_dragonAI::Reset();
events.ScheduleEvent(EVENT_LIGHTNING_WAVE, 12000);
}
@@ -394,7 +290,7 @@ class boss_ysondre : public CreatureScript
}
private:
- uint8 _stage;
+ uint8 _stage;
};
CreatureAI* GetAI(Creature* creature) const
@@ -409,8 +305,6 @@ class boss_ysondre : public CreatureScript
* ---
*
* TODO:
- * - NPC helper for spirit shades(?)
- * - Spirit shade NPC moves towards Lethon and heals him if close enough (each shade heals for 15000 HP)
* - Spell: Shadow bolt whirl casts needs custom handling (spellscript)
*/
@@ -424,7 +318,12 @@ enum LethonSpells
{
SPELL_DRAW_SPIRIT = 24811,
SPELL_SHADOW_BOLT_WHIRL = 24834,
- SPELL_SPIRIT_SHADE_VISUAL = 24908,
+ SPELL_DARK_OFFERING = 24804,
+};
+
+enum LethonCreatures
+{
+ NPC_SPIRIT_SHADE = 15261,
};
class boss_lethon : public CreatureScript
@@ -441,7 +340,6 @@ class boss_lethon : public CreatureScript
void Reset()
{
_stage = 1;
- _Reset();
emerald_dragonAI::Reset();
events.ScheduleEvent(EVENT_SHADOW_BOLT_WHIRL, 10000);
}
@@ -462,12 +360,22 @@ class boss_lethon : public CreatureScript
}
}
+ void SpellHitTarget(Unit* target, SpellInfo const* spell)
+ {
+ if (spell->Id == SPELL_DRAW_SPIRIT && target->GetTypeId() == TYPEID_PLAYER)
+ {
+ Position targetPos;
+ target->GetPosition(&targetPos);
+ me->GetMap()->SummonCreature(NPC_SPIRIT_SHADE, targetPos, NULL, 50000, (Unit*)this);
+ }
+ }
+
void ExecuteEvent(uint32 const eventId)
{
switch (eventId)
{
case EVENT_SHADOW_BOLT_WHIRL:
- DoCast(me, SPELL_SHADOW_BOLT_WHIRL, true);
+ me->CastSpell((Unit*)NULL, SPELL_SHADOW_BOLT_WHIRL, false);
events.ScheduleEvent(EVENT_SHADOW_BOLT_WHIRL, urand(15000, 30000));
break;
default:
@@ -477,7 +385,7 @@ class boss_lethon : public CreatureScript
}
private:
- uint8 _stage;
+ uint8 _stage;
};
CreatureAI* GetAI(Creature* creature) const
@@ -486,6 +394,42 @@ class boss_lethon : public CreatureScript
}
};
+class npc_spirit_shade : public CreatureScript
+{
+ public:
+ npc_spirit_shade() : CreatureScript("npc_spirit_shade") { }
+
+ struct npc_spirit_shadeAI : public PassiveAI
+ {
+ npc_spirit_shadeAI(Creature* creature) : PassiveAI(creature), _summonerGuid(0)
+ {
+ }
+
+ void IsSummonedBy(Unit* summoner)
+ {
+ _summonerGuid = summoner->GetGUID();
+ me->GetMotionMaster()->MoveFollow(summoner, 0.0f, 0.0f);
+ }
+
+ void MovementInform(uint32 moveType, uint32 data)
+ {
+ if (moveType == FOLLOW_MOTION_TYPE && data == _summonerGuid)
+ {
+ me->CastSpell((Unit*)NULL, SPELL_DARK_OFFERING, false);
+ me->DespawnOrUnsummon(1000);
+ }
+ }
+
+ private:
+ uint64 _summonerGuid;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_spirit_shadeAI(creature);
+ }
+};
+
/*
* ---
* --- Dragonspecific scripts and handling: EMERISS
@@ -519,7 +463,6 @@ class boss_emeriss : public CreatureScript
void Reset()
{
_stage = 1;
- _Reset();
emerald_dragonAI::Reset();
events.ScheduleEvent(EVENT_VOLATILE_INFECTION, 12000);
}
@@ -562,7 +505,7 @@ class boss_emeriss : public CreatureScript
}
private:
- uint8 _stage;
+ uint8 _stage;
};
CreatureAI* GetAI(Creature* creature) const
@@ -607,10 +550,6 @@ class boss_taerar : public CreatureScript
{
boss_taerarAI(Creature* creature) : emerald_dragonAI(creature)
{
- _stage = 1;
- _shades = 0;
- _banished = false;
- _banishedTimer = 0;
}
void Reset()
@@ -622,7 +561,6 @@ class boss_taerar : public CreatureScript
_banished = false;
_banishedTimer = 0;
- _Reset();
emerald_dragonAI::Reset();
events.ScheduleEvent(EVENT_ARCANE_BLAST, 12000);
events.ScheduleEvent(EVENT_BELLOWING_ROAR, 30000);
@@ -655,11 +593,11 @@ class boss_taerar : public CreatureScript
uint32 count = sizeof(TaerarShadeSpells) / sizeof(uint32);
for (uint32 i = 0; i < count; ++i)
- DoCastVictim(TaerarShadeSpells[i], true);
+ DoCast(me->getVictim(), TaerarShadeSpells[i], true);
_shades += count;
DoCast(SPELL_SHADE);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
me->SetReactState(REACT_PASSIVE);
++_stage;
@@ -696,7 +634,7 @@ class boss_taerar : public CreatureScript
{
_banished = false;
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
me->RemoveAurasDueToSpell(SPELL_SHADE);
me->SetReactState(REACT_AGGRESSIVE);
}
@@ -714,10 +652,10 @@ class boss_taerar : public CreatureScript
}
private:
- bool _banished; // used for shades activation testing
- uint32 _banishedTimer; // counter for banishment timeout
- uint8 _shades; // keep track of how many shades are dead
- uint8 _stage; // check which "shade phase" we're at (75-50-25 percentage counters)
+ bool _banished; // used for shades activation testing
+ uint32 _banishedTimer; // counter for banishment timeout
+ uint8 _shades; // keep track of how many shades are dead
+ uint8 _stage; // check which "shade phase" we're at (75-50-25 percentage counters)
};
CreatureAI* GetAI(Creature* creature) const
@@ -726,18 +664,122 @@ class boss_taerar : public CreatureScript
}
};
+/*
+ * --- Spell: Dream Fog
+ */
+
+class DreamFogTargetSelector
+{
+ public:
+ DreamFogTargetSelector() { }
+
+ bool operator()(WorldObject* object)
+ {
+ if (Unit* unit = object->ToUnit())
+ return unit->HasAura(SPELL_SLEEP);
+ return true;
+ }
+};
+
+class spell_dream_fog_sleep : public SpellScriptLoader
+{
+ public:
+ spell_dream_fog_sleep() : SpellScriptLoader("spell_dream_fog_sleep") { }
+
+ class spell_dream_fog_sleep_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_dream_fog_sleep_SpellScript);
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if(DreamFogTargetSelector());
+ }
+
+ void Register()
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dream_fog_sleep_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_dream_fog_sleep_SpellScript();
+ }
+};
+
+/*
+ * --- Spell: Mark of Nature
+ */
+
+class MarkOfNatureTargetSelector
+{
+ public:
+ MarkOfNatureTargetSelector() { }
+
+ bool operator()(WorldObject* object)
+ {
+ // return those not tagged or already under the influence of Aura of Nature
+ if (Unit* unit = object->ToUnit())
+ return !(unit->HasAura(SPELL_MARK_OF_NATURE) && !unit->HasAura(SPELL_AURA_OF_NATURE));
+ return true;
+ }
+};
+
+class spell_mark_of_nature : public SpellScriptLoader
+{
+ public:
+ spell_mark_of_nature() : SpellScriptLoader("spell_mark_of_nature") { }
+
+ class spell_mark_of_nature_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_mark_of_nature_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_MARK_OF_NATURE))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_AURA_OF_NATURE))
+ return false;
+ return true;
+ }
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if(MarkOfNatureTargetSelector());
+ }
+
+ void HandleEffect(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetHitUnit()->CastSpell(GetHitUnit(), SPELL_AURA_OF_NATURE, true);
+ }
+
+ void Register()
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mark_of_nature_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_mark_of_nature_SpellScript::HandleEffect, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_mark_of_nature_SpellScript();
+ }
+};
+
void AddSC_emerald_dragons()
{
// helper NPC scripts
new npc_dream_fog();
-
- // dragon spellscripts
- new spell_dream_fog_sleep();
- new spell_mark_of_nature();
+ new npc_spirit_shade();
// dragons
new boss_ysondre();
new boss_taerar();
new boss_emeriss();
new boss_lethon();
+
+ // dragon spellscripts
+ new spell_dream_fog_sleep();
+ new spell_mark_of_nature();
};
diff --git a/src/server/scripts/World/npc_taxi.cpp b/src/server/scripts/World/npc_taxi.cpp
index efdd4da73d6..18f776e7171 100644
--- a/src/server/scripts/World/npc_taxi.cpp
+++ b/src/server/scripts/World/npc_taxi.cpp
@@ -51,8 +51,6 @@ EndScriptData
#define GOSSIP_TARIOLSTRASZ2 "Can you spare a drake to travel to Lord Of Afrasastrasz, in the middle of the temple?"
#define GOSSIP_TORASTRASZA1 "I would like to see Lord Of Afrasastrasz, in the middle of the temple."
#define GOSSIP_TORASTRASZA2 "Yes, Please. I would like to return to the ground floor of the temple."
-#define GOSSIP_CAMILLE1 "I need to fly to the Windrunner Official business!"
-#define GOSSIP_CAMILLE2 "<The riding bat for the special task is necessary to me.>"
#define GOSSIP_CRIMSONWING "<Ride the gryphons to Survey Alcaz Island>"
#define GOSSIP_THRICESTAR1 "Do you think I could take a ride on one of those flying machines?"
#define GOSSIP_THRICESTAR2 "Kara, I need to be flown out the Dens of Dying to find Bixie."
@@ -159,12 +157,6 @@ public:
// top -> ground
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TORASTRASZA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22);
break;
- case 23816: // Howling Fjord - Bat Handler Camille
- if (!player->GetQuestRewardStatus(11229))
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CAMILLE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 23);
- if (player->GetQuestStatus(11170) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CAMILLE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 24);
- break;
case 23704: // Dustwallow Marsh - Cassa Crimsonwing
if (player->GetQuestStatus(11142) == QUEST_STATUS_INCOMPLETE)
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CRIMSONWING, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+25);