diff --git a/source/Core.hpp b/source/Core.hpp index c18bde23..d4779df1 100644 --- a/source/Core.hpp +++ b/source/Core.hpp @@ -303,6 +303,7 @@ protected: Function mOnRespawn; Function mOnClaimed; Function mOnCollected; + Function mOnWorld; }; /* -------------------------------------------------------------------------------------------- @@ -1011,6 +1012,7 @@ public: void EmitCheckpointRadius(Int32 checkpoint_id, Float32 old_radius, Float32 new_radius); void EmitObjectWorld(Int32 object_id, Int32 old_world, Int32 new_world); void EmitObjectAlpha(Int32 object_id, Int32 old_alpha, Int32 new_alpha, Int32 time); + void EmitPickupWorld(Int32 pickup_id, Int32 old_world, Int32 new_world); void EmitObjectReport(Int32 object_id, bool old_status, bool new_status, bool touched); void EmitPlayerHealth(Int32 player_id, Float32 old_health, Float32 new_health); void EmitPlayerArmour(Int32 player_id, Float32 old_armour, Float32 new_armour); @@ -1162,6 +1164,7 @@ private: Function mOnPickupClaimed; Function mOnPickupCollected; Function mOnPickupRespawn; + Function mOnPickupWorld; Function mOnCheckpointEntered; Function mOnCheckpointExited; Function mOnCheckpointWorld; diff --git a/source/CoreEvents.cpp b/source/CoreEvents.cpp index c26b60c8..a4009a50 100644 --- a/source/CoreEvents.cpp +++ b/source/CoreEvents.cpp @@ -708,6 +708,14 @@ void Core::EmitObjectAlpha(Int32 object_id, Int32 old_alpha, Int32 new_alpha, In Emit(mOnObjectAlpha, _object.mObj, old_alpha, new_alpha, time); } +// ------------------------------------------------------------------------------------------------ +void Core::EmitPickupWorld(Int32 pickup_id, Int32 old_world, Int32 new_world) +{ + PickupInst & _pickup = m_Pickups.at(pickup_id); + Emit(_pickup.mOnRespawn, old_world, new_world); + Emit(mOnPickupRespawn, _pickup.mObj, old_world, new_world); +} + // ------------------------------------------------------------------------------------------------ void Core::EmitObjectReport(Int32 object_id, bool old_status, bool new_status, bool touched) { diff --git a/source/CoreUtils.cpp b/source/CoreUtils.cpp index 4d48e139..4b141359 100644 --- a/source/CoreUtils.cpp +++ b/source/CoreUtils.cpp @@ -165,6 +165,7 @@ void Core::ResetFunc(PickupInst & inst) inst.mOnRespawn.ReleaseGently(); inst.mOnClaimed.ReleaseGently(); inst.mOnCollected.ReleaseGently(); + inst.mOnWorld.ReleaseGently(); } // ------------------------------------------------------------------------------------------------ @@ -222,6 +223,7 @@ void Core::ResetFunc(PlayerInst & inst) inst.mOnObjectTouched.ReleaseGently(); inst.mOnPickupClaimed.ReleaseGently(); inst.mOnPickupCollected.ReleaseGently(); + inst.mOnPickupCollected.ReleaseGently(); inst.mOnCheckpointEntered.ReleaseGently(); inst.mOnCheckpointExited.ReleaseGently(); inst.mOnClientScriptData.ReleaseGently(); @@ -352,6 +354,7 @@ void Core::ResetFunc() Core::Get().mOnObjectReport.ReleaseGently(); Core::Get().mOnPickupClaimed.ReleaseGently(); Core::Get().mOnPickupCollected.ReleaseGently(); + Core::Get().mOnPickupWorld.ReleaseGently(); Core::Get().mOnPickupRespawn.ReleaseGently(); Core::Get().mOnCheckpointEntered.ReleaseGently(); Core::Get().mOnCheckpointExited.ReleaseGently(); @@ -479,6 +482,7 @@ Function & Core::GetEvent(Int32 evid) case EVT_OBJECTREPORT: return mOnObjectReport; case EVT_PICKUPCLAIMED: return mOnPickupClaimed; case EVT_PICKUPCOLLECTED: return mOnPickupCollected; + case EVT_PICKUPWORLD: return mOnPickupWorld; case EVT_PICKUPRESPAWN: return mOnPickupRespawn; case EVT_CHECKPOINTENTERED: return mOnCheckpointEntered; case EVT_CHECKPOINTEXITED: return mOnCheckpointExited; @@ -598,6 +602,7 @@ Function & Core::GetPickupEvent(Int32 id, Int32 evid) case EVT_PICKUPRESPAWN: return inst.mOnRespawn; case EVT_PICKUPCLAIMED: return inst.mOnClaimed; case EVT_PICKUPCOLLECTED: return inst.mOnCollected; + case EVT_PICKUPWORLD: return inst.mOnWorld; default: return NullFunction(); } } diff --git a/source/Entity/Pickup.cpp b/source/Entity/Pickup.cpp index 4b4c9c53..89f119a6 100644 --- a/source/Entity/Pickup.cpp +++ b/source/Entity/Pickup.cpp @@ -37,7 +37,7 @@ Object & CPickup::GetNull() // ------------------------------------------------------------------------------------------------ CPickup::CPickup(Int32 id) : m_ID(VALID_ENTITYGETEX(id, SQMOD_PICKUP_POOL)) - , m_Tag(ToStrF("%d", id)) + , m_Tag(ToStrF("%d", id)), m_Data(), m_CircularLocks(0) { /* ... */ } @@ -167,12 +167,27 @@ Int32 CPickup::GetWorld() const } // ------------------------------------------------------------------------------------------------ -void CPickup::SetWorld(Int32 world) const +void CPickup::SetWorld(Int32 world) { // Validate the managed identifier Validate(); - // Perform the requested operation + // Grab the current value for this property + const Int32 current = _Func->GetPickupWorld(m_ID); + // Don't even bother if it's the same value + if (current == world) + { + return; + } + // Avoid property unwind from a recursive call _Func->SetPickupWorld(m_ID, world); + // Avoid infinite recursive event loops + if (!(m_CircularLocks & PICKUPCL_EMIT_PICKUP_WORLD)) + { + // Prevent this event from triggering while executed + BitGuardU32 bg(m_CircularLocks, PICKUPCL_EMIT_PICKUP_WORLD); + // Now forward the event call + Core::Get().EmitPickupWorld(m_ID, current, world); + } } // ------------------------------------------------------------------------------------------------ diff --git a/source/Entity/Pickup.hpp b/source/Entity/Pickup.hpp index bee1fa0a..d5a6ed77 100644 --- a/source/Entity/Pickup.hpp +++ b/source/Entity/Pickup.hpp @@ -7,6 +7,14 @@ // ------------------------------------------------------------------------------------------------ namespace SqMod { +/* ------------------------------------------------------------------------------------------------ + * Circular locks employed by the pickup manager. +*/ +enum PickupCircularLocks +{ + PICKUPCL_EMIT_PICKUP_WORLD = (1 << 0) +}; + /* ------------------------------------------------------------------------------------------------ * Manages a single pickup entity. */ @@ -35,6 +43,11 @@ private: */ Object m_Data; + /* -------------------------------------------------------------------------------------------- + * Prevent events from triggering themselves. + */ + Uint32 m_CircularLocks; + /* -------------------------------------------------------------------------------------------- * Base constructor. */ @@ -188,7 +201,7 @@ public: /* -------------------------------------------------------------------------------------------- * Mpdify the world in which the managed pickup entity exists. */ - void SetWorld(Int32 world) const; + void SetWorld(Int32 world); /* -------------------------------------------------------------------------------------------- * Retrieve the alpha of the managed pickup entity.