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

[Trigger] [GUI] Hero Revival System

Status
Not open for further replies.
Level 3
Joined
Feb 3, 2016
Messages
43
I am posting an early draft of my concept of a revival system for heroes. Testing showed heroes are revived in correct time, both by computer and user players (with a small condition change).
  • Revival System 1 Copy
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set Respawn_Table = (Last created hashtable)
      • Set Revive_Region = (Center of Hero Relocate <gen>)
      • Set Active_Players = (All players controlled by a User player)
  • Revival System 2 Copy
    • Events
      • Unit - A unit Dies
    • Conditions
      • ((Dying unit) is A Hero) Equal to True
    • Actions
      • Set Dying_Hero = (Triggering unit)
      • Set Player = (Triggering player)
      • Set Player_Number = (Player number of Player)
      • Hashtable - Save 1 as 1 of Player_Number in Respawn_Table
      • Hashtable - Save ((Hero level of Dying_Hero) x 2) as 2 of Player_Number in Respawn_Table
      • Hashtable - Save Handle OfDying_Hero as 3 of Player_Number in Respawn_Table
  • Revival System 3 Copy
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Player Group - Pick every player in Active_Players and do (Actions)
        • Loop - Actions
          • Set Integer_A = (Player number of (Picked player))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Load 1 of Integer_A from Respawn_Table) Equal to 1
            • Then - Actions
              • Hashtable - Save ((Load 2 of Integer_A from Respawn_Table) - 1) as 2 of Integer_A in Respawn_Table
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Load 2 of Integer_A from Respawn_Table) Equal to 0
            • Then - Actions
              • Hashtable - Save 0 as 1 of Integer_A in Respawn_Table
              • Hero - Instantly revive (Load 3 of Player_Number in Respawn_Table) at Revive_Region, Show revival graphics
            • Else - Actions
I'm looking for advices on how to improve this trigger - possible memory leaks and such. Thank you!

EDIT: The triggers have been updated to prevent leaks and is now working. Thank you for your suggestions!

EDIT#2: Triggers have been finalized and reduced as much as I can. Thanks to all the people that helped!
 
Last edited:

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
Revival System 2:
store dying unit and player number of owner of dying unit in variables to reduce number of function calls

Revival System 3:
Number of players in (All players controlled by a User player) does leak a player group I think.
Store Integer A in a variable or use custom variable loop instead to reduce number of function calls
Center of Hero Relocate <gen> leaks a point

Never use "Do nothing", because it does nothing, except increase the number of function calls. Just leave it empty
 
Level 3
Joined
Feb 3, 2016
Messages
43
Revival System 3:
Number of players in (All players controlled by a User player) does leak a player group I think.
Store Integer A in a variable or use custom variable loop instead to reduce number of function calls
Center of Hero Relocate <gen> leaks a point
1. So I should create an integer containing the "Number of players in (All players controlled by a User player)" and use that in the loop instead?
2. See 1.
3. So I should set the Center of Hero Relocate point to a variable too?
 
1. No i wouldn't do that. That would force players to pick specific player slots or developing an complex indexing mechanic, better would be to create an PlayerGroup/Force which you loop instead of using the for loops.
This playerGroup Variable you set in Revial System 1
  • Set PlayerGroup = (All players controlled by a User player)
  • inside Revial System 3
    • Spielergruppe - Pick every player in PlayerGroup and do (Actions)
      • Schleifen - Aktionen
3. yes, save the location
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
  • Player Group
    • Events
    • Conditions
    • Actions
      • Set PlayerGroup = (All players controlled by a User player)
      • Set NumberOfUsers = (Number of players in PlayerGroup)
      • Custom script: call DestroyForce(udg_PlayerGroup)
This is basic leak cleaning. Store the Player Group in a variable, use it (in this case store the numbers in a variable) and destroy the player group.
Keep in mind, that if you are using all players without an condition to not destroy the group.

As Tasyen said, it's probably better to use a Player Group loop. Then every player will use its player number as index.

3. You have two options:

Store the point to a variable at the beginning of the map, that you don't change/destroy as long as you need it:
  • Init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set HeroRelocatePoint = (Center of HeroRelocate <gen>)
Create and Remove the point when the trigger runs:

  • Trigger
    • Events
    • Conditions
    • Actions
      • Set TempPoint = (Center of HeroRelocate <gen>)
      • -------- use the point --------
      • Custom script: call RemoveLocation(udg_TempPoint)
The first one is more efficient, but the second one does not require its own variable, because you can use TempPoint for other triggers too.
 
Level 3
Joined
Feb 3, 2016
Messages
43
Like this?
  • Revival System 3 Copy
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Player Group - Pick every player in Active_Players and do (Actions)
        • Loop - Actions
          • Set Integer_A = (Player number of (Picked player))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Load 1 of Integer_A from Respawn_Table) Equal to 1
            • Then - Actions
              • Set Respawn_Timer[Integer_A] = (Respawn_Timer[Integer_A] - 1)
              • Hashtable - Save Respawn_Timer[Integer_A] as 2 of Integer_A in Respawn_Table
            • Else - Actions
      • Player Group - Pick every player in Active_Players and do (Actions)
        • Loop - Actions
          • Set Integer_A = (Player number of (Picked player))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Load 2 of Integer_A from Respawn_Table) Equal to 0
            • Then - Actions
              • Hashtable - Save 0 as 1 of Integer_A in Respawn_Table
              • Set Respawn_Timer[Integer_A] = 0
              • Hashtable - Save Respawn_Timer[Integer_A] as 2 of Integer_A in Respawn_Table
              • Hero - Instantly revive Revive_Target[Integer_A] at Revive_Region, Show revival graphics
            • Else - Actions
With the Active_Players player group defined in Revival System 1 trigger
  • Revival System 1 Copy
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set Respawn_Table = (Last created hashtable)
      • Set Revive_Region = (Center of Hero Relocate <gen>)
      • Set Active_Players = (All players controlled by a User player)
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
Overall the triggers look good in terms of efficiency and leak, but I can't say if it works, because I haven't tested the trigger. If it works for you I think it is fine.
You could think of merging the player group actions in one player group loop. It should work, because every player is treaten seperately and it is not necessary to do loop one first for all players, before loop two can run.
 
Level 3
Joined
Feb 3, 2016
Messages
43
Overall the triggers look good in terms of efficiency and leak, but I can't say if it works, because I haven't tested the trigger. If it works for you I think it is fine.
You could think of merging the player group actions in one player group loop. It should work, because every player is treaten seperately and it is not necessary to do loop one first for all players, before loop two can run.
Well I haven't tested it with all of these suggestions and changes, but I will report back with results.
Also, in order to avoid player group leaks I have to create it in the same trigger that I use it (Revival System 3) and then at the end of it use the custom script?
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
Also, in order to avoid player group leaks I have to create it in the same trigger that I use it (Revival System 3) and then at the end of it use the custom script?
The way how you do it is ok. You create one player group that is used for the rest of the game, so there is no leak. If you create something and no longer need it, but don't destroy it, it is considered a leak. So if you would create the player group in a trigger that runs multiple times and you don't destroy it, you will have leaks.
 
Level 3
Joined
Feb 3, 2016
Messages
43
The way how you do it is ok. You create one player group that is used for the rest of the game, so there is no leak. If you create something and no longer need it, but don't destroy it, it is considered a leak. So if you would create the player group in a trigger that runs multiple times and you don't destroy it, you will have leaks.
I am currently facing a problem as I can't test if this is MPI when I've set the player group to include only those controlled by another player. If you have interest in copying this trigger (I don't mind) to playtest it I would be grateful.
 
  • Revival System 1
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set Respawn_Table = (Last created hashtable)
  • Revival System 2
    • Events
      • Unit - A unit Dies
    • Conditions
      • ((Dying unit) is A Hero) Equal to True
    • Actions
      • Set Revive_Target[(Player number of (Owner of (Dying unit)))] = (Dying unit)
      • Hashtable - Save 1 as 1 of (Player number of (Owner of (Dying unit))) in Respawn_Table
      • Set Respawn_Timer[(Player number of (Owner of (Dying unit)))] = ((Hero level of (Dying unit)) x 2)
      • Hashtable - Save Respawn_Timer[(Player number of (Owner of (Dying unit)))] as 2 of (Player number of (Owner of (Dying unit))) in Respawn_Table
  • Revival System 3
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • For each (Integer A) from 1 to (Number of players in (All players controlled by a User player)), do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Load 1 of (Integer A) from Respawn_Table) Equal to 1
            • Then - Actions
              • Set Respawn_Timer[(Integer A)] = (Respawn_Timer[(Integer A)] - 1)
              • Hashtable - Save Respawn_Timer[(Integer A)] as 2 of (Integer A) in Respawn_Table
            • Else - Actions
              • Do nothing
      • For each (Integer A) from 1 to (Number of players in (All players controlled by a User player)), do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Load 2 of (Integer A) from Respawn_Table) Equal to 0
            • Then - Actions
              • Hashtable - Save 0 as 1 of (Integer A) in Respawn_Table
              • Set Respawn_Timer[(Integer A)] = 0
              • Hashtable - Save Respawn_Timer[(Integer A)] as 2 of (Integer A) in Respawn_Table
              • Hero - Instantly revive Revive_Target[(Integer A)] at (Center of Hero Relocate <gen>), Show revival graphics
            • Else - Actions
              • Do nothing
I'm looking for advices on how to improve this trigger - possible memory leaks and such. Thank you!

I would suggest:

Revival System 2

- changing (Dying Unit) to (Triggering Unit). They refer to the same unit.
- changing (Owner of (Dying Unit)) to (Triggering Player). It saves a function call. @Jampion suggested storing them into variables anyway.
- Based on how you use hashtables, you should just save the values directly. No need to write additional variables.

Revival System 3

- As per @Jampion 's suggestion, remove (Do nothing)

Aside from those, if you like this to be improved further (so to achieve MUI), I'll (help you) write it up.
 
Level 8
Joined
Jan 28, 2016
Messages
486
If you're looking to make a simple respawn system without hashtables, you can have a look at this post I made about an almost identical topic posted here on The Hive: Hero Revival System. Do note that this method is MPI and will only work if you plan to have one hero per player.
 
Level 3
Joined
Feb 3, 2016
Messages
43
If you're looking to make a simple respawn system without hashtables, you can have a look at this post I made about an almost identical topic posted here on The Hive: Hero Revival System. Do note that this method is MPI and will only work if you plan to have one hero per player.
Is it approved and working 100%? And yes, the limit is 1 hero per player.

I would suggest:

Revival System 2

- changing (Dying Unit) to (Triggering Unit). They refer to the same unit.
- changing (Owner of (Dying Unit)) to (Triggering Player). It saves a function call. @Jampion suggested storing them into variables anyway.
- Based on how you use hashtables, you should just save the values directly. No need to write additional variables.

Revival System 3

- As per @Jampion 's suggestion, remove (Do nothing)

Aside from those, if you like this to be improved further (so to achieve MUI), I'll (help you) write it up.
Well, from my testing it does appear to be MPI - unless you are refering to the revive location?
 
Last edited by a moderator:
Well, from my testing it does appear to be MPI - unless you are refering to the revive location?

Not really (in the sense that I'm talking about the revive location). What I had in my mind when I looked at the title was that it could be MUI, although it (my suggestion, that is) doesn't really make sense if you only ever have one Hero to be revived.

The following triggers, if optimized as suggested, would result to this:

Revival System 2
  • set DyingUnit = (Triggering Unit)
  • set Player = (Triggering Player)
  • set PlayerIndex = (Player number of Player)
  • Hashtable - Save 1 as 1 of PlayerIndex in Respawn_Table
  • Hashtable - Save ((Hero level of DyingUnit) x 2) as 2 of PlayerIndex in Respawn_Table
  • Hashtable - Save DyingUnit as 3 of PlayerIndex in Respawn_Table
Revival System 3
  • Events
    • Time - Every 1.00 seconds of game time
  • Conditions
  • Actions
    • Player Group - Pick every player in Active_Players and do (Actions)
      • Loop - Actions
        • Set Integer_A = (Player number of (Picked player))
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Load 1 of Integer_A from Respawn_Table) Equal to 1
          • Then - Actions
            • Hashtable - Save ((Load 2 of Integer_A from Respawn_Table) - 1) as 2 of Integer_A in Respawn_Table
          • Else - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Load 2 of Integer_A from Respawn_Table) Equal to 0
          • Then - Actions
            • Hashtable - Save 0 as 1 of Integer_A in Respawn_Table
            • Hero - Instantly revive (Load 3 of PlayerIndex from Respawn_Table) at Revive_Region, Show revival graphics
          • Else - Actions
Is it approved and working 100%? And yes, the limit is 1 hero per player.

Well, from my testing it does appear to be MPI - unless you are refering to the revive location?

Also, you can edit the post so that you will not double post.
 
Last edited:
Level 8
Joined
Jan 28, 2016
Messages
486
Is it approved and working 100%? And yes, the limit is 1 hero per player.

Approved by The Hive? No but it's taken from a DotA Template (there's a link to this in the post I linked above) posted by SD_Ryoko and AceHart on the World Editor Tutorials, an associated site of TheHelper.net if I'm not mistaken, which is quite trust worthy and has numerous threads on Warcraft 3 related topics too.

Does it work? Sure does but be aware that you need to use a timer array that is set to 12 (i.e. one for each player) in the Variable Editor otherwise the array will only work for Players 1 and 2.
 
Level 3
Joined
Feb 3, 2016
Messages
43
Not really (in the sense that I'm talking about the revive location). What I had in my mind when I looked at the title was that it could be MUI, although it (my suggestion, that is) doesn't really make sense if you only ever have one Hero to be revived.

The following triggers, if optimized as suggested, would result to this:

Revival System 2
  • set DyingUnit = (Triggering Unit)
  • set Player = (Triggering Player)
  • set PlayerIndex = (Player number of Player)
  • Hashtable - Save 1 as 1 of PlayerIndex in Respawn_Table
  • Hashtable - Save ((Hero level of DyingUnit) x 2) as 2 of PlayerIndex in Respawn_Table
  • Hashtable - Save DyingUnit as 3 of PlayerIndex in Respawn_Table
Revival System 3
  • Events
    • Time - Every 1.00 seconds of game time
  • Conditions
  • Actions
    • Player Group - Pick every player in Active_Players and do (Actions)
      • Loop - Actions
        • Set Integer_A = (Player number of (Picked player))
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Load 1 of Integer_A from Respawn_Table) Equal to 1
          • Then - Actions
            • Hashtable - Save ((Load 2 of Integer_A from Respawn_Table) - 1) as 2 of Integer_A in Respawn_Table
          • Else - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Load 2 of Integer_A from Respawn_Table) Equal to 0
          • Then - Actions
            • Hashtable - Save 0 as 1 of Integer_A in Respawn_Table
            • Hero - Instantly revive (Load 3 of PlayerIndex from Respawn_Table) at Revive_Region, Show revival graphics
          • Else - Actions




Also, you can edit the post so that you will not double post.

1. So, my system is MUI but not optimized well enough? I will update the code with your suggestion - thank you for your help!
2. I do not what you are refering to visa vi the post editing as I already have used the Edit function to update the triggers in the main post.

EDIT: Since there is no option to save the Dying_Hero unit variable in the hashtable, I find it impossible to complete your suggestion in the Editor!
 
Last edited:
Level 3
Joined
Feb 3, 2016
Messages
43
Yes. There is another way, though of getting a unique index, though that requires knowledge of allocation and deallocation.
Okay, I applied your suggestion and it works as intended so far. Still can't test it in multiplayer so I will just update the triggers in the main post and thank you for your help!
 
Status
Not open for further replies.
Top