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

[Snippet] IsUnitCorpse

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
JASS:
library IsUnitCorpse initializer onInit
    
    /*
        Simple library used to check whether a unit has become a corpse or not.
        
        How to use:
        - You must have a dummy caster at your OE
        - Copy this trigger into your map
        - Save your map, then re-open it
    */
        //! external ObjectMerger w3a Amel IRAA anam "CORPSE_CHECKER" abpy 0 auby 0 aart "" auar "" arac "other" ahky "" auhk "" aran 1 0 atar 1 "air,dead,ground,player" atp1 1 "" aub1 1 "" aut1 1 "" auu1 1 ""
    /*  
        - Delete or comment out that one line above and save again.
    */
    
    globals
        private constant integer DUMMY_ID     = 'h000'
        private constant integer SPELL_ID     = 'IRAA'
        private constant integer CONTAINER_ID = 'Sch2'
        private constant integer ORDER_ID     = 852053
        private constant player UNUSED_PLAYER = Player(15)
        private unit Dummy
    endglobals
    
    native UnitAlive takes unit id returns boolean
    
    function IsUnitCorpse takes unit u returns boolean
    
        local boolean b
        local player p
        
        if not UnitAlive(u) then
            set p = GetOwningPlayer(u)
            call SetUnitOwner(u, UNUSED_PLAYER, false)
            call SetUnitX(Dummy, GetUnitX(u) + 100)
            call SetUnitY(Dummy, GetUnitY(u) + 100)
            call IssueImmediateOrderById(Dummy, ORDER_ID)
            set b = GetUnitCurrentOrder(Dummy) == ORDER_ID
            call SetUnitPosition(Dummy, 1234567890, 1234567890)
            call SetUnitOwner(u, p, false)
        else
            return false
        endif
        
        return b
    endfunction
    
    private function onInit takes nothing returns nothing
        set Dummy = CreateUnit(UNUSED_PLAYER, DUMMY_ID, 1234567890, 1234567890, 0)
        call UnitAddAbility(Dummy, SPELL_ID)
        call UnitAddAbility(Dummy, CONTAINER_ID)
    endfunction
    
endlibrary
 
Last edited:

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
Awesome usefulness. :thumbs_up:

Which line though? I get confused. :eek:

Aren't you CakeMaster? :eek:

This line:
JASS:
//! external ObjectMerger w3a Amel IRAA anam "REVIVE_CHECKER" abpy 0 auby 0 aart "" auar "" arac "other" ahky "" auhk "" aran 1 0.01 atar 1 "air,dead,ground" atp1 1 "" aub1 1 "" aut1 1 "" auu1 1 ""
Sorry for the confusion :)
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
I'm fine with this although such scripts are part of UnitEvent-related resources, no need to submit them one by one.

Whatmore, if you want to know the truth, you don't need any dummy units or abilities in order to detect the "decay" event. What you do need is, an unit indexer and a constant decay timer found in game constants (or calculate it manually at the begining of the game). You won't have access to private stuff of given UI, thus it's probably better to write an extension for given indexer.

The undefend event fires more often than just once in certain cases. Thats why one usually needs proper differenciation in order to properly fire INDEX/DEINDEX event. With help of "decay constant", you can check the difference between time of death, and time of decay. If it's within range of your constant, fire "decay event".
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Dalvengyr >.>

But you need to catch that in order to tell if unit is decaying (IsUnitDecaying).
I believe different unit has a different death time
So what? Start the timer at the begining of the game and check the timer elapsed for given unit when it dies.
Later refer to that value when checking the difference between it and current game time.

Have you tried looking at UnitEvent and other related libraries?
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
Dalvengyr >.>

But you need to catch that in order to tell if unit is decaying (IsUnitDecaying).
So what? Start the timer at the begining of the game and check the timer elapsed for given unit when it dies.
Later refer to that value when checking the difference between it and current game time.

Have you tried looking at UnitEvent and other related libraries?

I'm sorry if I'm hardly understand. But I think I don't need any event. The function check whether a unit is currently decaying at time X, is that unit has become a corpse or not yet at that time X.

Note: DoesUnitDecay != IsUnitDecaying

Edit:
Anyway, value of 100 seems quite risky, perhaps I will reduce it to 0.1 or something...
 
Doesn't seem to work for me. Yes I have a dummy unit (from xe).

  • IUD Test
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Unit - Create 1 Footman for Player 1 (Red) at (Random point in (Playable map area)) facing Default building facing degrees
      • Unit - Kill (Last created unit)
      • Unit Group - Pick every unit in (Units in (Playable map area)) and do (Actions)
        • Loop - Actions
          • Custom script: if IsUnitDecaying(GetEnumUnit()) then
          • Game - Display to (All players) the text: ((Name of (Picked unit)) + is decaying.)
          • Custom script: endif

^ displays nothing.

The trigger below however, fires.

  • Untitled Trigger 001
    • Events
      • Unit - A unit Decays
    • Conditions
    • Actions
      • Game - Display to (All players) the text: true

Sorry if I missed something.
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
I think I misnamed it, this library actually checks whether a unit has become a corpse or not. If you check immediately after kills, then it indeed results false, because it hasn't become a corpse yet.

So what you are saying is that you don't actually revive the unit? If so, then decay time won't be reset ; )
Nope.

Updated Now it safe even for checking two units with exact same location and exact time. But requires dummy unit with 0 acquistion range
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
so before TriggerHappy rushes headlong into approving this

not UnitAlive(whichUnit) and GetUnitTypeId(whichUnit) != 0

IsUnitType(whichUnit, UNIT_TYPE_DEAD)

elaborate on why your solution is better than the standard approaches that have been used for years


be sure to show differences in behavior and performance and weigh the pros/cons
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
differences in behavior
This only returns true if the unit has actually become a corpse, that's the only difference.

performance and weigh the pros/cons
This seems slower. But can be useful for some abilities like Cannibalize where it can only consumes "real corpse" not dying unit.

I have an alternate approach that would probably work much better - Check the current animation of unit. If it's "decay bone" or "decay flesh" then it is a corpse.
It's easier and will probably work better.
Is there a way to check unit's current animation?
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
I wanted to point out smthing but I hadn't realise that this is not an "event" resource..

However, there is something hidden, and I'm pretty sure none of you realised that while examining this snippet.

Unit corpse != usable unit corpse
There are few rare situations where unit might not yield usable corpse, e.g consider a case when unit dies and has reincarnation ability - body won't decay. However, if the reincarnation ability is removed as soon as unit dies, the effect persists but now, unit yields a corpse, which is unfortunatelly unusable.
This, and few other combinations are usefull when you want to create "purified" corpses e.g prevent them from Scourge' magic ^)^

Result: this still might be usefull for determining "usable corpse" or differenciate usable one from non-usable. However, as pointed above - if you just want to say whether unit is a corpse or not, there isn't much required to test that out. I'm still waiting for you to rewrite this using the timer approach : )
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
You don't. It's not desired to interfere in actions performed by user on purpose, lol.
Lol @ "everyone is Nes" statement. Everyone here is unique, and you probably know that after spending few weeks visiting hive :p

I've proposed different approach in one of first posts in this thread ^)^
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
I still don't understand your different approace ^)^

If what you want is using unit decay event, utilize indexer, and use a boolean array global.. Well, that doesn't look like a snippet. ^)^
This is a trick, to shorten up the code and w/o requiring any burden dependecy. ^)^

And running that macro shit wont hurt anybody... ^)^ Also everybody got dummy caster in their maps, so what's the big deal? ^)^

@NesthaHolic
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
Dalvengyr, because I thought you wanted to extend this with "event" functionality.

Answer
attachment.php
 

Attachments

  • no.jpg
    no.jpg
    226.4 KB · Views: 281

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Very very minor improvement:

JASS:
    function IsUnitCorpse takes unit u returns boolean
    
        local boolean b = false
        local player p
        
        if not UnitAlive(u) then
            set p = GetOwningPlayer(u)
            call SetUnitOwner(u, UNUSED_PLAYER, false)
            call SetUnitX(Dummy, GetUnitX(u) + 100)
            call SetUnitY(Dummy, GetUnitY(u) + 100)
            call IssueImmediateOrderById(Dummy, ORDER_ID)
            set b = GetUnitCurrentOrder(Dummy) == ORDER_ID
            call SetUnitPosition(Dummy, 1234567890, 1234567890)
            call SetUnitOwner(u, p, false)
        endif
        
        return b
    endfunction
 
Top