HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Finding a unit/doodad's current animation

05-09-2007, 02:16 PM#1
Whitehorn
Pretty simple question here. Couldn't find the call to get a model's current animation.

Scenario:
I have a function to open and close doors. A closed door uses 'death alternate', whereas a destroyed door uses 'death'. My trigger used to simply check if it was alive (close it) or dead (open it), but I want to block destroyed doors from being closed again. So I want it to grab the current animation to check this.

Here's my terrible code:

Collapse JASS:
function Trig_Doors_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A003'
endfunction

function Trig_Doors_Act2 takes nothing returns nothing
    if GetDestructableTypeId(GetEnumDestructable()) == 'LTg1' or GetDestructableTypeId(GetEnumDestructable()) == 'LTg3' then
        if IsDestructableAliveBJ(GetEnumDestructable())  then
            call ModifyGateBJ( bj_GATEOPERATION_OPEN, GetEnumDestructable() )
        else
        call ModifyGateBJ( bj_GATEOPERATION_CLOSE, GetEnumDestructable() )
        endif
    endif
endfunction

function Trig_Doors_Actions takes nothing returns nothing
    local location a = GetUnitLoc(GetTriggerUnit())
    call EnumDestructablesInCircleBJ( 250.00, a, function Trig_Doors_Act2 )
    call RemoveLocation( a)
    set a = null
endfunction

//===========================================================================
function InitTrig_Doors takes nothing returns nothing
    set gg_trg_Doors = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Doors, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Doors,Condition( function Trig_Doors_Conditions))
    call TriggerAddAction( gg_trg_Doors, function Trig_Doors_Actions )
endfunction
05-09-2007, 02:30 PM#2
Rising_Dusk
There unfortunately is no native that can directly return what animation a unit or destructable is currently performing.
This makes it a bit more complicated than it should be.

The best you can do is keep some method for each door to know whether it was destroyed or merely opened.
For a gate, death simply means you can walk through it, no matter how you made it walkable. (Death/open)
(See below)

I took the liberty of optimizing your code a bunch.
Collapse JASS:
function Doors_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A003'
endfunction

function Doors_EnumCallback takes nothing returns nothing
    local destructable d = GetEnumDestructable()
    
    if GetDestructableTypeId(d) == 'LTg1' or GetDestructableTypeId(d) == 'LTg3' and GetDestructableMaxLife(d) > 0 then
    if GetDestructableLife(d) <= 0 then
            call ModifyGateBJ(bj_GATEOPERATION_OPEN, d)
    else
        call ModifyGateBJ(bj_GATEOPERATION_CLOSE, d)
    endif
    endif
    
    set d = null
endfunction

function Doors_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real radius = 250              //Makes life easier if you want to change it ever.
    local rect r = Rect(x-radius,y-radius,x+radius,y+radius)
    
    call EnumDestructablesInRect(r, filterEnumDestructablesInCircleBJ, Doors_EnumCallback)
    
    call RemoveRect(r)
    set r = null
    set u = null
endfunction

//===========================================================================
function InitTrig_Doors takes nothing returns nothing
    set gg_trg_Doors = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_Doors, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_Doors,Condition(function Doors_Conditions))
    call TriggerAddAction(gg_trg_Doors, function Doors_Actions)
endfunction
You'll see that red part.
There's a trick that I learned once; you can modify the max life of a destructable relatively easily via SetDestructableMaxLife(MyDes) and GetDestructableMaxLife(MyDes).
So whenever you DESTROY a gate, simply set its max life to 0.
Then check if max life is >0 if you should open/close it.

Hopefully that helped.
05-09-2007, 02:40 PM#3
Toink
I had the same questions the were never answered. :/ So can I ask in this thread( if you don't mind WH ) how to get a unit's current anim playing?

In Vex's spell factory, the charge thingy leaves images, which exactly does the same animation the unit was playing but has a 0% anim speed.
05-09-2007, 02:44 PM#4
Rising_Dusk
Quote:
how to get a unit's current anim playing?
Read my post above, there is no native for that.
You can use the alternate method I used above for destructables.

For units, like in that spell factory (Which you could have freakin' opened and LOOKED YOURSELF! -_-), you would store the animation you're setting the main unit to use into a variable by some method. (Probably index)
Then you would simply set the image animations to the same index as the main unit.

It's not "getting" the animation at all, just storing it when first set and then reusing it.
05-09-2007, 02:44 PM#5
Whitehorn
Cheers for optimising that. I wrote that crap a year ago :)

A question on registering a destructible death. How's the best way to detect this? Using play area/map only registers 64 destructibles which kinda limits how many I can use. Maybe detecting the character hitting the object and waiting for it to hit 0 life?
05-09-2007, 02:53 PM#6
Rising_Dusk
Quote:
Using play area/map only registers 64 destructibles which kinda limits how many I can use.
You can detect it alternately, see below.

Collapse JASS:
function GateDeath_Actions takes nothing returns nothing
    local destructable d = GetTriggerWidget()
    call SetDestructableMaxLife(d, 0.0)
    set d = null
endfunction

function GateDeath_Check takes nothing returns nothing
    local destructable d = GetEnumDestructable()
    
    if GetDestructableTypeId(d) == 'LTg1' or GetDestructableTypeId(d) == 'LTg3' then
        call TriggerRegisterDeathEvent(gg_trg_GateDeath, d)
    endif
    
    set d = null
endfunction

function InitTrig_GateDeath takes nothing returns nothing
    local rect r = GetWorldBounds()
    set gg_trg_GateDeath = CreateTrigger()
    call EnumDestructablesInRect(r, null, function GateDeath_Check)
    call TriggerAddAction(gg_trg_GateDeath, function GateDeath_Actions)
    call RemoveRect(r)
    set r = null
endfunction

That loads all destructables of your specific gate types into the trigger for death.
You may have to modify MaxLife of the destructable a bit more to understand if you should set max life to 0 or not.
Unfortunately destructables don't have user data, so we can't abuse that.

You also might have to modify the ModifyGateBJ() call a bit, but it can be done.
05-09-2007, 02:53 PM#7
Toink
If I may WH..

Quote:
Originally Posted by Rising_Dusk
For units, like in that spell factory (Which you could have freakin' opened and LOOKED YOURSELF! -_-), you would store the animation you're setting the main unit to use into a variable by some method. (Probably index)
Then you would simply set the image animations to the same index as the main unit.

I find it quite vague, as if you set it to walk it would walk but not the exact walking stance the unit was doing before.. It's hard to elaborate.. Here's an image..

Code:
Yay anim from  This:

  O
/| |\
 /  \

to this:

 \O/
 | |
/   \
Guess wutt? It's a stick man!
If I'd try to do what you said I think it would end up like :
  O
/| |\
 /  \

It's very hard to elaborate as you can see.
05-09-2007, 02:59 PM#8
Rising_Dusk
Take for example a spell from AotZ on the demon hunter hero.

He teleports to a target point and has an afterimage follow his path, using the walk animation.
The afterimage literally runs really f*cking fast (Via triggers) to the target point.
I used a method of setting the image's animation speed to 500% and setting it to the walk animation every .033 seconds.
You'd be surprised just how effective it turned out.

Experiment with it a bit.
It really depends upon what you're trying to achieve.
But the point remains that you have to store the animation by some means (Index or string, I recommend index) and then set the images to use that stored animation.

If you have a unit at 0% animation speed, it will lock in the first frame of the animation you give it.
This generally gives the impression he's walking, in the case of the walk animation anyways.
05-09-2007, 03:04 PM#9
Toink
Ohh I see.. Well thanks, and thank you too WH for letting me stay in yer thread <3