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

Regeneration when a unit is not attacking

Status
Not open for further replies.
Level 7
Joined
Dec 9, 2014
Messages
89
Hi,

I want to make it so my towers only regenerate when they have not attacked for 5 seconds.

I am using this damage system: GUI-Friendly Damage Detection v1.2.1

I am new to hashtables but I figured this would be the way to do it. So I removed the base regen of the towers and using hashtables/damage system I created a trigger that should set the timer to 5 everytime they attack, with a separate trigger counting down by 1 every second and regenerating the unit if the timer reaches zero.



But this doesn't seem to work, and I can't figure out where I have gone wrong. How do I achieve my goal?

Here are the triggers:

  • regen
    • Events
      • Game - GDD_Event becomes Equal to 0.00
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (GDD_DamageSource is in RegenTimeGroup) Equal to True
        • Then - Actions
          • Unit Group - Add GDD_DamageSource to TempGroup
          • Unit Group - Pick every unit in TempGroup and do (Actions)
            • Loop - Actions
              • Hashtable - Save 5.00 as 0 of (Key (Picked unit)) in RegenTimer
          • Custom script: call DestroyGroup(udg_TempGroup)
        • Else - Actions
  • start regen
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in RegenTimeGroup and do (Actions)
        • Loop - Actions
          • Set RegenTime = (Load 0 of (Key (Picked unit)) from RegenTimer)
          • Game - Display to (All players) the text: (String(RegenTime))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • RegenTime Greater than 0.00
            • Then - Actions
              • Hashtable - Save (RegenTime - 1.00) as 0 of (Key (Picked unit)) in RegenTimer
            • Else - Actions
              • Unit - Set life of (Picked unit) to ((Life of (Picked unit)) + ((Max life of (Picked unit)) / 300.00))
 
Last edited:

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
Have you initialised the hashtable?
Is the unit in the group RegenTimeGroup?
What message is displayed?

There is a problem in the first trigger. After using TempGroup for the first time, you destroy it, so after that you can no longer add any units to it.
In case this is the only time TempGroup is used, you can clear the group instead of destroying it. If you use it in other triggers, you would need to recreate it before adding units to it.
Using a unit group is a lot of overhead only for getting the handle id of the unit, but since GUI support for hashtables is horrible it is one method to do it with just GUI.

I would recommend creating a new integer variable called TempHandleId or something.
You can then use a custom script to save the handle id of the unit in that variable:
set udg_TempHandleId = GetHandleId(udg_GDD_DamageSource)
After that simply replace key (...) with your integer variable.

GetHandleId() is how Key() is named in JASS. Using a custom script you can use it on a unit variable.

edit:
The trigger would look like this:
  • regen
    • Events
      • Game - GDD_Event becomes Equal to 0.00
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (GDD_DamageSource is in RegenTimeGroup) Equal to True
        • Then - Actions
          • Custom script: set udg_TempHandleId = GetHandleId(udg_GDD_DamageSource)
          • Hashtable - Save 5.00 as 0 of (TempHandleId) in RegenTimer
        • Else - Actions
 
Level 7
Joined
Dec 9, 2014
Messages
89
That fixed it, thanks! Previously it would do the countdown but only for one unit/only once... which I'm guessing is because I destroyed the unit group?

Whenever you set a unit group that you only needed temporarily I thought you needed to destroy it for memory leak reasons, and you could then set the same group again later and have it work. Is it because I didn't set it before adding a unit to it?
 
Level 39
Joined
Feb 27, 2007
Messages
4,994
Whenever you set a unit group that you only needed temporarily I thought you needed to destroy it for memory leak reasons, and you could then set the same group again later and have it work. Is it because I didn't set it before adding a unit to it?
Yes you do need to destroy groups you don't use ever again. The difference is that when you use Unit Group - Pick every unit in <anything that isn't a group variable> it creates a group (same for setting a group = some collection of units, which would additionally leak the 'old' group if it had been previously set to one) but adding unit to a group doesn't create a new group. If you want to use your group for adding and removing only, you can 'clean' the group with GroupClear() instead of DestroyGroup(). Afaik there is no GUI equivalent line.

You can also automatically (beware: instantly after the line that creates the group) clean group leaks like this. It also works recursively.
  • Custom script: set bj_wantDestroyGroup = true
  • Unit Group - Pick every unit in (Units in Playable Map Area) and do (Actions)
    • Loop - Actions
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units in Playable Map Area matching (Unit-type of (Matching Unit) equal to (Unit type of (Picked unit)) and do (Actions)
        • Loop - Actions
          • -------- do something --------
      • -------- inner group destroyed here --------
  • -------- outer group destroyed here --------
 
Last edited:
Status
Not open for further replies.
Top