Created
December 21, 2011 08:15
-
-
Save walkline/1505180 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp | |
index 4ad00f5..5356680 100755 | |
--- a/src/server/game/Battlegrounds/Battleground.cpp | |
+++ b/src/server/game/Battlegrounds/Battleground.cpp | |
@@ -1237,16 +1237,19 @@ void Battleground::EventPlayerLoggedOut(Player* player) | |
m_Players[guid].OfflineRemoveTime = sWorld->GetGameTime() + MAX_OFFLINE_TIME; | |
if (GetStatus() == STATUS_IN_PROGRESS) | |
{ | |
- // drop flag and handle other cleanups | |
- RemovePlayer(player, guid, GetPlayerTeam(guid)); | |
+ if (!player->isSpectator()) | |
+ { | |
+ // drop flag and handle other cleanups | |
+ RemovePlayer(player, guid, GetPlayerTeam(guid)); | |
- // 1 player is logging out, if it is the last, then end arena! | |
- if (isArena()) | |
- if (GetAlivePlayersCountByTeam(player->GetTeam()) <= 1 && GetPlayersCountByTeam(GetOtherTeam(player->GetTeam()))) | |
- EndBattleground(GetOtherTeam(player->GetTeam())); | |
+ // 1 player is logging out, if it is the last, then end arena! | |
+ if (isArena()) | |
+ if (GetAlivePlayersCountByTeam(player->GetTeam()) <= 1 && GetPlayersCountByTeam(GetOtherTeam(player->GetTeam()))) | |
+ EndBattleground(GetOtherTeam(player->GetTeam())); | |
+ } | |
} | |
- | |
- player->LeaveBattleground(); | |
+ if (!player->isSpectator()) | |
+ player->LeaveBattleground(); | |
} | |
// This method should be called only once ... it adds pointer to queue | |
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp | |
index 185ac48..70b2885 100755 | |
--- a/src/server/game/Chat/Chat.cpp | |
+++ b/src/server/game/Chat/Chat.cpp | |
@@ -355,6 +355,9 @@ ChatCommand* ChatHandler::getCommandTable() | |
{ "notify", SEC_MODERATOR, true, OldHandler<&ChatHandler::HandleNotifyCommand>, "", NULL }, | |
{ "gmnotify", SEC_MODERATOR, true, OldHandler<&ChatHandler::HandleGMNotifyCommand>, "", NULL }, | |
{ "appear", SEC_MODERATOR, false, OldHandler<&ChatHandler::HandleAppearCommand>, "", NULL }, | |
+ { "spectate", SEC_PLAYER, false, OldHandler<&ChatHandler::HandleSpectateCommand>, "", NULL }, | |
+ { "spectatecancel", SEC_PLAYER, false, OldHandler<&ChatHandler::HandleSpectateCancelCommand>, "", NULL }, | |
+ { "spectatefrom", SEC_PLAYER, false, OldHandler<&ChatHandler::HandleSpectateFromCommand>, "", NULL }, | |
{ "summon", SEC_MODERATOR, false, OldHandler<&ChatHandler::HandleSummonCommand>, "", NULL }, | |
{ "groupsummon", SEC_MODERATOR, false, OldHandler<&ChatHandler::HandleGroupSummonCommand>, "", NULL }, | |
{ "commands", SEC_PLAYER, true, OldHandler<&ChatHandler::HandleCommandsCommand>, "", NULL }, | |
diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h | |
index 24652fc..a744d7a 100755 | |
--- a/src/server/game/Chat/Chat.h | |
+++ b/src/server/game/Chat/Chat.h | |
@@ -255,6 +255,9 @@ class ChatHandler | |
bool HandleSummonCommand(const char* args); | |
bool HandleAppearCommand(const char* args); | |
+ bool HandleSpectateCommand(const char* args); | |
+ bool HandleSpectateCancelCommand(const char* args); | |
+ bool HandleSpectateFromCommand(const char* args); | |
bool HandleGroupSummonCommand(const char* args); | |
bool HandleRecallCommand(const char* args); | |
bool HandleAnnounceCommand(const char* args); | |
diff --git a/src/server/game/Chat/Commands/Level0.cpp b/src/server/game/Chat/Commands/Level0.cpp | |
index 97173f7..9f9cedf 100755 | |
--- a/src/server/game/Chat/Commands/Level0.cpp | |
+++ b/src/server/game/Chat/Commands/Level0.cpp | |
@@ -157,3 +157,162 @@ bool ChatHandler::HandleServerMotdCommand(const char* /*args*/) | |
return true; | |
} | |
+bool ChatHandler::HandleSpectateCommand(const char *args) | |
+{ | |
+ Player* target; | |
+ uint64 target_guid; | |
+ std::string target_name; | |
+ if (!extractPlayerTarget((char*)args, &target, &target_guid, &target_name)) | |
+ return false; | |
+ | |
+ Player* _player = m_session->GetPlayer(); | |
+ if (target == _player || target_guid == _player->GetGUID()) | |
+ { | |
+ SendSysMessage(LANG_CANT_TELEPORT_SELF); | |
+ SetSentErrorMessage(true); | |
+ return false; | |
+ } | |
+ | |
+ // check online security | |
+ if (HasLowerSecurity(target, 0)) | |
+ return false; | |
+ | |
+ std::string chrNameLink = playerLink(target_name); | |
+ | |
+ if (_player->isInCombat()) | |
+ { | |
+ SendSysMessage(LANG_YOU_IN_COMBAT); | |
+ SetSentErrorMessage(true); | |
+ return false; | |
+ } | |
+ | |
+ if (!target) | |
+ { | |
+ SendSysMessage(LANG_PLAYER_NOT_EXIST_OR_OFFLINE); | |
+ SetSentErrorMessage(true); | |
+ return false; | |
+ } | |
+ | |
+ if (_player->GetMap()->IsBattlegroundOrArena() && !_player->isSpectator()) | |
+ { | |
+ PSendSysMessage("You are already on battleground or arena."); | |
+ SetSentErrorMessage(true); | |
+ return false; | |
+ } | |
+ | |
+ Map* cMap = target->GetMap(); | |
+ if (!cMap->IsBattlegroundOrArena()) | |
+ { | |
+ PSendSysMessage("Player didnt found in arena."); | |
+ SetSentErrorMessage(true); | |
+ return false; | |
+ } | |
+ | |
+ if (_player->GetMap()->IsBattleground()) | |
+ { | |
+ PSendSysMessage("Cant do that while you are on battleground."); | |
+ SetSentErrorMessage(true); | |
+ return false; | |
+ } | |
+ // all's well, set bg id | |
+ // when porting out from the bg, it will be reset to 0 | |
+ _player->SetBattlegroundId(target->GetBattlegroundId(), target->GetBattlegroundTypeId()); | |
+ // remember current position as entry point for return at bg end teleportation | |
+ if (!_player->GetMap()->IsBattlegroundOrArena()) | |
+ _player->SetBattlegroundEntryPoint(); | |
+ | |
+ if (target->isSpectator()) | |
+ { | |
+ PSendSysMessage("Can`t do that. Your target is spectator."); | |
+ SetSentErrorMessage(true); | |
+ return false; | |
+ } | |
+ | |
+ PSendSysMessage(LANG_APPEARING_AT, chrNameLink.c_str()); | |
+ | |
+ // stop flight if need | |
+ if (_player->isInFlight()) | |
+ { | |
+ _player->GetMotionMaster()->MovementExpired(); | |
+ _player->CleanupAfterTaxiFlight(); | |
+ } | |
+ // save only in non-flight case | |
+ else | |
+ _player->SaveRecallPosition(); | |
+ | |
+ // to point to see at target with same orientation | |
+ float x, y, z; | |
+ target->GetContactPoint(_player, x, y, z); | |
+ | |
+ _player->TeleportTo(target->GetMapId(), x, y, z, _player->GetAngle(target), TELE_TO_GM_MODE); | |
+ _player->SetPhaseMask(target->GetPhaseMask(), true); | |
+ _player->SetSpectate(true); | |
+ | |
+ return true; | |
+} | |
+ | |
+bool ChatHandler::HandleSpectateCancelCommand(const char */*args*/) | |
+{ | |
+ Player* _player = m_session->GetPlayer(); | |
+ | |
+ if (!_player->isSpectator()) | |
+ { | |
+ PSendSysMessage("You are not spectator."); | |
+ SetSentErrorMessage(true); | |
+ return false; | |
+ } | |
+ | |
+ _player->CancelSpectate(); | |
+ _player->TeleportToBGEntryPoint(); | |
+ | |
+ return true; | |
+} | |
+ | |
+bool ChatHandler::HandleSpectateFromCommand(const char *args) | |
+{ | |
+ Player* target; | |
+ uint64 target_guid; | |
+ std::string target_name; | |
+ if (!extractPlayerTarget((char*)args, &target, &target_guid, &target_name)) | |
+ return false; | |
+ | |
+ Player* _player = m_session->GetPlayer(); | |
+ | |
+ // check online security | |
+ if (HasLowerSecurity(target, 0)) | |
+ return false; | |
+ | |
+ if (!_player->isSpectator()) | |
+ { | |
+ PSendSysMessage("You are not spectator, spectate someone first."); | |
+ SetSentErrorMessage(true); | |
+ return false; | |
+ } | |
+ | |
+ if (target->isSpectator()) | |
+ { | |
+ PSendSysMessage("Can`t do that. Your target is spectator."); | |
+ SetSentErrorMessage(true); | |
+ return false; | |
+ } | |
+ | |
+ if (_player->GetMap() != target->GetMap()) | |
+ { | |
+ PSendSysMessage("Cant do that. Different arenas?"); | |
+ SetSentErrorMessage(true); | |
+ return false; | |
+ } | |
+ | |
+ //check for arena preperation | |
+ //if exists than battle didn`t begin | |
+ if (target->HasAura(32728) || target->HasAura(32727)) | |
+ { | |
+ PSendSysMessage("Cant do that. Arena didn`t started."); | |
+ SetSentErrorMessage(true); | |
+ return false; | |
+ } | |
+ | |
+ _player->SetViewpoint(target, true); | |
+ return true; | |
+} | |
+ | |
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp | |
index de1b0f8..b1f5905 100755 | |
--- a/src/server/game/Entities/GameObject/GameObject.cpp | |
+++ b/src/server/game/Entities/GameObject/GameObject.cpp | |
@@ -443,6 +443,9 @@ void GameObject::Update(uint32 diff) | |
if (ok) | |
{ | |
+ if (Player *tmpPlayer = ok->ToPlayer()) | |
+ if (tmpPlayer->isSpectator()) | |
+ return; | |
// some traps do not have spell but should be triggered | |
if (goInfo->trap.spellId) | |
CastSpell(ok, goInfo->trap.spellId); | |
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp | |
index b59c8c0..b498c53 100755 | |
--- a/src/server/game/Entities/Player/Player.cpp | |
+++ b/src/server/game/Entities/Player/Player.cpp | |
@@ -852,6 +852,10 @@ Player::Player (WorldSession* session): Unit(), m_achievementMgr(this), m_reputa | |
isDebugAreaTriggers = false; | |
+ spectatorFlag = false; | |
+ spectateCanceled = false; | |
+ spectateFrom = NULL; | |
+ | |
SetPendingBind(0, 0); | |
} | |
@@ -2308,7 +2312,12 @@ bool Player::TeleportToBGEntryPoint() | |
ScheduleDelayedOperation(DELAYED_BG_MOUNT_RESTORE); | |
ScheduleDelayedOperation(DELAYED_BG_TAXI_RESTORE); | |
ScheduleDelayedOperation(DELAYED_BG_GROUP_RESTORE); | |
- return TeleportTo(m_bgData.joinPos); | |
+ bool result = TeleportTo(m_bgData.joinPos); | |
+ | |
+ if (isSpectator() && result) | |
+ SetSpectate(false); | |
+ | |
+ return result; | |
} | |
void Player::ProcessDelayedOperations() | |
@@ -2715,6 +2724,7 @@ Creature* Player::GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask) | |
GameObject* Player::GetGameObjectIfCanInteractWith(uint64 guid, GameobjectTypes type) const | |
{ | |
+ sLog->outString("GetGameObjectIfCanInteractWith"); | |
if (GameObject* go = GetMap()->GetGameObject(guid)) | |
{ | |
if (go->GetGoType() == type) | |
@@ -2851,6 +2861,72 @@ void Player::SetGMVisible(bool on) | |
} | |
} | |
+void Player::SetSpectate(bool on) | |
+{ | |
+ if (on) | |
+ { | |
+ spectatorFlag = true; | |
+ | |
+ m_ExtraFlags |= PLAYER_EXTRA_GM_ON; | |
+ setFaction(35); | |
+ | |
+ if (Pet* pet = GetPet()) | |
+ { | |
+ pet->setFaction(35); | |
+ pet->getHostileRefManager().setOnlineOfflineState(false); | |
+ } | |
+ | |
+ RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); | |
+ ResetContestedPvP(); | |
+ | |
+ getHostileRefManager().setOnlineOfflineState(false); | |
+ CombatStopWithPets(); | |
+ | |
+ | |
+ m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GM, SEC_ADMINISTRATOR); | |
+ } | |
+ else | |
+ { | |
+ uint32 newPhase = 0; | |
+ AuraEffectList const& phases = GetAuraEffectsByType(SPELL_AURA_PHASE); | |
+ if (!phases.empty()) | |
+ for (AuraEffectList::const_iterator itr = phases.begin(); itr != phases.end(); ++itr) | |
+ newPhase |= (*itr)->GetMiscValue(); | |
+ | |
+ if (!newPhase) | |
+ newPhase = PHASEMASK_NORMAL; | |
+ | |
+ SetPhaseMask(newPhase, false); | |
+ | |
+ m_ExtraFlags &= ~ PLAYER_EXTRA_GM_ON; | |
+ setFactionForRace(getRace()); | |
+ RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM); | |
+ RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_ALLOW_CHEAT_SPELLS); | |
+ | |
+ if (Pet* pet = GetPet()) | |
+ { | |
+ pet->setFaction(getFaction()); | |
+ pet->getHostileRefManager().setOnlineOfflineState(true); | |
+ } | |
+ | |
+ if (spectateFrom) | |
+ SetViewpoint(spectateFrom, false); | |
+ | |
+ // restore FFA PvP Server state | |
+ if (sWorld->IsFFAPvPRealm()) | |
+ SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); | |
+ | |
+ // restore FFA PvP area state, remove not allowed for GM mounts | |
+ UpdateArea(m_areaUpdateId); | |
+ | |
+ getHostileRefManager().setOnlineOfflineState(true); | |
+ m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GM, SEC_PLAYER); | |
+ spectateCanceled = false; | |
+ spectatorFlag = false; | |
+ } | |
+ UpdateObjectVisibility(); | |
+} | |
+ | |
bool Player::IsGroupVisibleFor(Player const* p) const | |
{ | |
switch (sWorld->getIntConfig(CONFIG_GROUP_VISIBILITY)) | |
@@ -22817,9 +22893,19 @@ void Player::StopCastingBindSight() | |
} | |
void Player::SetViewpoint(WorldObject* target, bool apply) | |
-{ | |
+{ | |
if (apply) | |
{ | |
+ if (target->ToPlayer() == this) | |
+ return; | |
+ | |
+ //remove Viewpoint if already have | |
+ if (isSpectator() && spectateFrom) | |
+ { | |
+ SetViewpoint(spectateFrom, false); | |
+ spectateFrom = NULL; | |
+ } | |
+ | |
sLog->outDebug(LOG_FILTER_MAPS, "Player::CreateViewpoint: Player %s create seer %u (TypeId: %u).", GetName(), target->GetEntry(), target->GetTypeId()); | |
if (!AddUInt64Value(PLAYER_FARSIGHT, target->GetGUID())) | |
@@ -22832,7 +22918,12 @@ void Player::SetViewpoint(WorldObject* target, bool apply) | |
UpdateVisibilityOf(target); | |
if (target->isType(TYPEMASK_UNIT) && !GetVehicle()) | |
+ { | |
+ if (isSpectator()) | |
+ spectateFrom = (Unit*)target; | |
+ | |
((Unit*)target)->AddPlayerToVision(this); | |
+ } | |
} | |
else | |
{ | |
@@ -22847,6 +22938,9 @@ void Player::SetViewpoint(WorldObject* target, bool apply) | |
if (target->isType(TYPEMASK_UNIT) && !GetVehicle()) | |
((Unit*)target)->RemovePlayerFromVision(this); | |
+ if (isSpectator()) | |
+ spectateFrom = NULL; | |
+ | |
//must immediately set seer back otherwise may crash | |
m_seer = this; | |
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h | |
index 8ee7d1a..92e4564 100755 | |
--- a/src/server/game/Entities/Player/Player.h | |
+++ b/src/server/game/Entities/Player/Player.h | |
@@ -1157,6 +1157,10 @@ class Player : public Unit, public GridObject<Player> | |
void SetTaxiCheater(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_TAXICHEAT; else m_ExtraFlags &= ~PLAYER_EXTRA_TAXICHEAT; } | |
bool isGMVisible() const { return !(m_ExtraFlags & PLAYER_EXTRA_GM_INVISIBLE); } | |
void SetGMVisible(bool on); | |
+ bool isSpectateCanceled() { return spectateCanceled; } | |
+ bool CancelSpectate() { spectateCanceled = true; } | |
+ bool isSpectator() const { return spectatorFlag; } | |
+ void SetSpectate(bool on); | |
bool Has310Flyer(bool checkAllSpells, uint32 excludeSpellId = 0); | |
void SetHas310Flyer(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_HAS_310_FLYER; else m_ExtraFlags &= ~PLAYER_EXTRA_HAS_310_FLYER; } | |
void SetPvPDeath(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_PVP_DEATH; else m_ExtraFlags &= ~PLAYER_EXTRA_PVP_DEATH; } | |
@@ -2854,6 +2858,11 @@ class Player : public Unit, public GridObject<Player> | |
InstanceTimeMap _instanceResetTimes; | |
uint32 _pendingBindId; | |
uint32 _pendingBindTimer; | |
+ | |
+ //flag for spectator system | |
+ bool spectatorFlag; | |
+ bool spectateCanceled; | |
+ Unit *spectateFrom; | |
}; | |
void AddItemsSetItem(Player*player, Item* item); | |
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp | |
index 306af9c..3dcc26e 100755 | |
--- a/src/server/game/Maps/Map.cpp | |
+++ b/src/server/game/Maps/Map.cpp | |
@@ -2591,6 +2591,8 @@ bool BattlegroundMap::AddPlayerToMap(Player* player) | |
void BattlegroundMap::RemovePlayerFromMap(Player* player, bool remove) | |
{ | |
+ if (player->isSpectator() && !player->isSpectateCanceled()) | |
+ player->SetSpectate(false); | |
sLog->outDetail("MAP: Removing player '%s' from bg '%u' of map '%s' before relocating to another map", player->GetName(), GetInstanceId(), GetMapName()); | |
Map::RemovePlayerFromMap(player, remove); | |
} | |
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp | |
index e1c5b90..2099f37 100755 | |
--- a/src/server/game/Spells/Spell.cpp | |
+++ b/src/server/game/Spells/Spell.cpp | |
@@ -4604,6 +4604,12 @@ SpellCastResult Spell::CheckCast(bool strict) | |
return SPELL_FAILED_ONLY_INDOORS; | |
} | |
+ Player *tmpPlayer = m_caster->ToPlayer(); | |
+// sLog->outString("CASTING SPELL: %i", m_spellInfo->Id); | |
+ if (tmpPlayer != NULL) | |
+ if(tmpPlayer->isSpectator()) | |
+ return SPELL_FAILED_SPELL_UNAVAILABLE; | |
+ | |
// only check at first call, Stealth auras are already removed at second call | |
// for now, ignore triggered spells | |
if (strict && !(_triggeredCastFlags & TRIGGERED_IGNORE_SHAPESHIFT)) | |
diff --git a/src/server/scripts/Commands/cs_gm.cpp b/src/server/scripts/Commands/cs_gm.cpp | |
index ab077af..8ed1173 100644 | |
--- a/src/server/scripts/Commands/cs_gm.cpp | |
+++ b/src/server/scripts/Commands/cs_gm.cpp | |
@@ -134,6 +134,8 @@ public: | |
} | |
char const* name = itr->second->GetName(); | |
uint8 security = itrSec; | |
+ if (security == 0) | |
+ continue; | |
uint8 max = ((16 - strlen(name)) / 2); | |
uint8 max2 = max; | |
if ((max + max2 + strlen(name)) == 16) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment