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

Spawns at Decreasing Intervals

Status
Not open for further replies.
Level 12
Joined
May 9, 2009
Messages
735
Hello again. For another type of farm building on my map I want units to be spawned. The way I thought it out would base the interval of the unit spawn on the amount of farm buildings present, so a unit would spawn every 120 - (11 x Y) seconds, where Y is the amount of farms. At 10 farms the interval would be reduced to 10 seconds and would no longer decrease regardless of any additional farms built.

The issue I am having is that I can't think of a way right now of pulling this off without creating an interval trigger for each interval and a ton of if/then/else which check over and over again for the owners to get it to work for all 9 players. Is there some cleaner way to do this?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
You could run a single trigger every 10 seconds and have a counter which increments/decrements for each player based on the relative progress to their spawn. When it overflows you spawn the unit for that player. Any remaining time carries over so that within 10 seconds the correct number of units spawn.

You could also give each player his own timer, map the player index to the timer (eg hashtable), use triggering timer to get the player index and then spawn and restart appropriately. When farms are built or lost you could restart the timer with corrected remaining time to reflect the change in productivity.
 
Level 19
Joined
Jul 2, 2011
Messages
2,162
when event, new farm house built, is triggered

stop and clear trigger queues of timer trigger (I don't know what you time trigger.is called)

and

run that same trigger again assuming you set the timer to, run every 120 -(11 x y)

easy
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
when event, new farm house built, is triggered

stop and clear trigger queues of timer trigger (I don't know what you time trigger.is called)

and

run that same trigger again assuming you set the timer to, run every 120 -(11 x y)

easy
You need to factor in the current time progressed. Specifically if it was 50% through spawning time it should restart 50% completed otherwise upgrading will cause a temporary reduction in spawn rate.
 
Level 12
Joined
May 9, 2009
Messages
735
You could run a single trigger every 10 seconds and have a counter which increments/decrements for each player based on the relative progress to their spawn. When it overflows you spawn the unit for that player. Any remaining time carries over so that within 10 seconds the correct number of units spawn.

You could also give each player his own timer, map the player index to the timer (eg hashtable), use triggering timer to get the player index and then spawn and restart appropriately. When farms are built or lost you could restart the timer with corrected remaining time to reflect the change in productivity.
That sounds like that would work but I don't know where to start on it. How would a trigger with this counter look like? I never worked with counters before :vw_wtf: (are they like timers?)
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
That sounds like that would work but I don't know where to start on it. How would a trigger with this counter look like? I never worked with counters before (are they like timers?)
They are reals or integers used to tally units. In this case the units represent time.

Similar to how you learn to count numbers to 10 on your fingers, you can use an integer to count ticks of a timer. Since each tick represents a unit of time, after a certain number of ticks a certain amount of time will have passed. If enough time has passed you can do some actions (spawn units, etc). You can also remove that time from the counter since it has been processed so there is no need to keep track of it. You can even use a loop to do this that keeps running actions and removing time until no more time can be removed from the counter.
 
Level 12
Joined
May 9, 2009
Messages
735
I cannot be certain what exactly you meant but this is what I got out of it.

Every 1 second (not ten seconds since I am dealing with numbers that are almost all not divisible by 10 (109, 98, 87 etc.)) increase an integer variable by 1 and also then check if this variable is not larger than the spawning interval, which is calculated by 120 - (11x(number of farms)).
  • one looong ass trigger Copy 2
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Set AAAIntegerSpawn1 = (AAAIntegerSpawn1 + 1)
      • Set AAAGroupSpawn1 = (Units owned by Player 1 (Red) of type Ziggurat)
      • Set AAAIntegerSpawnA1 = (120 - (11 x (Number of units in AAAGroupSpawn1)))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in AAAGroupSpawn1) Greater than or equal to 10
        • Then - Actions
          • Set AAAIntegerSpawnA1 = 10
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in AAAGroupSpawn1) Not equal to 0
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AAAIntegerSpawn1 Greater than or equal to AAAIntegerSpawnA1
            • Then - Actions
              • Set AAAGroupSpawnB1 = (Random 1 units from (Random 1 units from AAAGroupSpawn1))
              • Unit Group - Pick every unit in AAAGroupSpawnB1 and do (Actions)
                • Loop - Actions
                  • Set AAAPositionSpawn1 = (Position of (Picked unit))
                  • Unit - Create 1 Skeleton Warrior (real) for (Owner of (Picked unit)) at AAAPositionSpawn1 facing Default building facing degrees
                  • Set AAAPositionSpawn1 = (Position of (Last created unit))
                  • Special Effect - Create a special effect at AAAPositionSpawn1 using Abilities\Spells\Undead\RaiseSkeletonWarrior\RaiseSkeleton.mdl
                  • Special Effect - Destroy (Last created special effect)
              • Set AAAIntegerSpawn1 = 0
              • Custom script: call DestroyGroup (udg_AAAGroupSpawnB1)
              • Custom script: call RemoveLocation(udg_AAAPositionSpawn1)
            • Else - Actions
        • Else - Actions
      • Custom script: call DestroyGroup (udg_AAAGroupSpawn1)
this just works for one player though. I want to ask what is better, to make 9 of these triggers for each player or to make 1 very long trigger that simply has it all inside it?

also I first tried running the trigger every 120 - (11x(number of farms)) seconds but that didn't work as the periodic event option seems to bugged and doesn't allow for selection of any variable types at all... i can't even select my group variables if i go to "number of units in group" sub-category.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
this just works for one player though. I want to ask what is better, to make 9 of these triggers for each player or to make 1 very long trigger that simply has it all inside it?
You repeat the code for each player using a loop. Each player is given his own index in an array, representing his slot number. You can then lookup and set unique values for each player by using the player's slot number as the array index. The loop then repeats the action for each appropriate player. Since each player is unique, each iteration of the loop will give you a player with a different slot index so a different array index. Since player slot indices run from 0 to 15 they easily fit inside the dynamic arrays of WC3 with range 0 to 8191.

also I first tried running the trigger every 120 - (11x(number of farms)) seconds but that didn't work as the periodic event option seems to bugged and doesn't allow for selection of any variable types at all... i can't even select my group variables if i go to "number of units in group" sub-category.
Look at the JASS it produces and you will understand why. The event bindings are called at map initialization and have all their arguments passed by value. As such formula or any other kind of dynamic argument will be evaluated at map initialization into a constant and that value used forever by the event.
 
Level 7
Joined
Nov 19, 2015
Messages
283
Heres another idea

Trigger 01
Every 1 second
For integer A 1 to 12
set timer[integerA] = timer[integerA] -1
Pick all units in map (or you can have added the farms prior and remove when they leave the map)
If unit equal to farm and is alive
set player_num = player number of picked unit
Set timer[player_num] = timer[player_num]-0.1

Trigger 02
Game real variable timer[1-12] less than or equal to 0
For integer A 1 to 12
if timer[integerA] = 0
then player_num = integer A

Set timer[player_num] = 120
Do stuff for player_num

This would take into accoint if a farm was destroyed. It reduces the spawn time for as long as it is alive. You could also use a timer and reduce the time remaining. Same thing.
 
Status
Not open for further replies.
Top