diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 9f787e0e1..d58979f0d 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -2088,8 +2088,14 @@ void GameObject::CastSpell(Unit* target, uint32 spellId) if (owner->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED)) trigger->SetUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED); if (owner->IsFFAPvP()) - trigger->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + { + if (!HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + { + sScriptMgr->OnFfaPvpStateUpdate(trigger, true); + trigger->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + } + } // xinef: Remove Immunity flags trigger->SetImmuneToNPC(false); // xinef: set proper orientation, fixes cast against stealthed targets diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 2c473e09c..79d8565cd 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2179,8 +2179,11 @@ void Player::SetGameMaster(bool on) pet->SetFaction(FACTION_FRIENDLY); pet->getHostileRefMgr().setOnlineOfflineState(false); } - - RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + { + RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + sScriptMgr->OnFfaPvpStateUpdate(this, false); + } ResetContestedPvP(); getHostileRefMgr().setOnlineOfflineState(false); @@ -2212,8 +2215,13 @@ void Player::SetGameMaster(bool on) // restore FFA PvP Server state if (sWorld->IsFFAPvPRealm()) - SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); - + { + if (!HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + { + SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + sScriptMgr->OnFfaPvpStateUpdate(this, true); + } + } // restore FFA PvP area state, remove not allowed for GM mounts UpdateArea(m_areaUpdateId); @@ -2656,8 +2664,12 @@ void Player::InitStatsForLevel(bool reapplyMods) RemovePlayerFlag(PLAYER_FLAGS_AFK | PLAYER_FLAGS_DND | PLAYER_FLAGS_GM | PLAYER_FLAGS_GHOST | PLAYER_ALLOW_ONLY_ABILITY); RemoveStandFlags(UNIT_STAND_FLAGS_ALL); // one form stealth modified bytes - RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP | UNIT_BYTE2_FLAG_SANCTUARY); + if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + { + RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP | UNIT_BYTE2_FLAG_SANCTUARY); + sScriptMgr->OnFfaPvpStateUpdate(this, false); + } // restore if need some important flags SetUInt32Value(PLAYER_FIELD_BYTES2, 0); // flags empty by default @@ -15001,7 +15013,11 @@ void Player::SetIsSpectator(bool on) AddUnitState(UNIT_STATE_ISOLATED); //SetFaction(1100); SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + { + RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + sScriptMgr->OnFfaPvpStateUpdate(this, false); + } ResetContestedPvP(); SetDisplayId(23691); } @@ -15021,7 +15037,14 @@ void Player::SetIsSpectator(bool on) // restore FFA PvP Server state // Xinef: it will be removed if necessery in UpdateArea called in WorldPortOpcode if (sWorld->IsFFAPvPRealm()) - SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + { + if (!HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + { + SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + sScriptMgr->OnFfaPvpStateUpdate(this, true); + + } + } } } } diff --git a/src/server/game/Entities/Player/PlayerMisc.cpp b/src/server/game/Entities/Player/PlayerMisc.cpp index 173b366f7..8c32b2cae 100644 --- a/src/server/game/Entities/Player/PlayerMisc.cpp +++ b/src/server/game/Entities/Player/PlayerMisc.cpp @@ -396,8 +396,11 @@ void Player::UpdateFFAPvPFlag(time_t currTime) } pvpInfo.FFAPvPEndTimer = time_t(0); - - RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + { + RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + sScriptMgr->OnFfaPvpStateUpdate(this, false); + } for (ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr) (*itr)->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); diff --git a/src/server/game/Entities/Player/PlayerUpdates.cpp b/src/server/game/Entities/Player/PlayerUpdates.cpp index 04f7fd011..953c35e69 100644 --- a/src/server/game/Entities/Player/PlayerUpdates.cpp +++ b/src/server/game/Entities/Player/PlayerUpdates.cpp @@ -1401,6 +1401,7 @@ void Player::UpdateFFAPvPState(bool reset /*= true*/) { if (!IsFFAPvP()) { + sScriptMgr->OnFfaPvpStateUpdate(this, true); SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); for (ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr) @@ -1419,8 +1420,11 @@ void Player::UpdateFFAPvPState(bool reset /*= true*/) !pvpInfo.EndTimer) { pvpInfo.FFAPvPEndTimer = time_t(0); - - RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + { + RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + sScriptMgr->OnFfaPvpStateUpdate(this, false); + } for (ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr) (*itr)->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 04a9f5d0e..70eb6ef98 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -954,7 +954,11 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder) // Set FFA PvP for non GM in non-rest mode if (sWorld->IsFFAPvPRealm() && !pCurrChar->IsGameMaster() && !pCurrChar->HasPlayerFlag(PLAYER_FLAGS_RESTING)) - pCurrChar->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + if (!pCurrChar->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + { + sScriptMgr->OnFfaPvpStateUpdate(pCurrChar,true); + pCurrChar->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + } if (pCurrChar->HasPlayerFlag(PLAYER_FLAGS_CONTESTED_PVP)) { diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index e3d8912ea..ed96dfd1a 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -772,8 +772,14 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recv_data) player->SetRestFlag(REST_FLAG_IN_TAVERN, atEntry->entry); if (sWorld->IsFFAPvPRealm()) - player->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + { + if (player->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + { + player->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + sScriptMgr->OnFfaPvpStateUpdate(player, false); + } + } return; } diff --git a/src/server/game/Scripting/ScriptDefines/CreatureScript.cpp b/src/server/game/Scripting/ScriptDefines/CreatureScript.cpp index 1bbc61f97..aadf276f1 100644 --- a/src/server/game/Scripting/ScriptDefines/CreatureScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/CreatureScript.cpp @@ -170,6 +170,15 @@ CreatureAI* ScriptMgr::GetCreatureAI(Creature* creature) return tempScript ? tempScript->GetAI(creature) : nullptr; } +//Fires whenever the UNIT_BYTE2_FLAG_FFA_PVP bit is Changed on the player +void ScriptMgr::OnFfaPvpStateUpdate(Creature* creature, bool InPvp) +{ + ExecuteScript([&](AllCreatureScript* script) + { + script->OnFfaPvpStateUpdate(creature, InPvp); + }); +} + void ScriptMgr::OnCreatureUpdate(Creature* creature, uint32 diff) { ASSERT(creature); diff --git a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp index 756231338..a8794e821 100644 --- a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp @@ -1263,6 +1263,7 @@ void ScriptMgr::OnGetArenaTeamId(Player* player, uint8 slot, uint32& result) }); } +//Signifies that IsFfaPvp has been called. void ScriptMgr::OnIsFFAPvP(Player* player, bool& result) { ExecuteScript([&](PlayerScript* script) @@ -1270,6 +1271,14 @@ void ScriptMgr::OnIsFFAPvP(Player* player, bool& result) script->OnIsFFAPvP(player, result); }); } +//Fires whenever the UNIT_BYTE2_FLAG_FFA_PVP bit is Changed +void ScriptMgr::OnFfaPvpStateUpdate(Player* player, bool result) +{ + ExecuteScript([&](PlayerScript* script) + { + script->OnFfaPvpStateUpdate(player, result); + }); +} void ScriptMgr::OnIsPvP(Player* player, bool& result) { diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 57913d695..c84a6dfae 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -619,6 +619,9 @@ public: // Called when a CreatureAI object is needed for the creature. [[nodiscard]] virtual CreatureAI* GetCreatureAI(Creature* /*creature*/) const { return nullptr; } + + //Called Whenever the UNIT_BYTE2_FLAG_FFA_PVP Bit is set on the creature + virtual void OnFfaPvpStateUpdate(Creature* /*creature*/, bool /*InPvp*/) {} }; class AllItemScript : public ScriptObject @@ -743,6 +746,10 @@ public: // Called when a CreatureAI object is needed for the creature. virtual CreatureAI* GetAI(Creature* /*creature*/) const { return nullptr; } + + //Called whenever the UNIT_BYTE2_FLAG_FFA_PVP bit is Changed on the player + virtual void OnFfaPvpStateUpdate(Creature* /*player*/, bool /*result*/) { } + }; class GameObjectScript : public ScriptObject, public UpdatableScript @@ -1307,6 +1314,9 @@ public: virtual void OnIsFFAPvP(Player* /*player*/, bool& /*result*/) { } + //Fires whenever the UNIT_BYTE2_FLAG_FFA_PVP bit is Changed on the player + virtual void OnFfaPvpStateUpdate(Player* /*player*/, bool /*result*/) { } + virtual void OnIsPvP(Player* /*player*/, bool& /*result*/) { } virtual void OnGetMaxSkillValueForLevel(Player* /*player*/, uint16& /*result*/) { } @@ -2127,6 +2137,7 @@ public: /* CreatureScript */ void OnCreatureUpdate(Creature* creature, uint32 diff); void OnCreatureAddWorld(Creature* creature); void OnCreatureRemoveWorld(Creature* creature); + void OnFfaPvpStateUpdate(Creature* creature, bool InPvp); public: /* GameObjectScript */ bool OnGossipHello(Player* player, GameObject* go); @@ -2324,6 +2335,7 @@ public: /* PlayerScript */ bool NotAvoidSatisfy(Player* player, DungeonProgressionRequirements const* ar, uint32 target_map, bool report); bool NotVisibleGloballyFor(Player* player, Player const* u); void OnGetArenaPersonalRating(Player* player, uint8 slot, uint32& result); + void OnFfaPvpStateUpdate(Player* player, bool result); void OnGetArenaTeamId(Player* player, uint8 slot, uint32& result); void OnIsFFAPvP(Player* player, bool& result); void OnIsPvP(Player* player, bool& result);