123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619 |
- //! Enum to determine what type of effect the Effect is
- enum EffectType
- {
- //! Plain Effect base
- NONE,
- //! EffectSound
- SOUND,
- //! EffectParticle
- PARTICLE,
- }
- /**
- \brief Base wrapper class for managing effects (Particles, Sound) through SEffectManager
- \note This is just a base class, not intended for direct usage
- */
- class Effect : Managed
- {
- /** \name Event invokers
- * ScriptInvonkers for certain events
- */
- //@{
- ref ScriptInvoker Event_OnStarted = new ScriptInvoker();
- ref ScriptInvoker Event_OnStopped = new ScriptInvoker();
- ref ScriptInvoker Event_OnEffectStarted = new ScriptInvoker();
- ref ScriptInvoker Event_OnEffectEnded = new ScriptInvoker();
- //@}
-
- /** \name Generic data
- * Generic data for the Effect
- */
- //@{
- //! Whether the Effect cleans up after itself when stopped
- protected bool m_IsAutodestroy;
- //! Whether the Destroy process has already been called
- protected bool m_IsPendingDeletion;
- //! Whether the Effect is currently playing
- protected bool m_IsPlaying;
- //! Cached parent
- protected Object m_ParentObject;
- //! Cached world position
- protected vector m_Position;
- //@}
-
- /** \name SEffectManager data
- * Data filled in by SEffectManager to identify it when it is registered
- */
- //@{
- //! ID of effect, given by SEffectManager when registered (automatically done when playing through it)
- protected int m_ID;
- //! Whether the effect is registered in SEffectManager
- protected bool m_IsRegistered;
- //@}
-
- /** \name Attachment data
- * Cached settings set through 'SetAttachment...' methods
- * Does not necessarily reflect the current state when EffectParticle
- */
- //@{
- //! Cached local pos
- protected vector m_LocalPos;
- //! Local orientation set by SetAttachedLocalOri, only used by EffectParticle
- protected vector m_LocalOri;
- //@}
-
-
-
- /**
- \brief ctor
- */
- void Effect()
- {
- if (GetGame().IsDedicatedServer())
- {
- ErrorEx("Created Effect on server.", ErrorExSeverity.WARNING);
- }
-
- m_IsPlaying = false;
-
- InitEffect();
- }
-
- /**
- \brief dtor
- */
- void ~Effect()
- {
- // Safety
- if ( IsRegistered() )
- SEffectManager.EffectUnregister(GetID());
-
- // Certain effects need to be stopped to clean up properly
- Stop();
-
- // Another safety
- SetEnableEventFrame(false);
- }
-
- /**
- \brief init
- */
- void InitEffect()
- {
- Event_OnStarted.Insert(Event_OnEffectStarted);
- Event_OnStarted.Insert(ValidateStart);
- Event_OnStopped.Insert(Event_OnEffectEnded);
- }
-
-
- /** \name EffectType
- Information about what type of effect the Effect is, without the need for casting
- */
- //@{
-
- /**
- \brief Get what type of effect the Effect is
- \return \p EffectType What type of effect the Effect is
- */
- EffectType GetEffectType()
- {
- return EffectType.NONE;
- }
-
- /**
- \brief Check whether the Effect is EffectSound without casting
- \return \p bool Whether the Effect is EffectSound
- */
- bool IsSound()
- {
- return false;
- }
-
- /**
- \brief Check whether the Effect is EffectParticle without casting
- \return \p bool Whether the Effect is EffectParticle
- */
- bool IsParticle()
- {
- return false;
- }
-
- //@}
-
-
-
- /** \name Playback
- * Methods to Play/Stop Effect
- * Generally, SEffectManager.Play methods are used instead of Start
- */
- //@{
-
- /**
- \brief Plays all elements this effects consists of
- \note Is called by SEffectManager.Play methods
- */
- void Start()
- {
- // It is already playing!
- if (IsPlaying())
- return;
-
- Event_OnStarted();
- // I can't call this from inside the method with same name
- // because that method is often overriden without super......
- Event_OnStarted.Invoke(this);
- }
-
- /**
- \brief Validation whether an effect truly started playing or if the Effect should stop as none is present
- \note Override this when inheriting to create own validation check
- \note Is called from Event_OnStarted invoker after Event_OnStarted has been performed
- */
- void ValidateStart()
- {
-
- }
-
- /**
- \brief Stops all elements this effect consists of
- \note Alternatively use SEffectManager.Stop( effect_id )
- */
- void Stop()
- {
- // It is not playing!
- if (!IsPlaying())
- return;
-
- Event_OnStopped();
- // Yes, that event is new, but let's keep up some consistency
- Event_OnStopped.Invoke(this);
- }
-
- /**
- \brief Returns true when the Effect is playing, false otherwise
- */
- bool IsPlaying()
- {
- return m_IsPlaying;
- }
-
- //@}
-
-
-
- /** \name Destroy
- Methods regarding automatic cleanup
- */
- //@{
-
- /**
- \brief Cleans up the Effect, including unregistering if needed
- \note Will stop the Effect and queue up the deletion in the callqueue
- \note Is intended for usage from within the Effect itself, use SEffectManager.DestroyEffect when working from a pointer
- */
- protected void Destroy()
- {
- // Already queued
- if (IsPendingDeletion())
- return;
-
- // Mark it to prevent queuing it up multiple times or get stuck in a call loop
- m_IsPendingDeletion = true;
-
- // Stop it, so that the effects can clean up themselves
- // Since if for example this is EffectParticle and the particle is looping
- // It NEEDS to be stopped to clean up the Particle
- Stop();
-
- // Queue up the destroying, as we should not do it while we are accessing it here
- if (GetGame())
- {
- GetGame().GetCallQueue(CALL_CATEGORY_GAMEPLAY).Call(SEffectManager.DestroyEffect, this);
- }
- }
-
- /**
- \brief Sets whether Effect automatically cleans up when it stops
- \note This means that it will be unregistered from SEffectManager as well
- \param auto_destroy \p bool Whether Effect automatically cleans up when it stops
- */
- void SetAutodestroy(bool auto_destroy)
- {
- m_IsAutodestroy = auto_destroy;
- }
-
- /**
- \brief Get whether Effect automatically cleans up when it stops
- \return \p bool Whether Effect automatically cleans up when it stops
- */
- bool IsAutodestroy()
- {
- return m_IsAutodestroy;
- }
-
- /**
- \brief Get whether the Effect is queued up for being cleaned up
- \return \p bool Whether the Effect is queued up for being cleaned up
- */
- bool IsPendingDeletion()
- {
- return m_IsPendingDeletion;
- }
-
- /**
- \brief Get whether the Effect can be destroyed right now
- \return \p bool Whether the Effect can be destroyed right now
- */
- bool CanDestroy()
- {
- return true;
- }
-
- //@}
-
-
-
- /**
- \brief Enable Event_OnFrameUpdate for the effect
- \note Read SEffectManager.Event_OnFrameUpdate for more info
- */
- void SetEnableEventFrame(bool enable)
- {
- if ( enable )
- {
- SEffectManager.Event_OnFrameUpdate.Insert(Event_OnFrameUpdate);
- }
- else
- {
- SEffectManager.Event_OnFrameUpdate.Remove(Event_OnFrameUpdate);
- }
- }
-
-
-
- /** \name Events
- Various events that can be overriden for custom behaviour
- */
- //@{
-
- /**
- \brief Event used when Start was called
- */
- void Event_OnStarted()
- {
- // Override this method for own use
- }
-
- /**
- \brief Event used when Stop was called
- */
- void Event_OnStopped()
- {
- // Override this method for own use
- }
-
- /**
- \brief Event used when the actual effect started playing
- */
- void Event_OnEffectStarted()
- {
- m_IsPlaying = true;
-
- Event_OnEffectStarted.Invoke(this);
- }
-
- /**
- \brief Event used when the actual effect stopped playing
- */
- void Event_OnEffectEnded()
- {
- m_IsPlaying = false;
-
- Event_OnEffectEnded.Invoke(this);
-
- if ( IsAutodestroy() )
- {
- Destroy();
- }
- }
-
- /**
- \brief Event called on frame when enabled by SetEnableEventFrame(true)
- \note Called from SEffectManager.Event_OnFrameUpdate in MissionGameplay.OnUpdate
- \param time_delta \p float Time passed since the previous frame
- */
- void Event_OnFrameUpdate(float time_delta)
- {
- // Override this method for own use
- }
-
- /**
- \brief Event called from SEffectManager when the Effect is registered
- \note Should only ever be called by SEffectManager!
- \param id \p int ID registered in SEffectManager
- */
- void Event_OnRegistered(int id)
- {
- SetID(id);
- m_IsRegistered = true;
- }
-
- /**
- \brief Event called from SEffectManager when the Effect is unregistered
- \note Should only ever be called by SEffectManager!
- */
- void Event_OnUnregistered()
- {
- SetID(SEffectManager.INVALID_ID);
- m_IsRegistered = false;
- }
-
- /**
- \brief Event used when EffectParticle.CheckLifeSpan was called (DEPRECATED)
- \note So this is EffectParticle specific...
- \note EffectParticle.CheckLifeSpan is currently not in use
- */
- void OnCheckUpdate()
- {
- }
-
- //@}
-
-
-
- /** \name Generic API
- Setters and getters for generic data and properties
- */
- //@{
-
- /**
- \brief Set parent of the Effect
- \note Same as SetAttachmentParent, but more generic name
- \warning Only sets the cached variable, for immediate effect use SetCurrent variant
- \param parent_obj \p Object The parent for the Effect
- */
- void SetParent(Object parent_obj)
- {
- m_ParentObject = parent_obj;
- }
-
- /**
- \brief Get parent of the Effect
- \note Same as GetAttachmentParent, but more generic name
- \warning Only gets the cached variable, for immediate effect use GetCurrent variant
- \return \p Object The parent of the Effect
- */
- Object GetParent()
- {
- return m_ParentObject;
- }
-
- /**
- \brief Set current parent of the managed effect
- \note Same as SetAttachmentParent, but more generic name
- \param parent_obj \p Object The parent for the Effect
- \param updateCached \p bool Whether to update the cached variable
- */
- void SetCurrentParent( Object parent_obj, bool updateCached = true )
- {
- if (updateCached)
- SetParent(parent_obj);
- }
-
- /**
- \brief Get the current parent of the managed Effect
- \return \p Object The current parent of the managed Effect
- */
- Object GetCurrentParent()
- {
- return null;
- }
-
- /**
- \brief Set the world position of the Effect
- \warning Only sets the cached variable, for immediate effect use SetCurrent variant
- \param pos \p vector The world position for the Effect
- */
- void SetPosition( vector pos )
- {
- m_Position = pos;
- }
- /**
- \brief Get the world position of the Effect
- \warning Only gets the cached variable, for immediate effect use GetCurrent variant
- \return \p vector The world position of the Effect
- */
- vector GetPosition()
- {
- return m_Position;
- }
-
- /**
- \brief Set the current world position of the managed effect
- \param pos \p vector The current world position for the Effect
- \param updateCached \p bool Whether to update the cached variable
- */
- void SetCurrentPosition( vector pos, bool updateCached = true )
- {
- if (updateCached)
- SetPosition(pos);
- }
-
- /**
- \brief Get the current world position of the managed effect
- \return \p vector The current world position of the managed effect
- */
- vector GetCurrentPosition()
- {
- return vector.Zero;
- }
-
- /**
- \brief Set the local position of the Effect
- \warning Only sets the cached variable, for immediate effect use SetCurrent variant
- \param pos \p vector The local position for the Effect
- */
- void SetLocalPosition( vector pos )
- {
- m_LocalPos = pos;
- }
- /**
- \brief Get the local position of the Effect
- \warning Only gets the cached variable, for immediate effect use GetCurrent variant
- \return \p vector The lcoal position of the Effect
- */
- vector GetLocalPosition()
- {
- return m_LocalPos;
- }
-
- /**
- \brief Set the current local position of the managed effect
- \param pos \p vector The current local position for the managed effect
- \param updateCached \p bool Whether to update the cached variable
- */
- void SetCurrentLocalPosition( vector pos, bool updateCached = true )
- {
- if (updateCached)
- SetLocalPosition(pos);
- }
- /**
- \brief Get the current local position of the managed effect
- \return \p vector The current local position of the managed effect
- */
- vector GetCurrentLocalPosition()
- {
- return vector.Zero;
- }
-
- //@}
-
-
-
- /** \name Effect ID
- The ID of the effect when registered in SEffectManager
- */
- //@{
-
- /**
- \brief Set the ID registered in SEffectManager
- \note Should only ever be called by Event_OnRegistered!
- \param id \p int ID registered in SEffectManager
- */
- protected void SetID(int id)
- {
- m_ID = id;
- }
-
- /**
- \brief Get the ID registered in SEffectManager
- \return \p int ID registered in SEffectManager, or 0 (SEffectManager.INVALID_ID) when not registered
- */
- int GetID()
- {
- return m_ID;
- }
-
- /**
- \brief Get whether this Effect is registered in SEffectManager
- \return \p bool Whether this Effect is registered in SEffectManager
- */
- bool IsRegistered()
- {
- return m_IsRegistered;
- }
-
- //@}
-
-
-
- /** \name Attachment API
- * Data to attach an Effect to a parent
- * Mostly replaced by equivalents without 'Attachment' in name
- * Mildly deprecated, exist for backwards compatibility
- */
- //@{
-
- /**
- \brief Set parent for the Effect
- \param obj \p Object The parent for the Effect
- */
- void SetAttachmentParent(Object obj)
- {
- SetParent(obj);
- }
-
- /**
- \brief Get the parent set by SetAttachmentParent
- \return \p Object The parent set by SetAttachmentParent
- */
- Object GetAttachmentParent()
- {
- return GetParent();
- }
-
- /**
- \brief Set local pos for the Effect relative to the parent
- \param pos \p vector The local pos relative to the parent
- */
- void SetAttachedLocalPos(vector pos)
- {
- SetLocalPosition(pos);
- }
-
- /**
- \brief Get the local pos set by SetAttachedLocalPos
- \return \p vector The local pos set by SetAttachedLocalPos
- */
- vector GetAttachedLocalPos()
- {
- return GetLocalPosition();
- }
-
- /**
- \brief Set local orientation for the Effectparticle to attach to when the Effect is started
- \warning Only caches it into a variable to be used by Start, does not live update when called afterwards
- \note Overrides the orientation set by EffectParticle.SetOrientation
- \param ori \p vector The local orientation to use on Start
- */
- void SetAttachedLocalOri(vector ori)
- {
- m_LocalOri = ori;
- }
-
- /**
- \brief Get the local orientation set by SetAttachedLocalOri
- \warning Is not necessarily the current local orientation
- \return \p vector The local orientation set by SetAttachedLocalOri
- */
- vector GetAttachedLocalOri()
- {
- return m_LocalOri;
- }
-
- //@}
- }
|