Special Effects Memory Management

Level 16
Joined
Feb 22, 2025
Messages
315
Update: I found some systems and guides on how to remove effects after a delay but I’m not sure how to implement the solution/s in this specific situation

For starters I’d like to say that I’m aware that special effects attached to removed units still do leak if we do not destroy them.

But I’ve encountered a specific situation where If I would destroy them right after creating them the effect wouldn’t show( probably due to not having a death animation).
Another problematic part is that effects used for the spell are created in two separate triggers that are using variables from loop trigger for the spell, which I’m aware could mess up with MUI. I was thinking of using a hashtable to store variables then load them in special effect triggers. I’m really cornered here on how to approach this matter without breaking the current visual i managed to create( the video is on the end of the post).
PS. I’m aware of waits, they’ll be replaced with timers, but again I feel that those 2 triggers for special effects could be managed differently, possibly removed if there is a way to integrate them into a loop without removing them instantly.) Basically I’m not sure what logic to use to manage effects that are created in loops that are in other loops. The effect in question is ephemeral slash. Any suggestion is welcome, regards!

  • SM Ini
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set SM_Visual_Dummy = Sylvanas Shadow Clone
  • Shadow Massacre Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Shadow Massacre (Neutral Hostile)
    • Actions
      • -------- get free instance --------
      • Set SM_TempInteger = 0
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SM_Recycle_Count Greater than 0
        • Then - Actions
          • Set SM_TempInteger = SM_Recycle_Stack[SM_Recycle_Count]
          • Set SM_Recycle_Count = (SM_Recycle_Count - 1)
        • Else - Actions
          • Set SM_Index = (SM_Index + 1)
          • Set SM_TempInteger = SM_Index
      • -------- store --------
      • Set SM_Caster[SM_TempInteger] = (Triggering unit)
      • Set SM_Strikes_Remaining[SM_TempInteger] = 7
      • Set SM_Active[SM_TempInteger] = True
      • Unit - Make SM_Caster[SM_TempInteger] Invulnerable
      • Unit - Pause SM_Caster[SM_TempInteger]
      • Selection - Remove SM_Caster[SM_TempInteger] from selection for (Owner of SM_Caster[SM_TempInteger])
      • Set SM_TempPoint = (Position of SM_Caster[SM_TempInteger])
      • Special Effect - Create a special effect at SM_TempPoint using Abilities\Spells\NightElf\shadowstrike\ShadowStrikeMissile.mdl
      • Special Effect - Destroy (Last created special effect)
      • Special Effect - Create a special effect at SM_TempPoint using world_expansion08_doodads_fx_9fx_raid2_sylvanas_dissolvecover.mdl
      • Set SM_Vanish_SFX[SM_TempInteger] = (Last created special effect)
      • Unit - Hide SM_Caster[SM_TempInteger]
      • Unit - Create 1 Sylvanas Shadow Clone for (Owner of SM_Caster[SM_TempInteger]) at SM_TempPoint facing Default building facing degrees
      • Set SM_Dummy[SM_TempInteger] = (Last created unit)
      • Unit - Pause SM_Dummy[SM_TempInteger]
      • Animation - Play SM_Dummy[SM_TempInteger]'s attack slam first animation
      • Special Effect - Create a special effect attached to the chest of SM_Dummy[SM_TempInteger] using Ephemeral Slash Purple.mdx
      • Special Effect - Set Orientation of (Last created special effect) to yaw: 200.00, pitch: 0.00, roll: 0.00
      • Special Effect - Destroy (Last created special effect)
      • Special Effect - Create a special effect attached to the chest of SM_Dummy[SM_TempInteger] using Abilities\Spells\NightElf\shadowstrike\ShadowStrikeMissile.mdl
      • Special Effect - Destroy (Last created special effect)
      • Custom script: call RemoveLocation( udg_SM_TempPoint)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SM_Index Equal to 1
        • Then - Actions
          • Trigger - Turn on SM Loop <gen>
        • Else - Actions
  • SM Loop
    • Events
      • Time - Every 0.33 seconds of game time
    • Conditions
    • Actions
      • For each (Integer SM_LoopIndex) from 1 to SM_Index, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • SM_Active[SM_LoopIndex] Equal to True
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • SM_Strikes_Remaining[SM_LoopIndex] Greater than 0
                • Then - Actions
                  • Set SM_TempPoint = (Position of SM_Dummy[SM_LoopIndex])
                  • Set SM_TempGroup = (Units within 800.00 of SM_TempPoint matching ((((Matching unit) belongs to an enemy of (Owner of SM_Caster[SM_LoopIndex]).) Equal to True) and ((((Matching unit) is alive) Equal to True) and (((Matching unit) is hidden) Equal to False))).)
                  • Set SM_TempUnit = (Random unit from SM_TempGroup)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • SM_TempUnit Not equal to No unit
                    • Then - Actions
                      • Set SM_TempPoint2 = (Position of SM_TempUnit)
                      • Unit - Move SM_Dummy[SM_LoopIndex] instantly to SM_TempPoint2, facing Default building facing degrees
                      • Animation - Play SM_Dummy[SM_LoopIndex]'s attack slam first animation
                      • Unit - Cause SM_Caster[SM_LoopIndex] to damage SM_TempUnit, dealing (Random real number between 300.00 and 400.00) damage of attack type Normal and damage type Normal
                      • Trigger - Turn on DR SE 2 <gen>
                      • Trigger - Turn on DR SE <gen>
                      • For each (Integer SM_Visual_Loop) from 1 to 2, do (Actions)
                        • Loop - Actions
                          • Set SM_TempReal = (Random real number between 0.00 and 250.00)
                          • Set SM_TempReal2 = (Random real number between 0.00 and 360.00)
                          • Set SM_TempPoint3 = ((Position of SM_TempUnit) offset by SM_TempReal towards SM_TempReal2 degrees.)
                          • Set SM_TempReal3 = (Random real number between 50.00 and 200.00)
                          • Unit - Create 1 SM_Visual_Dummy for (Owner of SM_Caster[SM_LoopIndex]) at SM_TempPoint3 facing SM_TempReal2 degrees
                          • Set SM_Visual_Dummy_Unit = (Last created unit)
                          • Unit - Add a (Random real number between 0.40 and 0.70) second Water Elemental expiration timer to SM_Visual_Dummy_Unit
                          • Unit - Add Crow Form to SM_Visual_Dummy_Unit
                          • Unit - Remove Crow Form from SM_Visual_Dummy_Unit
                          • Animation - Change SM_Visual_Dummy_Unit flying height to SM_TempReal3 at 0.00
                          • Special Effect - Create a special effect attached to the origin of SM_Visual_Dummy_Unit using Abilities\Weapons\AvengerMissile\AvengerMissile.mdl
                          • Special Effect - Destroy (Last created special effect)
                          • Special Effect - Create a special effect attached to the left arm of SM_Visual_Dummy_Unit using Ephemeral Cut Purple.mdl
                          • Special Effect - Destroy (Last created special effect)
                          • Set SM_TempReal = (Random real number between 0.80 and 1.50)
                          • Animation - Change SM_Visual_Dummy_Unit's animation speed to (SM_TempReal x 100.00)% of its original speed
                          • Animation - Play SM_Visual_Dummy_Unit's attack slam first animation
                          • Unit - Order SM_Visual_Dummy_Unit to Follow SM_Dummy[SM_LoopIndex]
                          • Custom script: call RemoveLocation( udg_SM_TempPoint3)
                    • Else - Actions
                      • Set SM_Strikes_Remaining[SM_LoopIndex] = 0
                  • Custom script: call DestroyGroup( udg_SM_TempGroup)
                  • Custom script: call RemoveLocation(udg_SM_TempPoint2)
                  • Custom script: call RemoveLocation(udg_SM_TempPoint)
                  • Set SM_Strikes_Remaining[SM_LoopIndex] = (SM_Strikes_Remaining[SM_LoopIndex] - 1)
                • Else - Actions
                  • Set SM_TempPoint = (Position of SM_Caster[SM_LoopIndex])
                  • Unit - Move SM_Dummy[SM_LoopIndex] instantly to SM_TempPoint, facing (Facing of SM_Dummy[SM_LoopIndex]) degrees
                  • Unit - Unhide SM_Caster[SM_LoopIndex]
                  • Unit - Make SM_Caster[SM_LoopIndex] Vulnerable
                  • Unit - Unpause SM_Caster[SM_LoopIndex]
                  • Selection - Add SM_Caster[SM_LoopIndex] to selection for (Owner of SM_Caster[SM_LoopIndex])
                  • Unit - Remove SM_Dummy[SM_LoopIndex] from the game
                  • Special Effect - Destroy SM_Vanish_SFX[SM_LoopIndex]
                  • Special Effect - Create a special effect attached to the chest of SM_Caster[SM_LoopIndex] using Abilities\Weapons\AvengerMissile\AvengerMissile.mdl
                  • Special Effect - Destroy (Last created special effect)
                  • Set SM_Active[SM_LoopIndex] = False
                  • Set SM_Strikes_Remaining[SM_LoopIndex] = 0
                  • Set SM_Recycle_Count = (SM_Recycle_Count + 1)
                  • Set SM_Recycle_Stack[SM_Recycle_Count] = SM_LoopIndex
                  • Custom script: call RemoveLocation( udg_SM_TempPoint)
            • Else - Actions
      • Set SM_TempInteger = 0
      • For each (Integer SM_LoopIndex) from 1 to SM_Index, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • SM_Active[SM_LoopIndex] Equal to True
            • Then - Actions
              • Set SM_TempInteger = (SM_TempInteger + 1)
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SM_TempInteger Equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
  • DR SE
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Set SM_SFX_P = (Position of SM_Visual_Dummy_Unit)
      • Special Effect - Create a special effect at SM_SFX_P using Ephemeral Slash Purple.mdx
      • Set DR_SE1 = (Last created special effect)
      • Special Effect - Set Time Scale of DR_SE1 to 1.00
      • Special Effect - Set Orientation of DR_SE1 to yaw: (Random real number between 100.00 and 200.00), pitch: (Random real number between 0.00 and 360.00), roll: (Random real number between 0.00 and 360.00)
      • Special Effect - Set Scale of DR_SE1 to (Random real number between 1.00 and 1.50)
      • Wait 0.10 seconds
      • Custom script: call RemoveLocation( udg_SM_SFX_P)
      • Trigger - Turn off (This trigger)
  • DR SE 2
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Set SM_SFX_P2 = (Position of SM_Dummy[SM_LoopIndex])
      • Special Effect - Create a special effect at SM_SFX_P2 using Ephemeral Slash Purple.mdx
      • Set DR_SE2 = (Last created special effect)
      • Special Effect - Set Time Scale of DR_SE2 to 1.00
      • Special Effect - Set Orientation of DR_SE2 to yaw: (Random real number between 120.00 and 180.00), pitch: (Random real number between 0.00 and 360.00), roll: (Random real number between 0.00 and 360.00)
      • Special Effect - Set Scale of DR_SE2 to (Random real number between 1.00 and 1.70)
      • Wait 0.10 seconds
      • Custom script: call RemoveLocation( udg_SM_SFX_P2)
      • Trigger - Turn off (This trigger)


 
Last edited:
I’ve encountered a specific situation where If I would destroy them right after creating them the effect wouldn’t show( probably due to not having a death animation).
It's the other way around: If special effect does not have death animation, then it will play it's "stand" animation fully before being removed.
You will either have to use a custom special effect which does not have animations, or track and manage effect's lifetime yourself.

Your DR SE and DR SE 2 triggers will never work the way they are set up, as they depend/reference variables that you have no idea what they contain at the time the DR SE/DR SE 2 triggers run.

Your DR SE/2 triggers will still be problematic even if you move everything after the "Wat 0.1" to separate trigger and use timers, because those triggers will run 3 times before the first run finishes, meaning those triggers will leak 2 locations, not to mention leak special effects which are not being removed.

As for how to bind effects from DR SE/2 to your instance of the Shadow Massacre spell (which I assume is what you are asking for), you can use array bucketing. Bucket size will represent how many effects each instance of spell can have at the time. In your case, during the span of 0.1 seconds those two triggers will run 3 times and each run will create new effect (I assume here that only trigger will remain in final version of your spell, if both will be in final version then bucket size should be twice the amount: 6).
When adding an effect to bucketed array, you will need to first calculate offset based off the spell instance's id. The calculation is (spell_instance_id - 1) * bucket_size.
So instance #1 will have instance_id == 1, offset (1-1)*6 => 0 and in the bucketed array that instance's effects will populate indexes 1-6.
Instance #2 will instance_id == 2, have offset (2-1)*6 => 6 and that instance's effect will populate indexes 7-12, etc.

In you case you could create arrays:
  • SM_Effects (array variable of type 'special effect') which would be used to track special effects you've created
  • SM_EffectsDurations (array variable of type 'real') which would be used to track remaining durations of each created special effect
  • SM_EffectCounts (array variable of type 'integer') which would be used to track how many special effects for given instance of spell you have created so far.

In your SM Loop trigger, before turning DR SE/2 triggers on, set SM_EffectCounts[SM_LoopIndex] to 0, because given instance of spell did not create any new effects yet (and, since the SM loop runs every 0.33 seconds, next run will be long after all effects have been created and removed in DR SE/2).

DR SE/2 triggers will need to use for loop to run over all instances of SM spell (like your SM Loop) but in this case each run will create new effects if SM_EffectCounts[instance_id] is less than maximum effect count (e.g. by comparing SM_EffectCounts[instance_id] to bucket_sze of 3 or 6) and also manage lifetime of already created effects via SM_EffectsDurations array.
 
It's the other way around: If special effect does not have death animation, then it will play it's "stand" animation fully before being removed.
You will either have to use a custom special effect which does not have animations, or track and manage effect's lifetime yourself.

Your DR SE and DR SE 2 triggers will never work the way they are set up, as they depend/reference variables that you have no idea what they contain at the time the DR SE/DR SE 2 triggers run.

Your DR SE/2 triggers will still be problematic even if you move everything after the "Wat 0.1" to separate trigger and use timers, because those triggers will run 3 times before the first run finishes, meaning those triggers will leak 2 locations, not to mention leak special effects which are not being removed.

As for how to bind effects from DR SE/2 to your instance of the Shadow Massacre spell (which I assume is what you are asking for), you can use array bucketing. Bucket size will represent how many effects each instance of spell can have at the time. In your case, during the span of 0.1 seconds those two triggers will run 3 times and each run will create new effect (I assume here that only trigger will remain in final version of your spell, if both will be in final version then bucket size should be twice the amount: 6).
When adding an effect to bucketed array, you will need to first calculate offset based off the spell instance's id. The calculation is (spell_instance_id - 1) * bucket_size.
So instance #1 will have instance_id == 1, offset (1-1)*6 => 0 and in the bucketed array that instance's effects will populate indexes 1-6.
Instance #2 will instance_id == 2, have offset (2-1)*6 => 6 and that instance's effect will populate indexes 7-12, etc.

In you case you could create arrays:
  • SM_Effects (array variable of type 'special effect') which would be used to track special effects you've created
  • SM_EffectsDurations (array variable of type 'real') which would be used to track remaining durations of each created special effect
  • SM_EffectCounts (array variable of type 'integer') which would be used to track how many special effects for given instance of spell you have created so far.

In your SM Loop trigger, before turning DR SE/2 triggers on, set SM_EffectCounts[SM_LoopIndex] to 0, because given instance of spell did not create any new effects yet (and, since the SM loop runs every 0.33 seconds, next run will be long after all effects have been created and removed in DR SE/2).

DR SE/2 triggers will need to use for loop to run over all instances of SM spell (like your SM Loop) but in this case each run will create new effects if SM_EffectCounts[instance_id] is less than maximum effect count (e.g. by comparing SM_EffectCounts[instance_id] to bucket_sze of 3 or 6) and also manage lifetime of already created effects via SM_EffectsDurations array.
Sorry for not addressing this earlier! Those 2 triggers were just for the testing of desired visauls, I was aware they leak and reference god knows what, so after studying your advice, here is what I came up with, I hope this is accurate.

  • Set SM_Bucket_Size = 12
  • -----------------
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • SM_Active_SFX Equal to 1
    • Then - Actions
      • Trigger - Turn on SM SFX Recycle <gen>
    • Else - Actions
  • --------------------
  • For each (Integer SM_LoopIndex) from 1 to SM_Index, do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SM_Active[SM_LoopIndex] Equal to True
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • SM_Strikes_Remaining[SM_LoopIndex] Greater than 0
            • Then - Actions
              • Set SM_TempPoint = (Position of SM_Dummy[SM_LoopIndex])
              • Set SM_TempGroup = (Units within 800.00 of SM_TempPoint matching ((((Matching unit) belongs to an enemy of (Owner of SM_Caster[SM_LoopIndex]).) Equal to True) and ((((Matching unit) is alive) Equal to True) and (((Matching unit) is hidden) Equal to False))).)
              • Set SM_TempUnit = (Random unit from SM_TempGroup)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • SM_TempUnit Not equal to No unit
                  • (SM_TempUnit is alive) Equal to True
                • Then - Actions
                  • Set SM_TempPoint2 = (Position of SM_TempUnit)
                  • Unit - Move SM_Dummy[SM_LoopIndex] instantly to SM_TempPoint2, facing Default building facing degrees
                  • Animation - Play SM_Dummy[SM_LoopIndex]'s attack slam first animation
                  • Unit - Cause SM_Caster[SM_LoopIndex] to damage SM_TempUnit, dealing (Random real number between 300.00 and 400.00) damage of attack type Normal and damage type Normal
                  • -------- drse1 --------
                  • Special Effect - Create a special effect at SM_TempPoint2 using Ephemeral Slash Purple.mdx
                  • Set DR_SE1 = (Last created special effect)
                  • Special Effect - Set Time Scale of DR_SE1 to 1.00
                  • Special Effect - Set Orientation of DR_SE1 to yaw: (Random real number between 100.00 and 200.00), pitch: (Random real number between 0.00 and 360.00), roll: (Random real number between 0.00 and 360.00)
                  • Special Effect - Set Scale of DR_SE1 to (Random real number between 1.00 and 1.50)
                  • -------- storing --------
                  • Set SM_Temp_Offset = (((SM_LoopIndex - 1) x SM_Bucket_Size) + 1)
                  • Set SM_Effect_Count[SM_LoopIndex] = (SM_Effect_Count[SM_LoopIndex] + 1)
                  • Set SM_Temp_Slot = (SM_Temp_Offset + (SM_Effect_Count[SM_LoopIndex] - 1))
                  • Set SM_Effect[SM_Temp_Slot] = DR_SE1
                  • Set SM_Effect_Timer[SM_Temp_Slot] = 2.00
                  • For each (Integer SM_Visual_Loop) from 1 to 2, do (Actions)
                    • Loop - Actions
                      • Set SM_TempReal = (Random real number between 0.00 and 250.00)
                      • Set SM_TempReal2 = (Random real number between 0.00 and 360.00)
                      • Set SM_TempPoint3 = ((Position of SM_TempUnit) offset by SM_TempReal towards SM_TempReal2 degrees.)
                      • Set SM_TempReal3 = (Random real number between 50.00 and 200.00)
                      • Unit - Create 1 SM_Visual_Dummy for (Owner of SM_Caster[SM_LoopIndex]) at SM_TempPoint3 facing SM_TempReal2 degrees
                      • Set SM_Visual_Dummy_Unit = (Last created unit)
                      • Unit - Add a (Random real number between 0.40 and 0.70) second Water Elemental expiration timer to SM_Visual_Dummy_Unit
                      • Unit - Add Crow Form to SM_Visual_Dummy_Unit
                      • Unit - Remove Crow Form from SM_Visual_Dummy_Unit
                      • Animation - Change SM_Visual_Dummy_Unit flying height to SM_TempReal3 at 0.00
                      • Special Effect - Create a special effect attached to the origin of SM_Visual_Dummy_Unit using Abilities\Weapons\AvengerMissile\AvengerMissile.mdl
                      • Special Effect - Destroy (Last created special effect)
                      • Special Effect - Create a special effect attached to the left arm of SM_Visual_Dummy_Unit using Ephemeral Cut Purple.mdl
                      • Special Effect - Destroy (Last created special effect)
                      • Set SM_TempReal = (Random real number between 0.80 and 1.50)
                      • -------- drse2 --------
                      • Special Effect - Create a special effect at SM_TempPoint3 using Ephemeral Slash Purple.mdx
                      • Set DR_SE2 = (Last created special effect)
                      • Special Effect - Set Time Scale of DR_SE2 to 1.00
                      • Special Effect - Set Orientation of DR_SE2 to yaw: (Random real number between 120.00 and 180.00), pitch: (Random real number between 0.00 and 360.00), roll: (Random real number between 0.00 and 360.00)
                      • Special Effect - Set Scale of DR_SE2 to (Random real number between 1.00 and 1.70)
                      • -------- storing --------
                      • Set SM_Effect_Count[SM_LoopIndex] = (SM_Effect_Count[SM_LoopIndex] + 1)
                      • Set SM_Temp_Slot = (SM_Temp_Offset + (SM_Effect_Count[SM_LoopIndex] - 1))
                      • Set SM_Effect[SM_Temp_Slot] = DR_SE2
                      • Set SM_Effect_Timer[SM_Temp_Slot] = 2.00
                      • Animation - Change SM_Visual_Dummy_Unit's animation speed to (SM_TempReal x 100.00)% of its original speed
                      • Animation - Play SM_Visual_Dummy_Unit's attack slam first animation
                      • Unit - Order SM_Visual_Dummy_Unit to Follow SM_Dummy[SM_LoopIndex]
                      • Custom script: call RemoveLocation( udg_SM_TempPoint3)
                • Else - Actions
                  • Set SM_Strikes_Remaining[SM_LoopIndex] = 0
              • Custom script: call DestroyGroup( udg_SM_TempGroup)
              • Custom script: call RemoveLocation(udg_SM_TempPoint2)
              • Custom script: call RemoveLocation(udg_SM_TempPoint)
              • Set SM_Strikes_Remaining[SM_LoopIndex] = (SM_Strikes_Remaining[SM_LoopIndex] - 1)
            • Else - Actions
              • Set SM_TempPoint = (Position of SM_Caster[SM_LoopIndex])
              • Unit - Move SM_Dummy[SM_LoopIndex] instantly to SM_TempPoint, facing (Facing of SM_Dummy[SM_LoopIndex]) degrees
              • Unit - Unhide SM_Caster[SM_LoopIndex]
              • Unit - Make SM_Caster[SM_LoopIndex] Vulnerable
              • Unit - Unpause SM_Caster[SM_LoopIndex]
              • Selection - Add SM_Caster[SM_LoopIndex] to selection for (Owner of SM_Caster[SM_LoopIndex])
              • Unit - Remove SM_Dummy[SM_LoopIndex] from the game
              • Special Effect - Destroy SM_Vanish_SFX[SM_LoopIndex]
              • Special Effect - Create a special effect attached to the chest of SM_Caster[SM_LoopIndex] using Abilities\Weapons\AvengerMissile\AvengerMissile.mdl
              • Special Effect - Destroy (Last created special effect)
              • -------- clear sfx for this instance --------
              • Set SM_Temp_Offset = (((SM_LoopIndex - 1) x SM_Bucket_Size) + 1)
              • For each (Integer SM_Slot) from SM_Temp_Offset to ((SM_Temp_Offset + SM_Bucket_Size) - 1), do (Actions)
                • Loop - Actions
                  • Special Effect - Destroy SM_Effect[SM_Slot]
                  • Set SM_Effect_Timer[SM_Slot] = 0.00
              • Set SM_Effect_Count[SM_LoopIndex] = 0
              • Set SM_Active[SM_LoopIndex] = False
              • Set SM_Active_SFX = (SM_Active_SFX - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • SM_Active_SFX Equal to 0
                • Then - Actions
                  • Trigger - Turn off SM SFX Recycle <gen>
                • Else - Actions
              • Set SM_Strikes_Remaining[SM_LoopIndex] = 0
              • Set SM_Recycle_Count = (SM_Recycle_Count + 1)
              • Set SM_Recycle_Stack[SM_Recycle_Count] = SM_LoopIndex
              • Custom script: call RemoveLocation( udg_SM_TempPoint)
        • Else - Actions
  • -------------------------------------
  • SM SFX Recycle
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • For each (Integer SM_Slot) from 1 to (SM_Index x SM_Bucket_Size), do (Actions)
        • Loop - Actions
          • Set SM_Effect_Timer[SM_Slot] = (SM_Effect_Timer[SM_Slot] - 0.10)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • SM_Effect_Timer[SM_Slot] Less than or equal to 0.01
            • Then - Actions
              • Special Effect - Destroy SM_Effect[SM_Slot]
              • Set SM_Effect_Timer[SM_Slot] = 0.00
            • Else - Actions
So basically, i integrated the effects directly into the main spell loop so each spell instance gets a fixed slot (bucket size = 12) in a global array for effects. When creating an effect, I store its handle in the next free slot for that instance and set a 2 sec timer. Also added a separate cleanup trigger that runs every 0.1s, decrements timers for all active effects, and destroys them when they expire. At the end of the instance a cleanup for any remaining effects.
PS The visuals still look pretty the same :D Ty for replying and giving a helping hand, cheers!:ogre_haosis:
 
Back
Top