System Hero Revival System

wraithseeker

Tired.
Reaction score
122
JASS:
Hero Revival System by wraithseeker 
    v1.00
    
            Changelog v1.00
        - Initial release.
        

HRS is a system that behaves similarly like World of Warcraft 's' revival system added to the
system dies, a spirit and a corpse is created in place to fake the death and the spirit must go
to the spirit healer to revive and the time can vary depending on your globals.


Spirit healers

They are created through the usage of AddReviver(whichUnit) which takes a unit not a unit type
and when a unit comes within a range specified from your globals, they begin to revive with a
timeout depending on your globals again.

Heroes

Heroes must be added to the system with AddHero(HeroId) which takes a integer and not a unit.
When that happens, the HeroId will be registered to the system and the system will then function.

After learning objectmerger, I decided if possible, I will include them for users to use so
you can now use the objectmerger to generate the healers and spirit for the system.

Enjoy!.


JASS:
library HeroRevival initializer Init uses Table, TimerUtils, AutoIndex


// configurable globals
globals
    private constant integer SPIRIT = 'sPIR' // ID of spirit
    private constant integer AMOUNTOfEFFECT = 2 // Actual effect is 3, lowest amount of effect created is 1.
    // AMOUNTOFEFFECT is taken in seconds
    private constant real TIMEDMOVEMENT = 0. // how long the camera takes to pan?
    private constant real RANGE = 600. // the range to trigger revival
    private constant real RESPAWNTIME = 3 // The time you want each hero to respawn
    private boolean RespawnPoint = true // whether u want the unit to respawn at his corpse when spirit healer is reviving you.
    private boolean PauseSpirit = true // pause the spirit on reviving?
    private boolean ShowRespawnEyeCandy = false // show respawn SFX?
    private constant string EFFECT = "Abilities\\Spells\\Human\\Resurrect\\ResurrectTarget.mdl" // effect when reviving
    private constant string OtherRespawnEyeCandy = "Abilities\\Spells\\Human\\Resurrect\\ResurrectTarget.mdl" // other eyecandy?
endglobals

//Not configuarable
globals
    private Table HeroTable
    private integer Count = 0
    private trigger InRange = CreateTrigger()
    private boolexpr Spiritcheck
    private boolexpr Healercheck
    private group Healers = CreateGroup()
    private group CHECK = CreateGroup()
    private group GROUP = CreateGroup()
endglobals
// this is for spirit ( Uncomment them after creation )
//! external ObjectMerger w3u ewsp sPIR unam "Spirit" uabi Avul,Aeth usca "1.20" ussc "1.20" udty divine udup "0" umvs "350" ucol 0. ufoo 0 ubba 0 ubdi 0 ubsi 0 uhpm 150000 uhpr 0. uhrt none ubdg 1 urac human ugor 0 ubui _ upgr _    
// night elf healer
//! external ObjectMerger w3u ewsp lSHA unam "Spirit Healer" uabi Avul,Aeth usca "1.80" ussc "1.80" udty divine udup "0" umvs "350" ucol 0. ufoo 0 ubba 0 ubdi 0 ubsi 0 uhpm 150000 uhpr 0. uhrt none ubdg 1 urac human ugor 0 utyp _ uico "ReplaceableTextures\CommandButtons\BTNKeeperGhostBlue.blp" umdl "units\nightelf\HeroKeeperoftheGroveGhost\HeroKeeperoftheGroveGhost.mdl" uspa _ ubui _ upgr _    
// undead healer
//! external ObjectMerger w3u ewsp dSHA unam "Spirit Healer" uabi Avul,Aeth usca "1.80" ussc "1.80" udty divine udup "0" umvs "350" ucol 0. ufoo 0 ubba 0 ubdi 0 ubsi 0 uhpm 150000 uhpr 0. uhrt none ubdg 1 urac human ugor 0 utyp _ uico ReplaceableTextures\CommandButtons\BTNGhostOfKelThuzad.blp umdl "units\undead\KelThuzadGhost\KelThuzadGhost.mdl" uspa _ ubui _ upgr _


// no touch

private function Conditions takes nothing returns boolean
    local integer i = 0
    local unit u = GetTriggerUnit()
    loop
        exitwhen i >= Count // I know this is a o[n] search but it doesn't matter does it
        if GetUnitTypeId(u) == HeroTable<i> then
            set u = null
            return true
        endif
        set i = i + 1
    endloop
    set u = null
    return false
endfunction

private struct data // doesn&#039;t matter what I name right?
    unit hero // the dead hero
    unit spirit // self explainary
    unit corpse
    unit reviver
    timer t // used to display effects
    timer respawntime
    integer ticks // for timer t
    
static method create takes unit u returns data
    local data d = data.allocate()
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    set d.corpse = CreateCorpse(GetOwningPlayer(u),GetUnitTypeId(u),x,y,GetUnitFacing(u))
    set d.spirit = CreateUnit(GetOwningPlayer(u),SPIRIT,x,y,GetUnitFacing(u))
    call SetUnitAnimation(d.corpse,&quot;death&quot;) // when you create a corpse you set the animation to death to fake it
    set d.hero = u // initialization
    set d.ticks = 0
    set d.t = NewTimer()
    set d.respawntime = NewTimer()
    set data[d.spirit] = d
    return d
endmethod

method onDestroy takes nothing returns nothing
    local real x = GetUnitX(.corpse)
    local real y = GetUnitY(.corpse)
    local real sx = GetUnitX(.spirit)
    local real sy = GetUnitY(.spirit)
    if not RespawnPoint then
        if ShowRespawnEyeCandy then// some globals
            call ReviveHero(.hero,x,y,true)
        else
            call ReviveHero(.hero,x,y,false)
            if OtherRespawnEyeCandy != &quot;&quot; then
                call DestroyEffect(AddSpecialEffect(OtherRespawnEyeCandy,GetUnitX(.hero),GetUnitY(.hero)))
            endif
        endif
    else
        if ShowRespawnEyeCandy then
            call ReviveHero(.hero,sx,sy,true)
        else
            call ReviveHero(.hero,sx,sy,false)
            if OtherRespawnEyeCandy != &quot;&quot; then
                call DestroyEffect(AddSpecialEffect(OtherRespawnEyeCandy,GetUnitX(.hero),GetUnitY(.hero)))
            endif
        endif
    endif
    if GetLocalPlayer() == GetOwningPlayer(.spirit) then
        if RespawnPoint then
            call PanCameraToTimed(GetUnitX(.spirit),GetUnitY(.spirit),TIMEDMOVEMENT)
        else
            call PanCameraToTimed(x,y,TIMEDMOVEMENT)
        endif
    endif
    if PauseSpirit then
        call PauseUnit(.spirit,false)
    endif
    call KillUnit(.spirit) // kill the spirit after reviving, else it looks weird.
    call RemoveUnitEx(.corpse) // AutoIndex!
    call SetUnitAnimation(.reviver,&quot;stand&quot;) // revert animation?
endmethod

static method Revival takes nothing returns nothing
    call data(GetTimerData(GetExpiredTimer())).destroy()
endmethod

implement AutoData
endstruct

private function Respawn takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local data d = data.create(u) // start creation
    set u = null
endfunction

private function SpiritCheck takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == SPIRIT
endfunction

function AddHero takes integer HeroId returns nothing
    set HeroTable[Count] = HeroId // adds it into the table array
    set Count = Count + 1 // increase count of heroIds
endfunction

function AddReviver takes unit u returns nothing
    call TriggerRegisterUnitInRange(InRange,u,RANGE,Spiritcheck)
    call GroupAddUnit(Healers,u)
endfunction

private function Effects takes nothing returns nothing
    local data d = GetTimerData(GetExpiredTimer())
    local real x = GetUnitX(d.spirit)
    local real y = GetUnitY(d.spirit)
    local boolean b = false
    if d.ticks &gt;= AMOUNTOfEFFECT then
        set b = true
        call ReleaseTimer(d.t)
    endif
    if not b then
        call DestroyEffect(AddSpecialEffect(EFFECT,x,y))
    endif
    set d.ticks = d.ticks + 1
endfunction

private function HealerCheck takes nothing returns boolean
    return IsUnitInGroup(GetFilterUnit(),Healers)
endfunction

private function GetNearestUnit takes unit target, boolexpr b returns unit// Had to use this as I can&#039;t detect spirit healer
    local real x = GetUnitX(target)
    local real y = GetUnitY(target)
    local real tx = 0. 
    local real ty = 0.
    local real ClosestDist = 99999999
    local real dist = 0.
    local unit u
    local unit Closest
        call GroupEnumUnitsInRect(GROUP,bj_mapInitialPlayableArea,b)
         loop
            set u = FirstOfGroup(GROUP)
            exitwhen u == null
            set tx = GetUnitX(u) - x
            set ty = GetUnitY(u) - y
            set dist = SquareRoot(tx*tx-ty*ty)
            if dist &lt;= ClosestDist then
                set Closest = u
                set ClosestDist = dist
            endif
            call GroupRemoveUnit(GROUP,u)
        endloop
    return Closest
endfunction

private function Revive takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local unit f
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real angle = 0.
    local data d = data<u>
    set d.reviver = GetNearestUnit(u,Healercheck)
    set angle = Atan2(y-GetUnitY(d.reviver),x-GetUnitX(d.reviver)) * bj_RADTODEG
    call UnitRemoveType(d.reviver,UNIT_TYPE_STRUCTURE) // set the facing
    call SetUnitAnimation(d.reviver,&quot;stand channel&quot;)
    call SetUnitFacing(d.reviver,angle)
    call UnitAddType(d.reviver,UNIT_TYPE_STRUCTURE)
    if PauseSpirit then
        call PauseUnit(u,true)
    endif
    call DestroyEffect(AddSpecialEffect(EFFECT,x,y))
    call SetTimerData(d.t,d)
    call TimerStart(d.t,1,true,function Effects)
    call SetTimerData(d.respawntime,d)
    call TimerStart(d.respawntime,RESPAWNTIME,false,function data.Revival)
    // if you want it to depend on level then use this
    //call TimerStart(d.respawntime,GetHeroLevel(d.hero),false,function data.Revival)
    set u = null
endfunction

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    set HeroTable = Table.create()
    set Spiritcheck = Filter(function SpiritCheck)
    set Healercheck = Filter(function HealerCheck)
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddCondition(t,Condition(function Conditions))
    call TriggerAddAction(t,function Respawn)
    call TriggerAddAction(InRange,function Revive)
endfunction
endlibrary</u></i>
 

Attachments

  • HRS v1.00.w3x
    77.2 KB · Views: 394
  • HRS.jpg
    HRS.jpg
    428.5 KB · Views: 496

GetTriggerUnit-

DogEntrepreneur
Reaction score
129
>Simple
There must have atleast 200 lines of codes.

>Easy
Gui users won't be ables to use it if they don't know Jass.

Edit: Not enough customizable.
 

UndeadDragon

Super Moderator
Reaction score
448
>>Simple
>There must have atleast 200 lines of codes.

A lot of code doesn't mean it's not simple.

>>Easy
>Gui users won't be ables to use it if they don't know Jass.

I thought he explained how to use it well enough, even for GUI users. It just takes a bit of thought.

>Edit: Not enough customizable.

Not really much more to customize.
 

wraithseeker

Tired.
Reaction score
122
200 lines for a system is short and sweet enough for this kind of things.

I only gave people 2 functions, AddHero(heroId) and AddReviver(whichUnit) and then u configure the globals, very simple.
 

GetTriggerUnit-

DogEntrepreneur
Reaction score
129
200 lines for a system is short and sweet enough for this kind of things.

Loool.

>Not enough customizable

I mean maybe someone wouldnt have wanted wisp, it's not a "respawn system" like dota or custom hero line war, for example.
 

wraithseeker

Tired.
Reaction score
122
JASS:
   private constant integer SPIRIT = &#039;sPIR&#039; // ID of spirit


Read the code and as I said, it is customizable for god sake, believe in vJASS.
 

WolfieeifloW

WEHZ Helper
Reaction score
372
I agree with Jesus4Lyf.
And 'it's their problem' isn't really a viable answer :p .

There should be an option to revive them at their death spot or a specified region(s).
 

wraithseeker

Tired.
Reaction score
122
JASS:
   private boolean RespawnPoint = true // whether u want the unit to respawn at his corpse when spirit healer is reviving you.


There's a option to respawn at their death spot or at the position of the wisp but no specific region, I don't know why they would want to do that anyway.
 

WolfieeifloW

WEHZ Helper
Reaction score
372
In an AoS, for example.
You'd have two regions (Assuming two teams) for units to spawn back at after their deaths.
 

Komaqtion

You can change this now in User CP.
Reaction score
469
I kinda agree with wraithseeker, because if they want to respawn at some region, then why not put the spirit healer at that region ?? :p
 

BlackRose

Forum User
Reaction score
239
Isn't this simliar to Halloween Map? Except more better? (The Revive Part), you bring your dead spirit to the body, and bam, revived :D
 

Andrewgosu

The Silent Pandaren Helper
Reaction score
715
"onDestroy" method:

if ShowRespawnEyeCandy then// some globals
- call ReviveHero(.hero,x,y,true)
else
- call ReviveHero(.hero,x,y,false)

can just be:

- call ReviveHero(.hero,x,y,ShowRespawnEyeCandy)


if PauseSpirit then
-call PauseUnit(.spirit,false)
endif

can just be:

- call PauseUnit(.spirit, not PauseSpirit)


"GetNearestUnit" function:

You can omit the square root call if you're doing a simple distance check:

- set dist = tx * tx + ty * ty
- if dist <= ClosestDist * ClosestDist then


Anyway, approved.
 

Andrewgosu

The Silent Pandaren Helper
Reaction score
715
I meant you're just checking the distance and you don't need the real value anywhere else.

e.g
"SquareRoot(25) < 6" boolean value is the same as "25 < 36" boolean value.

Saves you a function call.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      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