Reincarnation Event

Lyle.

New Member
Reaction score
32
What is the best way to catch when a unit that has reincarnation has revived?
 

WolfieeifloW

WEHZ Helper
Reaction score
372
Ahh, I had this problem a while ago too.
Just wondering, to see if it's the same problem I had, why do you need to catch this event?
 

Lyle.

New Member
Reaction score
32
I want to give the unit an item. The item is auto-used and adds a desired buff.
 

WolfieeifloW

WEHZ Helper
Reaction score
372
Darnit.
I had mine cast a spell when he was reincarnated.
It was saw792 who helped me out;
Maybe you could PM him a link to this thread?

Don't know if this will help you at all [if you even know JASS ;) ?] but here's the trigger he made me:
Fucking spoiler tags...The admins need to fix these...
JASS:
library_once TimerUtils
//*********************************************************************
//* TimerUtils (Blue flavor)
//* ----------
//*
//*  To implement it , create a custom text trigger called TimerUtils
//* and paste the contents of this script there.
//*
//*  To copy from a map to another, copy the trigger holding this
//* library to your map.
//*
//* (requires vJass)   More scripts: htt://www.wc3campaigns.net
//*
//* For your timer needs:
//*  * Attaching
//*  * Recycling (with double-free protection)
//*
//* set t=NewTimer()      : Get a timer (alternative to CreateTimer)
//* ReleaseTimer(t)       : Relese a timer (alt to DestroyTimer)
//* SetTimerData(t,2)     : Attach value 2 to timer
//* GetTimerData(t)       : Get the timer's value.
//*                         You can assume a timer's value is 0
//*                         after NewTimer.
//*
//* Blue Flavor: Slower than the red flavor, it got a 408000 handle id
//*             limit, which means that if more than 408000 handle ids
//*             are used in your map, TimerUtils might fail, this
//*             value is quite big and it is much bigger than the 
//*             timer limit in Red flavor.
//*
//********************************************************************

//================================================================
    globals
        private constant integer MAX_HANDLE_ID_COUNT = 408000
        // values lower than 8191: very fast, but very unsafe.
        // values bigger than 8191: not that fast, the bigger the number is the slower the function gets
        // Most maps don't really need a value bigger than 50000 here, but if you are unsure, leave it
        // as the rather inflated value of 408000
    endglobals

    //=================================================================================================
    private function H2I takes handle h returns integer
        return h
        return 0
    endfunction

    //==================================================================================================
    globals
        private integer array data[MAX_HANDLE_ID_COUNT]
        private constant integer MIN_HANDLE_ID=0x100000
    endglobals

    //It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
    function SetTimerData takes timer t, integer value returns nothing
        debug if(H2I(t)-MIN_HANDLE_ID>=MAX_HANDLE_ID_COUNT) then
        debug     call BJDebugMsg("SetTimerData: Handle id too big, increase the max handle id count or use gamecache instead")
        debug endif
        set data[H2I(t)-MIN_HANDLE_ID]=value
    endfunction

    function GetTimerData takes timer t returns integer
        debug if(H2I(t)-MIN_HANDLE_ID>=MAX_HANDLE_ID_COUNT) then
        debug     call BJDebugMsg("GetTimerData: Handle id too big, increase the max handle id count or use gamecache instead")
        debug endif
        return data[H2I(t)-MIN_HANDLE_ID]
    endfunction

    //==========================================================================================
    globals
        private timer array tT
        private integer tN = 0
        private constant integer HELD=0x28829022
        //use a totally random number here, the more improbable someone uses it, the better.
    endglobals

    //==========================================================================================
    function NewTimer takes nothing returns timer
        if (tN==0) then
            set tT[0]=CreateTimer()
        else
            set tN=tN-1
        endif
        call SetTimerData(tT[tN],0)
     return tT[tN]
    endfunction

    //==========================================================================================
    function ReleaseTimer takes timer t returns nothing
        if(t==null) then
            debug call BJDebugMsg("Warning: attempt to release a null timer")
            return
        endif
        if (tN==8191) then
            debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")

            //stack is full, the map already has much more troubles than the chance of bug
            call DestroyTimer(t)
        else
            call PauseTimer(t)
            if(GetTimerData(t)==HELD) then
                debug call BJDebugMsg("Warning: ReleaseTimer: Double free!")
                return
            endif
            call SetTimerData(t,HELD)
            set tT[tN]=t
            set tN=tN+1
        endif    
    endfunction

endlibrary

JASS:
library RemovalDetection initializer Init needs TimerUtils
    // Notes: CANNOT have two defend based abilities on same unit, or fires twice.
    // ASSUMES that summoned units cannot be revived in any way. This ought to be true.
    // If not, replace IsAnimated with 'return false' and don't use animate dead, or something.
    // Devour ain't a problem, but they'll die and then decay, you just can't see them decaying.
    
    //Config
    
    // This line creates a new ability based off of defend - make sure it doesn't conflict.
    //! external ObjectMerger w3a Adef rdd& anam "Removal Detection Defend"
    
    globals
        private constant integer SPELL_ID = 'rdd&' // must be the same as the parameter after "w3a Adef" above
        private constant integer ORDER_ID = 852056 // undefend
        private constant integer MAX_ARRAY_SIZE = 401000 //for the unit flag arrays
    endglobals
    
    private function AddAbility takes unit u returns nothing // have ALL defend based spells here
        if (GetUnitAbilityLevel(u, SPELL_ID) + GetUnitAbilityLevel(u, 'Adef')) == 0 then
            call UnitAddAbility(u, SPELL_ID)
        endif
    endfunction
    
    private function IsAnimated takes unit u returns boolean
        debug if IsUnitType(u, UNIT_TYPE_SUMMONED) then
            // check needed due to animate dead sucking
            debug call BJDebugMsg("Animated")
        debug endif
        return IsUnitType(u, UNIT_TYPE_SUMMONED)
    endfunction
    
    // DO NOT EDIT BELOW HERE
    
    globals
        //Unit flags
        private boolean array dead[MAX_ARRAY_SIZE]
        private boolean array animated[MAX_ARRAY_SIZE]
        private boolean array reincarnated[MAX_ARRAY_SIZE]
        
        //Event handling
        private trigger array reincS
        private trigger array reincF
        private trigger array rez
        private trigger array oos
        
        private integer reincSMax = 0
        private integer reincFMax = 0
        private integer rezMax = 0
        private integer oosMax = 0
        
        private integer cnt = 0
        
        //Event responses
        private unit trg = null
        private boolean amd = false
    endglobals
    
    //"Event Responses" and event registration
    
    function TriggerRegisterReincarnationEvent takes trigger t, boolean finish returns nothing
        if finish then
            set reincF[reincFMax] = t
            set reincFMax = reincFMax + 1
        else
            set reincS[reincSMax] = t
            set reincSMax = reincSMax + 1
        endif
    endfunction
    
    function TriggerRegisterResurrectionEvent takes trigger t returns nothing
        set rez[rezMax] = t
        set rezMax = rezMax + 1
    endfunction
    
    function TriggerRegisterOutOfScopeEvent takes trigger t returns nothing
        set oos[oosMax] = t
        set oosMax = oosMax + 1
    endfunction
    
    function GetReincarnatingUnit takes nothing returns unit
        return trg
    endfunction
    
    function GetResurrectedUnit takes nothing returns unit
        return trg
    endfunction
    
    function GetScopingUnit takes nothing returns unit
        return trg
    endfunction
    
    function GetWasAnimated takes nothing returns boolean
        return amd
    endfunction
    
    //System
    
    private function H2I takes handle h returns integer
        return h
        return 0
    endfunction
    
    private function GetIndex takes handle h returns integer
        return H2I(h) - 0x100000
    endfunction

    private struct Data
        integer i
        unit u
        static method create takes unit u, integer i returns Data
            local Data dat = Data.allocate()
            set dat.u = u
            set dat.i = i
            return dat
        endmethod
    endstruct

    private function Child takes nothing returns nothing
        local Data dat = GetTimerData(GetExpiredTimer())
        if reincarnated[dat.i] then
            set trg = dat.u
            if GetUnitTypeId(trg) != 0 then
                set cnt = 0
                loop
                    exitwhen cnt >= reincSMax
                    if TriggerEvaluate(reincS[cnt]) then
                        call TriggerExecute(reincS[cnt])
                    endif
                    set cnt = cnt + 1
                endloop
                debug call BJDebugMsg("Reincarnating")
            else
                set reincarnated[dat.i] = false
                debug call BJDebugMsg("Removed")
            endif
        endif
        set dat.u = null
        call dat.destroy()
        call ReleaseTimer(GetExpiredTimer())
    endfunction
    
    private function Ordered takes nothing returns boolean
        local integer index = GetIndex(GetTriggerUnit())
        local timer t
        set trg = GetTriggerUnit()
        if GetTriggerEventId() == EVENT_PLAYER_UNIT_ISSUED_ORDER then
            if GetIssuedOrderId() == ORDER_ID then
                set amd = false
                if IsUnitType(trg,UNIT_TYPE_DEAD) then
                    if dead[index] or animated[index] then
                        if dead[index] then
                            set dead[index] = false //it has just gone out of scope
                            debug call BJDebugMsg("Out of scope")
                        else
                            set animated[index] = false
                            debug call BJDebugMsg("Out of scope from animated")
                            set amd = true
                        endif
                        set cnt = 0
                        loop
                            exitwhen cnt >= oosMax
                            if TriggerEvaluate(oos[cnt]) then
                                call TriggerExecute(oos[cnt])
                            endif
                            set cnt = cnt + 1
                        endloop
                    else
                        set dead[index] = true
                        set reincarnated[index] = true //Set to false if the unit
                        set t = NewTimer()             //is registered to have died
                        call SetTimerData(t,Data.create(trg,index))
                        call TimerStart(t,0,false,function Child)
                        set t = null
                    endif
                elseif dead[index] then
                    if IsAnimated(trg) then
                        set animated[index] = true
                        set amd = true
                    endif
                    if reincarnated[index] then
                        set reincarnated[index] = false
                        set cnt = 0
                        loop
                            exitwhen cnt >= reincFMax
                            if TriggerEvaluate(reincF[cnt]) then
                                call TriggerExecute(reincF[cnt])
                            endif
                            set cnt = cnt + 1
                        endloop
                        debug call BJDebugMsg("Reincarnated")
                    elseif not IsUnitType(trg,UNIT_TYPE_HERO) then
                        set cnt = 0          //hero revive already has an event
                        loop
                            exitwhen cnt >= rezMax
                            if TriggerEvaluate(rez[cnt]) then
                                call TriggerExecute(rez[cnt])
                            endif
                            set cnt = cnt + 1
                        endloop
                        debug call BJDebugMsg("Resurrected")
                    endif
                    set dead[index] = false //it has just been resurrected/reincarnated
                endif //the else is just a normal call
            endif
        else
            set reincarnated[index] = false //The order fires before the death event
            debug call BJDebugMsg("Died")   //and thus lame workarounds are required
        endif
        return false
    endfunction
    
    private function Ex takes nothing returns boolean
        call AddAbility(GetFilterUnit())
        return false
    endfunction
    
    private function Enters takes nothing returns boolean
        call AddAbility(GetTriggerUnit())
        return false
    endfunction
    
    private function Init takes nothing returns nothing
        local group g = CreateGroup()
        local rect r = GetWorldBounds()
        local region world = CreateRegion()
        local trigger t = CreateTrigger()
        local integer i = 0
        
        call RegionAddRect(world, r)
        call GroupEnumUnitsInRect(g, r, Condition(function Ex))
        call DestroyGroup(g)
        set g = null
        call RemoveRect(r)
        set r = null
        
        call TriggerAddCondition(t, Condition(function Enters))
        call TriggerRegisterEnterRegion(t, world, null)
        
        set t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_ORDER)
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
        call TriggerAddCondition(t, Condition(function Ordered))
        
        loop
            exitwhen i >= 16
            call SetPlayerAbilityAvailable(Player(i), SPELL_ID, false)
            set i = i + 1
        endloop
    endfunction
endlibrary

JASS:
scope StompOnRez initializer Init

  globals
    private integer UNIT_TYPE = 'Otch'  //Rawcode of reincarnating unit-type
    private integer DUMMY_ID = 'n000'  //Rawcode of dummy unit
    private integer ABILITY_ID = 'A001'  //Rawcode of stomp ability
    private string STOMP_ORDER_STRING = "stomp" //Order string of base ability
    private boolean USE_DUMMY = true //Have dummy cast or hero cast
                                     //Recommended true
  endglobals
  
  private function Conditions takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit()) == UNIT_TYPE
  endfunction
  
  private function AltActions takes nothing returns nothing
    local unit rez = GetReincarnatingUnit()
    call TriggerSleepAction(0.0) //Required
    call IssueImmediateOrder(rez, STOMP_ORDER_STRING)
    set rez = null
  endfunction
  
  private function Actions takes nothing returns nothing
    local unit rez = GetReincarnatingUnit()
    local unit u = CreateUnit(GetOwningPlayer(rez), DUMMY_ID, GetUnitX(rez), GetUnitY(rez), 0)
    call UnitAddAbility(u, ABILITY_ID)
    call IssueImmediateOrder(u, STOMP_ORDER_STRING)
    call UnitApplyTimedLife(u, 'BTLF', 3)
    call DestroyEffect(AddSpecialEffectTarget("war3mapImported\\FrostStomp.mdx", rez, "origin"))
    set rez = null
    set u = null
  endfunction
  
  private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterReincarnationEvent(t, true)
    call TriggerAddCondition(t, Condition(function Conditions))
    if USE_DUMMY then
      call TriggerAddAction(t, function Actions)
    else
      call TriggerAddAction(t, function AltActions)
    endif
  endfunction
  
endscope
 

Lyle.

New Member
Reaction score
32
I don't know they syntax for JASS but I know programming so I think I can understand it... I think imma hunt for an easier GUI solution for now though.
 

saw792

Is known to say things. That is all.
Reaction score
280
Copy the top two code sections that Wolfie posted and paste them into blank custom text triggers (Edit > Convert to Custom Test, delete all text there, paste - requires Newgen).

Then create an eventless trigger that does your actions in GUI, convert it to custom text and add in this line between 'set gg_trg_xxx = CreateTrigger()' and 'call TriggerAddAction(...'

JASS:
call TriggerRegisterReincarnationEvent(t, true)


Then replace all the parts of your actions that say GetTriggerUnit() with GetReincarnatingUnit() (the brackets are important) and you are set.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top