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

Help! Trying to make a trigger for a collapsing ceiling on each hero unit in a region

Status
Not open for further replies.
Level 4
Joined
Nov 16, 2019
Messages
55
So I am making this boss fight with a huge dragon. And basically it has a phase where it breathes fire 6 times in 6 angles around it. Once it is done with breathing fire, the ceiling will collapse at the point of where each hero stands after while. I tried to make a trigger for it here. It seems to be in the "Falling Ceiling Zone" trigger, where something goes wrong, but I am not sure what. When I test the fight, none of the components of the trigger activates at all (And yes, player hero units are present in the region while testing).

1624841729213.png


1624841789367.png
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,540
You can't use Waits inside of the Pick Every Unit function. Here's a working design that uses variables to keep track of the necessary information over a period of time. Note that I cleaned up the Unit Group / Point memory leaks and slightly tweaked some things. The variables are very important to prevent bugs and have things work properly.

When it comes to Waits and Event Responses you need to be careful since they're shared between all triggers. This means that things like "Last created unit" can easily change in the middle of your trigger without you wanting it to. For example, after you create your Dummy unit you refer to it 3 seconds later using "Last created unit", but there's no guarantee that the Dummy is still going to be considered the Last unit that was created. Perhaps the player summoned a Water Elemental, or maybe some other trigger ran that Created a unit, these things need to be kept into consideration and avoided. That's where variables come into play.


This trigger gets all of the living heroes in Cavern of Forgotten Terror, adds them to a Unit Group, and begins the Spawning Rocks process.
  • Falling Ceiling Zone
    • Events
    • Conditions
    • Actions
      • Set VariableSet Uzgor_Group = (Units in (Cavern Of Forgotten Terror <gen>) matching ((((Matching unit) is A Hero) Equal to True) and (((Matching unit) is alive) Equal to True)))
      • Set VariableSet Uzgor_Count = (Number of units in Uzgor_Group)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Uzgor_Count Greater than 0
        • Then - Actions
          • Trigger - Turn on Remove Dead Heroes <gen>
          • Trigger - Run Spawn Rocks <gen> (ignoring conditions)
        • Else - Actions
          • Custom script: call DestroyGroup (udg_Uzgor_Group)

This picks a random living hero and spawns a rock on it. Then it checks to see if there's any targets left in the group and repeats the process if so:
  • Spawn Rocks
    • Events
    • Conditions
    • Actions
      • Set VariableSet Uzgor_Target = (Random unit from Uzgor_Group)
      • Unit Group - Remove Uzgor_Target from Uzgor_Group.
      • Set VariableSet Uzgor_Count = (Uzgor_Count - 1)
      • Wait 0.50 seconds
      • -------- --------
      • Set VariableSet Uzgor_Point = (Center of (Cavern Of Forgotten Terror <gen>))
      • Unit - Create 1 Dummy for Neutral Hostile at Uzgor_Point facing Default building facing degrees
      • Custom script: call RemoveLocation (udg_Uzgor_Point)
      • Set VariableSet Uzgor_Dummy = (Last created unit)
      • Unit - Add a 10.00 second Generic expiration timer to Uzgor_Dummy
      • -------- --------
      • Wait 3.00 seconds
      • -------- --------
      • Unit - Add Collapse to Uzgor_Dummy
      • Set VariableSet Uzgor_Point = (Position of Uzgor_Target)
      • Unit - Order Uzgor_Dummy to Undead Dreadlord - Inferno Uzgor_Point
      • -------- --------
      • Wait 1.25 seconds
      • Destructible - Create a Rock Chunks at Uzgor_Point facing (Random angle) with scale 1.00 and variation 0
      • Custom script: call RemoveLocation (udg_Uzgor_Point)
      • -------- --------
      • -------- Do these actions last: --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Uzgor_Count Greater than 0
        • Then - Actions
          • -------- If there's still more heroes alive in the group then run this again: --------
          • Trigger - Run Spawn Rocks <gen> (ignoring conditions)
        • Else - Actions
          • -------- Otherwise, there are no more units left and the effect ends: --------
          • Trigger - Turn off Remove Dead Heroes <gen>
          • Custom script: call DestroyGroup (udg_Uzgor_Group)

Optional trigger: If a hero dies then you can prevent them from being a target for the spawning rocks by removing them from the group:
  • Remove Dead Heroes
    • Events
      • Unit - A unit Dies
    • Conditions
      • ((Triggering unit) is in Uzgor_Group.) Equal to True
    • Actions
      • Unit Group - Remove (Triggering unit) from Uzgor_Group.
      • Set VariableSet Uzgor_Count = (Number of units in Uzgor_Group)

Variables:
Uzgor_Group = Unit Group
Uzgor_Point = Point
Uzgor_Dummy = Unit
Uzgor_Target = Unit
Uzgor_Count = Integer

The attached map requires the latest version of Warcraft 3 and the triggers need to be adjusted to work in your map.
 

Attachments

  • Falling Ceiling Example.w3m
    18.6 KB · Views: 11
Last edited:
Level 4
Joined
Nov 16, 2019
Messages
55
You can't use Waits inside of the Pick Every Unit function. Here's a working design that uses variables to keep track of the necessary information over a period of time. Note that I cleaned up the Unit Group / Point memory leaks and slightly tweaked some things. The variables are very important to prevent bugs and have things work properly.

When it comes to Waits and Event Responses you need to be careful since they're shared between all triggers. This means that things like "Last created unit" can easily change in the middle of your trigger without you wanting it to. For example, after you create your Dummy unit you refer to it 3 seconds later using "Last created unit", but there's no guarantee that the Dummy is still going to be considered the Last unit that was created. Perhaps the player summoned a Water Elemental, or maybe some other trigger ran that Created a unit, these things need to be kept into consideration and avoided. That's where variables come into play.


This trigger gets all of the living heroes in Cavern of Forgotten Terror, adds them to a Unit Group, and begins the Spawning Rocks process.
  • Falling Ceiling Zone
    • Events
    • Conditions
    • Actions
      • Set VariableSet Uzgor_Group = (Units in (Cavern Of Forgotten Terror <gen>) matching ((((Matching unit) is A Hero) Equal to True) and (((Matching unit) is alive) Equal to True)))
      • Set VariableSet Uzgor_Count = (Number of units in Uzgor_Group)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Uzgor_Count Greater than 0
        • Then - Actions
          • Trigger - Turn on Remove Dead Heroes <gen>
          • Trigger - Run Spawn Rocks <gen> (ignoring conditions)
        • Else - Actions
          • Custom script: call DestroyGroup (udg_Uzgor_Group)

This picks a random living hero and spawns a rock on it. Then it checks to see if there's any targets left in the group and repeats the process if so:
  • Spawn Rocks
    • Events
    • Conditions
    • Actions
      • Set VariableSet Uzgor_Target = (Random unit from Uzgor_Group)
      • Unit Group - Remove Uzgor_Target from Uzgor_Group.
      • Set VariableSet Uzgor_Count = (Uzgor_Count - 1)
      • Wait 0.50 seconds
      • -------- --------
      • Set VariableSet Uzgor_Point = (Center of (Cavern Of Forgotten Terror <gen>))
      • Unit - Create 1 Dummy for Neutral Hostile at Uzgor_Point facing Default building facing degrees
      • Custom script: call RemoveLocation (udg_Uzgor_Point)
      • Set VariableSet Uzgor_Dummy = (Last created unit)
      • Unit - Add a 10.00 second Generic expiration timer to Uzgor_Dummy
      • -------- --------
      • Wait 3.00 seconds
      • -------- --------
      • Unit - Add Collapse to Uzgor_Dummy
      • Set VariableSet Uzgor_Point = (Position of Uzgor_Target)
      • Unit - Order Uzgor_Dummy to Undead Dreadlord - Inferno Uzgor_Point
      • -------- --------
      • Wait 1.25 seconds
      • Destructible - Create a Rock Chunks at Uzgor_Point facing (Random angle) with scale 1.00 and variation 0
      • Custom script: call RemoveLocation (udg_Uzgor_Point)
      • -------- --------
      • -------- Do these actions last: --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Uzgor_Count Greater than 0
        • Then - Actions
          • -------- If there's still more heroes alive in the group then run this again: --------
          • Trigger - Run Spawn Rocks <gen> (ignoring conditions)
        • Else - Actions
          • -------- Otherwise, there are no more units left and the effect ends: --------
          • Trigger - Turn off Remove Dead Heroes <gen>
          • Custom script: call DestroyGroup (udg_Uzgor_Group)

Optional trigger: If a hero dies then you can prevent them from being a target for the spawning rocks by removing them from the group:
  • Remove Dead Heroes
    • Events
      • Unit - A unit Dies
    • Conditions
      • ((Triggering unit) is in Uzgor_Group.) Equal to True
    • Actions
      • Unit Group - Remove (Triggering unit) from Uzgor_Group.
      • Set VariableSet Uzgor_Count = (Number of units in Uzgor_Group)

Variables:
Uzgor_Group = Unit Group
Uzgor_Point = Point
Uzgor_Dummy = Unit
Uzgor_Target = Unit
Uzgor_Count = Integer

The attached map requires the latest version of Warcraft 3 and the triggers need to be adjusted to work in your map.

Thank you so much! Works like a charm. I was however expecting the ceiling to collapse on all units at the same time, rather than periodically after eachother, but this actually makes up for a more interesting mechanic anyways, so cheers :)
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,540
Thank you so much! Works like a charm. I was however expecting the ceiling to collapse on all units at the same time, rather than periodically after eachother, but this actually makes up for a more interesting mechanic anyways, so cheers :)
No problem, here's how you could make it collapse on all units at the same time.
  • Spawn Rocks
    • Events
    • Conditions
    • Actions
      • Custom script: local unit udg_Uzgor_Target = GetEnumUnit()
      • Custom script: local unit udg_Uzgor_Dummy
      • Custom script: local location udg_Uzgor_Point
      • Wait 0.50 seconds
      • -------- --------
      • Set VariableSet Uzgor_Point = (Center of (Playable map area))
      • Unit - Create 1 Dummy for Neutral Hostile at Uzgor_Point facing Default building facing degrees
      • Set VariableSet Uzgor_Dummy = (Last created unit)
      • Unit - Add a 10.00 second Generic expiration timer to Uzgor_Dummy
      • -------- --------
      • Wait 3.00 seconds
      • -------- --------
      • Unit - Add Collapse to Uzgor_Dummy
      • Custom script: call MoveLocation(udg_Uzgor_Point, GetUnitX(udg_Uzgor_Target), GetUnitY(udg_Uzgor_Target))
      • Unit - Order Uzgor_Dummy to Undead Dreadlord - Inferno Uzgor_Point
      • -------- --------
      • Wait 1.25 seconds
      • Destructible - Create a Rock Chunks at Uzgor_Point facing (Random angle) with scale 1.00 and variation 0
      • -------- --------
      • -------- Clean up memory leaks: --------
      • Custom script: call RemoveLocation (udg_Uzgor_Point)
      • Custom script: set udg_Uzgor_Point = null
      • Custom script: set udg_Uzgor_Dummy = null
      • Custom script: set udg_Uzgor_Target = null
  • Falling Ceiling Zone
    • Events
    • Conditions
    • Actions
      • Set VariableSet Uzgor_Group = (Units in (Playable map area) matching ((((Matching unit) is A Hero) Equal to True) and (((Matching unit) is alive) Equal to True)))
      • Unit Group - Pick every unit in Uzgor_Group and do (Actions)
        • Loop - Actions
          • Trigger - Run Spawn Rocks <gen> (ignoring conditions)
      • -------- --------
      • -------- Clean up memory leaks: --------
      • Custom script: call DestroyGroup (udg_Uzgor_Group)

So I scrapped Uzgor_Count and the whole "repeat process" stuff and instead relied on the Pick Every Unit function + running the Spawn Rocks trigger once for each unit. GetEnumUnit() is the Jass term for "Picked unit" in case you were wondering.

I know I said Waits don't work inside of the Pick Every Unit function but this an exception since the Waits are technically in the Run trigger and not the function itself.

Finally, to make sure that our Variables don't get overwritten I use a trick called "Shadowing" which turns our global variables into local variables. Local variables are different from global variables in that they're unique entities that only exist in the instance (Trigger) that created them. This means that we don't have to worry about another trigger or the same trigger running again and messing with their values.

The Shadowing trick allows us to use these local variables in a way that's normally not possible. They sort of turn into hybrid local/global variables.
So we can Set them like we do with Global variables -> Set Variable Uzgor_Point = (Center of (Playable map area)), but they retain the behavior of a local variable. Normally, you can't reference a local variable inside of a GUI function but this technique allows that.

The major flaw of Shadowing is that you can't reference your Shadowed variables inside of a Conditions block. This means that your If Then Else statements won't work properly if their Conditions use one of your Shadowed variables. If this doesn't really make any sense than don't worry too much. Long story short you can use this Shadowing technique to make MUI triggers that won't break/leak, you just need to make sure that you do it properly (basically, be wary of conditions in If Then Else statements).
 

Attachments

  • Falling Ceiling Example 2.w3m
    17.8 KB · Views: 13
Last edited:
Status
Not open for further replies.
Top