diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/server/game/Battlegrounds/Battleground.cpp | 22 | ||||
-rwxr-xr-x | src/server/game/Battlegrounds/BattlegroundMgr.cpp | 14 | ||||
-rwxr-xr-x | src/server/game/Battlegrounds/BattlegroundQueue.cpp | 2 | ||||
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 7 | ||||
-rwxr-xr-x | src/server/game/Handlers/BattleGroundHandler.cpp | 156 | ||||
-rw-r--r-- | src/server/game/Handlers/MiscHandler.cpp | 38 | ||||
-rwxr-xr-x | src/server/game/Miscellaneous/Language.h | 4 | ||||
-rw-r--r-- | src/server/game/Movement/Spline/MoveSpline.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Server/WorldSocket.cpp | 11 | ||||
-rwxr-xr-x | src/server/game/Spells/Spell.cpp | 3 | ||||
-rwxr-xr-x | src/server/game/Texts/CreatureTextMgr.cpp | 53 | ||||
-rw-r--r-- | src/server/game/Warden/Warden.cpp | 21 | ||||
-rw-r--r-- | src/server/game/Warden/WardenMac.cpp | 19 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_lookup.cpp | 97 | ||||
-rw-r--r-- | src/server/scripts/World/boss_emerald_dragons.cpp | 310 |
15 files changed, 432 insertions, 327 deletions
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index 022ff8fa6ee..92a6d39a3ca 100755 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -652,7 +652,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) @@ -1092,7 +1097,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 @@ -1106,9 +1111,6 @@ void Battleground::Reset() SetElapsedTime(0); SetRemainingTime(0); SetLastResurrectTime(0); - SetArenaType(0); - SetRated(false); - m_Events = 0; if (m_InvitedAlliance > 0 || m_InvitedHorde > 0) @@ -1205,10 +1207,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 { @@ -1231,9 +1232,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 c18a8c48f14..8e145a49fb4 100755 --- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp +++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp @@ -133,7 +133,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, @@ -1250,16 +1250,12 @@ 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_TP: @@ -1268,11 +1264,15 @@ BattlegroundQueueTypeId BattlegroundMgr::BGQueueTypeId(BattlegroundTypeId bgType return BATTLEGROUND_QUEUE_BFG; 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 25b0f86fbe2..90e44c32eae 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 7ee40ce9fed..66926d94e0a 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -1298,7 +1298,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 @@ -1311,7 +1311,10 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss) uint32 VictimDefense = victim->GetMaxSkillValueForLevel(this); uint32 AttackerMeleeSkill = GetMaxSkillValueForLevel(); - 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 6ad0c7c0b2b..47586c32a2e 100755 --- a/src/server/game/Handlers/BattleGroundHandler.cpp +++ b/src/server/game/Handlers/BattleGroundHandler.cpp @@ -431,14 +431,16 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData) 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 Slot: %u, Unk: %u, Time: %u, Action: %u. Player not in queue!", + GetPlayerInfo().c_str(), queueSlot, unk, time, action); return; } BattlegroundQueueTypeId bgQueueTypeId = _player->GetBattlegroundQueueTypeId(queueSlot); if (bgQueueTypeId == BATTLEGROUND_QUEUE_NONE) { - sLog->outDebug(LOG_FILTER_BATTLEGROUND, "BattlegroundHandler: invalid queueSlot (%u) received.", queueSlot); + sLog->outDebug(LOG_FILTER_BATTLEGROUND, "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, Action: %u. Invalid queueSlot!", + GetPlayerInfo().c_str(), queueSlot, unk, time, action); return; } @@ -449,27 +451,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 Slot: %u, Unk: %u, Time: %u, Action: %u. Player not in queue (No player Group Info)!", + GetPlayerInfo().c_str(), queueSlot, unk, time, 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 Slot: %u, Unk: %u, Time: %u, Action: %u. Player is not invited to any bg!", + GetPlayerInfo().c_str(), queueSlot, unk, time, 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 Slot: %u, Unk: %u, Time: %u, Action: %u. Cant find BG with id %u!", + GetPlayerInfo().c_str(), queueSlot, unk, time, action); + 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 Slot: %u, Unk: %u, Time: %u, Action: %u.", + GetPlayerInfo().c_str(), queueSlot, unk, time, action); + // expected bracket entry PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); if (!bracketEntry) @@ -486,87 +500,83 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData) sBattlegroundMgr->BuildStatusFailedPacket(&data2, bg, _player, 0, 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->outDebug(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; } } 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, _player, queueSlot, STATUS_IN_PROGRESS, _player->GetBattlegroundQueueJoinTime(bgTypeId), bg->GetElapsedTime(), 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, _player, queueSlot, STATUS_IN_PROGRESS, _player->GetBattlegroundQueueJoinTime(bgTypeId), bg->GetElapsedTime(), 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, _player, queueSlot, STATUS_NONE, _player->GetBattlegroundQueueJoinTime(bgTypeId), 0, 0); + } + _player->RemoveBattlegroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs + sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, _player, queueSlot, STATUS_NONE, _player->GetBattlegroundQueueJoinTime(bgTypeId), 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; + 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 780117c029b..bf260743d6a 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -1445,25 +1445,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(); @@ -1530,7 +1526,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; } @@ -1541,7 +1537,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; } @@ -1562,7 +1558,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; } @@ -1597,7 +1593,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; } @@ -1620,7 +1616,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 0aaee6ecd48..b1eb24c507b 100755 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -958,8 +958,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 20d7f57daca..70e4aad2967 100644 --- a/src/server/game/Movement/Spline/MoveSpline.cpp +++ b/src/server/game/Movement/Spline/MoveSpline.cpp @@ -208,7 +208,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 38c6ed6276e..5c71c9e503c 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -918,6 +918,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 bb482704bb7..5beaa49c050 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5469,6 +5469,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 6e592e47fb8..612e2ecd7ed 100644 --- a/src/server/scripts/Commands/cs_lookup.cpp +++ b/src/server/scripts/Commands/cs_lookup.cpp @@ -1027,109 +1027,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; + handler->SendSysMessage(ss.str().c_str()); - 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()); - - if (!found) - found = true; + ++counter; } } } - if (!found) + if (!counter) handler->SendSysMessage(LANG_COMMAND_NOMAPFOUND); - */ + return true; } 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(); }; |