• Check out the results of the Techtree Contest #19!
  • Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • Create a void inspired texture for Warcraft 3 and enter Hive's 34th Texturing Contest: Void! Click here to enter!
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!

[vJASS] [Snippet] ReviveEvent

Allows to revive units, similar to [Snippet] ReviveUnit

I thought about to add compatibility with the latter but it is not possible at the moment because the names of structs match.

JASS:
library ReviveEvent/*
**************************************************************************************************
*
*   **********************************************************************************************
*
*   */ uses /*
*       */ TimerUtilsEx           /* hiveworkshop.com/forums/graveyard-418/system-timerutilsex-204500/
*       */ WorldBounds            /* github.com/nestharus/JASS/blob/master/jass/Systems/WorldBounds/script.j
*       */ UnitIndexer            /* old version (v4.0.2.8)
*       */ optional ReTimerdialog /* hiveworkshop.com/threads/snippet-reviveevent.263628/post-2663325
*       */ optional ReLeaderboard /* hiveworkshop.com/threads/snippet-reviveevent.263628/post-2663325
*   
*   **********************************************************************************************
*
*   ReviveEvent
*   ___________
*   v2.1.2.2
*   by Thelordmarshall
*   
*   You can:
*   ________
*
*       - Revive units.
*       - Use custom fx on revived units.
*       - See the cooldown in timerdialog or leaderboard.
*       - Detect when hero/unit is revived.
*
*   API:
*   ____
*
*   struct Revive extends array:
*       - method execute takes nothing returns boolean
*       - method getCooldown takes nothing returns real
*
*   method operator:
*       - method operator onX= takes real x returns nothing
*       - method operator onY= takes real y returns nothing
*       - method operator awakenFx= takes string fx returns nothing
*       - method operator cooldown= takes real cooldown returns nothing
*       - method operator select= takes boolean select returns nothing
*           - instantly select unit on revive.
*       - method operator showTd= takes boolean show returns nothing
*           - show Timerdialog.
*       - method operator showLd= takes boolean show returns nothing
*           - show Leaderboard.
*       - method operator simpleLd= takes boolean simple returns nothing
*           - when is enabled only show the timer of player units in the leaderboard 
*             and not the timer of the other players units.
*
*   Functions:
*   __________
*
*       - function ReviveUnit takes unit whichUnit, real x, real y, string fx returns nothing
*       - function GetLastRevivedUnit takes nothing returns unit
*       - function IsUnitDead takes unit whichUnit returns boolean
*       - function ReviveGetCooldown takes unit whichUnit returns real
*       - function SetReviveUnitAutomatic takes unit whichUnit, real x, real y, string fx, real cd, boolean upCd, boolean select returns nothing
*       - function ReviveUnitReset takes unit whichUnit returns nothing
*       - function RegisterReviveEvent takes code c returns nothing
*
*   Credits:
*   ________
*
*       - Nestharus: UnitIndexer, WorldBounds.
*       - Vexorian, Bribe & Magtheridon96: TimerUtils.
*       - Special thanks to Bannar, IcemanBo and BPower.
**************************************************************************************************/

    //CONFIGURATION
    //=====================================================================================
    globals
        // Public awaken fx
        constant string DEFAULT_AWAKEN_FX = "Abilities\\Spells\\Other\\Awaken\\Awaken.mdl"
    endglobals
    
    // Cooldown for each lvl
    private function CooldownFactor takes real base, integer lvl returns real
        return base/*cooldown base*/+ 4.00/*cooldown per lvl*/*I2R(lvl)/*lvl of unit*/
    endfunction
    //=====================================================================================
    //ENDCONFIGURATION                                                        
    
    globals
        private trigger r=CreateTrigger()
        private trigger t=CreateTrigger()
        private trigger o=CreateTrigger()
        private trigger p=CreateTrigger()
        unit re_lastRevivedUnit=null
    endglobals
    
    //Core.
    struct Revive extends array
        private unit u
        private real x
        private real y
        private real c
        private real l
        private string f
        private boolean re_upCooldown
        private boolean re_instSelect
        implement optional re_Timerdialog
        implement optional re_Leaderboard
        
        static method operator [] takes unit u returns thistype
            local thistype this=GetUnitId(u)
            set .u=u
            return this
        endmethod
        method getCooldown takes nothing returns real
            return .l
        endmethod
        
        private static method hook_removeUnit takes unit u returns nothing
            set thistype(GetUnitId(u)).u=null
        endmethod
        private method selectUnit takes nothing returns nothing
            if(.re_instSelect and GetLocalPlayer()==GetOwningPlayer(.u))then
                call PanCameraToTimed(.x,.y,0.)
                call ClearSelection()
                call SelectUnit(re_lastRevivedUnit,true)
            endif
        endmethod
        private method addAwaken takes nothing returns nothing
            if(.f!=null or .f!="")then
                call DestroyEffect(AddSpecialEffectTarget(.f,.u,"origin"))
            endif
        endmethod
        
        method execute takes nothing returns boolean
            local player p=GetOwningPlayer(.u)
            local thistype newId=GetUnitTypeId(.u)
            local boolean done
            if(IsUnitType(.u,UNIT_TYPE_DEAD) and not (newId==0))then
                if(IsUnitType(.u,UNIT_TYPE_HERO))then
                    set done=ReviveHero(.u,.x,.y,false)
                    if(done)then
                        call .addAwaken()
                        call .selectUnit()
                    endif
                    return done
                else
                    set re_lastRevivedUnit=CreateUnit(p,newId,0.,0.,0.)
                    set newId=GetUnitId(re_lastRevivedUnit)
                    set newId.u=re_lastRevivedUnit
                    set newId.f=.f
                    set newId.x=.x
                    set newId.y=.y
                    set newId.c=.c
                    set newId.re_upCooldown=.re_upCooldown
                    set newId.re_instSelect=.re_instSelect
                    static if(LIBRARY_ReTimerdialog)then
                        set newId.re_showDialog=.re_showDialog
                    endif
                    static if(LIBRARY_ReLeaderboard)then
                        set newId.re_showBoard=.re_showBoard
                        set newId.re_simpleBoard=.re_simpleBoard
                    endif
                    call RemoveUnit(.u)
                    call SetUnitX(re_lastRevivedUnit,newId.x)
                    call SetUnitY(re_lastRevivedUnit,newId.y)
                    call newId.addAwaken()
                    call newId.selectUnit()
                    call TriggerEvaluate(r)
                    set .u=null
                    return true
                endif
            endif
            return false
        endmethod

        private static method onDeathLoop takes nothing returns nothing
            local timer t=GetExpiredTimer()
            local thistype this=GetTimerData(t)
            set .l=.l-.03125
            if(.l<=0. or not IsUnitType(.u,UNIT_TYPE_DEAD))then
                call .execute()
                call ReleaseTimer(t)
            endif
            set t=null
        endmethod

        private static method onDeath takes nothing returns boolean
            local unit u=GetTriggerUnit()
            local thistype this=GetUnitId(u)
            if(.c>0.)then
                if(.re_upCooldown and IsUnitType(u,UNIT_TYPE_HERO))then
                    set .l=CooldownFactor(.c,GetUnitLevel(u))
                else
                    set .l=.c
                endif
                static if(LIBRARY_ReTimerdialog)then
                    if(.re_showDialog)then
                        call .startDialog(.l)
                    endif
                endif
                static if(LIBRARY_ReLeaderboard)then
                    if(.re_showBoard)then
                        call .startBoard(.l)
                    endif
                endif
                call TimerStart(NewTimerEx(this),.03125,true,function thistype.onDeathLoop)
            endif
            set u=null
            return false
        endmethod
        
        private static method runEvent takes nothing returns boolean
            set re_lastRevivedUnit=GetTriggerUnit()
            return TriggerEvaluate(r)
        endmethod
        private static method onEnter takes nothing returns boolean
            call TriggerRegisterUnitStateEvent(p,GetTriggerUnit(),UNIT_STATE_LIFE,GREATER_THAN,.405)
            return false
        endmethod
        
        //! textmacro re_Operator takes NAME,VAR_TYPE,VAR_NAME
        method operator $NAME$= takes $VAR_TYPE$ v returns nothing
            set .$VAR_NAME$=v
        endmethod
        //! endtextmacro
        
        //! runtextmacro re_Operator("onX","real","x")
        //! runtextmacro re_Operator("onY","real","y")
        //! runtextmacro re_Operator("awakenFx","string","f")
        //! runtextmacro re_Operator("cooldown","real","c")
        //! runtextmacro re_Operator("upCooldown","boolean","re_upCooldown")
        //! runtextmacro re_Operator("select","boolean","re_instSelect")
        //! runtextmacro optional re_td_Operator("showTd","boolean","re_showDialog")
        //! runtextmacro optional re_lb_Operator("showLd","boolean","re_showBoard")
        //! runtextmacro optional re_lb_Operator("simpleLd","boolean","re_simpleBoard")
        
        private static method onInit takes nothing returns nothing
            local group g=CreateGroup()
            local unit u
            call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DEATH)
            call TriggerAddCondition(t,function thistype.onDeath)
            call TriggerRegisterEnterRegion(o,WorldBounds.worldRegion,null)
            call TriggerAddCondition(o,function thistype.onEnter)
            call GroupEnumUnitsInRect(g,WorldBounds.world,null)
            loop
                set u=FirstOfGroup(g)
                exitwhen(u==null)
                call GroupRemoveUnit(g,u)
                call TriggerRegisterUnitStateEvent(p,u,UNIT_STATE_LIFE,GREATER_THAN,.405)
            endloop
            call TriggerAddCondition(p,function thistype.runEvent)
            call DestroyGroup(g)
            set g=null
        endmethod
    endstruct
    
    hook RemoveUnit Revive.hook_removeUnit
    
    function ReviveUnit takes unit whichUnit, real x, real y, string fx returns boolean
        set Revive[whichUnit].onX=x
        set Revive[whichUnit].onY=y
        set Revive[whichUnit].awakenFx=fx
        return Revive[whichUnit].execute()
    endfunction

    function GetLastRevivedUnit takes nothing returns unit
        return re_lastRevivedUnit
    endfunction
    
    function IsUnitDead takes unit whichUnit returns boolean
        return IsUnitType(whichUnit,UNIT_TYPE_DEAD)
    endfunction
    
    function ReviveGetCooldown takes unit whichUnit returns real
        return Revive[whichUnit].getCooldown()
    endfunction

    function SetReviveUnitAutomatic takes unit whichUnit, real x, real y, string fx, real cd, boolean upCd, boolean select returns nothing
        set Revive[whichUnit].onX=x
        set Revive[whichUnit].onY=y
        set Revive[whichUnit].awakenFx=fx
        set Revive[whichUnit].cooldown=cd
        set Revive[whichUnit].upCooldown=upCd
        set Revive[whichUnit].select=select
    endfunction

    function ReviveUnitReset takes unit whichUnit returns nothing
        if(not(Revive[whichUnit].getCooldown()>0.))then
            set Revive[whichUnit].onX=0.
            set Revive[whichUnit].onY=0.
            set Revive[whichUnit].awakenFx=DEFAULT_AWAKEN_FX
            set Revive[whichUnit].cooldown=0.
            static if LIBRARY_ReTimerdialog then
                set Revive[whichUnit].showTd=false
            endif
            static if LIBRARY_ReLeaderboard then
                set Revive[whichUnit].showLd=false
            endif
        endif
    endfunction
    
    function RegisterReviveEvent takes code c returns nothing
        call TriggerAddCondition(r,Filter(c))
    endfunction
endlibrary

Optional plugings:

JASS:
library ReTimerdialog
    
    module re_Timerdialog
        private static constant string TIMER_TITLE = "Respawn in"
        private static constant integer TD_RED     = 0    //Timerdialog red
        private static constant integer TD_GREEN   = 255  //Timerdialog green
        private static constant integer TD_BLUE    = 0    //Timerdialog blue
        private timerdialog td
        boolean re_showDialog
        
        private static method endDialog takes nothing returns nothing
            local timer t=GetExpiredTimer()
            local thistype this=GetTimerData(t)
            call DestroyTimerDialog(.td)
            call ReleaseTimer(t)
        endmethod

        method startDialog takes real c returns nothing
            local timer t=NewTimerEx(this)
            set .td=CreateTimerDialog(t)
            call TimerDialogDisplay(.td,GetLocalPlayer()==GetOwningPlayer(.u))
            call TimerDialogSetTitle(.td,TIMER_TITLE)
            call TimerDialogSetTitleColor(.td,TD_RED,TD_GREEN,TD_BLUE,0)
            call TimerStart(t,c,false,function thistype.endDialog)
            set t=null
        endmethod
        
        //! textmacro re_td_Operator takes NAME,VAR_TYPE,VAR_NAME
            method operator $NAME$= takes $VAR_TYPE$ v returns nothing
                set .$VAR_NAME$=v
            endmethod
        //! endtextmacro
    endmodule
endlibrary

JASS:
library ReLeaderboard

    module re_Leaderboard
        private static constant string TITLE = "Respawn in"
        private static constant string PLAYERS_TITLE = "Players respawn in:"
        private static constant string TITLE_PREFIX = "seconds"
        private static integer boardsInUse=0
        private leaderboard ld
        private real d
        private thistype h
        private boolean isShow
        boolean re_showBoard
        boolean re_simpleBoard
        
        private method endBoard takes nothing returns nothing
            local thistype i=0
            local player p=Player(this)
            set boardsInUse=boardsInUse-1
            set .isShow=false
            if not .h.re_simpleBoard then
                loop
                    exitwhen i==bj_MAX_PLAYERS
                    call LeaderboardRemovePlayerItem(i.ld,p)
                    if boardsInUse==0 then
                        call LeaderboardSetLabel(i.ld,PLAYERS_TITLE)
                        call LeaderboardResizeBJ(i.ld)
                        call LeaderboardDisplay(i.ld,false)
                    else
                        call LeaderboardSetLabel(.ld,PLAYERS_TITLE)
                        call LeaderboardResizeBJ(i.ld)
                    endif
                    set i=i+1
                endloop
            else
                call LeaderboardDisplay(.ld,false)
                call LeaderboardSetLabel(.ld,TITLE)
                call LeaderboardResizeBJ(.ld)
            endif
        endmethod
        
        private static method updateBoard takes nothing returns nothing
            local timer t=GetExpiredTimer()
            local thistype this=GetTimerData(t)
            local thistype i=0
            set .d=.d-.03125
            loop
                exitwhen i==bj_MAX_PLAYERS
                call LeaderboardSetItemValue(i.ld,LeaderboardGetPlayerIndex(i.ld,Player(this)),R2I(.d))
                set i=i+1
            endloop
            call LeaderboardSetLabel(.ld,TITLE+" "+I2S(R2I(.d))+" "+TITLE_PREFIX)
            if(.d<=0. or not IsUnitType(.h.u,UNIT_TYPE_DEAD))then
                call .endBoard()
                call ReleaseTimer(t)
            endif
            set t=null
        endmethod
        
        method startBoard takes real d returns nothing
            local player p=GetOwningPlayer(.u)
            local thistype id=GetPlayerId(p)
            local thistype i=0
            if not id.isShow then
                set id.d=d
                set id.h=this
                set id.isShow=true
                if not .re_simpleBoard then
                    loop
                        exitwhen i==bj_MAX_PLAYERS
                        if not LeaderboardHasPlayerItem(i.ld,p) then
                            call LeaderboardAddItem(i.ld,GetPlayerName(p),R2I(d),p)
                        endif
                        if boardsInUse==0 then
                            call LeaderboardSetLabel(i.ld,PLAYERS_TITLE)
                        endif
                        call LeaderboardResizeBJ(i.ld)
                        call LeaderboardDisplay(i.ld,true)
                        set i=i+1
                    endloop
                else
                    call LeaderboardDisplay(id.ld,true)
                endif
                if LeaderboardHasPlayerItem(id.ld,p) then
                    call LeaderboardRemovePlayerItem(id.ld,p)
                    call LeaderboardResizeBJ(id.ld)
                endif
                set boardsInUse=boardsInUse+1
                call TimerStart(NewTimerEx(id),.03125,true,function thistype.updateBoard)
            endif
        endmethod

        private static method onInit takes nothing returns nothing
            local thistype i=0
            local player p
            loop
                exitwhen i==bj_MAX_PLAYERS
                set p=Player(i)
                if (GetPlayerController(p)==MAP_CONTROL_USER and GetPlayerSlotState(p)==PLAYER_SLOT_STATE_PLAYING) then
                    set i.ld=CreateLeaderboard()
                    call PlayerSetLeaderboard(p,i.ld)
                    call LeaderboardSetLabel(i.ld,TITLE)
                    call LeaderboardDisplay(i.ld,false)
                endif
                set i=i+1
            endloop
        endmethod
        
        //! textmacro re_lb_Operator takes NAME,VAR_TYPE,VAR_NAME
            method operator $NAME$= takes $VAR_TYPE$ v returns nothing
                set .$VAR_NAME$=v
            endmethod
        //! endtextmacro
    endmodule
endlibrary
 
Last edited:
Please don't name your methods/functions execute or evaluate. It's very confusing to read as
a JassHelper feature is myFunction.execute()/.evaluate()

I suggest you make a new thread in the spell section for ReviveEvent and
post your code there. Wrap it up with a nice demo map, showing every facette
of this system. With some polishing here and there it will be a good addition to our
database.

For the jass section, this piece of code is too specific and you will not get
too much positive feedback or none at all. ( My opinion )

In the spell section we want resources/snippets/wrappers which help to create
systems like ReviveEvent, for example your MultiboardTools library.

Hope to see this snippet in the spell section.
BPower
 
Please don't name your methods/functions execute or evaluate. It's very confusing to read as
a JassHelper feature is myFunction.execute()/.evaluate()

I suggest you make a new thread in the spell section for ReviveEvent and
post your code there. Wrap it up with a nice demo map, showing every facette
of this system. With some polishing here and there it will be a good addition to our
database.

For the jass section, this piece of code is too specific and you will not get
too much positive feedback or none at all. ( My opinion )

In the spell section we want resources/snippets/wrappers which help to create
systems like ReviveEvent, for example your MultiboardTools library.

Hope to see this snippet in the spell section.
BPower

Yes, can send it to GY
 
Back
Top