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

[General] Trigger to revive only trees on the map (globally)

Status
Not open for further replies.
Level 18
Joined
Jan 12, 2011
Messages
1,512
I need a very specific trigger, I found examples in both GUI and Jass which revives trees in the map every X seconds (however most use wait and I believe that wait isn't recommended, right?)

Alright so:

The trigger consists on reviving every single tree on the map that has been destroyed every 5 minutes, however my map has both destructible gates and crates, so reviving every destructible isn't a choice.

Anyone knows of an optimized way to do this? my map has several (a lot) different types of trees not just ashenvale trees.


Trigger can be in either GUI or Jass/vJass, it's fine either way


I really have no idea whatsoever on Jass, I can read code though but I suppose you can make a filter function that works like this:

GetDestructableTypeId

which is passed
GetEnumDestructable as an argument?

This should return if the destructable is a tree(?) if so then revive it?


If someone can help me do it in Jass I would be very grateful.
 
Last edited:
Level 6
Joined
Jun 4, 2017
Messages
172
If you want that every 5 minutes all dead trees are resurrected you can just create something like this:
  • Revive Trees
    • Events
      • Time - Every 300.00 seconds of game time
    • Conditions
    • Actions
      • Destructible - Pick every destructible in (Playable map area) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked destructible) is dead) Equal to TRUE
              • (Destructible-type of (Picked destructible)) Equal to Tree
            • Then - Actions
              • Destructible - Resurrect (Picked destructible) with (Max life of (Picked destructible)) life and Show birth animation
            • Then - Actions
I didn't test this, but I think it should work just fine.
 
Level 18
Joined
Jan 12, 2011
Messages
1,512
If you want that every 5 minutes all dead trees are resurrected you can just create something like this:
  • Revive Trees
    • Events
      • Time - Every 300.00 seconds of game time
    • Conditions
    • Actions
      • Destructible - Pick every destructible in (Playable map area) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked destructible) is dead) Equal to TRUE
              • (Destructible-type of (Picked destructible)) Equal to Tree
            • Then - Actions
              • Destructible - Resurrect (Picked destructible) with (Max life of (Picked destructible)) life and Show birth animation
            • Then - Actions
I didn't test this, but I think it should work just fine.

Does this leak? Btw, there's no generic "tree" in GUI
 
Level 6
Joined
Jun 4, 2017
Messages
172
Does this leak?
I'm not sure about the "pick every destructible" action, but the other actions don't leak. However I remember that the "pick every destructible action" doesn't leak(I'm not 100% sure though).
EDIT: I searched in other threads, "pick every destructible" does not leak.
EDIT2:
Btw, there's no generic "tree" in GUI
You have to put the tree destructible that you want to recreate every 5 minutes, what's the difference if it is called "tree" or "wall of trees" or "abcd"? You decide how to name your destructibles.
 
Last edited:
Level 18
Joined
Jan 12, 2011
Messages
1,512
I'm not sure about the "pick every destructible" action, but the other actions don't leak. However I remember that the "pick every destructible action" doesn't leak(I'm not 100% sure though).
EDIT: I searched in other threads, "pick every destructible" does not leak.
EDIT2:
You have to put the tree destructible that you want to recreate every 5 minutes, what's the difference if it is called "tree" or "wall of trees" or "abcd"? You decide how to name your destructibles.

Yeah I understand that, I meant that In the thread I specified that I had to revive several different trees, so how would I go on doing it with multiple ones? do I just create a bunch of nested if else?
 
Level 6
Joined
Jun 4, 2017
Messages
172
Yeah I understand that, I meant that In the thread I specified that I had to revive several different trees, so how would I go on doing it with multiple ones? do I just create a bunch of nested if else?
Ah, sorry, I forgot to add that in the trigger.
You just need to put an Or(multiple conditions) and do this:
  • Revive Trees
    • Events
      • Time - Every 300.00 seconds of game time
    • Conditions
    • Actions
      • Destructible - Pick every destructible in (Playable map area) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked destructible) is dead) Equal to TRUE
              • Or - Any (Conditions) are true
                • Conditions
                  • (Destructible-type of (Picked destructible)) Equal to Tree1
                  • (Destructible-type of (Picked destructible)) Equal to Tree2
                  • (Destructible-type of (Picked destructible)) Equal to Tree3
            • Then - Actions
              • Destructible - Resurrect (Picked destructible) with (Max life of (Picked destructible)) life and Show birth animation
            • Then - Actions
 
There's a lib which can check if a destructable is a tree. [Snippet] IsDestructableTree

At game start you can pick all trees on map using lib above, and registering event when it dies to a trigger. From then, you can ensure the trigger fires only when a tree dies, so then you can start a timer, binding the tree to the timer. When the timer runs and has expired, you can revive the binded tree.
Here's a sample:

JASS:
globals
    hashtable TreeReviveTable = InitHashtable()
    constant real TREE_REVIVE_TIME = 5.00
endglobals

function TreeRevive_callback takes nothing returns nothing
    local timer clock = GetExpiredTimer()
    local destructable tree = LoadDestructableHandle(TreeReviveTable, GetHandleId(clock), 0)
    call DestructableRestoreLife( tree, GetDestructableMaxLife(tree), true )
    call DestroyTimer(clock)
    set clock = null
endfunction

function Trig_TreeDeath_Actions takes nothing returns nothing
    local timer clock = CreateTimer()
    call SaveDestructableHandle(TreeReviveTable, GetHandleId(clock), 0, GetTriggerDestructable())
    call TimerStart(clock, TREE_REVIVE_TIME, false, function TreeRevive_callback)
    set clock = null
endfunction

function RegisterTreeDeath takes nothing returns nothing
    local destructable tree = GetEnumDestructable()
    if IsDestructableTree(tree) then
        call TriggerRegisterDeathEvent( gg_trg_TreeDeath, tree )
    endif
endfunction

function InitTrig_TreeDeath takes nothing returns nothing
    set gg_trg_TreeDeath = CreateTrigger(  )
    call TriggerAddAction( gg_trg_TreeDeath, function Trig_TreeDeath_Actions )
    call EnumDestructablesInRect(GetWorldBounds(), null, function RegisterTreeDeath)
endfunction
 

Attachments

  • Tree Revive.w3x
    16.1 KB · Views: 50
Good it works out. :)

Good you mention leaks.. not that it will have great impact, but I forgot some cleaning (3 new lines..) :

JASS:
globals
    hashtable TreeReviveTable = InitHashtable()
    constant real TREE_REVIVE_TIME = 5.00
endglobals

function TreeRevive_callback takes nothing returns nothing
    local timer clock = GetExpiredTimer()
    local destructable tree = LoadDestructableHandle(TreeReviveTable, GetHandleId(clock), 0)
    call RemoveSavedHandle(TreeReviveTable, GetHandleId(clock), 0) // NEW
    call DestructableRestoreLife( tree, GetDestructableMaxLife(tree), true )
    call DestroyTimer(clock)
    set clock = null
    set tree = null // NEW
endfunction

function Trig_TreeDeath_Actions takes nothing returns nothing
    local timer clock = CreateTimer()
    call SaveDestructableHandle(TreeReviveTable, GetHandleId(clock), 0, GetTriggerDestructable())
    call TimerStart(clock, TREE_REVIVE_TIME, false, function TreeRevive_callback)
    set clock = null
endfunction

function RegisterTreeDeath takes nothing returns nothing
    local destructable tree = GetEnumDestructable()
    if IsDestructableTree(tree) then
        call TriggerRegisterDeathEvent( gg_trg_TreeDeath, tree )
    endif
    set tree = null // NEW
endfunction

function InitTrig_TreeDeath takes nothing returns nothing
    set gg_trg_TreeDeath = CreateTrigger(  )
    call TriggerAddAction( gg_trg_TreeDeath, function Trig_TreeDeath_Actions )
    call EnumDestructablesInRect(GetWorldBounds(), null, function RegisterTreeDeath)
endfunction

Btw, the GUI version is free from leaks, but as I understood it's probably wanted to wait x seconds for one tree when it died, instead of one global period to revive death trees. ( so one tree could wait much time, and one other tree could wait only a few seconds maybe)
 
Level 18
Joined
Jan 12, 2011
Messages
1,512
Good it works out. :)

Good you mention leaks.. not that it will have great impact, but I forgot some cleaning (3 new lines..) :

JASS:
globals
    hashtable TreeReviveTable = InitHashtable()
    constant real TREE_REVIVE_TIME = 5.00
endglobals

function TreeRevive_callback takes nothing returns nothing
    local timer clock = GetExpiredTimer()
    local destructable tree = LoadDestructableHandle(TreeReviveTable, GetHandleId(clock), 0)
    call RemoveSavedHandle(TreeReviveTable, GetHandleId(clock), 0) // NEW
    call DestructableRestoreLife( tree, GetDestructableMaxLife(tree), true )
    call DestroyTimer(clock)
    set clock = null
    set tree = null // NEW
endfunction

function Trig_TreeDeath_Actions takes nothing returns nothing
    local timer clock = CreateTimer()
    call SaveDestructableHandle(TreeReviveTable, GetHandleId(clock), 0, GetTriggerDestructable())
    call TimerStart(clock, TREE_REVIVE_TIME, false, function TreeRevive_callback)
    set clock = null
endfunction

function RegisterTreeDeath takes nothing returns nothing
    local destructable tree = GetEnumDestructable()
    if IsDestructableTree(tree) then
        call TriggerRegisterDeathEvent( gg_trg_TreeDeath, tree )
    endif
    set tree = null // NEW
endfunction

function InitTrig_TreeDeath takes nothing returns nothing
    set gg_trg_TreeDeath = CreateTrigger(  )
    call TriggerAddAction( gg_trg_TreeDeath, function Trig_TreeDeath_Actions )
    call EnumDestructablesInRect(GetWorldBounds(), null, function RegisterTreeDeath)
endfunction

Btw, the GUI version is free from leaks, but as I understood it's probably wanted to wait x seconds for one tree when it died, instead of one global period to revive death trees. ( so one tree could wait much time, and one other tree could wait only a few seconds maybe)

Yeah per tree is better too since it won't have units getting randomly stuck if trees were killed right before the 5 minutes pass
 
Status
Not open for further replies.
Top