• 🏆 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!

[Solved] [GUI] MUI indexing issue I can't figure out on my spell

Status
Not open for further replies.
Level 8
Joined
Jul 6, 2012
Messages
65
So I have this spell which is replaces the hero with another unit (a spirit) when it dies, which lasts until your hero revives/respawns. When your hero respawns, it respawns at the unit's location, and the unit disappears.

The ability itself works fine. But it breaks down when I have multiple heroes with that ability.

The first part of it works completely fine, no matter how many heroes with it die. But upon respawning, it messes up. The first respawning hero removes its own unit, and the 2nd hero's unit as well. The 2nd respawning hero therefore respawns at the altar, instead of where its spirit was, because it doesn't have a spirit anymore. The 3rd respawning hero respawns at the altar as well and its spirit isn't removed at all.

So there clearly is an indexing issue, but I can't figure out what's wrong. I used the same indexing for several other spells and they all work fine. This is the only instance where I use it with deaths/respawning units.

Here are the codes

death event trigger

  • Light Form death
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Level of Light Form for (Dying unit)) Greater than 0
    • Actions
      • Set LightFormDeathIndex = (LightFormDeathIndex + 1)
      • Set LightFormDeathHero[LightFormDeathIndex] = (Dying unit)
      • Set LightFormDeathTimer[LightFormDeathIndex] = 2.60
      • Set LightFormDeathLoc[LightFormDeathIndex] = (Position of LightFormDeathHero[LightFormDeathIndex])
      • Unit - Create 1 Light Image for (Owner of LightFormDeathHero[LightFormDeathIndex]) at LightFormDeathLoc[LightFormDeathIndex] facing (Facing of LightFormDeathHero[LightFormDeathIndex]) degrees
      • Set LightFormDeathSummon[LightFormDeathIndex] = (Last created unit)
      • Unit - Make LightFormDeathSummon[LightFormDeathIndex] Invulnerable
      • Unit - Hide LightFormDeathSummon[LightFormDeathIndex]
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of Light Form for LightFormDeathHero[LightFormDeathIndex]) Equal to 1
        • Then - Actions
          • Unit - Add Revealing Light (Light Image 1) to LightFormDeathSummon[LightFormDeathIndex]
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Level of Light Form for LightFormDeathHero[LightFormDeathIndex]) Equal to 2
            • Then - Actions
              • Unit - Add Revealing Light (Light Image 1) to LightFormDeathSummon[LightFormDeathIndex]
              • Unit - Add Teleport (Light Image 2) to LightFormDeathSummon[LightFormDeathIndex]
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Level of Light Form for LightFormDeathHero[LightFormDeathIndex]) Equal to 3
                • Then - Actions
                  • Unit - Add Revealing Light (Light Image 1) to LightFormDeathSummon[LightFormDeathIndex]
                  • Unit - Add Teleport (Light Image 2) to LightFormDeathSummon[LightFormDeathIndex]
                  • Unit - Add Blinding Aura (Light Image 3) to LightFormDeathSummon[LightFormDeathIndex]
                • Else - Actions
      • Special Effect - Create a special effect at LightFormDeathLoc[LightFormDeathIndex] using Abilities\Spells\Items\TomeOfRetraining\TomeOfRetrainingCaster.mdl
      • Special Effect - Destroy (Last created special effect)
      • Animation - Change LightFormDeathHero[LightFormDeathIndex]'s animation speed to 70.00% of its original speed
      • If (LightFormDeathIndex Equal to 1) then do (Trigger - Turn on Light Form death effect <gen>) else do (Do nothing)
periodic trigger

  • Light Form death effect
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • For each (Integer LightFormDeathLoop) from 1 to LightFormDeathIndex, do (Actions)
        • Loop - Actions
          • Set LightFormDeathTimer[LightFormDeathLoop] = (LightFormDeathTimer[LightFormDeathLoop] - 0.10)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • LightFormDeathTimer[LightFormDeathLoop] Equal to 2.50
            • Then - Actions
              • Custom script: call SetUnitAnimationByIndex(udg_LightFormDeathHero[udg_LightFormDeathLoop], 3)
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • LightFormDeathTimer[LightFormDeathLoop] Equal to 1.50
            • Then - Actions
              • Special Effect - Create a special effect at LightFormDeathLoc[LightFormDeathLoop] using Abilities\Spells\Items\TomeOfRetraining\TomeOfRetrainingCaster.mdl
              • Special Effect - Destroy (Last created special effect)
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • LightFormDeathTimer[LightFormDeathLoop] Equal to 0.00
            • Then - Actions
              • Unit - Hide LightFormDeathHero[LightFormDeathLoop]
              • Unit - Move LightFormDeathSummon[LightFormDeathLoop] instantly to LightFormDeathLoc[LightFormDeathLoop], facing (Facing of LightFormDeathHero[LightFormDeathLoop]) degrees
              • Unit - Unhide LightFormDeathSummon[LightFormDeathLoop]
              • Animation - Change LightFormDeathHero[LightFormDeathLoop]'s animation speed to 100.00% of its original speed
              • Selection - Add LightFormDeathSummon[LightFormDeathLoop] to selection for (Owner of LightFormDeathSummon[LightFormDeathLoop])
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (LightFormDeathHero[LightFormDeathLoop] is alive) Equal to True
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (LightFormDeathSummon[LightFormDeathLoop] is in (Units currently selected by (Owner of LightFormDeathSummon[LightFormDeathLoop]))) Equal to True
                • Then - Actions
                  • Selection - Add LightFormDeathHero[LightFormDeathLoop] to selection for (Owner of LightFormDeathHero[LightFormDeathLoop])
                • Else - Actions
              • Unit - Hide LightFormDeathSummon[LightFormDeathLoop]
              • Set LightFormDeathLocSummon = (Position of LightFormDeathSummon[LightFormDeathLoop])
              • Unit - Move LightFormDeathHero[LightFormDeathLoop] instantly to LightFormDeathLocSummon, facing (Facing of LightFormDeathSummon[LightFormDeathLoop]) degrees
              • Custom script: call RemoveLocation(udg_LightFormDeathLocSummon)
              • Unit - Kill LightFormDeathSummon[LightFormDeathLoop]
              • Set LightFormDeathSummon[LightFormDeathLoop] = LightFormDeathSummon[LightFormDeathIndex]
              • Set LightFormDeathHero[LightFormDeathLoop] = LightFormDeathHero[LightFormDeathIndex]
              • Set LightFormDeathTimer[LightFormDeathLoop] = LightFormDeathTimer[LightFormDeathIndex]
              • Custom script: call RemoveLocation(udg_LightFormDeathLoc[udg_LightFormDeathLoop])
              • Set LightFormDeathLoc[LightFormDeathLoop] = LightFormDeathLoc[LightFormDeathIndex]
              • Set LightFormDeathIndex = (LightFormDeathIndex - 1)
              • Set LightFormDeathLoop = (LightFormDeathLoop - 1)
              • If (LightFormDeathIndex Equal to 0) then do (Trigger - Turn off (This trigger)) else do (Do nothing)
            • Else - Actions
If I disable the last 8 lines of the periodic trigger, it works fine, but that's bad for obvious reasons. So the error lies within this part

  • ...
    • Set LightFormDeathSummon[LightFormDeathLoop] = LightFormDeathSummon[LightFormDeathIndex]
    • Set LightFormDeathHero[LightFormDeathLoop] = LightFormDeathHero[LightFormDeathIndex]
    • Set LightFormDeathTimer[LightFormDeathLoop] = LightFormDeathTimer[LightFormDeathIndex]
    • Custom script: call RemoveLocation(udg_LightFormDeathLoc[udg_LightFormDeathLoop])
    • Set LightFormDeathLoc[LightFormDeathLoop] = LightFormDeathLoc[LightFormDeathIndex]
    • Set LightFormDeathIndex = (LightFormDeathIndex - 1)
    • Set LightFormDeathLoop = (LightFormDeathLoop - 1)
    • If (LightFormDeathIndex Equal to 0) then do (Trigger - Turn off (This trigger)) else do (Do nothing)
    • Else - Actions
 
Level 12
Joined
Mar 24, 2011
Messages
1,082
Remove this:
  • Set LightFormDeathLoop = (LightFormDeathLoop - 1)
Also, you are leaking a location in there...

  • ...
    • Set LightFormDeathSummon[LightFormDeathLoop] = LightFormDeathSummon[LightFormDeathIndex]
    • Set LightFormDeathHero[LightFormDeathLoop] = LightFormDeathHero[LightFormDeathIndex]
    • Set LightFormDeathTimer[LightFormDeathLoop] = LightFormDeathTimer[LightFormDeathIndex]
    • Custom script: call RemoveLocation(udg_LightFormDeathLoc[udg_LightFormDeathLoop])
    • Set LightFormDeathLoc[LightFormDeathLoop] = LightFormDeathLoc[LightFormDeathIndex]
    • Custom script: call RemoveLocation(udg_LightFormDeathLoc[udg_LightFormDeathIndex]) /////ADD THIS LINE
    • Set LightFormDeathIndex = (LightFormDeathIndex - 1)
    • Set LightFormDeathLoop = (LightFormDeathLoop - 1) /////REMOVE THIS LINE
    • If (LightFormDeathIndex Equal to 0) then do (Trigger - Turn off (This trigger)) else do (Do nothing)
    • Else - Actions
-Ned
 
Level 8
Joined
Jul 6, 2012
Messages
65
That didn't fix it, it just shifted the unwanted effect. Now the 2nd hero removes the 3rd hero's unit.

E: I'm using this mui system, reducing the loop integer by 1 is a part of it.

E2: That loc isn't leaking.. It loops through every LightFormIndex, so that RemoveLocation call clears all the locations.
 
Last edited:
Level 12
Joined
Mar 24, 2011
Messages
1,082
Ok, true that for the index.
The point has to be cleared though.

Looks ok on all other aspects... will keep looking for a bit.

Edit// I could only guess that assignments to dead units don't work as expected...
Have you tried debugging yourself ?

-Ned
 
Last edited:
Level 8
Joined
Jul 6, 2012
Messages
65
I don't see anything wrong with your index/deindex method. Given you have other spells using the same indexing system, maybe one of the other spells is accidently using a variable meant for this spell? Would you be able to confirm if this spell works in a map by itself?

I tried that before. I tested it on an new empty map with just those 2 codes, and it had the same result.

Edit// I could only guess that assignments to dead units don't work as expected...
Have you tried debugging yourself ?

-Ned

I have tried a few things, and all I figured out is that it works if I remove the leak clearing part, as mentioned in OP. If I turn off the last 8 lines of the trigger, it works fine, so the issue lies in there somewhere.
 
  • Custom script: call RemoveLocation(udg_LightFormDeathLoc[udg_LightFormDeathIndex]) /////ADD THIS LINE
The point has to be cleared though.
No, because the Loc[DeathIndex] object itself is still needed, and now also stored in Loc[LoopIndex]. If, then the Loc[DeathIndex] should only be nulled, but not removed.

The problem is the select for player, like:
  • Selection - Add LightFormDeathHero[LightFormDeathLoop] to selection for (Owner of LightFormDeathHero[LightFormDeathLoop])
^because it's not instant. Select operation takes some time, and so the all actions after the select operation are delayed, too. Within this time-gap another run of the periodic trigger might fire, and bug out.
 
Level 12
Joined
Mar 24, 2011
Messages
1,082
I've found something particulatly interesting and weird in the map provided...
LightFormDeathLoop has no data type, it is not an integer, just empty type...

...are you using any sort of custom WE ????

@IcemanBo Mmmm, you sure on that? As I see it, the last index loc has to be recycled.
Edit// Oh, hold on, In some variable types, Variable = Variable created reference while Variable = Data copied the data onto the variable for some var types, as such removing Index also removes Loop in that particular code... ???

-Ned
 
Last edited:
Level 8
Joined
Jul 6, 2012
Messages
65
I've found something particulatly interesting and weird in the map provided...
LightFormDeathLoop has no data type, it is not an integer, just empty type...

...are you using any sort of custom WE ????

I copy-pasted the triggers onto the new map, it auto-generates the variables when doing that. No idea why it wouldn't show its type. Regardless, variable still seems to work and behave normally.

I don't use anything else but the default wc3 editor.
 
Any way force-select units instantly without it messing up triggers?
  1. I would de-couple the revive part from loop trigger.

  2. Instead of dynamic indexing, I would use hashtable, or indexer approach (under MUI topic explained in case it's new to you), example: GUI unit Indexer

  3. So I would put died heroes in a group onDeath event. Using hero's custom value you attach all data, like the dummy unit.

  4. Loop over the death hero group periodically, and use the custom value of "PickedUnit" to access binded data here again. The loop logics only handles the timed logics, where you check for certain values. When times runs out you remove hero from group, so loop doesn't run anymore.

  5. Then, in a seperate trigger, you catch the event when a hero revives. You check if dummy unit exists with custom value of revived hero, and move it there. Data recylcing or cleaning of attached data can be done here, too.
Don't be too afraid of many changes, I think finaly it's doable and will be a bit cleaner code to overlook. Or we may help, too, if I was missing something.

I've found something particulatly interesting and weird in the map provided...
LightFormDeathLoop has no data type, it is not an integer, just empty type...
Regardless, variable still seems to work and behave normally.
It was faulty generated, it might happen with.. I'm not very sure, iirc with combination of renaming, but idk anymore. But yes, the demo didn't work - one first needs to reselect the type "integer" for the loop variable, to make the variable work.
 
Status
Not open for further replies.
Top