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

How to re-create/ revive trees after they die?

Status
Not open for further replies.

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Ypu mean resurrecting a tree? You can use my GUI-friendly TreeRevive system.

~Uses converted IsDestructableTree by PitzerMike from wc3C.net to get rid of NewGen requirement.

EDIT: Updated - in case I just noticed that Bribe posted shorter version. Even that I catch up the idea about cuting IsDestructableTree into one 'if', my script wans't using 'uloc' (it's much better dummy), but standard 'hfoo' - the first one enables us to omit adding locust ability action. Neat idea.
One mistake Bribe - your unit isn't hidden.
JASS:
//************************************************************************************************
//*                                                                                              *
//*                                Tree Revival System                                           *
//*                                    by Spinnaker                                              *
//*                                                                                              *
//************************************************************************************************



//*************************************************************************
//*
//* Globals required
//*
//*************************************************************************


    //* udg_TreeRevivalTrig                      Trigger for handling the revive actions
    //* udg_TRhash                               Hashtable for timer issues
    //* udg_dummyh                               Dummy harvester for IsDestructibleTree function
    

//* Configurable function for delay before tree gets resurrected     
    constant function TreeReviveDelay takes nothing returns real
        return 5.
    endfunction

//* Tells if birth animation should be shown while resurrecting a tree
    constant function TreeShowAnimation takes nothing returns boolean
        return true
    endfunction

   
//* System itself
function TrCallback takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local destructable d = LoadDestructableHandle(udg_TRhash, GetHandleId(t), 0)
    call DestructableRestoreLife(d, GetDestructableMaxLife(d), TreeShowAnimation())
    call PauseTimer(t)
    call DestroyTimer(t)
    call FlushChildHashtable(udg_TRhash, GetHandleId(t))
    set d = null
    set t = null
endfunction
    
function CallTreeRevive takes nothing returns boolean
    local timer t = CreateTimer()
    call SaveDestructableHandle(udg_TRhash, GetHandleId(t), 0, GetTriggerDestructable())
    call TimerStart(t, TreeReviveDelay(), false, function TrCallback)
    set t = null
    return false
endfunction

function IsDestructableTree takes destructable dest returns boolean
    return IssueTargetOrderById(udg_dummyh, 852018, dest)
endfunction

function CallAddTree takes nothing returns nothing
    if IsDestructableTree(GetEnumDestructable()) then
        call TriggerRegisterDeathEvent(udg_TreeReviveTrig, GetEnumDestructable())
    endif
endfunction

//***************************************************************************
function InitTrig_TreeRevive takes nothing returns nothing
    set udg_TreeReviveTrig = CreateTrigger()
    set udg_TRhash = InitHashtable() 

  //* Actions required for IsDestructibleTree function
    set udg_dummyh = CreateUnit(Player(15), 'uloc', 0., 0., 0.)
    call ShowUnit(udg_dummyh, false)
    call UnitAddAbility(udg_dummyh, 'Ahrl')
    call UnitRemoveAbility(udg_dummyh, 'Amov')

  //* Revival setup
    call EnumDestructablesInRect(bj_mapInitialPlayableArea, null, function CallAddTree)
    call TriggerAddCondition(udg_TreeReviveTrig, Condition(function CallTreeRevive))
endfunction
Test map attached.
 

Attachments

  • TreeRevive.w3x
    26.4 KB · Views: 76
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,468
Thanks I totally didn't pay attention to hiding the unit, I forgot that
the locust has a model file :p too used to using dummy units ey.

Well the issue with enumerating these destructables is that it only
counts 64 destructables. You'd want to divide the map into various
regions so that each region contains less than or equal to 64 trees.
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
The 64-limit derives from the functions for the bj-event.

JASS:
function RegisterDestDeathInRegionEnum takes nothing returns nothing
    set bj_destInRegionDiesCount = bj_destInRegionDiesCount + 1
    if (bj_destInRegionDiesCount <= bj_MAX_DEST_IN_REGION_EVENTS) then
        call TriggerRegisterDeathEvent(bj_destInRegionDiesTrig, GetEnumDestructable())
    endif
endfunction

function TriggerRegisterDestDeathInRegionEvent takes trigger trig, rect r returns event
    set bj_destInRegionDiesTrig = trig
    set bj_destInRegionDiesCount = 0
    call EnumDestructablesInRect(r, null, function RegisterDestDeathInRegionEnum)
    return trig
endfunction

Enumerating destructables by EnumDestructablesInRect works for more than 64.
 
For a GUI version of the system : Link of Map

  • OneSec Elapsed GT
    • Evénements
      • Temps - Elapsed game time is 1.00 seconds
    • Conditions
    • Actions
      • Destructible - Pick every destructible in (Entire map) and do (Actions)
        • Boucle - Actions
          • Déclencheur - Add to Respawn Tree <gen> the event (Destructible - (Picked destructible) dies)
  • Respawn Tree
    • Evénements
    • Conditions
      • (Destructible-type of (Dying destructible)) Egal à Mur d'arbres d'été
    • Actions
      • Wait 60.00 seconds
      • Destructible - Resurrect (Dying destructible) with (Max life of (Dying destructible)) life and Montrer birth animation
With the pick every detructible, the system works for all trees.
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Well the issue with enumerating these destructables is that it only
counts 64 destructables. You'd want to divide the map into various
regions so that each region contains less than or equal to 64 trees.
Bribe, everything what you say is fine although 64 limitation happens only if you register destructible death event while refering to given region.

If you enumerate the destructibles on map and than call register death event (picked dest here) everything works fine and function registers '64 <' trees without any problem. Furthermore you can check my test map. There are total of 351 trees (=

Could I post this mini-system on Spells section, or it's too small? =p
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
If you want to post it in the spell section you should either make it run on only one timer or make a timer recycler (because I really dislike that only we doing "vJASS/ZINC/cJASS" have to recycle timers/run on the same timer, you can do it in JASS as well, it's not that difficult, good practice as well - and we also want to increase the standards in the spells section, don't we?). You can either make it somewhat hashindexing with only 1 parentkey and put the trees into the childkeys (to get rid of the flush call all the time, just flush when instances == 0 and also you can use the second parent key for timer recycling so you dont waste hashes if you wanna still do it with a hash) or normal indexing (will require a few more variables though). I'm just curious about the DestroyTimer leak will be if it's 1 timer/tree each time a tree does in a map, let's say DOTA (worst example ever). And if you should completly rip it off you should add the treedead function :p Great anyway.

@Vladadamm

Every single second you register a new event? Nice!
 
Status
Not open for further replies.
Top