• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece!🔗 Click here to enter!

call GroupClear vs call DestroyGroup

Status
Not open for further replies.
Level 37
Joined
Jul 22, 2015
Messages
3,485
GroupClear() removes all units from the unit group. DestroyGroup() destroys the handle of the unit group. If you plan on creating another group using the same variable, GroupClear will not get rid of the leak.

It's okay ot use GroupClear if you're recycling the group (creating the unit group once and then adding/removing units as you go). If you post the triggers, I'll be able to see the issue.
 
Ok, here goes.
This spell has 2 parts, the first one is Silencing an area, the second one is whenever the original caster casts a different spell, it will damage the "Silenced" units with a DoT debuff. The unit group issue occurs in the 2nd part.
Also the spell is powered by Bribe's Unit Indexing and GUI Spell system, so both parts have their own config triggers (which I omitted because they just say which triggers are to run upon casting a spell) and Custom value of a unit makes it MUI.

  • WaveEx effect
    • Events
    • Conditions
    • Actions
      • Set Spell__InRangePoint = Spell__TargetPoint
      • Set Spell__InRange = (250.00 + (50.00 x (Real(Spell__Level))))
      • -------- --------
      • Unit Group - Add all units of Spell__InRangeGroup to Spell__TargetGroup
      • Custom script: if udg_WaveExGroup[GetUnitUserData(udg_Spell__Caster)] == null then
      • Custom script: set udg_WaveExGroup[GetUnitUserData(udg_Spell__Caster)] = CreateGroup()
      • Custom script: endif
      • Unit - Create 1 Spell__DummyType for Spell__CasterOwner at Spell__TargetPoint facing Default building facing degrees
      • Unit - Add a Spell__Duration second Generic expiration timer to (Last created unit)
      • Unit - Add Dummy Detector to (Last created unit)
      • Unit - Add VY - Wave of Exhaustion (Dummy) to (Last created unit)
      • Set WaveExCaster[(Custom value of Spell__Caster)] = Spell__Caster
      • -------- --------
      • Set Spell__Time = 0.25
      • Set Spell__Duration = (3.96 + (2.00 x (Real(Spell__Level))))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Spell__Caster has buff Brilliance ) Equal to True
        • Then - Actions
          • Set WaveExBigRoll[Spell__Index] = (Random integer number between 0 and 2)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • WaveExBigRoll[Spell__Index] Equal to 2
            • Then - Actions
              • Set Spell__InRange = 450.00
              • Set Spell__Duration = 12.00
            • Else - Actions
        • Else - Actions
      • -------- --------
      • Unit Group - Pick every unit in Spell__TargetGroup and do (Actions)
        • Loop - Actions
          • Animation - Change (Picked unit) turn speed to (0.20 x (Default turn speed of (Picked unit)))
          • Set WaveExDamage[(Custom value of (Picked unit))] = ((Real((Intelligence of Spell__Caster (Include bonuses)))) x 0.50)
          • Set WaveExSource[(Custom value of (Picked unit))] = Spell__Caster
          • Unit Group - Add (Picked unit) to WaveExGroup[(Custom value of Spell__Caster)]
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • (Spell__Caster has buff Brilliance ) Equal to True
              • WaveExBigRoll[Spell__Index] Equal to 2
        • Then - Actions
          • Unit - Set level of VY - Wave of Exhaustion (Dummy) for (Last created unit) to (Spell__Level + 1)
        • Else - Actions
          • Unit - Set level of VY - Wave of Exhaustion (Dummy) for (Last created unit) to Spell__Level
      • Unit - Order (Last created unit) to Neutral Dark Ranger - Silence Spell__TargetPoint
      • Set WaveExDamage[(Custom value of (Picked unit))] = ((Real((Intelligence of (Triggering unit) (Include bonuses)))) x 0.50)
      • Set WaveExSource[(Custom value of (Picked unit))] = WaveExCaster[(Custom value of (Triggering unit))]
  • WaveEx loop
    • Events
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Spell__Expired Equal to True
        • Then - Actions
          • Set WaveExCaster[(Custom value of Spell__Caster)] = No unit
          • Unit Group - Pick every unit in Spell__TargetGroup and do (Actions)
            • Loop - Actions
              • Animation - Change (Picked unit) turn speed to (Default turn speed of (Picked unit))
          • Custom script: call GroupClear (udg_WaveExGroup[GetUnitUserData(udg_Spell__Caster)])
        • Else - Actions
  • WaveEx side init
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Not equal to VY - Wave of Exhaustion
      • (Ability being cast) Not equal to VY - Change Attack
      • (Level of VY - Wave of Exhaustion for (Triggering unit)) Greater than 0
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Triggering unit) Equal to WaveExCaster[(Custom value of (Triggering unit))]
        • Then - Actions
          • Unit Group - Pick every unit in WaveExGroup[(Custom value of (Triggering unit))] and do (Actions)
            • Loop - Actions
              • Set ExhaustionLocation[(Custom value of (Picked unit))] = (Position of (Picked unit))
              • Unit - Create 1 Spell__DummyType for (Owner of (Triggering unit)) at ExhaustionLocation[(Custom value of (Picked unit))] facing Default building facing degrees
              • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
              • Unit - Add Wave of Exhaustion (DoT init) to (Last created unit)
              • Unit - Order (Last created unit) to Human Sorceress - Slow (Picked unit)
        • Else - Actions
  • WaveEx side effect
    • Events
    • Conditions
    • Actions
      • Set Spell__Time = 0.50
      • Set Spell__Duration = 4.05
      • Special Effect - Create a special effect attached to the chest of Spell__Target using Abilities\Spells\Other\SoulBurn\SoulBurnbuff.mdl
      • Set WaveExFX[Spell__Index] = (Last created special effect)
      • Set WaveExDPS[Spell__Index] = WaveExDamage[(Custom value of Spell__Target)]
      • Set WaveExDPS_Source[Spell__Index] = WaveExSource[(Custom value of Spell__Target)]
  • WaveEx side loop
    • Events
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Spell__Expired Equal to True
        • Then - Actions
          • Special Effect - Destroy WaveExFX[Spell__Index]
          • Custom script: call RemoveLocation (udg_ExhaustionLocation[GetUnitUserData(udg_Spell__Target)])
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Spell__Target is alive) Equal to True
            • Then - Actions
              • Unit - Cause WaveExDPS_Source[Spell__Index] to damage Spell__Target, dealing WaveExDPS[Spell__Index] damage of attack type Spells and damage type Poison
            • Else - Actions
              • Set Spell__Expired = True
              • Special Effect - Destroy WaveExFX[Spell__Index]
              • Custom script: call RemoveLocation (udg_ExhaustionLocation[GetUnitUserData(udg_Spell__Target)])
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
You have to set the group to null after you destroy it. Since you are not setting it to null, and you cast it the second time, this if block won't run:
  • Custom script: if udg_WaveExGroup[GetUnitUserData(udg_Spell__Caster)] == null then
  • Custom script: set udg_WaveExGroup[GetUnitUserData(udg_Spell__Caster)] = CreateGroup()
  • Custom script: endif

You have to use DestroyGroup() or you will leak. ClearGroup() worked since you didn't have to recreate the group.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
Clear group removes the contents of the group setting it back to the same state as if it were freshly returned by CreateGroup. DestroyGroup does what it is called removing the group object and making any future attempt to evaluate it result in undefined behaviour.

One cannot replace the other and both have distinct use cases.
 
Last edited:
Level 26
Joined
Aug 18, 2009
Messages
4,097
Unless you have recursive behavior or do not need a function anymore at some point, DestroyGroup usually is not needed and more dangerous (destruction+recreation is costlier, DestroyGroup has been proven to leak memory, especially if there are still units contained, you may invalidate your object and have therefore to pay attention).

Dynamically allocated groups may be used when you need to hold on the data like in aura abilities, unit classifications while the grouping attribute fans out but then again, better have yourself a wrapper since that may be implemented differently like with hashtables or unit arrays.

If you only require the group to pick units (invoking the enum functions), you may consider hiding the group rather and offer a static call instead.
 
Status
Not open for further replies.
Top