//=====================================================================================
// | Health Reserve System |
// | by hell gate and Deaod |
//=====================================================================================
// how to use:
// Cnp this system in your map
// if you don't have BoundSentinel in your map also Cnp it else this system can cause a critical error!
// how to create a new Health Ball:
// call NewHealthBall(X ,Y ,Z ,ModelPath ,Heal ,ManaHeal ,SpeedX ,SpeedY ,SpeedZ ,HealingUnit, Red ,Green ,Blue ,Scale)
// real real real string real real real real real unit intger intger intger real
//=====================================================================================
library HealthReserve initializer Init //requires BoundSentinel
globals
private real SpeedIncraise = 10. //
private real MaxSpeed = 500. //the maximum speed of a ball
private constant real RopeLength = 750. //
private constant real RefreshTime = 1./40 //refresh intervall
private constant integer DummyId = 'h000' //the health reserve dummy
private constant real DistanceNeeded = 100. //how far away the ball have to be to heal
private constant string HealEffect = "Abilities\\Spells\\Undead\\VampiricAura\\VampiricAuraTarget.mdl"
endglobals
private struct HealthBalls
real x
real y
real z
//----- vectors -----
real Heal
real Mana
unit Ball
unit Target
effect Model
private integer i
private static group RecycledDummys=CreateGroup()
private static integer Count =0
private static timer Tim = CreateTimer()
private static integer Total = 0
private static thistype array Balls
private static location LocZ=Location(0,0)
private static method GetUnitZ takes unit u returns real
call MoveLocation(LocZ, GetUnitX(u), GetUnitY(u))
return GetLocationZ(LocZ)+GetUnitFlyHeight(u)
endmethod
private static method SetUnitZ takes unit u, real z returns nothing
call MoveLocation(LocZ, GetUnitX(u), GetUnitY(u))
call SetUnitFlyHeight(u, z-GetLocationZ(LocZ), 0)
endmethod
private method onDestroy takes nothing returns nothing
set Total = Total - 1
set Balls[i] = Balls[Total]
set Balls[i].i=i
if Total==0 then
call PauseTimer(Tim)
endif
endmethod
private static method BallLoop takes nothing returns nothing
local thistype dat
local integer i = Total-1
local real x
local real y
local real z
local real dx // delta x
local real dy // delta y
local real dz // delta z
local real d // absolute distance
loop
exitwhen i < 0
set dat = Balls[i]
if IsUnitType(dat.Target, UNIT_TYPE_DEAD) == false then
set x=GetUnitX(dat.Ball)
set y=GetUnitY(dat.Ball)
set z=GetUnitZ(dat.Ball)
set dx=GetUnitX(dat.Target)-x
set dy=GetUnitY(dat.Target)-y
set dz=GetUnitZ(dat.Target)-z
set d=SquareRoot(dx*dx+dy*dy+dz*dz)
set dat.x=dat.x+dx/d*(SpeedIncraise*RopeLength/d)
set dat.y=dat.y+dy/d*(SpeedIncraise*RopeLength/d)
set dat.z=dat.z+dz/d*(SpeedIncraise*RopeLength/d)
// reuse d
if d <= DistanceNeeded then
call DestroyEffect(dat.Model)
call GroupAddUnit(RecycledDummys,dat.Ball)
set Count=Count+1
call SetWidgetLife(dat.Target,GetWidgetLife(dat.Target)+dat.Heal)
call SetUnitState(dat.Target, UNIT_STATE_MANA, GetUnitState(dat.Target,UNIT_STATE_MANA)+dat.Mana)
call DestroyEffect(AddSpecialEffectTarget(HealEffect,dat.Target,"origin"))
call dat.destroy()
else
set d=SquareRoot(dat.x*dat.x+dat.y*dat.y+dat.z*dat.z)
if d>MaxSpeed then
set dat.x=dat.x/d*MaxSpeed
set dat.y=dat.y/d*MaxSpeed
set dat.z=dat.z/d*MaxSpeed
endif
call SetUnitX(dat.Ball, x+dat.x)
call SetUnitY(dat.Ball, y+dat.y)
call SetUnitZ(dat.Ball, z+dat.z)
endif
else
call RemoveUnit(dat.Ball)
call dat.destroy()
endif
set i = i-1
endloop
endmethod
static method create takes real X, real Y, real Z, string modeleffect, real HP_Add, real Mana_Add, real vX, real vY, real vZ, unit TargetUnit, real Scale returns thistype
local thistype dat = allocate()
set Balls[Total] = dat
if Total==0 then
call TimerStart(Tim,RefreshTime,true,function thistype.BallLoop)
endif
set dat.i=Total
set Total = Total+1
set dat.Heal = HP_Add
set dat.Mana = Mana_Add
set dat.x = vX
set dat.y = vY
set dat.z = vZ
set dat.Target = TargetUnit
if Count == 0 then
set dat.Ball=CreateUnit(Player(15),DummyId,X,Y,0.)
call UnitAddAbility(dat.Ball,'Amrf')
call UnitRemoveAbility(dat.Ball,'Amrf')
call SetUnitPathing(dat.Ball,false)
else
set dat.Ball=FirstOfGroup(RecycledDummys)
call GroupRemoveUnit(RecycledDummys,dat.Ball)
set Count=Count-1
call SetUnitX(dat.Ball,X)
call SetUnitY(dat.Ball,Y)
endif
set dat.Model = AddSpecialEffectTarget(modeleffect,dat.Ball,"chest")
call SetUnitFlyHeight(dat.Ball,Z,0.)
call SetUnitScale(dat.Ball,Scale*0.01,Scale*0.01,Scale*0.01)
return dat
endmethod
endstruct
function NewHealthBall takes real X, real Y, real Z, string modeleffect, real HP_Add, real Mana_Add, real vX, real vY, real vZ, unit TargetUnit, real Scale returns nothing
call HealthBalls.create( X, Y, Z, modeleffect, HP_Add, Mana_Add, vX, vY, vZ, TargetUnit, Scale)
endfunction
private function Init takes nothing returns nothing
set SpeedIncraise = SpeedIncraise*RefreshTime
set MaxSpeed = MaxSpeed*RefreshTime
endfunction
endlibrary