Dispeller
|
Дата: Воскресенье, 26.08.2012, 21:24 | Сообщение # 1 |
Сержант
Сообщений: 59
| Code 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..3449d9e 100755 --- a/src/server/game/Chat/Commands/Level0.cpp +++ b/src/server/game/Chat/Commands/Level0.cpp @@ -157,3 +157,163 @@ 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->SetSpectate(true); + _player->TeleportTo(target->GetMapId(), x, y, z, _player->GetAngle(target), TELE_TO_GM_MODE); + _player->SetPhaseMask(target->GetPhaseMask(), 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() && target != _player) + { + 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; + } + + (target == _player) ? _player->SetViewpoint(_player->getSpectateFrom(), 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..6dcb89a 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); @@ -1016,6 +1019,10 @@ void GameObject::SwitchDoorOrButton(bool activate, bool alternative /* = false *
void GameObject::Use(Unit* user) { + if (Player *tmpPlayer = user->ToPlayer()) + if (tmpPlayer->isSpectator()) + return; + // by default spell caster is user Unit* spellCaster = user; uint32 spellId = 0; @@ -1590,6 +1597,10 @@ void GameObject::Use(Unit* user)
void GameObject::CastSpell(Unit* target, uint32 spellId) { + if (Player *tmpPlayer = target->ToPlayer()) + if (tmpPlayer->isSpectator()) + return; + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); if (!spellInfo) return; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index b59c8c0..9d736bb 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,78 @@ void Player::SetGMVisible(bool on) } }
+void Player::SetSpectate(bool on) +{ + if (on) + { + //add aspectof the cheetah + AddAura(5118, this); + spectatorFlag = true; + + m_ExtraFlags |= PLAYER_EXTRA_GM_ON; + setFaction(35); + + if (Pet* pet = GetPet()) + { + pet->setFaction(35); + pet->getHostileRefManager().setOnlineOfflineState(false); + RemovePet(pet, PET_SAVE_AS_CURRENT); + } + + UnsummonPetTemporaryIfAny(); + + 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; + RemoveAura(5118); + } + UpdateObjectVisibility(); +} + bool Player::IsGroupVisibleFor(Player const* p) const { switch (sWorld->getIntConfig(CONFIG_GROUP_VISIBILITY)) @@ -22817,9 +22899,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 +22924,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 +22944,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..e5bd4a9 100755 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1157,6 +1157,11 @@ 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; } + Unit* getSpectateFrom() { return spectateFrom; } + 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 +2859,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/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 5a7645b..1ca2de8 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -3988,6 +3988,11 @@ void Unit::RemoveArenaAuras() { AuraApplication const* aurApp = iter->second; Aura const* aura = aurApp->GetBase(); + //allow aspect for spectator + if (Player *tmpPlayer = ToPlayer() ) + if (tmpPlayer->isSpectator() && aura->GetId() == 5118) + ++iter; + if (!(aura->GetSpellInfo()->AttributesEx4 & SPELL_ATTR4_UNK21) // don't remove stances, shadowform, pally/hunter auras && !aura->IsPassive() // don't remove passive auras && (aurApp->IsPositive() || !(aura->GetSpellInfo()->AttributesEx3 & SPELL_ATTR3_DEATH_PERSISTENT))) // not negative death persistent auras 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..09fdc3d 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -4604,6 +4604,10 @@ SpellCastResult Spell::CheckCast(bool strict) return SPELL_FAILED_ONLY_INDOORS; }
+ if (Player *tmpPlayer = m_caster->ToPlayer()) + if(tmpPlayer->isSpectator() && m_spellInfo->Id != 5118) + 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)
|
|
| |