Snippet Simple Hero Revival [v1.1] - GUI FRIENDLY -

baassee

Member
Reaction score
5
Simple Hero Revival [v1.1b] - GUI FRIENDLY - [Includes vJASS and JASS versions]

A simple hero revival system, requires one call per hero to use. Got a very simple code so I guess this is a snippet (and not a system anyway). Special thanks goes to bribe for a recode of the system (changed the methods into functions for simpleness).

NO THIS DOESNT SHOW ANY KIND OF TIMER DIALOG I KEPT IT SIMPLE, MAKE ONE YOUR OWN. And no I don't got any interface like "onLoop" or a function "GetCurrentTime" I apologize for that.

Contains a formula functions so you can just put the "takes real time" to 0 and let the function to the time stuff. Also have a simple filter function that will protect the users from themselves.

THIS IS GUI FRIENDLY, I HAVE A GREAT EXAMPLE HOW TO USE THIS IN GUI AND IT IS VERY EASY. IF YOU ENCOUNTER ANY PROBLEMS PLEASE REPLY TO THIS THREAD OR PM/VM ME FOR HELP.

*Requirements*
TimerUtils by Vexorian

*HOW TO IMPORT*

1. Copy the library code or the trigger into your map.

2. If you dont have TimerUtils, copy that too.

3. You're good to go! Gui Users can copy my example

4. If you want, you can read the documentation and change the pancam constant, probably useful I guess, in my map it's 0.6 but in the script I changed it to 0.0.

Credits goes to Vexorian for JASSHelper and TimerUtils.

Please credit if used,

Enjoy!

~baassee

changelog

v1.0 release

v1.1 berbs fix and other fixes

v1.1b thanks to hell gate for noticing the problem, it revived the reverse

JASS:
library HeroRevival requires TimerUtils
//*******************************************************************************************************************************
//
// This is just a simple hero revival
//      by baassee
//      Credits are appreciated
//          and please credit bribe too for his brilliant remake.
//
//         *Requires:
//              TimerUtils by Vexorian
//              A vJass Compiler
//
//
//      Credits flies out to:
//              Axarion for showing me his scope
//              Hell Gate and Deaod for their Health Reserve system, taught me alot
//              Vexorian for TimerUtils, JassHelper and vJass
//              Bribe for recoding the system.
//
//  How to use:
//      This library provides you with these functions
//          function HeroRevive takes unit hero, real time, real x, real y, boolean eff
//          function HeroReviveLoc takes unit hero, real time, location loc, boolean eff
//
//          The unit hero is obviously the hero you are going to revive.
//          The real time is the time you want to revive your hero.
//              ps. you can set this to 0 and use the GetTime func to make your formula.
//          The real x states which x coordinate where you are going to revive your hero.
//          The real y states which y coordinate where you are going to revive your hero.
//          The location loc is for those who don't know to use coordinates.
//          The boolean eff is for show or not show rebirth effect.
//
//      Example 1:
//          call HeroRevive(GetTriggerUnit(), 30., 0., 0., true)
//
//      If you use this with an event "A Unit Dies" then it will
//          Revive the dying unit, revive it after 30 seconds at coord (0,0) showing revival effect
//
//      Example 2:
//          call HeroRevive(GetTriggerUnit(), 0., GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), false)
//
//      If you use this as said above it will
//          Revive the dying unit, it will USE the formula function so you better customize it there.
//          It will revive where it died and will not show revival effect.
//
//      Example 3:
//          call HeroReviveLoc(GetTriggerUnit(), 0., udg_TempLoc, true)
//
//      If you use this as said above with a location for all GUI users it will
//          Revive the dying unit, it will USE the formula function so you better customize it there.
//          It will revive the unit at a location you've set
//          Just remember to remove the location afterwards!
//
//      End of Documentation
//
//***************************************************************************************************************************
//
//      SETUP
//
//
globals
//
//*************GUI USERS LOOK BELOW HERE****************************
//
//      This variable is where you can set how fast the camera should pan to the revived unit.
//      As this usally is set to a low value, lower the greater the size is, you can set it
//      to 0. if you want to, then it will be panned instantly.
//
    private constant real PANCAM        = 0.6
    
endglobals
    
    private function GetAdjustedTime takes real time, integer herolvl returns real
        
        return time + 0. * herolvl
        
        //if you want something extra or you can set the time to 0
        //and use this for a formula instead
        //I call this function for the formula func in the documentation
    endfunction
    
    
    private function FilterHero takes unit u returns boolean
        
        return IsUnitType(u, UNIT_TYPE_HERO) and GetWidgetLife(u) < 0.405 and IsUnitType(u, UNIT_TYPE_DEAD)
        
        //just check if the unit is a hero
        //and to check if the unit is already dead (thanks to axarion for this one)
        //you can edit the filter if you want
    endfunction
                
//      END SETUP
//******************************************************************************************************************************
//

globals
//
//      To make sure that the users wont run several instances with the same unit
//
    private group NOSTACK   = CreateGroup()
    
endglobals
    

    private struct data
        unit    hero
        real    x
        real    y
        boolean eff
    endstruct
    
    
    private function finish takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local data dat = data(GetTimerData(t))
        call ReleaseTimer(t)                                //recycle timer
    
        call ReviveHero(dat.hero, dat.x, dat.y, dat.eff)    //revive hero
        call GroupRemoveUnit(NOSTACK, dat.hero)
        
        if GetLocalPlayer() == GetOwningPlayer(dat.hero) then
            call PanCameraToTimed(dat.x, dat.y, PANCAM)
            call ClearSelection()
            call SelectUnit(dat.hero, true)
        endif
        call dat.destroy()
    endfunction
    
    
    function HeroRevive takes unit hero, real time, real x, real y, boolean eff returns nothing
        local data dat
        local timer t
        
        if FilterHero(hero) and not IsUnitInGroup(hero, NOSTACK) then
            set dat = data.create()
            set t = NewTimer()
            
            set dat.hero = hero
            set dat.x = x
            set dat.y = y
            set dat.eff = eff
            
            call GroupAddUnit(NOSTACK, hero)
            call SetTimerData(t, dat)
            call TimerStart(t, GetAdjustedTime(time, GetHeroLevel(hero)), false, function finish)
            
        debug else
            debug call BJDebugMsg("HeroRevival Error: The unit is either alive or isn't a hero unit or is already in the system, please check your trigger calls.")
        endif
    endfunction
    
    
    function HeroReviveLoc takes unit hero, real time, location loc, boolean eff returns nothing
        call HeroRevive(hero, time, GetLocationX(loc), GetLocationY(loc), eff)
    endfunction
    
    
endlibrary


GUI example in the spoiler
Trigger:
  • Test GUI FRIENDLY
    • Events
      • Unit - A unit Dies
    • Conditions
      • ((Triggering unit) is A Hero) Equal to True
    • Actions
      • -------- This is the unit that will be Revived by the system --------
      • -------- set it to whatever unit you want to --------
      • -------- that you want the system to revive after set time --------
      • Set TempUnit = (Triggering unit)
      • -------- Here we get the location, where the unit will be revived at --------
      • -------- as we will use the "loc" function --------
      • -------- also more friendly for GUI users --------
      • Set TempLoc = (Position of TempUnit)
      • -------- This variable shouldn't be necessary but just for an example --------
      • -------- and to help GUI coders --------
      • -------- This value below will represent the revival time of the hero --------
      • Set TempReal = 7.00
      • -------- This variable below will tell the system that it should --------
      • -------- Show revival animations (birth animation) --------
      • -------- Set it to true and it will show, set it to false and it wont --------
      • Set TempEff = True
      • -------- That was it --------
      • -------- Now I will call the function below --------
      • -------- And it will start reviving the unit --------
      • Custom script: call HeroReviveLoc(udg_TempUnit, udg_TempReal, udg_TempLoc, udg_TempEff)
      • -------- Clear the point leak --------
      • Custom script: call RemoveLocation(udg_TempLoc)
      • -------- Just to show in-game that the unit will be revived soon. --------
      • Game - Display to (All players) the text: ((Proper name of (Triggering unit)) + will be revived in 7 seconds!)

I apologize for the grammar.

NEW FOR THOSE WHO DON'T WANT TO USE JNGP, PURE JASS, REQUIRES YOU TO CREATE THE VARIABLES BELOW, THE NAMES MUST FIT EXACTLY!

- A Hashtable variable named: SHRS_Hashtable
- An Integer variable named: SHRS_N
- A Timer Array variable named SHRS_Timers

Trigger:
  • SHRS Variables create
    • Events
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set SHRS_Hashtable = (Last created hashtable)
      • Set SHRS_N = 0
      • Set SHRS_Timers[0] = (Last started timer)


The jass script below, copy it into the trigger header.

JASS:
//just a standard timer recycler, credits goes to 
//for showing me this simple The_Reborn_Devil
function SHRS_GetTimer takes nothing returns timer
        if udg_SHRS_N == 0 then
            return CreateTimer()
        endif
        set udg_SHRS_N = udg_SHRS_N - 1
        return udg_SHRS_Timers[udg_SHRS_N]
endfunction

function SHRS_ReleaseTimer takes timer t returns nothing
    if t != null then
        call PauseTimer(t)
        set udg_SHRS_Timers[udg_SHRS_N] = t
        set udg_SHRS_N = udg_SHRS_N + 1
    else
        call BJDebugMsg("Tried to release a null timer!")
    endif
endfunction

function SHRS_Revive takes nothing returns nothing
    local integer id = GetHandleId(GetExpiredTimer()) //just for simpleness and no indexing
    local unit u = LoadUnitHandle(udg_SHRS_Hashtable, id, 1) //loads the hero
    local real x = LoadReal(udg_SHRS_Hashtable, id, 2) //loads the x coordinate
    local real y = LoadReal(udg_SHRS_Hashtable, id, 3) //loads the y coordinate
    local boolean b = LoadBoolean(udg_SHRS_Hashtable, id, 4) //loads the boolean
    local integer i = LoadInteger(udg_SHRS_Hashtable, StringHash("Instances"), 0) //loads the amount of instances
    //the revive part
    call ReviveHero(u, x, y, b)
    //recycle part below
    //restore the timer
    call SHRS_ReleaseTimer(GetExpiredTimer())
    //flush the child keys of the id
    call FlushChildHashtable(udg_SHRS_Hashtable, id)
    //this isn't a must I think but for the better
    //reduce amount of instances
    set i = i - 1
    //if it's 0 instances, we flush the whole table
    if i == 0 then
        call FlushParentHashtable(udg_SHRS_Hashtable)
    else
    //ekse we just save the new value
        call SaveInteger(udg_SHRS_Hashtable, StringHash("Instances"), 0, i)
    endif
    // null the local
    set u = null
endfunction

function SHRS_HeroRevive takes unit hero, real time, real x, real y, boolean eff returns nothing
    local timer t
    local integer id
    local integer i
    //the if below is just to protect the users from themselves
    if IsUnitType(hero, UNIT_TYPE_HERO) and IsUnitType(hero, UNIT_TYPE_DEAD) and GetWidgetLife(hero) < 0.405 then
        set t = SHRS_GetTimer()
        //load the amount of instances
        set i = LoadInteger(udg_SHRS_Hashtable, StringHash("Instances"), 0)
        // with this it could support unlimited instances although the timer stuff
        // have 8191 instances so that's the limit, it was much simplier than using hash
        set id = GetHandleId(t)
        // store unit
        call SaveUnitHandle(udg_SHRS_Hashtable, id, 1, hero)
        // store x coordinate
        call SaveReal(udg_SHRS_Hashtable, id, 2, x)
        // store y coordinate
        call SaveReal(udg_SHRS_Hashtable, id, 3, y)
        // store the boolean
        call SaveBoolean(udg_SHRS_Hashtable, id, 4, eff)
        //increase the amount of instances
        set i = i + 1
        //save the amount of instances
        call SaveInteger(udg_SHRS_Hashtable, StringHash("Instances"), 0, i)
        // fire the timer
        call TimerStart(t, time, false, function SHRS_Revive)
    else
        // just a simple error message for those who don't understand the words dead and hero
        call BJDebugMsg("SHRS Error - The unit is either not dead or is not a hero")
    endif
endfunction

// same function as above but with a location
function SHRS_HeroReviveLoc takes unit hero, real time, location loc, boolean eff returns nothing
    local timer t
    local integer id
    if IsUnitType(hero, UNIT_TYPE_HERO) and IsUnitType(hero, UNIT_TYPE_DEAD) and GetWidgetLife(hero) < 0.405 then
        set t = SHRS_GetTimer()
        set id = GetHandleId(t)
        call SaveUnitHandle(udg_SHRS_Hashtable, id, 1, hero)
        call SaveReal(udg_SHRS_Hashtable, id, 2, GetLocationX(loc))
        call SaveReal(udg_SHRS_Hashtable, id, 3, GetLocationY(loc))
        call SaveBoolean(udg_SHRS_Hashtable, id, 4, eff)
        call TimerStart(t, time, false, function SHRS_Revive)
    else
        call BJDebugMsg("SHRS Error - The unit is either not dead or is not a hero")
    endif
endfunction


changelog for the jass version

v1.0 released

v1.1 fixed the reverse death check, thanks to hell gate for noticing, also made the final flush of parent keys not depending on the timer recycle, now stores the amount of instances in the hashtable so you can use the timer recycle for what ever you want
 

Attachments

  • simpleherorevival.v1.0.jpg
    simpleherorevival.v1.0.jpg
    208.6 KB · Views: 391
  • baassee.SimpleHeroRevival.v1.1b.w3x
    23.5 KB · Views: 345
  • baassee.SimpleHeroRevival.v1.1[JASS].w3x
    16.3 KB · Views: 311
If you take a look at the other GUI-Friendly Jass resources here on the site, you'll see that none of them actually even require Jasshelper... That is one thing that I would very much recommend you trying to achieve as GUI users don't usually have Jasshelper (Newgen) downloaded...
 
Ah the common problem of installing JNGP.

I'll see what I can do but it would probably require some user defined globals (I don't like hashtables, that's why :p I usually index).

I put it as gui friendly as they can always use my example, copy it straigth away and read the comments, change the stuff and they're done :D
 
Bump, new update!

Made a full JASS version, no need for JNGP now. Functions have almost the same names, just added prefix.

[ljass]function SHRS_HeroRevive takes unit hero, real time, real x, real y, boolean eff returns nothing[/ljass]

and

[ljass]function SHRS_HeroReviveLoc takes unit hero, real time, location loc, boolean eff returns nothing[/ljass]

Remember to create the 3 variables in the variable editor and make the "Create Hashtable" & "Set SHRS_Hashtable = Last Created Hashtable"

The code is in the main post.
 
Nice system for gui users
but can you change
Trigger:
  • -------- This value below will represent the revival time of the hero --------
    • Set TempReal = 7.00

to
Trigger:
  • set TempReal = ( I2R(GetHeroLevel(GetDyingUnit())) * 10.00 )

So people can add level of dying hero to the revival timer :D
 
Can't they do that themselves? As said, it's just a value that I used to test the system although it is clearly stated that you can change it to whatever you want to. Thanks anyways!
 
I notice three things :x

1 - Your linkback of TimerUtils is wrong because the quote

2 - [ljass]local data dat = data(GetTimerData(t))[/ljass], this compile? Oo to me this should be [ljass]local data dat = GetTimerData(t)[/ljass]

3 - If the hero revive after it die (like resurrection), the system will fail in some point like revive nothing and move camera, select unit and so :p

Also I think you leak 2 locals in the timers :~

Sorry, don't looked at the Jass version because I don't use much hashtable and I'm not so familiar with it >.<


EDIT: Maybe an auto revive after hero die? (event/action)
 
1. Fixed. Sometimes happen when you edit forums lol :p

2. Yes it does :)

3. Still it will not bug, just selects the unit and pans the camera :D that's the coders fault if the unit revives after a made call, would be kinda unnecessary to check if the unit is STILL dead as you did in the create.

4. What leak? I release the timers? and I just declare them at first, that's not a leak. Or you mean the JASS version? I made just a quick timer recycler there too :D

5. Auto revive? Nah I kept it simple :p
 
I'm not sure if timers need to be nulled too, is that what I mean.. you use 2 local variable type timer and don't null they
 
I think not as you release them for reusing them again, nulling would just destroy that option wouldn't it? As TimerUtils have a debug message for releasing nulled timers I just guessed but I have never seen anyone before nulled a timer in vJASS using a timer recycler (although I have seen in JASS but that's when they destroyed the timer, just like you do with locations in JASS).
 
You should be making sequential timers for more efficiency. And make some commented out globals if someone wants to use vJASS and the JASS system. In the vJASS version, the convention is to name structs with capital letters and then the locals lowercase ([ljass]local Data data[/ljass]).

You also forgot to, you know, make a list of the variables in the JASS version. You should also have a function for the return time.

Edit: you need a variable creator.

EditEdit: This looks much nicer, and you shouldn't be checking if your own timers fail, afterall, we're assuming that you know what you're doing in your own system. You also had a lot of unneccassary comments (set u=null is nulling? orly?)

JASS:
.
    //globals
    //    private hashtable udg_SHRS_Hashtable=InitHashtable()
    //    private timer array udg_SHRS_Timers[8191]
    //	  private integer udg_SHRS_N=0
    //globals

    function SHRS_GetTimer takes nothing returns timer
    	if udg_SHRS_N == 0 then
            return CreateTimer()
        endif
        set udg_SHRS_N = udg_SHRS_N - 1
        return udg_SHRS_Timers[udg_SHRS_N]
    endfunction

    function SHRS_ReleaseTimer takes timer t returns nothing
        call PauseTimer(t)
        set udg_SHRS_Timers[udg_SHRS_N] = t
        set udg_SHRS_N = udg_SHRS_N + 1
    endfunction

    function SHRS_Revive takes nothing returns nothing
        local integer id = GetHandleId(GetExpiredTimer())
        local unit u = LoadUnitHandle(udg_SHRS_Hashtable, id, 1)                              // Loads the Hero
        local real x = LoadReal(udg_SHRS_Hashtable, id, 2)                                    // Loads the X Coordinate
        local real y = LoadReal(udg_SHRS_Hashtable, id, 3)                                    // Loads the Y Coordinate
        local boolean b = LoadBoolean(udg_SHRS_Hashtable, id, 4)                              // Loads the Boolean
        local integer instances = LoadInteger(udg_SHRS_Hashtable, StringHash(&quot;Instances&quot;), 0) // Loads the amount of instances
        call ReviveHero(u,x,y,b)
        call SHRS_ReleaseTimer(GetExpiredTimer())
        call FlushChildHashtable(udg_SHRS_Hashtable, id)
        set instances=instances-1
        if instances == 0 then
             call FlushParentHashtable(udg_SHRS_Hashtable)
        else
             call SaveInteger(udg_SHRS_Hashtable,StringHash(&quot;Instances&quot;),0,instances)
        endif
        set u = null
    endfunction

    function SHRS_HeroRevive takes unit hero, real time, real x, real y, boolean eff returns nothing
        local timer t
        local integer id
        local integer i
        // Protecting the users from themselves: 
        if IsUnitType(hero, UNIT_TYPE_HERO) and IsUnitType(hero, UNIT_TYPE_DEAD) and GetWidgetLife(hero) &lt; 0.405 then
            set t = SHRS_GetTimer()
            set i = LoadInteger(udg_SHRS_Hashtable, StringHash(&quot;Instances&quot;), 0)
            set id = GetHandleId(t)
            call SaveUnitHandle(udg_SHRS_Hashtable, id, 1, hero)
            call SaveReal(udg_SHRS_Hashtable, id, 2, x)
            call SaveReal(udg_SHRS_Hashtable, id, 3, y)
            call SaveBoolean(udg_SHRS_Hashtable, id, 4, eff)
            set i = i + 1
            call SaveInteger(udg_SHRS_Hashtable, StringHash(&quot;Instances&quot;), 0, i)
            call TimerStart(t, time, false, function SHRS_Revive)
        else
            call BJDebugMsg(&quot;SHRS Error - The unit is either not dead or is not a hero&quot;)
        endif
    endfunction


Why are you even using a hashtable? :p
 
You should be making sequential timers for more efficiency.

Doesn't really matter as I guess you wont run as many revivals as its needed to notice the performance difference.

And make some commented out globals if someone wants to use vJASS and the JASS system.

Why would you use a JASS system when you use vJASS that is more efficient? I don't see the point in this although I get what you mean. And this didn't work for me for another system (Weep's DD).

In the vJASS version, the convention is to name structs with capital letters and then the locals lowercase (local Data data).

Yes I know this but that part was changed when Bribe fixed it. I guess it wont matter either.

You also forgot to, you know, make a list of the variables in the JASS version.

NEW FOR THOSE WHO DON'T WANT TO USE JNGP, PURE JASS, REQUIRES YOU TO CREATE THE VARIABLES BELOW, THE NAMES MUST FIT EXACTLY!

- A Hashtable variable named: SHRS_Hashtable
- An Integer variable named: SHRS_N
- A Timer Array variable named SHRS_Timers

Trigger:
  • SHRS Variables create
    • Events
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set SHRS_Hashtable = (Last created hashtable)
      • Set SHRS_N = 0
      • Set SHRS_Timers[0] = (Last started timer)

You should also have a function for the return time.

I'll add that to both versions.

This looks much nicer, and you shouldn't be checking if your own timers fail, afterall, we're assuming that you know what you're doing in your own system. You also had a lot of unneccassary comments (set u=null is nulling? orly?)

also made the final flush of parent keys not depending on the timer recycle, now stores the amount of instances in the hashtable so you can use the timer recycle for what ever you want

That's why I check if the timers fail.

It's normal documentation, for experienced it's a pain but for the inexperienced it might be the key.

Thanks for the reply. I'll update it as soon as I can.
 
Why are you letting users use your own timer system that is for private use? That's horribly illogical. And you still didn't even mention a variable creator. And if it's in every other GUI friendly system, you can add commented globals.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • The Helper The Helper:
    News portal has been retired. Main page of site goes to Headline News forum now
  • The Helper The Helper:
    I am working on getting access to the old news portal under a different URL for those that would rather use that for news before we get a different news view.
  • Ghan Ghan:
    Easily done
    +1
  • The Helper The Helper:
    https://www.thehelper.net/pages/news/ is a link to the old news portal - i will integrate it into the interface somewhere when i figure it out
  • Ghan Ghan:
    Need to try something
  • Ghan Ghan:
    Hopefully this won't cause problems.
  • Ghan Ghan:
    Hmm
  • Ghan Ghan:
    I have converted the Headline News forum to an Article type forum. It will now show the top 20 threads with more detail of each thread.
  • Ghan Ghan:
    See how we like that.
  • The Helper The Helper:
    I do not see a way to go past the 1st page of posts on the forum though
  • The Helper The Helper:
    It is OK though for the main page to open up on the forum in the view it was before. As long as the portal has its own URL so it can be viewed that way I do want to try it as a regular forum view for a while
  • Ghan Ghan:
    Yeah I'm not sure what the deal is with the pagination.
  • Ghan Ghan:
    It SHOULD be there so I think it might just be an artifact of having an older style.
  • Ghan Ghan:
    I switched it to a "Standard" article forum. This will show the thread list like normal, but the threads themselves will have the first post set up above the rest of the "comments"
  • The Helper The Helper:
    I don't really get that article forum but I think it is because I have never really seen it used on a multi post thread
  • Ghan Ghan:
    RpNation makes more use of it right now as an example: https://www.rpnation.com/news/
  • The Helper The Helper:
  • The Helper The Helper:
    What do you think Tom?
  • tom_mai78101 tom_mai78101:
    I will have to get used to this.
  • tom_mai78101 tom_mai78101:
    The latest news feed looks good
  • The Helper The Helper:
    I would like to see it again like Ghan had it the first time with pagination though - without the pagination that view will not work but with pagination it just might...
  • The Helper The Helper:
    This drink recipe I have had more than a few times back in the day! Mind Eraser https://www.thehelper.net/threads/cocktail-mind-eraser.194720/

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top