System HeroRevive System

Joker(Div)

Always Here..
Reaction score
86
HeroRevive (HR) System v1.0c
By: Joker(Div)

Requires

Code:
JASS:
library HR uses TimerUtils
//*************************************************************************************************
//* HeroRevive System v1.0c
//*   By: Joker(Div)
//*************************************************************************************************
//*
//* Requirements:
//* -------------
//*  -vJass (JassHelper/NewGen)
//*  -TimerUtils
//*
//* How to Implement:
//* -----------------
//*  -Copy the trigger and paste it onto your map 
//*
//* What Does it Do:
//* ----------------
//*  -Revives your hero after a set time
//*
//* Functions (methods):
//* -----------
//*  -Revive.Set takes unit a, real x, real y, boolean eyecandy returns nothing
//*  -Revive.SetSelf takes unit a, real x, real y, boolean eyecandy, real duration returns nothing
//*
//*   (The difference? .SetSelf lets you use your own delay)
//*
//*************************************************************************************************

globals
    private constant real    BASE           = 5.    //Starting interval
    private constant real    LVL_FACTOR     = 1.5   //Increments based on Hero lvl
    private constant boolean USE_UNIT_NAME  = true  //If false, uses the owner's name
    private constant boolean PAN_CAMERA     = true  //Pans the owners camera to the hero when revived
    private constant boolean SELECT_HERO    = true  //Selects the hero when revived for the owner
    private constant boolean ROUND_DELAY    = false //Timer dialogs show the countdown as an integer. Timers use real timeouts.
endglobals

    //-----------
    struct Revive
        unit a
        real x
        real y
        timer t
        timerdialog td
        boolean eyecandy
        
        //==============================================================================================
        static method Set takes unit a, real x, real y, boolean eyecandy returns nothing
            local Revive dat = Revive.create()
            local real Lvl = GetHeroLevel(a)*1.
            
              set dat.a = a
              set dat.y = y
              set dat.x = x
              set dat.t = NewTimer() //TimerUtils
              set dat.td = CreateTimerDialog(dat.t)
              set dat.eyecandy = eyecandy
            
            call SetTimerData(dat.t, dat) //TimerUtils
            if ROUND_DELAY then
                call TimerStart(dat.t, R2I(BASE+(LVL_FACTOR*Lvl)+0.5), false, function Revive.Callback)
            else
                call TimerStart(dat.t, BASE+(LVL_FACTOR*Lvl), false, function Revive.Callback)
            endif
            
            if USE_UNIT_NAME then 
                call TimerDialogSetTitle(dat.td, GetUnitName(a))
            else
                call TimerDialogSetTitle(dat.td, GetPlayerName(GetOwningPlayer(a)))
            endif
            call TimerDialogDisplay(dat.td, true)
        endmethod
        
        static method SetSelf takes unit a, real x, real y, boolean eyecandy, real delay returns nothing
            local Revive dat = Revive.create()
            local real Lvl = GetHeroLevel(a)*1.
            
              set dat.a = a
              set dat.y = y
              set dat.x = x
              set dat.t = NewTimer() //TimerUtils
              set dat.td = CreateTimerDialog(dat.t)
              set dat.eyecandy = eyecandy
            
            call SetTimerData(dat.t, dat) //TimerUtils
            if ROUND_DELAY then
                call TimerStart(dat.t, R2I(delay+0.5), false, function Revive.Callback)
            else
                call TimerStart(dat.t, delay, false, function Revive.Callback)
            endif
            
            if USE_UNIT_NAME then 
                call TimerDialogSetTitle(dat.td, GetUnitName(a))
            else
                call TimerDialogSetTitle(dat.td, GetPlayerName(GetOwningPlayer(a)))
            endif
            call TimerDialogDisplay(dat.td, true)
        endmethod
        
        //==============================================================================================
        private static method Callback takes nothing returns nothing
            local Revive dat = GetTimerData(GetExpiredTimer()) //TimerUtils
            call ReviveHero(dat.a, dat.x, dat.y, dat.eyecandy)
            
            if PAN_CAMERA and GetLocalPlayer() == GetOwningPlayer(dat.a) then
                call PanCameraToTimed(dat.x, dat.y, 0)
            endif
            
            if SELECT_HERO and GetLocalPlayer() == GetOwningPlayer(dat.a) then
                call SelectUnit(dat.a, true)
            endif
            
            call dat.destroy()
        endmethod
        
        //==============================================================================================
        method onDestroy takes nothing returns nothing
            call ReleaseTimer(.t)
            call DestroyTimerDialog(.td)
        endmethod
    endstruct
    
//*************************************************************************************************
//* End of HeroRevive System
//*************************************************************************************************
endlibrary

Example:
JASS:
scope Example initializer Init

//==========================================================================
private function Conditions takes nothing returns boolean
    return IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true
endfunction

//==========================================================================
private function Actions takes nothing returns nothing
    local unit a = GetDyingUnit()
    local real x = GetUnitX(a)
    local real y = GetUnitY(a)
    call Revive.Set(a, x, y, true)
    //call Revive.SetSelf(a, x, y, true, 1.)
    set a = null
endfunction

//==========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( t, Condition( function Conditions ) )
    call TriggerAddAction( t, function Actions )
endfunction

endscope

I was just practicing struct usage and thought I'd release it in case someone found it useful.

Changelog
Code:
Changelog:
<1.0c> (9/26/08)
  -No longer need to create instance

<1.0b> (9/25/08)
  -Added a ROUND_DELAY boolean
  -Made the .Callback method private
 

Attachments

  • HR System 1.0c.w3m
    20.2 KB · Views: 201

Flare

Stops copies me!
Reaction score
662
What exactly is the difference between Set and SetSelf? Just the allowance of a user-determined delay in SetSelf, right?

Also:
JASS:
            if USE_UNIT_NAME then 
                call TimerDialogSetTitle(dat.td, GetUnitName(a))
            else
                call TimerDialogSetTitle(dat.td, GetPlayerName(GetOwningPlayer(a)))
            endif

Very nice idea to allow unit's name or player's name

Good job[del], all you have to do is release the timer (call ReleaseTimer (GetExpiredTimer ()) before calling .destroy and it should be perfect[/del]
Oops, never saw your onDestroy method down there, my bad :p

Perhaps you should make a location alternative for the sake of GUI'ers

And why are you returning a struct instance? People might play around with the values and break the revival :p
 

Joker(Div)

Always Here..
Reaction score
86
What exactly is the difference between Set and SetSelf? Just the allowance of a user-determined delay in SetSelf, right?
Yup.
why are you returning a struct instance? People might play around with the values and break the revival
You need to create a local Revive to use it, which requires a struct return. Think of my functions as .create. I just put all the "takes" stuff (Damn it, I forgot what they were called) in it for the sake of saving lines.

Edit: New version, just minor changes
 

Artificial

Without Intelligence
Reaction score
326
> which requires a struct return
No it doesn't. Nothing is preventing you from having methods that create new instances but don't return them. Only create must return an instance, as that's the way it's defined in JassHelper.

As the user isn't supposed to do anything with the struct instance, you also shouldn't make them able to by returning a struct instance. Making the methods not return the instances would protect them from desyroying the struct or changing the members' values. You could also avoid them changing the members' values by making them private, but the destroying is something you can't prevent when you give them the instances. :p
 

Joker(Div)

Always Here..
Reaction score
86
Ok so I could have the users make two lines, when only one is necessary. You have to create an instance of Revive no matter what. Like I said, think of the methods as an alternate .create.
 

Flare

Stops copies me!
Reaction score
662
You have to create an instance of Revive no matter what.
But there isn't any requirement to return it - just leave everything work internally, which guarantees* safety from people using the struct and breaking it

*Someone will probably still manage to break stuff, but it's far less likely :p

Ok so I could have the users make two lines, when only one is necessary
Not really - just remove the 'returns StructName' and the return line from both methods, and there is still only one thing that needs to be done i.e.
JASS:
call Revive.Set (myUnit, x, y, eyecandyBool)

Tada!
 

Joker(Div)

Always Here..
Reaction score
86
Oops, I thought I made a post...

I could have sworn it gave me an error when I tried to get rid of the instance. :p

Updated!
 

emjlr3

Change can be a good thing
Reaction score
395
i don't really see a purpose to this, lets compare your example, to the normal way, even using your "special" wait function

JASS:
private function Actions takes nothing returns nothing
    local unit a = GetDyingUnit()
    local real x = GetUnitX(a)
    local real y = GetUnitY(a)
    call Revive.Set(a, x, y, true)
    //call Revive.SetSelf(a, x, y, true, 1.)
    set a = null
endfunction

private function Actions takes nothing returns nothing
    local unit a = GetDyingUnit()
    local real x = GetUnitX(a)
    local real y = GetUnitY(a)
    
    call TriggerSleepAction(time you want)
    call ReviveHero(a,x,y,true) // basically same as what you got, minus the time, which is above
    if GetLocalPlayer()==GetOwningPlayer(a) then
        call PanCameraTo(x,y)
        call SelectUnit(a,true)
    endif // this is the only extra bit, and seeing has this is only needed once in a map...its not tough
    
    //set a = null // its a hero it does not need to be nulled
endfunction


yea yours adds a timerdialog, which is ok I guess - but it just seems to me like reviving a hero is once of those simple things you don't really need some big system for

I guess what I am saying is, for something you are only going to do once in your map, do you really need a system composed of three times the code you need had you just taken 5 minutes to write it yourself?

**in fact, this took me about 5 minutes here:

JASS:
scope HeroRevive initializer Init

private keyword data

globals  
    private data array Data
    private constant integer SUB = 0x100000
    public trigger Trigger = CreateTrigger()
endglobals  
    
private struct data
    unit u
    real x
    real y
    timer t = NewTimer()
    timerdialog td  = CreateTimerDialog(t)
    
    method onDestroy takes nothing returns nothing
        call ReleaseTimer(.t)
        call DestroyTimerDialog(.td)
    endmethod
endstruct

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

private function End takes nothing returns nothing
    local data d = Data[H2I(GetExpiredTimer())-SUB]
    
    call ReviveHero(d.u,d.x,d.y,true) // change true to false to not show fx
    if GetLocalPlayer()==GetOwningPlayer(d.u) then
        call SelectUnit(d.u,true) // uncomment to not select
        call PanCameraTo(d.x,d.y) // pan camera
    endif
    call d.destroy()
endfunction
private function Start takes nothing returns boolean
    local data d 
    
    if not IsUnitType(GetTriggerUnit(),UNIT_TYPE_HERO) then
        return false
    endif
    
    set d = data.create()
    set d.u = GetTriggerUnit()
    set d.x = GetUnitX(d.u) // where to revive x
    set d.y = GetUnitY(d.u) // where to revive y
    set Data[H2I(d.t)-SUB]
    call TimerStart(d.t,GetHeroLevel(d.u)*4.,false,function End) // time until revival
    call TimerDialogDisplay(d.td,true)
    call TimerDialogSetTitle(d.td,GetHeroProperName(d.u)+&quot;&#039;s Revival&quot;) // dialog title
    
    return true  
endfunction

private function Init takes nothing returns nothing
    call TriggerRegisterAnyUnitEventBJ(Trigger,EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddCondition(Trigger,Condition(function Start))   
endfunction

endscope


everything yours does, /3 in size, and no need to call
just to prove a point
ppl could very well use that, with a minute of configuration
**UNTESTED**
 

emjlr3

Change can be a good thing
Reaction score
395
im not God, might as well get a second opinion
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      • Ghan
        Administrator - Servers are fun

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top