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

[Trigger] Unit selection group GUI glitch? Help!

Status
Not open for further replies.
Level 11
Joined
Feb 11, 2010
Messages
199
So, I've got a 95% finished spell that requires that the casting unit be hidden during the effect then unhidden when the effect is finished. When unhidden, I want the spell to check if the player has any units selected and, if not, reselect the casting hero when it is unhidden automatically (to make it more like a spell that *doesn't* involve pausing/hiding).

Now on its face, this would seem simple. You would just have something like so:

  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • ((Units currently selected by ThundergodOwner[ThundergodA]) is empty) Equal to True
    • Then - Actions
      • Selection - Select ThundergodCaster[ThundergodA] for ThundergodOwner[ThundergodA]
    • Else - Actions
However, this doesn't work (e.g, the unit ThundergodCaster[ThundergodA] is not being selected) is not being selected), and it's not a problem with the indexing or anything like that. That is to say, if I put
  • Selection - Select ThundergodCaster[ThundergodA] for ThundergodOwner[ThundergodA]
in without any if, things work fine. Also, if I put in
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • ((Units currently selected by ThundergodOwner[ThundergodA]) is empty) Equal to True
    • Then - Actions
      • Game - Display to (All players) the text: Condition Is Working
    • Else - Actions
, likewise, I get a confirmation that the trigger is working just fine. The only conclusion I can reach is that Blizzard's "Units selected" function is glitched in such a way that you can't put two units selected functions together without messing up indexing in a completely erroneous fashion.

This being the case, what sort of workarounds are available? Is there some kind of custom script I can use in place of Blizzard's buggy GUI script? Tell me!

+Rep of course for anyone who can help.
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
  • ((Units currently selected by ThundergodOwner[ThundergodA]) is empty) Equal to True
To stop the memory leak you're getting here, you need to do this:

  • Set Group = (Units currently selected by ThundergodOwner[ThundergodA])
  • If Group is Empty Equal To True
    • Then - Actions
    • Else - Actions
  • Custom script: call DestroyGroup(udg_Group)
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
You haven't really given a description of what is going wrong. Why don't you try putting a Game message and display how many units are currently selected by the player --that way you know if it's a problem with the blizzard native, or perhaps you're overlooking something.

From my experience, "Units selected by Player" works fine.
 
Level 11
Joined
Feb 11, 2010
Messages
199
You haven't really given a description of what is going wrong.
It is not selecting the unit. It will select the unit if I put the selection action OUTSIDE of the "then". This is odd, because everything ELSE I put inside the "then" DOES run. Just not the selection bit. Not sure how I can be much more clear than that...

Why don't you try putting a Game message and display how many units are currently selected by the player --that way you know if it's a problem with the blizzard native, or perhaps you're overlooking something.

I have already tried this. It displays "0." I also gave an example in the OP that accomplishes the same thing as what you're suggesting ("if 0, display true" displays true)

  • ((Units currently selected by ThundergodOwner[ThundergodA]) is empty) Equal to True
To stop the memory leak you're getting here, you need to do this:

  • Set Group = (Units currently selected by ThundergodOwner[ThundergodA])
  • If Group is Empty Equal To True
    • Then - Actions
    • Else - Actions
  • Custom script: call DestroyGroup(udg_Group)

Yes, I've already done that in my map, I just skipped that part in the OP to make the post shorter and more concise. And the problem I'm having isn't a leak.

  • Thundergod
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Thundergod
    • Actions
      • Set Thundergod = (Thundergod + 1)
      • Set ThundergodSkip = (ThundergodSkip + 1)
      • Set ThundergodCaster[Thundergod] = (Triggering unit)
      • Set ThundergodPoint1[Thundergod] = (Position of ThundergodCaster[Thundergod])
      • Set ThundergodPoint2[Thundergod] = (Target point of ability being cast)
      • Set ThundergodDistance[Thundergod] = (Distance between ThundergodPoint1[Thundergod] and ThundergodPoint2[Thundergod])
      • Set ThundergodAngle[Thundergod] = (Angle from ThundergodPoint1[Thundergod] to ThundergodPoint2[Thundergod])
      • Set ThundergodOn3[Thundergod] = True
      • Set ThundergodSpeed[Thundergod] = (ThundergodDistance[Thundergod] / 10.00)
      • Set ThundergodOwner[Thundergod] = (Owner of ThundergodCaster[Thundergod])
      • Unit - Create 1 Dummy(Thundergod2) for ThundergodOwner[Thundergod] at ThundergodPoint1[Thundergod] facing ThundergodAngle[Thundergod] degrees
      • Unit - Add a 1.50 second Generic expiration timer to (Last created unit)
      • Unit - Hide ThundergodCaster[Thundergod]
      • Unit - Create 1 Dummy(Thundergod Node) for ThundergodOwner[Thundergod] at ThundergodPoint1[Thundergod] facing ThundergodAngle[Thundergod] degrees
      • Set ThundergodDummy[Thundergod] = (Last created unit)
      • Unit - Add Storm Crow Form to ThundergodDummy[Thundergod]
      • Unit - Remove Storm Crow Form from ThundergodDummy[Thundergod]
      • Unit - Add Storm Crow Form to ThundergodCaster[Thundergod]
      • Unit - Remove Storm Crow Form from ThundergodCaster[Thundergod]
      • Special Effect - Create a special effect at ThundergodPoint1[Thundergod] using Abilities\Spells\Other\GeneralAuraTarget\GeneralAuraTarget.mdl
      • Set ThundergodSpecial[Thundergod] = (Last created special effect)
      • Animation - Change ThundergodDummy[Thundergod] flying height to 900.00 at 800.00
      • Set ThundergodTimer[Thundergod] = (MASTERTIMER + 0.90)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ThundergodSkip Equal to 1
        • Then - Actions
          • Trigger - Turn on Thundergod Loop <gen>
        • Else - Actions
      • Custom script: call RemoveLocation(udg_ThundergodPoint1[udg_Thundergod])
      • Custom script: call RemoveLocation(udg_ThundergodPoint2[udg_Thundergod])
  • Thundergod Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer ThundergodA) from 1 to Thundergod, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ThundergodOn3[ThundergodA] Equal to True
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • MASTERTIMER Greater than or equal to ThundergodTimer[ThundergodA]
                • Then - Actions
                  • Set ThundergodOn[ThundergodA] = True
                  • Set ThundergodOn3[ThundergodA] = False
                • Else - Actions
                  • Animation - Change ThundergodCaster[ThundergodA] flying height to ((Current flying height of ThundergodCaster[ThundergodA]) + 27.00) at 0.00
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ThundergodOn[ThundergodA] Equal to True
                • Then - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • ThundergodDistance[ThundergodA] Less than or equal to 0.00
                    • Then - Actions
                      • Set ThundergodOn[ThundergodA] = False
                      • Set ThundergodOn2[ThundergodA] = True
                      • Set ThundergodTimer[ThundergodA] = (MASTERTIMER + 1.00)
                      • Animation - Change ThundergodDummy[ThundergodA] flying height to 0.00 at 900.00
                      • Set ThundergodPoint2[ThundergodA] = (Position of ThundergodDummy[ThundergodA])
                      • Special Effect - Create a special effect at ThundergodPoint2[ThundergodA] using war3mapImported\Mjolnir.mdx
                      • Special Effect - Destroy (Last created special effect)
                      • Custom script: call RemoveLocation(udg_ThundergodPoint2[udg_ThundergodA])
                    • Else - Actions
                      • Set ThundergodDistance[ThundergodA] = (ThundergodDistance[ThundergodA] - ThundergodSpeed[ThundergodA])
                      • Set ThundergodPoint1[ThundergodA] = (Position of ThundergodDummy[ThundergodA])
                      • Set ThundergodPoint2[ThundergodA] = (ThundergodPoint1[ThundergodA] offset by ThundergodSpeed[ThundergodA] towards ThundergodAngle[ThundergodA] degrees)
                      • Unit - Move ThundergodDummy[ThundergodA] instantly to ThundergodPoint2[ThundergodA]
                      • Unit - Move ThundergodCaster[ThundergodA] instantly to ThundergodPoint2[ThundergodA]
                      • Special Effect - Destroy ThundergodSpecial[ThundergodA]
                      • Special Effect - Create a special effect at ThundergodPoint2[ThundergodA] using Abilities\Spells\Other\GeneralAuraTarget\GeneralAuraTarget.mdl
                      • Set ThundergodSpecial[ThundergodA] = (Last created special effect)
                      • Custom script: call RemoveLocation(udg_ThundergodPoint1[udg_ThundergodA])
                      • Custom script: call RemoveLocation(udg_ThundergodPoint2[udg_ThundergodA])
                • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • ThundergodOn2[ThundergodA] Equal to True
                    • Then - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • MASTERTIMER Greater than or equal to ThundergodTimer[ThundergodA]
                        • Then - Actions
                          • Set ThundergodOn2[ThundergodA] = False
                          • Set ThundergodPoint2[ThundergodA] = (Position of ThundergodDummy[ThundergodA])
                          • Special Effect - Destroy ThundergodSpecial[ThundergodA]
                          • Unit - Unhide ThundergodCaster[ThundergodA]
                          • Unit - Move ThundergodCaster[ThundergodA] instantly to ThundergodPoint2[ThundergodA]
                          • Unit - Kill ThundergodDummy[ThundergodA]
                          • Special Effect - Create a special effect at ThundergodPoint2[ThundergodA] using Abilities\Spells\Human\ThunderClap\ThunderClapCaster.mdl
                          • Special Effect - Destroy (Last created special effect)
                          • -------- W T F !? --------
                          • Set ThundergodSelection[ThundergodA] = (Units currently selected by ThundergodOwner[ThundergodA])
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • (ThundergodSelection[ThundergodA] is empty) Equal to True
                            • Then - Actions
                              • Selection - Select ThundergodCaster[ThundergodA] for ThundergodOwner[ThundergodA]
                            • Else - Actions
                          • Custom script: call DestroyGroup(udg_ThundergodSelection[udg_ThundergodA])
                          • Set ThundergodSkip = (ThundergodSkip - 1)
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • ThundergodSkip Equal to 0
                            • Then - Actions
                              • Set Thundergod = 0
                              • Trigger - Turn off (This trigger)
                            • Else - Actions
                          • Custom script: call RemoveLocation(udg_ThundergodPoint2[udg_ThundergodA])
                        • Else - Actions
                          • Animation - Change ThundergodCaster[ThundergodA] flying height to ((Current flying height of ThundergodCaster[ThundergodA]) - 27.00) at 0.00
                    • Else - Actions
The full trigger. See the area around the comment labeled "WTF!?"
 
Last edited:
Level 18
Joined
Jan 21, 2006
Messages
2,552
Ah yes, the GUI action uses EnumUnitsSelected which uses SyncSelections. That is the problem. Only another reason why JASS is so much better than GUI.
 
Last edited:
Level 18
Joined
Jan 21, 2006
Messages
2,552
This code has been tested, deselecting a unit and then trying to select it (using this method) afterward.

  • Actions
    • Custom script: call GroupEnumUnitsSelected(udg_Selection, udg_ThundergodOwner[udg_ThundergodA], null)
    • Set Selected = (Number of units in Selection)
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • Selected Equal to 0
      • Then - Actions
        • Selection - Select ThundergodCaster[ThundergodA] for ThundergodOwner[ThundergodA]
      • Else - Actions
    • Unit Group - Remove all units from Selection
 
Level 11
Joined
Feb 11, 2010
Messages
199
This code has been tested, deselecting a unit and then trying to select it (using this method) afterward.

  • Actions
    • Custom script: call GroupEnumUnitsSelected(udg_Selection, udg_ThundergodOwner[udg_ThundergodA], null)
    • Set Selected = (Number of units in Selection)
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • Selected Equal to 0
      • Then - Actions
        • Selection - Select ThundergodCaster[ThundergodA] for ThundergodOwner[ThundergodA]
      • Else - Actions
    • Unit Group - Remove all units from Selection

Your workaround works perfectly. Awesome. +Rep.
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
This code has been tested, deselecting a unit and then trying to select it (using this method) afterward.

  • Actions
    • Custom script: call GroupEnumUnitsSelected(udg_Selection, udg_ThundergodOwner[udg_ThundergodA], null)
    • Set Selected = (Number of units in Selection)
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • Selected Equal to 0
      • Then - Actions
        • Selection - Select ThundergodCaster[ThundergodA] for ThundergodOwner[ThundergodA]
      • Else - Actions
    • Unit Group - Remove all units from Selection

did you also test it for multiplayer?
it might cause desync in certain cases cause of local player abuse
 
In local player blocks, you need to avoid creating/destroying handles, using a string for the first time (first time it is entered in the string table), modifying anything gameplay-wise or generally modifying interactive stuff (especially units), assigning a new random seed, and TriggerSleepAction (waits). There are other cases as well where GetLocalPlayer() can just ruin your map, but as long as you avoid most these listed things, you can be safe.

For selecting, it is fine to use for local player. You might need to use SyncSelections() before grouping and retrieving selections, but GUI does that for you in their BJ functions (afaik) so it isn't something to worry about.

http://www.thehelper.net/forums/showthread.php?t=89207

^Might be of use, either that or the one on this site.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
PurgeandFire111 said:
For selecting, it is fine to use for local player. You might need to use SyncSelections() before grouping and retrieving selections, but GUI does that for you in their BJ functions (afaik) so it isn't something to worry about.

The BJ function is the reason why it wasn't working before.

Also, the only thing I can see having an effect on the result is the fact that I omitted the SyncSelections() command. This is the BJ function:

JASS:
function EnumUnitsSelected takes player whichPlayer, boolexpr enumFilter, code enumAction returns nothing
    local group g = CreateGroup()
    call SyncSelections()
    call GroupEnumUnitsSelected(g, whichPlayer, enumFilter)
    call DestroyBoolExpr(enumFilter)
    call ForGroup(g, enumAction)
    call DestroyGroup(g)
endfunction

Now, these are the important lines:

JASS:
    call SyncSelections()
    call GroupEnumUnitsSelected(g, whichPlayer, enumFilter)

I have used GroupEnumUnitsSelected before without much problem, though I can't say for sure in an online multiplayer game whether or not it will work properly. I really don't know what the heck the point of SyncSelections is.
 
Level 11
Joined
Feb 11, 2010
Messages
199
I thought that you tested it and it works fine? I'm quite certain that there is no problem behind avoiding SyncSelections.

I tested to see that it WORKED on a basic functional level (and, hey, even WAIT does that), not whether it caused desyncs or anything like that from repeated testing in online games. I'm not even sure how I would go about reliably testing for something like that.
 
I have used GroupEnumUnitsSelected before without much problem, though I can't say for sure in an online multiplayer game whether or not it will work properly. I really don't know what the heck the point of SyncSelections is.

I'm guessing SyncSelections() acts to develop a time period for the selection to occur on all computers. Not sure if it will desync without since I have never tested it.
 
Status
Not open for further replies.
Top