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

[Trigger] Replacing Random N Units Depending on Duration

Status
Not open for further replies.
Hello, i would like to ask what's wrong with my triggers, i can't figure out how to make it work.

The goal is when the storm duration ends all the collector units (collector without water) should have been replaced with a new unit (collector with water).

Edit: Yes i did convert Real to Integers, im sure there's something wrong with that part. Also, i've set the divisor to "/ 5" at the second trigger because the loop at the third trigger is set to 5 seconds. There are also 64 water collectors (empty) placed.

  • Rad Storm Init
    • Events
      • Time - Elapsed game time is 0.00 seconds
    • Conditions
    • Actions
      • Environment - Create at (Playable map area) the weather effect Ashenvale Rain (Light)
      • Set Storm_Weather = (Last created weather effect)
      • Set Storm_Countdown = 5.00
      • Set Storm_Duration = 30.00
      • Set Storm_CountdownInt = (Integer(Storm_Countdown))
      • Set Storm_DurationInt = (Integer(Storm_Duration))
      • Environment - Turn Storm_Weather Off
      • Trigger - Run Rad Storm Setup <gen> (ignoring conditions)
  • Rad Storm Fill Water Collectors
    • Events
    • Conditions
    • Actions
      • Set Storm_MathStuff = (Storm_DurationInt / 5)
      • Set Storm_WaterCollectorsGroup = (Random ((Number of units in (Units of type Rain Collector (Without Water))) / Storm_MathStuff) units from (Units of type Rain Collector (Without Water)))
      • Unit Group - Pick every unit in Storm_WaterCollectorsGroup and do (Actions)
        • Loop - Actions
          • Unit - Add a 0.03 second Generic expiration timer to (Picked unit)
      • Custom script: call DestroyGroup(udg_Storm_WaterCollectorsGroup)
  • Rad Storm Loop
    • Events
      • Time - Every 5.00 seconds of game time
    • Conditions
    • Actions
      • Set Storm_Sound = (Last played sound)
      • Sound - Play MonsoonLightningHit <gen>
      • Cinematic - Fade in over Storm_RealLoop seconds using texture White Mask and color (100.00%, 100.00%, 100.00%) with 90.00% transparency
      • Custom script: call SetDayNightModels("Environment\\DNC\\DNCDungeon\\DNCDungeonTerrain\\DNCDungeonTerrain.mdl" , "Environment\\DNC\\DNCDungeon\\DNCDungeonUnit\\DNCDungeonUnit.mdl")
      • Wait 0.05 seconds
      • Custom script: call SetDayNightModels("Environment\\DNC\\DNCAshenvale\\DNCAshenvaleTerrain\\DNCAshenvaleTerrain.mdl" , "Environment\\DNC\\DNCAshenvale\\DNCAshenvaleUnit\\DNCAshenvaleUnit.mdl")
      • Trigger - Run Rad Storm Fill Water Collectors <gen> (ignoring conditions)
      • Sound - Stop Storm_Sound After fading
      • Sound - Destroy Storm_Sound
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,024
  • You didn't post the trigger Rad Storm Setup, which is run by the Init trigger.
  • You're leaking two groups, one each time you use: (Units of type Rain Collector (Without Water))
  • If you want to make it easy to configure the frequency of the Loop trigger, you can remove the event from it and add it manually from within any trigger than runs on map init:
    Trigger - Add to Rad Storm Loop <gen> the event: Time - Every Storm_Countdown seconds of game-time
  • Why are you also storing the values or Storm_Countdown and Storm_Duration as integers? Integer division truncates and never rounds, so you usually want to do all of your computation as reals and then convert to an integer at the end step, not the beginning step. I2R is not a computationally taxing conversion and can be done many times in rapid succession without issue.

  • Your math results in 0 collectors being picked: (Storm_MathStuff / (Number of units in (Units of type Rain Collector (Without Water)))) translates to (30/5)/64. Integer division truncates and does not round so 6/64 = 0.

  • Rad Storm Fill Water Collectors
    • Events
    • Conditions
    • Actions
      • -------- these can both be set on map init --------
      • Set TOTAL_COLLECTORS = 64
      • Set FILL_NUM = TOTAL_COLLECTORS / Real((Storm_Duration / Storm_Countdown))
      • -------- --------
      • Set Storm_WaterCollectorsGroup = (Units of type Rain Collector (Without Water))
      • Set TempGroup = Random FILL_NUM units from Storm_WaterCollectorsGroup
      • Unit Group - Pick every unit in TempGroup and do (Actions)
        • Loop - Actions
          • Unit - Add a 0.03 second Generic expiration timer to (Picked unit)
      • Custom script: call DestroyGroup(udg_Storm_WaterCollectorsGroup)
      • Custom script: call DestroyGroup(udg_TempGroup)
Now the problem here is that to fill all of the collectors in 6 chunks (one every 5 seconds) you would need to fill 10.66 collectors per chunk. But you can't fill a partial collector because that rounds down to 10, so you will have to decide what to do with those 4 unfilled ones. Do you fill them at the beginning of the storm? At the end? Do you slightly up the fill rate by 1 for the first 4 chunks? That's for you to decide.
 
You didn't post the trigger Rad Storm Setup, which is run by the Init trigger.

That trigger only set up the countdown timers, there's nothing in there related to the topic/problem.

  • Rad Storm Setup
    • Events
    • Conditions
    • Actions
      • Countdown Timer - Create a timer window for Storm_Timer with title Storm
      • Set Storm_TimerWindow = (Last created timer window)
      • Countdown Timer - Start Storm_Timer as a One-shot timer that will expire in Storm_Countdown seconds
      • Countdown Timer - Show Storm_TimerWindow
      • Countdown Timer - Resume Storm_Timer
If you want to make it easy to configure the frequency of the Loop trigger, you can remove the event from it and add it manually from within any trigger than runs on map init:
Trigger - Add to Rad Storm Loop <gen> the event: Time - Every Storm_Countdown seconds of game-time

I actually didn't know about this, thank you for letting me know!

You're leaking two groups, one each time you use: (Units of type Rain Collector (Without Water))

I'm aware about this lol, i did add it afterwards.

Why are you also storing the values or Storm_Countdown and Storm_Duration as integers? Integer division truncates and never rounds, so you usually want to do all of your computation as reals and then convert to an integer at the end step, not the beginning step. I2R is not a computationally taxing conversion and can be done many times in rapid succession without issue.

I stored it to integers so i can do math, i never thought you can actually math real numbers here since Arithmetic only accepts integers (by default). I did not know about Real() until you mentioned it here.

Now the problem here is that to fill all of the collectors in 6 chunks (one every 5 seconds) you would need to fill 10.66 collectors per chunk. But you can't fill a partial collector because that rounds down to 10, so you will have to decide what to do with those 4 unfilled ones. Do you fill them at the beginning of the storm? At the end? Do you slightly up the fill rate by 1 for the first 4 chunks? That's for you to decide.

I added +1 before dividing Total Count & Duration so it will not leave a single one after the rain event.

  • Rad Storm Fill Water Collectors
    • Events
    • Conditions
    • Actions
      • Set Storm_MathConvertToReal = (1.00 + ((Real(Storm_TotalCountBeforeStorm)) / Storm_Duration))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Storm_MathConvertToReal Less than or equal to 1.00
        • Then - Actions
          • Set Storm_MathConvertToReal = 0.00
        • Else - Actions
      • Set Storm_WaterCollectorsGroup = (Units of type Rain Collector (Without Water))
      • Set Storm_WaterCollectorsGroupTemp = (Random Storm_TotalCountBeforeStorm units from Water_CollectorsGroup)
      • Game - Display to (All players) the text: (String(Storm_MathConvertToReal))
      • Unit Group - Pick every unit in Storm_WaterCollectorsGroupTemp and do (Actions)
        • Loop - Actions
          • Unit - Add a 0.03 second Generic expiration timer to (Picked unit)
      • Custom script: call DestroyGroup(udg_Storm_WaterCollectorsGroup)
      • Custom script: call DestroyGroup(udg_Storm_WaterCollectorsGroupTemp)
  • Rad Storm Coming
    • Events
      • Time - Storm_Timer expires
    • Conditions
    • Actions
      • Countdown Timer - Hide Storm_TimerWindow
      • Countdown Timer - Pause Storm_Timer
      • Environment - Turn Storm_Weather On
      • Set Storm_TotalCountBeforeStorm = (Number of units in (Units of type Rain Collector (Without Water)))
      • Trigger - Turn on Rad Storm Loop <gen>
      • Wait Storm_Duration seconds
      • Trigger - Turn off Rad Storm Loop <gen>
      • Environment - Turn Storm_Weather Off
      • Trigger - Run Rad Storm Setup <gen> (ignoring conditions)
  • Rad Storm Loop
    • Events
      • Time - Every 5.00 seconds of game time
    • Conditions
    • Actions
      • Sound - Play MonsoonLightningHit <gen>
      • Set Storm_Sound = (Last played sound)
      • Cinematic - Fade in over 0.05 seconds using texture White Mask and color (100.00%, 100.00%, 100.00%) with 90.00% transparency
      • Custom script: call SetDayNightModels("Environment\\DNC\\DNCDungeon\\DNCDungeonTerrain\\DNCDungeonTerrain.mdl" , "Environment\\DNC\\DNCDungeon\\DNCDungeonUnit\\DNCDungeonUnit.mdl")
      • Wait 0.05 seconds
      • Custom script: call SetDayNightModels("Environment\\DNC\\DNCAshenvale\\DNCAshenvaleTerrain\\DNCAshenvaleTerrain.mdl" , "Environment\\DNC\\DNCAshenvale\\DNCAshenvaleUnit\\DNCAshenvaleUnit.mdl")
      • Trigger - Run Rad Storm Fill Water Collectors <gen> (ignoring conditions)
      • Sound - Stop Storm_Sound After fading
      • Sound - Destroy Storm_Sound
This works now. Thank you very much.

By the way, may i ask, shouldn't i avoid using "Units of Type" function? I read here Things That Leak it says Units of Type shouldn't be used, I might be wrong here i'm not really that good at triggers.
 
Last edited:
Status
Not open for further replies.
Top