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 039;s039; 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 = 039;sPIR039; // 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'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,"death") // 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 != "" 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 != "" 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,"stand") // 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 >= 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'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 <= 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,"stand channel")
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>