Hi guys, i'm struggling with the issue of setting variables and checking conditions of an idle unit. What im looking to have happen with my trigger is that once a unit becomes idle a timer is started. Once that timer reaches 0, the unit must be checked to see if it is still idle. I'm looking for that unit to be tagged with a an "on/off" status (probably using a variable of some sort) so that If it is idle after the timer, then it runs the defeat trigger.
I have searched through many threads on these forums about idle units, but none have really offered a solution specific to my issue. The most suitable one was after the timer, checking whether player 1 had any idle units on the map. This is not ideal to me because if my scv becomes idle and the countdown starts, but i move him back to the mineral field the countdown still occurs, and if i have a new scv begin idleing, the trigger would activate anyway because there is still an idle unit provided it wasn't the same one. Obviously the new idle scv should get its own 10 second timer to be tested.
This image below shows my current setup. If anybody would be so kind as to suggest a way to make my goal possible, it would be greatly appreciated
The best way to achieve this is to have a Record which references your unit.
Inside the record you'd have the variables...
Current Position = Point
Old Position = Point
Moving = Boolean
You'd setup a periodic timer that sets the Current Position and compares it to the Old Position, if it's changed update the old position and keep looping. If it's the same, start a new timer and set the Moving boolean to False, if it's different set the Moving boolean to true.
Then you'd have another trigger that runs when the timer you created ends, check if the moving boolean is false, if so run defeat.
Sorry, but I'm not very good with the galaxy editor, only been using it for about a week.
I created a "new record" with the 4 variables you selected. I'm not entirely sure how to reference the unit which became idle. I thought I could do it through by setting the variable on the triggering unit but i cant even find how to apply the record.
I understand how to setup a periodic timer using Events, but how would i tell it to target 1 idle unit in comparison to another idle unit?
If you could explain some of the steps or offer a link to an article which offers more information on how to reference units to Records that would be very helpful. Sorry to be a bother :(
Ok, I have been playing with and tweaking the code you provided. I removed the pause and unpause feature because i am simply looking for the timer to activate once any unit is idle and provide that unit with 10 seconds to get non Idle or else the game will end. I loved the debug code so much that once the "Unit becomes Idle" (i replaced the "when unit enters map") trigger activates, It will place a timer on top that units idle location for 10 seconds which is the alloted time to move that unit.
What I would like to Do:
In the "Movement Vars" Trigger, I have set it so that if movement == false, it runs "lose" trigger. But if the movement == true and it runs the "else" function, I would like to clear the Player CountDown Timer for that specifcly for that unit. I'm looking for the equivalent of removing that unit from the UI_get_unit_index. This way if that unit were to idle again, it would start a fresh 10 seconds for the Player CountDown Timer. Without getting effected by any previous CountDown Timer.
Current Example:
at 0 seconds:
Unit goes idle.
CountDown Timer begins for 10 seconds.
at 5 seconds:
Unit moves becoming not idle.
at 6 seconds:
Unit becomes idle again.
New 10 second timer starts.
at 10 seconds:
the original timer will finish and check to see if unit is idle (which it is, but it hasn't been idle for 10 seconds its only been idle for 4)
Is there an easy way to do this using the else function i suggested in the Movement Vars Trigger? Below is a link provided to the modified code you sent me, if it helps for reference. Thank you for all your assistance.
There is a trigger event called "Unit becomes Idle". Use that to start your timer.
When the timer runs out, use the "Unit is in Unit Group" Condition with Unit Group "Idle Units of Player" and Player "Owner of Init" to check if your Units is still idle
Note that the second trigger is just for stopping the timer when the units is not idle any more.
You can use "Any Unit" instead of <My Unit>-Variablebut then the timer gets started when ever a unit gets idle.
Thank you for the help, the main issue I have had with the method you suggested is that it can not create a timer for multiple units at overlapping times..
Example:
at 0 seconds:
unit becomes idle.
10s timer starts.
at 5 seconds:
a different unit becomes idle.
Timer is reset to 10 seconds.
at 14 seconds:
second scv to idle tops being idle.
timer is paused
~~~~~
the first scv to idle can now remain idle indefinitely. So while this method is simple, it is not robust enough to handle what I am looking for. Thank you for your input, as always I appreciate any members help.
I managed to do what I believe you want. I did it using galaxy++ though, since that was way easier for dynamic arrays and such.
I split it into 3 script files - two utility files, and the map script. I attached them along with the output map and the raw galaxy script.
I know this is the GUI forum, but I just won't write all the GUI needed to do this, so I hope you are at least somewhat familiar with programming or galaxy.
If you plan to use it for a lot of units, I suggest adding a trigger that remove units/timers from the dictionary when the unit dies.
In case you want to make this in GUI, you can make dynamic arrays using the data table. The list is just a convenient wrapper around a dynamic array in G++. The dictionary uses two lists - in our case, a list of units and a list of their corresponding timers. Such that index i of the unit list is "linked" with index i of the timer list.
When a unit becomes idle, I then check if we had already created a timer for that unit by running through the unit list looking for our unit. If no timer was created, create one, add an event to the TimerEnd trigger (requires custom script), and add the unit and list to the dictionary. Next, start the timer as a 10 second non periodic timer.
When a unit is no longer idle, you first need to check if we had created a timer for that unit (again, run throught the unit list). If a timer had been created, pause it.
When the timer expires, you can fetch the unit from your dictionary by looking for the Triggering Timer.
All right.. We do a lot of running through a list, which takes linear time in the number of elements in the list. So if you use this system for many units, try to delete them from the lists when they die. Also, you can use constant data about the unit to make a more complex, and faster data structure (like unit type, owner and such). But if you are not that much into programming, it might be best to just stick with the arrays.
The way of using multiple timers, one for each SCV, is propably one of the best ways to approach.
But wouldn't it be much more efficient to use some kind of reuseable information about the unit/timer for dictionary keys instead of running through the entire list? I think that on a bigger amout of units or frequent stop and go commands the run-through method could create lags.
You could for example use a custom value for the unit. But something similar for a timer? dunno.
Just to clarify this:
Is your goal that if at least one SCV is idle for 10sec, the owning player getting defeated?
If so, there comes an other idea in my mind:
Use one timer for each player.
When a SCV gets idle and the timer for the owning player is not started, (re)start it.
When a SCV stops being idle, check if number of idle workers for that player is zero. If so, stop the timer, otherwise not.
When the timer expires, defeat the player.
by that, the timer gets started when the first SCV becomes idle and stoped, when the last stops being idle. In other words, it runs as long as any SCV of that player is idle.
Yeah, I know it might be less efficient for many units - that is what I meant by the last section about implementing a more complex data structure based on stuff like unit type and owner.
However, I won't go into details about that, since it is already complex enough as it is. First make it work, then optimize if efficiency is a problem. Creating unnecessary complex data structures just gives you lots of bugs.
Rollback Post to RevisionRollBack
To post a comment, please login or register a new account.
Hi guys, i'm struggling with the issue of setting variables and checking conditions of an idle unit. What im looking to have happen with my trigger is that once a unit becomes idle a timer is started. Once that timer reaches 0, the unit must be checked to see if it is still idle. I'm looking for that unit to be tagged with a an "on/off" status (probably using a variable of some sort) so that If it is idle after the timer, then it runs the defeat trigger.
I have searched through many threads on these forums about idle units, but none have really offered a solution specific to my issue. The most suitable one was after the timer, checking whether player 1 had any idle units on the map. This is not ideal to me because if my scv becomes idle and the countdown starts, but i move him back to the mineral field the countdown still occurs, and if i have a new scv begin idleing, the trigger would activate anyway because there is still an idle unit provided it wasn't the same one. Obviously the new idle scv should get its own 10 second timer to be tested.
This image below shows my current setup. If anybody would be so kind as to suggest a way to make my goal possible, it would be greatly appreciated
http://imageshack.us/photo/my-images/708/triggery.jpg/
@nrtwenty: Go
The best way to achieve this is to have a Record which references your unit.
Inside the record you'd have the variables...
Current Position = Point Old Position = Point Moving = Boolean
You'd setup a periodic timer that sets the Current Position and compares it to the Old Position, if it's changed update the old position and keep looping. If it's the same, start a new timer and set the Moving boolean to False, if it's different set the Moving boolean to true.
Then you'd have another trigger that runs when the timer you created ends, check if the moving boolean is false, if so run defeat.
@Dustin374: Go Thats very clever. I will definitely set that up, and let you know how it goes. Thank you!
@Dustin374: Go
Sorry, but I'm not very good with the galaxy editor, only been using it for about a week.
I created a "new record" with the 4 variables you selected. I'm not entirely sure how to reference the unit which became idle. I thought I could do it through by setting the variable on the triggering unit but i cant even find how to apply the record.
I understand how to setup a periodic timer using Events, but how would i tell it to target 1 idle unit in comparison to another idle unit?
If you could explain some of the steps or offer a link to an article which offers more information on how to reference units to Records that would be very helpful. Sorry to be a bother :(
@nrtwenty: Go
Here, I whipped this up.
http://dl.dropbox.com/u/843426/Unit%20Idle%20Check%20By%20Dustin.SC2Map
Tell me if you have any questions about it.
@Dustin374: Go
This is tremendously helpful. I will be taking time to analyze and learn from your example. Thanks for all your help so far.
@Dustin374: Go
What I've Done:
Ok, I have been playing with and tweaking the code you provided. I removed the pause and unpause feature because i am simply looking for the timer to activate once any unit is idle and provide that unit with 10 seconds to get non Idle or else the game will end. I loved the debug code so much that once the "Unit becomes Idle" (i replaced the "when unit enters map") trigger activates, It will place a timer on top that units idle location for 10 seconds which is the alloted time to move that unit.
What I would like to Do:
In the "Movement Vars" Trigger, I have set it so that if movement == false, it runs "lose" trigger. But if the movement == true and it runs the "else" function, I would like to clear the Player CountDown Timer for that specifcly for that unit. I'm looking for the equivalent of removing that unit from the UI_get_unit_index. This way if that unit were to idle again, it would start a fresh 10 seconds for the Player CountDown Timer. Without getting effected by any previous CountDown Timer.
Current Example:
at 0 seconds: Unit goes idle. CountDown Timer begins for 10 seconds.
at 5 seconds: Unit moves becoming not idle.
at 6 seconds: Unit becomes idle again. New 10 second timer starts.
at 10 seconds: the original timer will finish and check to see if unit is idle (which it is, but it hasn't been idle for 10 seconds its only been idle for 4)
Is there an easy way to do this using the else function i suggested in the Movement Vars Trigger? Below is a link provided to the modified code you sent me, if it helps for reference. Thank you for all your assistance.
http://dl.dropbox.com/u/8338934/Unit%20Idle%20Check%20By%20Dustin%20modded.SC2Map
@nrtwenty: Go
There could be a much easier way.
There is a trigger event called "Unit becomes Idle". Use that to start your timer. When the timer runs out, use the "Unit is in Unit Group" Condition with Unit Group "Idle Units of Player" and Player "Owner of Init" to check if your Units is still idle
You need Triggers similar to these three:
Note that the second trigger is just for stopping the timer when the units is not idle any more. You can use "Any Unit" instead of <My Unit>-Variablebut then the timer gets started when ever a unit gets idle.
Hope this solves your problem.
Cheers
Then
@Thenarden: Go
Thank you for the help, the main issue I have had with the method you suggested is that it can not create a timer for multiple units at overlapping times..
Example:
at 0 seconds: unit becomes idle. 10s timer starts.
at 5 seconds: a different unit becomes idle. Timer is reset to 10 seconds.
at 14 seconds: second scv to idle tops being idle. timer is paused
~~~~~
the first scv to idle can now remain idle indefinitely. So while this method is simple, it is not robust enough to handle what I am looking for. Thank you for your input, as always I appreciate any members help.
@nrtwenty: Go
Can anybody offer a suggestion related to this post?
I managed to do what I believe you want. I did it using galaxy
++
though, since that was way easier for dynamic arrays and such.I split it into 3 script files - two utility files, and the map script. I attached them along with the output map and the raw galaxy script.
I know this is the GUI forum, but I just won't write all the GUI needed to do this, so I hope you are at least somewhat familiar with programming or galaxy.
If you plan to use it for a lot of units, I suggest adding a trigger that remove units/timers from the dictionary when the unit dies.
In case you want to make this in GUI, you can make dynamic arrays using the data table. The list is just a convenient wrapper around a dynamic array in G
++
. The dictionary uses two lists - in our case, a list of units and a list of their corresponding timers. Such that index i of the unit list is "linked" with index i of the timer list.When a unit becomes idle, I then check if we had already created a timer for that unit by running through the unit list looking for our unit. If no timer was created, create one, add an event to the TimerEnd trigger (requires custom script), and add the unit and list to the dictionary. Next, start the timer as a 10 second non periodic timer.
When a unit is no longer idle, you first need to check if we had created a timer for that unit (again, run throught the unit list). If a timer had been created, pause it.
When the timer expires, you can fetch the unit from your dictionary by looking for the Triggering Timer.
All right.. We do a lot of running through a list, which takes linear time in the number of elements in the list. So if you use this system for many units, try to delete them from the lists when they die. Also, you can use constant data about the unit to make a more complex, and faster data structure (like unit type, owner and such). But if you are not that much into programming, it might be best to just stick with the arrays.
@SBeier: Go
Perfect. Thank you for your direction.
@SBeier: Go
The way of using multiple timers, one for each SCV, is propably one of the best ways to approach.
But wouldn't it be much more efficient to use some kind of reuseable information about the unit/timer for dictionary keys instead of running through the entire list? I think that on a bigger amout of units or frequent stop and go commands the run-through method could create lags. You could for example use a custom value for the unit. But something similar for a timer? dunno.
@nrtwenty: Go
Just to clarify this:
Is your goal that if at least one SCV is idle for 10sec, the owning player getting defeated?
If so, there comes an other idea in my mind:
Use one timer for each player.
When a SCV gets idle and the timer for the owning player is not started, (re)start it.
When a SCV stops being idle, check if number of idle workers for that player is zero. If so, stop the timer, otherwise not.
When the timer expires, defeat the player.
by that, the timer gets started when the first SCV becomes idle and stoped, when the last stops being idle. In other words, it runs as long as any SCV of that player is idle.
Cheers
Then
@Thenarden: Go
Yeah, I know it might be less efficient for many units - that is what I meant by the last section about implementing a more complex data structure based on stuff like unit type and owner.
However, I won't go into details about that, since it is already complex enough as it is. First make it work, then optimize if efficiency is a problem. Creating unnecessary complex data structures just gives you lots of bugs.