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

[vJASS] [Snippet] ReviveEvent

Level 9
Joined
Jun 21, 2012
Messages
432
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/forums/submissions-414/snippet-reviveevent-263628/#post2663325
*       */ optional ReLeaderboard /* hiveworkshop.com/forums/submissions-414/snippet-reviveevent-263628/#post2663325
*   
*   **********************************************************************************************
*
*   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:
Level 19
Joined
Mar 18, 2012
Messages
1,716
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
 
Level 9
Joined
Jun 21, 2012
Messages
432
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
 
Top