• 🏆 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!
  • ✅ HD Level Design Contest #1 POLL is now OPEN! Check out the stunning visuals of the final entries. 🔗Click here to cast your vote!

[vJASS][Utility]Udn- Unit Decaying

Level 31
Joined
Jul 10, 2007
Messages
6,306
Udn- Unit Decaying
Current Version- v4.0 (part 1 ^^)
Guide Version- (NA)




Advanced ---> Gameplay Constants ---> Decay Time (sec) - Bones ---> 99999.90


News Count- 2




JASS can only decay units for up to 8 seconds. After that they can't be retrieved. I found this sucky and thought that they should be able to be retrieved up to the point at which they actually decay off of the map.


Because this is so short on use, no need for a guide really.

User area looks like this-
JASS:
//! textmacro Udn_SETTINGS
    private constant real UNIT_DECAY = 90
//! endtextmacro

//! textmacro Udn_REGISTERED_PLAYERS
    exitwhen x == Mfn_playerCount
    set p = Mfn_players[x]
//! endtextmacro

//! textmacro Udn_EXTRA_PLAYERS
    //call TriggerRegisterPlayerUnitEvent(decay, Player(15), EVENT_PLAYER_UNIT_DEATH, null)
//! endtextmacro

//! textmacro Udn_DECAY
    return not IsUnitType(u, UNIT_TYPE_HERO)
//! endtextmacro

UNIT_DECAY refers to global decay time for all units.

x refers to the maximum player count of the players you want to go thru (like if you want 0 thru 11, use 11) and p is the player. In this case, it's using Mfn's player tracking : ).

The extra players area are for single players. Let's say you just want player 15 ^^.

Decay area is used to put in things you don't want to decay on default. You can still make them decay, but you have to use inverse booleans (true is false and false is true) to do it via Udn_decayUnit =).

to use it-
JASS:
call Udn_triggerRegisterDecayEvent(yourTrigger)

Easy enough. yourTrigger refers to whatever trigger you want to fire when a unit decays.

And then... a few other events
JASS:
1. call Udn_triggerRegisterPlayerUnitDecayEvent(trigger, playerId)
1. call Udn_triggerRegisterPlayerUnitDecayEvent(yourTrigger, 0)
1. //fires whenever a unit owned by player 0 decays

2. call Udn_triggerRegisterUnitTypeDecayEvent(trigger, unitTypeId)
2. call Udn_triggerRegisterUnitTypeDecayEvent(trigger, 'hpea')
2. //fires whenever a unit of type 'hpea' decays, which is a peasant

3. call Udn_triggerRegisterUnitDecayEvent(trigger, unit)
3. call Udn_triggerRegisterUnitDecayEvent(trigger, CreateUnit(Player(0), 'hfoo', Mfn_Map_centerX, Mfn_Map_centerY, 270))
3. //fires whenever the specific unit specified decays, in this case a newly created unit.

Next, getting the decaying unit.
JASS:
call Udn_getLastDecayingUnit()

You should store this into a variable asap so you don't lose it. It is cleaned up by a garbage collector, so uhm... I do this ^^

JASS:
local unit triggerUnit = Udn_getLastDecayingUnit()

Setting a unit type's decay time-
JASS:
call Udn_setDecay(unitType, time)

Just sets the decay time of a unit type. If there is no defined decay time, it'll just use the global one.

JASS:
call Udn_setDecay('hpea', 50)

unsetting a decay time ^^
JASS:
call Udn_unsetDecay(unitType)

And this just unsets it and makes it go back to default global time.

JASS:
call Udn_unsetDecay('hpea')

So peasant would go from 50 second decay time back to DECAY_TIME.

There is also making it so a unit does or does not get removed on decay-
JASS:
call Udn_decayUnit(unit, true/false)

ex-
JASS:
call Udn_decayUnit(triggerUnit, false)
That would make it so it is not removed : ).

And finally there is cleanUnit, which is used to remove a decaying unit that wasn't auto cleaned. You need to use this instead of RemoveUnit or you'll have memory leaks : o.

JASS:
call Udn_cleanUnit(unit)

JASS:
call Udn_cleanUnit(triggerUnit)

And then get remaining time on a decaying unit before it is gone-
JASS:
call Udn_getRemainingDecay(unit)

and get elapsed time on a decaying unit-
JASS:
call Udn_getElapsedDecay(unit)

And that's all there is to this really : D.


-News Section-


The first release of the decaying units. Works perfectly, so I think this will be the only release and probably the only news ^^.



Because this has gotten kind of big, I might now write proper documentation for it o-o



-Utility Section-

JASS:
//! textmacro Udn_SETTINGS
    private constant real UNIT_DECAY = 90
//! endtextmacro

//! textmacro Udn_REGISTERED_PLAYERS
    exitwhen x == Mfn_playerCount
    set p = Mfn_players[x]
//! endtextmacro

//! textmacro Udn_EXTRA_PLAYERS
    call TriggerRegisterPlayerUnitEvent(decay, Player(11), EVENT_PLAYER_UNIT_DEATH, null)
//! endtextmacro

//! textmacro Udn_DECAY
    return not IsUnitType(u, UNIT_TYPE_HERO)
//! endtextmacro

JASS:
library Udn initializer ini requires RequiresMfn
    globals
        //Version Information
        private constant string SYSTEM = "Udn"
        private constant string VERSION = "4.0"
        private constant string AUTHOR = "Nestharus"
        private constant string HELPERS = "None"
        private constant string TEXTURE_PATH = "ReplaceableTextures\\CommandButtons\\BTNAnimateDead.blp"
        private constant string DESCRIPTION = "Unit Decaying"
        
        private constant trigger decay = CreateTrigger()
        
        //! runtextmacro Udn_SETTINGS()
    endglobals
    
    scope NonRemovedUnits
        globals
            public boolean array remove
        endglobals
        
        //! runtextmacro Hash_CREATE("")
    endscope
    
    scope UdnUnitTypeDecay
        globals
            public real array decayTime
        endglobals
        
        //! runtextmacro Hash_CREATE("")
    endscope
    
    scope UdnSuspendTimer
        globals
            public timer array timers
        endglobals
        
        //! runtextmacro Hash_CREATE("")
    endscope
    
    scope UdnSuspend
        globals
            public unit array suspendedUnits
            public integer decayed = 0
            public real decayedEventPlayerUnit = 0
            public real decayedEventUnitType = 0
            public real decayedEventUnit = 0
        endglobals
        
        //! runtextmacro Hash_CREATE("")
    endscope
    
    private function doesRemove takes unit u returns boolean
        //! runtextmacro Udn_DECAY()
    endfunction
    
    private function cleanup takes nothing returns nothing
        local integer handleId = GetHandleId(GetExpiredTimer())
        local integer id = UdnSuspend_Hash(handleId)
        local integer handleId2 = GetHandleId(UdnSuspend_suspendedUnits[id])
        local integer id2 = UdnSuspendTimer_Hash(handleId2)
        local integer id3 = NonRemovedUnits_Hash(handleId2)
        call UdnSuspend_HashFree(handleId)
        call UdnSuspendTimer_HashFree(handleId2)
        call PauseTimer(GetExpiredTimer())
        call DestroyTimer(GetExpiredTimer())
        if (NonRemovedUnits_remove[id3] == false and doesRemove(UdnSuspend_suspendedUnits[id])) or (not doesRemove(UdnSuspend_suspendedUnits[id]) and NonRemovedUnits_remove[id3] == true) then
            call RemoveUnit(UdnSuspend_suspendedUnits[id])
        endif
        set UdnSuspendTimer_timers[id2] = null
        set UdnSuspend_suspendedUnits[id] = null
    endfunction
    
    private function endDecay takes nothing returns nothing
        local integer handleId = GetHandleId(GetExpiredTimer())
        local integer handleId2
        local integer id = UdnSuspend_Hash(handleId)
        local integer id2
        if GetUnitState(UdnSuspend_suspendedUnits[id], UNIT_STATE_LIFE) <= 0 and UdnSuspend_suspendedUnits[id] != null then
            set UdnSuspend_decayed = id
            set UdnSuspend_decayedEventPlayerUnit = NonRemovedUnits_Hash(GetPlayerId(GetOwningPlayer(UdnSuspend_suspendedUnits[id])))
            set UdnSuspend_decayedEventUnitType = NonRemovedUnits_Hash(GetUnitTypeId(UdnSuspend_suspendedUnits[id]))
            set UdnSuspend_decayedEventUnit = id
            
            call TimerStart(GetExpiredTimer(), .1, false, function cleanup)
        else
            set UdnSuspend_suspendedUnits[id] = null
            set handleId2 = GetHandleId(UdnSuspend_suspendedUnits[id])
            set id2 = UdnSuspendTimer_Hash(handleId2)
            set UdnSuspendTimer_timers[id2] = null
            call UdnSuspend_HashFree(handleId)
            call UdnSuspendTimer_HashFree(handleId2)
            call PauseTimer(GetExpiredTimer())
            call DestroyTimer(GetExpiredTimer())
        endif
    endfunction
    
    private function startDecay takes nothing returns nothing
        local integer handleId = GetHandleId(GetTriggerUnit())
        local integer id = UdnSuspendTimer_Hash(handleId)
        local real decayTime = UdnUnitTypeDecay_decayTime[UdnUnitTypeDecay_Hash(GetUnitTypeId(GetTriggerUnit()))]
        if GetTriggerUnit() == null then
            call UdnUnitTypeDecay_HashFree(GetUnitTypeId(GetTriggerUnit()))
            return
        endif
        if decayTime <= 0 then
            set decayTime = UNIT_DECAY
            call UdnUnitTypeDecay_HashFree(GetUnitTypeId(GetTriggerUnit()))
        endif
        if UdnSuspendTimer_timers[id] == null then
            set UdnSuspendTimer_timers[id] = CreateTimer()
            set UdnSuspend_suspendedUnits[UdnSuspend_Hash(GetHandleId(UdnSuspendTimer_timers[id]))] = GetTriggerUnit()
            call TimerStart(UdnSuspendTimer_timers[id], decayTime, false, function endDecay)
        else
            call TimerStart(UdnSuspendTimer_timers[id], decayTime, false, function endDecay)
        endif
    endfunction
    
    private function ini takes nothing returns nothing
        local integer x = 0
        local player p
        call Mfn_createCredit1(SYSTEM, VERSION, AUTHOR, HELPERS, TEXTURE_PATH, DESCRIPTION)
        call TriggerAddAction(decay, function startDecay)
        loop
            //! runtextmacro Udn_REGISTERED_PLAYERS()
            call TriggerRegisterPlayerUnitEvent(decay, p, EVENT_PLAYER_UNIT_DEATH, null)
            set x = x + 1
        endloop
        //! runtextmacro Udn_EXTRA_PLAYERS()
        set p = null
    endfunction
    
    public function setDecay takes integer unitTypeId, real decayTime returns nothing
        set UdnUnitTypeDecay_decayTime[UdnUnitTypeDecay_Hash(unitTypeId)] = decayTime
    endfunction
    
    public function unsetDecay takes integer unitTypeId returns nothing
        local integer hash = UdnUnitTypeDecay_Hash(unitTypeId)
        set UdnUnitTypeDecay_decayTime[hash] = 0
        call UdnUnitTypeDecay_HashFree(unitTypeId)
    endfunction
    
    public function getLastDecayingUnit takes nothing returns unit
        return UdnSuspend_suspendedUnits[UdnSuspend_decayed]
    endfunction
    
    public function triggerRegisterDecayEvent takes trigger t returns nothing
        call TriggerRegisterVariableEvent(t, "Udn_UdnSuspend_decayed", GREATER_THAN, -1)
    endfunction
    
    public function triggerRegisterPlayerUnitDecayEvent takes trigger t, integer playerId returns nothing
        call TriggerRegisterVariableEvent(t, "Udn_UdnSuspend_decayedEventPlayerUnit", EQUAL, I2R(NonRemovedUnits_Hash(playerId)))
    endfunction
    
    public function triggerRegisterUnitTypeDecayEvent takes trigger t, integer unitType returns nothing
        call TriggerRegisterVariableEvent(t, "Udn_UdnSuspend_decayedEventUnitType", EQUAL, I2R(NonRemovedUnits_Hash(unitType)))
    endfunction
    
    public function triggerRegisterUnitDecayEvent takes trigger t, unit u returns nothing
        local integer hash = UdnSuspendTimer_Hash(GetHandleId(u))
        local integer hash2
        set UdnSuspendTimer_timers[hash] = CreateTimer()
        set hash2 = UdnSuspend_Hash(GetHandleId(UdnSuspendTimer_timers[hash]))
        set UdnSuspend_suspendedUnits[hash2] = u
        call TriggerRegisterVariableEvent(t, "Udn_UdnSuspend_decayedEventUnit", EQUAL, I2R(hash2))
    endfunction
    
    public function decayUnit takes unit u, boolean remove returns nothing
        set NonRemovedUnits_remove[NonRemovedUnits_Hash(GetHandleId(u))] = not remove
    endfunction
    
    public function getRemainingDecay takes unit u returns real
        return TimerGetRemaining(UdnSuspendTimer_timers[UdnSuspendTimer_Hash(GetHandleId(u))])
    endfunction
    
    public function getElapsedDecay takes unit u returns real
        return TimerGetElapsed(UdnSuspendTimer_timers[UdnSuspendTimer_Hash(GetHandleId(u))])
    endfunction
    
    public function cleanUnit takes unit u returns nothing
        local integer handleId = GetHandleId(u)
        set NonRemovedUnits_remove[NonRemovedUnits_Hash(handleId)] = false
        call RemoveUnit(u)
    endfunction
endlibrary

library RequiresUdn requires Udn
endlibrary
 

Attachments

  • Udn.w3m
    13.4 KB · Views: 62
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
I can't really do that in this Switch : \.

But one interesting thing is you can use this in a framework to make custom decay times. When a unit decays, remove the unit or do w/e with it : ). You can just set the constant to something like 4395803958093485093489053809 and then use your own settings for full custom decay times on dif unit types and full control over what happens when a unit decays.

It's just an interesting thought : ).
 
Top