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

[System] Tree Revival

Level 17
Joined
Jun 17, 2007
Messages
1,433
A simple tree revival system.

Requirements:
TimerUtils, by Vexorian.
IsDestructableTree by PitzerMike

Code:

JASS:
library TreeRevival initializer Init requires TimerUtils, DestructableLib

globals
    //**Configuration***********************
    private constant boolean BIRTH_ANIMATION = true
    private constant real REVIVAL_TIME = 30.
endglobals

private function Conditions takes nothing returns boolean
    return true
endfunction
//**************************************
    
globals
    public trigger Trigger = CreateTrigger()
endglobals

private struct Data
    destructable d
endstruct

private function Enum takes nothing returns nothing
    call TriggerRegisterDeathEvent(Trigger, GetEnumDestructable())
endfunction

private function TreeFilter takes nothing returns boolean
    return IsDestructableTree(GetFilterDestructable())
endfunction

private function ReviveTree takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local Data d = GetTimerData(t)
    call DestructableRestoreLife(d.d, GetDestructableMaxLife(d.d), BIRTH_ANIMATION)
    call ReleaseTimer(t)
    call d.destroy()
    set t = null
endfunction

private function Actions takes nothing returns nothing
    local timer t = NewTimer()
    local Data d = Data.create()
    set d.d = GetDyingDestructable()
    call TimerStart(t, REVIVAL_TIME, false, function ReviveTree)
    call SetTimerData(t, d)
    set t = null
endfunction

private function Init takes nothing returns nothing
    call EnumDestructablesInRect(bj_mapInitialPlayableArea, Filter(function TreeFilter), function Enum)
    call TriggerAddAction(Trigger, function Actions)
    call TriggerAddCondition(Trigger, Condition(function Conditions))
endfunction

endlibrary
 
Last edited:
Level 16
Joined
Oct 12, 2008
Messages
1,570
Seems like an ok system, though i have a question for you:
You use BoolexprUtils, nothing wrong with it, but why still write your own Condition, always returning true then? You can either use the BOOLEXPR_TRUE, or just add no condition, right? Or is the condition there for a reason?
 
Level 11
Joined
Feb 22, 2006
Messages
752
Man, I keep getting the feeling I've seen a system like this somewhere...but until I can verify that:

I'd like to see some more documentation, like some instructions telling people that the Conditions function is called on destructable death so they know wut it's doing there in the config section.

I'd also like to see some more flexibility when it comes to revival delay. Right now you have it so that all destructables must have the same delay.
 
Man, I keep getting the feeling I've seen a system like this somewhere...but until I can verify that:

I'd like to see some more documentation, like some instructions telling people that the Conditions function is called on destructable death so they know wut it's doing there in the config section.

I'd also like to see some more flexibility when it comes to revival delay. Right now you have it so that all destructables must have the same delay.

Acehart made Regrowing Trees.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
This doesn't look as weird:

JASS:
library TreeRevival initializer Init requires TimerUtils, DestructableLib
    
//**Configuration***********************
    
    globals
        private constant boolean BIRTH_ANIMATION = true
        private constant real REVIVAL_TIME = 30.00
    endglobals

    private function Evaluate takes destructable dyingDest returns boolean
        return true
    endfunction
    
//**************************************
            
    globals
        private trigger Trigger = CreateTrigger()
        private destructable Dest = null
        private timer Timer = null
        private Data Dat = Data(0)
    endglobals

    private struct Data
        destructable d
    endstruct

    private function TreeFilter takes nothing returns boolean
        set Dest = GetFilterDestructable()
        if IsDestructableTree(Dest) then
            call TriggerRegisterDeathEvent(Trigger, Dest)
        endif
        return false
    endfunction

    private function ReviveTree takes nothing returns nothing
        set Timer = GetExpiredTimer()
        set Dat = GetTimerData(Timer)
        set Dest = Dat.d
        call DestructableRestoreLife(Dest, GetDestructableMaxLife(Dest), BIRTH_ANIMATION)
        call ReleaseTimer(Timer)
        call Dat.destroy()
    endfunction

    private function Setup takes nothing returns boolean
        set Dest = GetTriggerDestructable()
        if Evaluate(Dest) then
            set Timer = NewTimer()
            set Dat = Data.create()
            set Dat.d = Dest
            call TimerStart(Timer, REVIVAL_TIME, false, function ReviveTree)
            call SetTimerData(Timer, integer(Dat))
        endif
        return false
    endfunction

    private function Init takes nothing returns nothing
        call EnumDestructablesInRect(bj_mapInitialPlayableArea, Condition(function TreeFilter), null)
        call TriggerAddCondition(Trigger, Condition(function Setup))
    endfunction

endlibrary
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
Here is a fine re-write of this library:

JASS:
library TreeReviver initializer Init requires DestructableLib, Tq

private function TreeFilter takes nothing returns boolean
    return IsDestructableTree(GetFilterDestructable())
endfunction

private struct Data extends array
    static constant real INTERVAL = 30. // Revival time
    static constant boolean SHOW_BIRTH_ANIMATION = true
    static trigger trig
    destructable d
    method expire takes nothing returns nothing
        call DestructableRestoreLife(this.d, GetDestructableMaxLife(this.d), SHOW_BIRTH_ANIMATION)
        call Tq_D(this)
    endmethod
    implement Tq
endstruct

private function TreeDeath takes nothing returns boolean
    set Data.allocate().d = GetTriggerDestructable()
    return false
endfunction

private function TreeSetup takes nothing returns nothing
    call TriggerRegisterDeathEvent(Data.trig, GetEnumDestructable())
endfunction

private function Init takes nothing returns nothing
    set Data.trig = CreateTrigger()
    call EnumDestructablesInRect(bj_mapInitialPlayableArea, Filter(function TreeFilter), function TreeSetup)
    call TriggerAddCondition(Data.trig, Condition(function TreeDeath))
endfunction

endlibrary

http://www.hiveworkshop.com/forums/jass-functions-413/system-timerqueue-187502/
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
The reasoning is thread OP limits. A large globals block full of CreateTriggers and InitHashtable, if packed enough, can crash the thread. This is coming from Vexorian :-/

Library initializers are called from ExecuteFunc, therefore... no thread crashing. And since this already needs an initializer (not wasting an entire thread just to create the trigger), I figure I should combine all things in one.
 
Level 7
Joined
Dec 3, 2006
Messages
339
This doesn't destroy events of removed trees, but is there ever such a case?

Yes, terrain generation through triggers. Where there are new trees created later on and old ones removed.
 
Top