• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Spell] Integer_1 [CV_A] = Integer_1 [CV_B] ?

Status
Not open for further replies.
Level 12
Joined
May 16, 2020
Messages
660
Hello all,

I'm trying to make the following spell MUI. The spell is supposed to keep track of the amont of summoned units and, if too many units get summoned, remove the oldest summoned unit.

The trigger below works for 1 Hero. However, when I test this with 2 Heroes, the trigger always deletes units which belong to the other Hero. In my mind the following set-up should prevent this, since for me I clearly refer to different units:

Unit [integer_1 [CV_A]] =/= integer_1 [CV_B]]​

...but for the game these two seem to be the same. Could it be that arrays of integers are ultimately the same? And if so, how can I fix this?

  • Spin Web Summon
    • Events
      • Unit - A unit Spawns a summoned unit
    • Conditions
      • (Unit-type of (Summoned unit)) Equal to Spin Web
    • Actions
      • Set VariableSet SpinWeb_Caster = (Summoning unit)
      • Set VariableSet SpinWeb_CV = (Custom value of SpinWeb_Caster)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SpinWeb_TotalWebs[SpinWeb_CV] Less than SpinWeb_MaxWebs[SpinWeb_CV]
        • Then - Actions
          • Set VariableSet SpinWeb_TotalWebs[SpinWeb_CV] = (SpinWeb_TotalWebs[SpinWeb_CV] + 1)
          • Set VariableSet SpinWeb_Counter[SpinWeb_CV] = (SpinWeb_Counter[SpinWeb_CV] + 1)
          • Set VariableSet SpinWeb_WebUnit[SpinWeb_Counter[SpinWeb_CV]] = (Summoned unit)
        • Else - Actions
          • Set VariableSet SpinWeb_Counter[SpinWeb_CV] = (SpinWeb_Counter[SpinWeb_CV] + 1)
          • Unit - Kill SpinWeb_WebUnit[(SpinWeb_Counter[SpinWeb_CV] - SpinWeb_MaxWebs[SpinWeb_CV])]
          • Set VariableSet SpinWeb_WebUnit[SpinWeb_Counter[SpinWeb_CV]] = (Summoned unit)
 
Level 12
Joined
May 16, 2020
Messages
660
Yes, it's a MUI issue. Sorry don't understand fully what you are saying. Example:

Caster A, custom value = 130
Caster B, custom value = 145

Caster A casts the ability 1x:
  • SpinWeb_CV = 130
  • SpinWeb_Counter = 1 [130]
  • Thus, SpinWeb_WebUnit[1[130]]
Now Caster B casts the ability 1x:
  • SpinWeb_CV = 145
  • SpinWeb_Counter = 1 [145]
  • Thus, SpinWeb_WebUnit[1[145]]

Are you saying that it's correct that SpinWeb_WebUnit[1[130]] is referring to the same unit as SpinWeb_WebUnit[1[145]]?

But then how can I fix this in my case...?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Are you saying that it's correct that SpinWeb_WebUnit[1[130]] is referring to the same unit as SpinWeb_WebUnit[1[145]]?
Assuming you mean a variable named "1" (technically not allowed as variables cannot start with number characters) then yes. This is because you deference the same indices of SpinWeb_WebUnit as they run in the range of 1 to SpinWeb_MaxWeb.
But then how can I fix this in my case...?
Allocate unique storage space within the array for the units. For example use a dynamic data structure like a linked list. If SpinWeb_MaxWeb is known at compile time then you can use a 2D array approach to allocate unique storage space for each instance at the cost of maximum instance count.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,538
Use a Hashtable and save the Summons to the Summoner using it's handle as the key.

Save (Summoned Unit) as Spin_Counter[CV] of Key(Summoning Unit) in YourHashtable

Also, it's probably good practice to drop the indices down when a summon dies so your counter can eventually reset back to 0.
 
Last edited:
Level 12
Joined
May 16, 2020
Messages
660
Thanks you two.

The following works in-game, but not sure how well it's done (it's my first hashtable):

  • Spin Web Summon
    • Events
      • Unit - A unit Spawns a summoned unit
    • Conditions
      • (Unit-type of (Summoned unit)) Equal to Spin Web
    • Actions
      • Set VariableSet SpinWeb_Caster = (Summoning unit)
      • Set VariableSet SpinWeb_CV = (Custom value of SpinWeb_Caster)
      • Set VariableSet SpinWeb_Counter[SpinWeb_CV] = (SpinWeb_Counter[SpinWeb_CV] + 1)
      • Hashtable - Save Handle Of(Summoned unit) as SpinWeb_Counter[SpinWeb_CV] of (Key (Summoning unit).) in SpinWeb_Hashtable.
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SpinWeb_Counter[SpinWeb_CV] Greater than SpinWeb_MaxWebs[SpinWeb_CV]
        • Then - Actions
          • Unit - Kill (Load (SpinWeb_Counter[SpinWeb_CV] - SpinWeb_MaxWebs[SpinWeb_CV]) of (Key (Summoning unit).) in SpinWeb_Hashtable.)
        • Else - Actions
Also, it's probably good practice to drop the indices down when a summon dies so your counter can eventually reset back to 0.

Mmm for this I would need to adjust an entry which is already saved in the hashtable, but I only found "Save" and "Load".

FYI: Turning the integer back to 0 should not be possible, as the Webs live forever once summoned. But I agree, it would be nice to not let the integer increase to infinity. So ideally the integer should, once SpinWeb_Counter[SpinWeb_CV] = SpinWeb_MaxWebs[SpinWeb_CV], stay at SpinWeb_MaxWebs[SpinWeb_CV] and not go above it.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,538
  • Cast Web
    • Events
      • Unit - A unit Spawns a summoned unit
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • WebCounter Equal to WebMax
        • Then - Actions
          • -------- Load and kill first web --------
          • Set VariableSet WebUnit = (Load 1 of (Key (Summoning unit).) in WebHash.)
          • Custom script: call RemoveSavedHandle(udg_WebHash, GetHandleId(GetSummoningUnit()), GetHandleId(udg_WebUnit))
          • Unit - Kill WebUnit
          • -------- --------
          • -------- Drop down indices (so 2 becomes 1, 3 becomes 2, etc...) --------
          • For each (Integer WebLoop) from 1 to WebMax, do (Actions)
            • Loop - Actions
              • Set VariableSet WebUnit = (Load (WebLoop + 1) of (Key (Summoning unit).) in WebHash.)
              • Custom script: call RemoveSavedHandle(udg_WebHash, GetHandleId(GetSummoningUnit()), GetHandleId(udg_WebUnit))
              • Hashtable - Save Handle OfWebUnit as WebLoop of (Key (Summoning unit).) in WebHash.
        • Else - Actions
          • -------- Only increase WebCounter if it's less than WebMax --------
          • Set VariableSet WebCounter = (WebCounter + 1)
      • -------- --------
      • Set VariableSet WebUnit = (Summoned unit)
      • Hashtable - Save Handle OfWebUnit as WebCounter of (Key (Summoning unit).) in WebHash.
Overwriting a value in a Hashtable (exception being integers, reals, booleans, and strings) will create a leak. In this case it would create a Unit leak since we're overwriting one unit with another. To remedy this, we use the Custom script below:
  • Custom script: call RemoveSavedHandle(udg_WebHash, GetHandleId(GetSummoningUnit()), GetHandleId(udg_WebUnit))
To be honest i'm not 100% sure if I'm handling the leak properly, but I believe this works. @Dr Super Good
 

Attachments

  • Web Hash Example.w3m
    17.7 KB · Views: 15
Last edited:
Status
Not open for further replies.
Top