diff --git a/source/Core.hpp b/source/Core.hpp index 52a79b3f..a22e0abc 100644 --- a/source/Core.hpp +++ b/source/Core.hpp @@ -422,6 +422,7 @@ protected: Function mOnHeading; Function mOnPosition; Function mOnOption; + Function mOnAdmin; }; /* -------------------------------------------------------------------------------------------- @@ -992,6 +993,7 @@ public: void EmitPlayerHeading(Int32 player_id, Float32 old_heading, Float32 new_heading); void EmitPlayerPosition(Int32 player_id); void EmitPlayerOption(Int32 player_id, Int32 option_id, bool value, Int32 header, Object & payload); + void EmitPlayerAdmin(Int32 player_id, bool old_admin, bool new_admin); void EmitVehicleColour(Int32 vehicle_id, Int32 changed); void EmitVehicleHealth(Int32 vehicle_id, Float32 old_health, Float32 new_health); void EmitVehiclePosition(Int32 vehicle_id); @@ -1129,6 +1131,7 @@ private: Function mOnPlayerHeading; Function mOnPlayerPosition; Function mOnPlayerOption; + Function mOnPlayerAdmin; Function mOnVehicleColour; Function mOnVehicleHealth; Function mOnVehiclePosition; diff --git a/source/CoreEvents.cpp b/source/CoreEvents.cpp index 8d484f30..b91a2a0c 100644 --- a/source/CoreEvents.cpp +++ b/source/CoreEvents.cpp @@ -725,6 +725,14 @@ void Core::EmitPlayerOption(Int32 player_id, Int32 option_id, bool value, Emit(mOnPlayerOption, _player.mObj, option_id, value, header, payload); } +// ------------------------------------------------------------------------------------------------ +void Core::EmitPlayerAdmin(Int32 player_id, bool old_admin, bool new_admin) +{ + PlayerInst & _player = m_Players.at(player_id); + Emit(_player.mOnAdmin, old_admin, new_admin); + Emit(mOnPlayerAdmin, _player.mObj, old_admin, new_admin); +} + // ------------------------------------------------------------------------------------------------ void Core::EmitVehicleColour(Int32 vehicle_id, Int32 changed) { diff --git a/source/CoreUtils.cpp b/source/CoreUtils.cpp index 10a57cee..b0c635b0 100644 --- a/source/CoreUtils.cpp +++ b/source/CoreUtils.cpp @@ -227,6 +227,7 @@ void Core::ResetFunc(PlayerInst & inst) inst.mOnHeading.ReleaseGently(); inst.mOnPosition.ReleaseGently(); inst.mOnOption.ReleaseGently(); + inst.mOnAdmin.ReleaseGently(); } // ------------------------------------------------------------------------------------------------ @@ -341,6 +342,7 @@ void Core::ResetFunc() Core::Get().mOnPlayerHeading.ReleaseGently(); Core::Get().mOnPlayerPosition.ReleaseGently(); Core::Get().mOnPlayerOption.ReleaseGently(); + Core::Get().mOnPlayerAdmin.ReleaseGently(); Core::Get().mOnVehicleColour.ReleaseGently(); Core::Get().mOnVehicleHealth.ReleaseGently(); Core::Get().mOnVehiclePosition.ReleaseGently(); @@ -447,6 +449,7 @@ Function & Core::GetEvent(Int32 evid) case EVT_PLAYERHEADING: return mOnPlayerHeading; case EVT_PLAYERPOSITION: return mOnPlayerPosition; case EVT_PLAYEROPTION: return mOnPlayerOption; + case EVT_PLAYERADMIN: return mOnPlayerAdmin; case EVT_VEHICLECOLOUR: return mOnVehicleColour; case EVT_VEHICLEHEALTH: return mOnVehicleHealth; case EVT_VEHICLEPOSITION: return mOnVehiclePosition; @@ -603,6 +606,7 @@ Function & Core::GetPlayerEvent(Int32 id, Int32 evid) case EVT_PLAYERHEADING: return inst.mOnHeading; case EVT_PLAYERPOSITION: return inst.mOnPosition; case EVT_PLAYEROPTION: return inst.mOnOption; + case EVT_PLAYERADMIN: return inst.mOnAdmin; default: return NullFunction(); } } diff --git a/source/Entity/Player.cpp b/source/Entity/Player.cpp index af26f4b9..06150c07 100644 --- a/source/Entity/Player.cpp +++ b/source/Entity/Player.cpp @@ -194,12 +194,27 @@ bool CPlayer::GetAdmin() const } // ------------------------------------------------------------------------------------------------ -void CPlayer::SetAdmin(bool toggle) const +void CPlayer::SetAdmin(bool toggle) { // Validate the managed identifier Validate(); - // Perform the requested operation + // Grab the current value for this property + const bool current = _Func->IsPlayerAdmin(m_ID); + // Don't even bother if it's the same value + if (current == toggle) + { + return; + } + // Avoid property unwind from a recursive call _Func->SetPlayerAdmin(m_ID, toggle); + // Avoid infinite recursive event loops + if (!(m_CircularLocks & PCL_EMIT_PLAYER_ADMIN)) + { + // Prevent this event from triggering while executed + BitGuardU32 bg(m_CircularLocks, PCL_EMIT_PLAYER_ADMIN); + // Now forward the event call + Core::Get().EmitPlayerAdmin(m_ID, current, toggle); + } } // ------------------------------------------------------------------------------------------------ diff --git a/source/Entity/Player.hpp b/source/Entity/Player.hpp index 9b2b8332..95d5cf4b 100644 --- a/source/Entity/Player.hpp +++ b/source/Entity/Player.hpp @@ -13,7 +13,8 @@ namespace SqMod { */ enum PlayerCircularLocks { - PCL_EMIT_PLAYER_OPTION = (1 << 0) + PCL_EMIT_PLAYER_OPTION = (1 << 0) + PCL_EMIT_PLAYER_ADMIN = (2 << 0), }; /* ------------------------------------------------------------------------------------------------ @@ -248,7 +249,7 @@ public: /* -------------------------------------------------------------------------------------------- * Set whether the managed player entity has administrator privileges. */ - void SetAdmin(bool toggle) const; + void SetAdmin(bool toggle); /* -------------------------------------------------------------------------------------------- * Retrieve the ip address of the managed player entity. diff --git a/source/SqBase.hpp b/source/SqBase.hpp index ed91b147..8e437d02 100644 --- a/source/SqBase.hpp +++ b/source/SqBase.hpp @@ -376,6 +376,7 @@ enum EventType EVT_PLAYERHEADING, EVT_PLAYERPOSITION, EVT_PLAYEROPTION, + EVT_PLAYERADMIN, EVT_VEHICLECOLOUR, EVT_VEHICLEHEALTH, EVT_VEHICLEPOSITION,