Name | Type | is_array | initial_value |
//TESH.scrollpos=36
//TESH.alwaysfold=0
library_once TimerUtils initializer redInit
//*********************************************************************
//* TimerUtils (Red flavor)
//* ----------
//*
//* To implement it , create a custom text trigger called TimerUtils
//* and paste the contents of this script there.
//*
//* To copy from a map to another, copy the trigger holding this
//* library to your map.
//*
//* (requires vJass) More scripts: htt://www.wc3campaigns.net
//*
//* For your timer needs:
//* * Attaching
//* * Recycling (with double-free protection)
//*
//* set t=NewTimer() : Get a timer (alternative to CreateTimer)
//* ReleaseTimer(t) : Relese a timer (alt to DestroyTimer)
//* SetTimerData(t,2) : Attach value 2 to timer
//* GetTimerData(t) : Get the timer's value.
//* You can assume a timer's value is 0
//* after NewTimer.
//*
//* Red flavor: Fastest, method in existence for timer attaching,
//* only takes an array lookup, H2I and subtraction.
//* However, all the code in your map requires extra care
//* not to forget to call ReleaseTimer. It also requires
//* to preload a lot of timers at map init, they use
//* memory and handle ids.
//*
//* I recommend you run your map in debug mode the first
//* time after adding it, make sure you can see map init messages
//* if nothing appears, all is done, if an error appears, it might
//* suggest you a value with OFFSET, in that case, update that value
//* if it still does not work after updating (rare), try a bigger
//* OFFSET by 1000 for example. (Sounds hard? Then use blue or purple
//* timerutils that are friendlier though not as fast)
//*
//********************************************************************
//================================================================
globals
private constant integer OFFSET = 0x100000
private constant integer QUANTITY = 256
private constant integer ARRAY_SIZE = 8191 //changing this to a higher value would effectively
//cripple the performance making this thing irrelevant
endglobals
//=================================================================================================
private function H2I takes handle h returns integer
return GetHandleId( h )
endfunction
//==================================================================================================
globals
private integer array data[ARRAY_SIZE]
endglobals
//It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
function SetTimerData takes timer t, integer value returns nothing
debug if(H2I(t)-OFFSET<0) then
debug call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
debug endif
set data[H2I(t)-OFFSET]=value
endfunction
function GetTimerData takes timer t returns integer
debug if(H2I(t)-OFFSET<0) then
debug call BJDebugMsg("GetTimerData: Wrong handle id, only use GetTimerData on timers created by NewTimer")
debug endif
return data[H2I(t)-OFFSET]
endfunction
//==========================================================================================
globals
private timer array tT
private integer tN = 0
private constant integer HELD=0x28829022
//use a totally random number here, the more improbable someone uses it, the better.
endglobals
//==========================================================================================
function NewTimer takes nothing returns timer
if (tN==0) then
//If this happens then the QUANTITY rule has already been broken, try to fix the
// issue, else fail.
debug call BJDebugMsg("NewTimer: Warning, Exceeding TimerUtils_QUANTITY, please increase it for your map, fix your map's timer leaks or switch to blue flavor when applicable")
set tT[0]=CreateTimer()
if (H2I(tT[0])-OFFSET<0) or (H2I(tT[0])-OFFSET>=ARRAY_SIZE) then
//all right, couldn't fix it
call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably switch to the blue flavor or fix timer leaks.")
return null
endif
else
set tN=tN-1
endif
call SetTimerData(tT[tN],0)
return tT[tN]
endfunction
//==========================================================================================
function ReleaseTimer takes timer t returns nothing
if(t==null) then
debug call BJDebugMsg("Warning: attempt to release a null timer")
return
endif
if (tN==8191) then
debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")
//stack is full, the map already has much more troubles than the chance of bug
call DestroyTimer(t)
else
call PauseTimer(t)
if(GetTimerData(t)==HELD) then
debug call BJDebugMsg("Warning: ReleaseTimer: Double free!")
return
endif
call SetTimerData(t,HELD)
set tT[tN]=t
set tN=tN+1
endif
endfunction
private function redInit takes nothing returns nothing
local integer i=0
local integer bestoffset=-1
loop
exitwhen (i==QUANTITY)
set tT[i] = CreateTimer()
if(i==0) then
set bestoffset=H2I(tT[i])
endif
if (H2I(tT[i])-OFFSET>=ARRAY_SIZE) then
debug call BJDebugMsg("TimerUtils_redInit: Failed a initializing attempt")
debug call BJDebugMsg("The timer limit is "+I2S(i))
debug call BJDebugMsg("This is a rare ocurrence, if the timer limit is too low, to change OFFSET to "+I2S(bestoffset) )
exitwhen true
endif
if (H2I(tT[i])-OFFSET>=0) then
set i=i+1
endif
endloop
set tN=i
endfunction
endlibrary
//TESH.scrollpos=44
//TESH.alwaysfold=0
library BoundSentinel initializer init
//*************************************************
//* BoundSentinel
//* -------------
//* Don't leave your units unsupervised, naughty
//* them may try to get out of the map bounds and
//* crash your game.
//*
//* To implement, just get a vJass compiler and
//* copy this library/trigger to your map.
//*
//*************************************************
//==================================================
globals
// High enough so the unit is no longer visible, low enough so the
// game doesn't crash...
//
// I think you need 0.0 or soemthing negative prior to patch 1.22
//
private constant real EXTRA = 500.0
endglobals
//=========================================================================================
globals
private real maxx
private real maxy
private real minx
private real miny
endglobals
//=======================================================================
private function dis takes nothing returns nothing
local unit u=GetTriggerUnit()
local real x=GetUnitX(u)
local real y=GetUnitY(u)
if(x>maxx) then
set x=maxx
elseif(x<minx) then
set x=minx
endif
if(y>maxy) then
set y=maxy
elseif(y<miny) then
set y=miny
endif
call SetUnitX(u,x)
call SetUnitY(u,y)
set u=null
endfunction
private function init takes nothing returns nothing
local trigger t=CreateTrigger()
local region r=CreateRegion()
local rect rc
set minx=GetCameraBoundMinX() - EXTRA
set miny=GetCameraBoundMinY() - EXTRA
set maxx=GetCameraBoundMaxX() + EXTRA
set maxy=GetCameraBoundMaxY() + EXTRA
set rc=Rect(minx,miny,maxx,maxy)
call RegionAddRect(r, rc)
call RemoveRect(rc)
call TriggerRegisterLeaveRegion(t,r, null)
call TriggerAddAction(t, function dis)
//this is not necessary but I'll do it anyway:
set t=null
set r=null
set rc=null
endfunction
endlibrary
//TESH.scrollpos=131
//TESH.alwaysfold=0
library VectorLib
globals
private location loc = Location(0.0,0.0)
endglobals
struct vector
real x
real y
real z
static method create takes real x, real y, real z returns vector
local vector v = vector.allocate()
set v.x=x
set v.y=y
set v.z=z
return v
endmethod
method getLength takes nothing returns real
return SquareRoot(.x*.x + .y*.y + .z*.z)
endmethod
static method sum takes vector augend, vector addend returns vector
local vector v = vector.allocate()
set v.x = augend.x+addend.x
set v.y = augend.y+addend.y
set v.z = augend.z+addend.z
return v
endmethod
method add takes vector addend returns nothing
set this.x=this.x+addend.x
set this.y=this.y+addend.y
set this.z=this.z+addend.z
endmethod
static method difference takes vector minuend, vector subtrahend returns vector
local vector v = vector.allocate()
set v.x = minuend.x-subtrahend.x
set v.y = minuend.y-subtrahend.y
set v.z = minuend.z-subtrahend.z
return v
endmethod
method subtract takes vector subtrahend returns nothing
set this.x=this.x-subtrahend.x
set this.y=this.y-subtrahend.y
set this.z=this.z-subtrahend.z
endmethod
method scale takes real factor returns nothing
set this.x=this.x*factor
set this.y=this.y*factor
set this.z=this.z*factor
endmethod
method setLength takes real length returns nothing
local real l = SquareRoot(.x*.x + .y*.y + .z*.z)
if l == 0.0 then
debug call BJDebugMsg("Attempted to set the length of a vector with no length!")
return
endif
set l = length/l
set this.x = this.x*l
set this.y = this.y*l
set this.z = this.z*l
endmethod
static method dotProduct takes vector a, vector b returns real
return (a.x*b.x+a.y*b.y+a.z*b.z)
endmethod
static method crossProduct takes vector a, vector b returns vector
local vector v = vector.allocate()
set v.x = a.y*b.z - a.z*b.y
set v.y = a.z*b.x - a.x*b.z
set v.z = a.x*b.y - a.y*b.x
return v
endmethod
static method projectionVector takes vector projected, vector direction returns vector
local vector v = vector.allocate()
local real l = direction.x*direction.x+direction.y*direction.y+direction.z*direction.z
if l == 0.0 then
call v.destroy()
debug call BJDebugMsg("Attempted to project onto a vector with no length!")
return null
endif
set l = (projected.x*direction.x+projected.y*direction.y+projected.z*direction.z) / l
set v.x = direction.x*l
set v.y = direction.y*l
set v.z = direction.z*l
return v
endmethod
method projectVector takes vector direction returns nothing
local real l = direction.x*direction.x+direction.y*direction.y+direction.z*direction.z
if l == 0.0 then
debug call BJDebugMsg("Attempted to project onto a vector with no length!")
return
endif
set l = (this.x*direction.x+this.y*direction.y+this.z*direction.z) / l
set this.x = direction.x*l
set this.y = direction.y*l
set this.z = direction.z*l
endmethod
static method projectionPlane takes vector projected, vector normal returns vector
local vector v = vector.allocate()
local real l = normal.x*normal.x+normal.y*normal.y+normal.z*normal.z
if l == 0.0 then
call v.destroy()
debug call BJDebugMsg("Attempted to project onto an undefined plane!")
return null
endif
set l = (projected.x*normal.x+projected.y*normal.y+projected.z*normal.z) / l
set v.x = projected.x - normal.x*l
set v.y = projected.y - normal.y*l
set v.z = projected.z - normal.z*l
return v
endmethod
method projectPlane takes vector normal returns nothing
local real l = normal.x*normal.x+normal.y*normal.y+normal.z*normal.z
if l == 0.0 then
debug call BJDebugMsg("Attempted to project onto an undefined plane!")
return
endif
set l = (this.x*normal.x+this.y*normal.y+this.z*normal.z) / l
set this.x = this.x - normal.x*l
set this.y = this.y - normal.y*l
set this.z = this.z - normal.z*l
endmethod
static method getAngle takes vector a, vector b returns real
local real l = SquareRoot(a.x*a.x + a.y*a.y + a.z*a.z)*SquareRoot(b.x*b.x + b.y*b.y + b.z*b.z)
if l == 0 then
debug call BJDebugMsg("Attempted to get angle between vectors with no length!")
return 0.0
endif
return Acos((a.x*b.x+a.y*b.y+a.z*b.z)/l) //angle is returned in radians
endmethod
method rotate takes vector axis, real angle returns nothing //angle is taken in radians
local real xx
local real xy
local real xz
local real yx
local real yy
local real yz
local real zx
local real zy
local real zz
local real al = axis.x*axis.x+axis.y*axis.y+axis.z*axis.z //axis length^2
local real f
local real c = Cos(angle)
local real s = Sin(angle)
if al == 0.0 then
debug call BJDebugMsg("Attempted to project onto a vector with no length!")
return
endif
set f = (this.x*axis.x+this.y*axis.y+this.z*axis.z) / al
set zx = axis.x*f
set zy = axis.y*f
set zz = axis.z*f //axis component of rotated vector
set xx = this.x-zx
set xy = this.y-zy
set xz = this.z-zz //component of vector perpendicular to axis
set al = SquareRoot(al)
set yx = (axis.y*xz - axis.z*xy)/al
set yy = (axis.z*xx - axis.x*xz)/al //y same length as x by using cross product and dividing with axis length
set yz = (axis.x*xy - axis.y*xx)/al //x,y - coordinate system in which we rotate
set this.x=xx*c+yx*s+zx
set this.y=xy*c+yy*s+zy
set this.z=xz*c+yz*s+zz
endmethod
static method createTerrainPoint takes real x, real y returns vector
local vector v = vector.allocate()
call MoveLocation(loc,x,y)
set v.x=x
set v.y=y
set v.z=GetLocationZ(loc)
return v
endmethod
method getTerrainPoint takes real x, real y returns nothing
call MoveLocation(loc,x,y)
set this.x=x
set this.y=y
set this.z=GetLocationZ(loc)
endmethod
static method createTerrainNormal takes real x, real y, real sampleRadius returns vector
local vector v = vector.allocate()
local real z1
local real z2
local real z3
local real z4
call MoveLocation(loc, x-sampleRadius, y)
set z1=GetLocationZ(loc)
call MoveLocation(loc, x+sampleRadius, y)
set z2=GetLocationZ(loc)
call MoveLocation(loc, x, y-sampleRadius)
set z3=GetLocationZ(loc)
call MoveLocation(loc, x, y+sampleRadius)
set z4=GetLocationZ(loc)
set sampleRadius=2*sampleRadius
set v.x = (z1-z2)*sampleRadius
set v.y = (z3-z4)*sampleRadius
set v.z = sampleRadius*sampleRadius
return v
endmethod
method getTerrainNormal takes real x, real y, real sampleRadius returns nothing
local real z1
local real z2
local real z3
local real z4
call MoveLocation(loc, x-sampleRadius, y)
set z1=GetLocationZ(loc)
call MoveLocation(loc, x+sampleRadius, y)
set z2=GetLocationZ(loc)
call MoveLocation(loc, x, y-sampleRadius)
set z3=GetLocationZ(loc)
call MoveLocation(loc, x, y+sampleRadius)
set z4=GetLocationZ(loc)
set sampleRadius=2*sampleRadius
set this.x = (z1-z2)*sampleRadius
set this.y = (z3-z4)*sampleRadius
set this.z = sampleRadius*sampleRadius
endmethod
method isInCylinder takes vector cylinderOrigin, vector cylinderHeight, real cylinderRadius returns boolean
local real l
local real x = this.x-cylinderOrigin.x
local real y = this.y-cylinderOrigin.y
local real z = this.z-cylinderOrigin.z
if x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z < 0.0 then //point below cylinder
return false
endif
set x = x-cylinderHeight.x
set y = y-cylinderHeight.y
set z = z-cylinderHeight.z
if x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z > 0.0 then //point above cylinder
return false
endif
set l = cylinderHeight.x*cylinderHeight.x+cylinderHeight.y*cylinderHeight.y+cylinderHeight.z*cylinderHeight.z
if l == 0.0 then
debug call BJDebugMsg("Cylinder with no height!")
return false
endif
set l = (x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z) / l
set x = x - cylinderHeight.x*l
set y = y - cylinderHeight.y*l
set z = z - cylinderHeight.z*l
if x*x+y*y+z*z > cylinderRadius*cylinderRadius then //point outside cylinder
return false
endif
return true
endmethod
method isInCone takes vector coneOrigin, vector coneHeight, real coneRadius returns boolean
local real l
local real x = this.x-coneOrigin.x
local real y = this.y-coneOrigin.y
local real z = this.z-coneOrigin.z
if x*coneHeight.x+y*coneHeight.y+z*coneHeight.z < 0.0 then //point below cone
return false
endif
set l = coneHeight.x*coneHeight.x+coneHeight.y*coneHeight.y+coneHeight.z*coneHeight.z
if l == 0.0 then
debug call BJDebugMsg("cone with no height!")
return false
endif
set l = (x*coneHeight.x+y*coneHeight.y+z*coneHeight.z) / l
set x = x - coneHeight.x*l
set y = y - coneHeight.y*l
set z = z - coneHeight.z*l
if SquareRoot(x*x+y*y+z*z) > coneRadius*(1.0-l) then //point outside cone
return false
endif
return true
endmethod
method isInSphere takes vector sphereOrigin, real sphereRadius returns boolean
if sphereRadius*sphereRadius < ((this.x-sphereOrigin.x)*(this.x-sphereOrigin.x)+(this.y-sphereOrigin.y)*(this.y-sphereOrigin.y)+(this.z-sphereOrigin.z)*(this.z-sphereOrigin.z)) then
return false
endif
return true
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Heights
globals
private location loc = Location( 0.00, 0.00 )
endglobals
function GetFloorHeight takes real x, real y returns real
call MoveLocation( loc, x, y )
return GetLocationZ( loc )
endfunction
function GetUnitZ takes unit whichUnit returns real
local real z = ( GetFloorHeight( GetUnitX( whichUnit ), GetUnitY( whichUnit ) ) + GetUnitFlyHeight( whichUnit ) )
set whichUnit = null
return z
endfunction
function SetUnitZ takes unit whichUnit, real z returns nothing
local boolean whichUnitHasNotAmrf = ( GetUnitAbilityLevel( whichUnit, 'Amrf' ) <= 0 ) and IsUnitType(whichUnit, UNIT_TYPE_FLYING) == false
if ( whichUnitHasNotAmrf ) then
call UnitAddAbility( whichUnit, 'Amrf' )
endif
call SetUnitFlyHeight( whichUnit, z - GetFloorHeight( GetUnitX( whichUnit ), GetUnitY( whichUnit ) ), 0.00 )
if ( whichUnitHasNotAmrf ) then
call UnitRemoveAbility( whichUnit, 'Amrf' )
endif
set whichUnit = null
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope BurningOrbit initializer init
//*************************************************************************************************************//
// Shocking Fence v0.01 //
// by //
// cedi //
// //
// needs: TimerUtils by Vexorian //
// Bound Sentinel by Vexorian //
// Dummy Model by //
// Vector lib by //
// Heights by cedi //
//*************************************************************************************************************//
//For use, copy the trigger to your map, copy the dummy create a spell and adjust the values below.
private keyword Sub
private keyword Main
globals
//ID of the spell
private constant integer SPELL_ID = 'A000'
//ID of your dummy
private constant integer DUMMY_ID = 'h000'
//Interval of the moves
private constant real TIMER_INTERVAL = 0.035
//Main
//Height between each fence
private constant real MAIN_HEIGHT = 20.00
//MS of the fence when it is in the air ( in wc3 units )
private constant real MAIN_SPEED = 500.00
//Distance needed of the fence to the unit when the fence flies.
private constant real MAIN_COL = 10.00
//Angle of the bow when the fence flies. Like oe value.
private constant real MAIN_FLY_HEIGHT = 0.45
//Time needed between each time damage
private constant real MAIN_DAMAGE_INT = 2.00
//Percent of the full damage each time the fence deals damage.
private constant real MAIN_DMG_PERCENT = 0.10 //% pro interval
//SFX when the fence damages a unit.
private constant string MAIN_DMG_SFX = "Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl"
//Sub
//Color rgb.
private constant integer SUB_COLOR_RED = 255
private constant integer SUB_COLOR_GREEN = 255
private constant integer SUB_COLOR_BLUE = 255
private constant integer SUB_COLOR_ALPHA = 255
//Count of the corners
private constant integer SUB_MAX = 6
//Distance to the unit ( of the corners )
private constant real SUB_DISTANCE = 75.00
//Amount of grad the corners turn each second.
private constant real SUB_TURN_SPEED = 180.00
//Size of the corner units
private constant real SUB_SIZE = 1.00
//Model of the corners
private constant string SUB_MODEL = "Abilities\\Weapons\\VengeanceMissile\\VengeanceMissile.mdl"
//Lightning
//Color of the lightning in rgb. ( these things are very strange, looks like they're in percent. )
private constant real LIGHT_COLOR_RED = 1
private constant real LIGHT_COLOR_GREEN = 1
private constant real LIGHT_COLOR_BLUE = 1
private constant real LIGHT_COLOR_ALPHA = 1
//If of the lightning.
private constant string LIGHT_ID = "AFOD"
//System
private vector AXIS
private hashtable HASH = InitHashtable()
private trigger DAMAGE_TRIG = CreateTrigger()
private trigger SPELL_TRIG = CreateTrigger()
private real TEMPREAL
private unit TEMPUNIT
private Main TEMPMAIN
endglobals
private function DAMAGE takes integer level returns real
return 100.00 + 20.00 * level
endfunction
private function SHIELD takes integer level returns real
return 100.00 + 20.00 * level
endfunction
//*************************************************************************************************************//
// !SYSTEM! //
//*************************************************************************************************************//
private function AngleBetweenCoordinates takes real x1, real x2, real y1, real y2 returns real
return bj_RADTODEG * Atan2(y2 - y1, x2 - x1)
endfunction
private function DistanceBetweenCoordinates takes real x1, real x2, real y1, real y2 returns real
local real dx = x2 - x1
local real dy = y2 - y1
return SquareRoot(dx * dx + dy * dy)
endfunction
private function AngleBetweenUnits takes unit u, unit u2 returns real
return bj_RADTODEG * Atan2(GetUnitY( u2 ) - GetUnitY( u ), GetUnitX( u2 ) - GetUnitX( u ))
endfunction
private function IsAliveAndUnitAndNotMagicImmune takes nothing returns boolean
return GetWidgetLife( GetFilterUnit() ) > 0.405 and IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false and IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false
endfunction
private function Heal takes nothing returns nothing
call DestroyTimer( GetExpiredTimer() )
call SetWidgetLife( TEMPUNIT, GetWidgetLife( TEMPUNIT ) + TEMPREAL )
endfunction
private function ParabolaZ2 takes real y0, real y1, real h, real d, real x returns real
local real A = (2*(y0+y1)-4*h)/(d*d)
local real B = (y1-y0-A*d*d)/d
return A*x*x + B*x + y0
endfunction
private function OuterControl takes nothing returns nothing
set TEMPMAIN = GetTimerData( GetExpiredTimer() )
call TEMPMAIN.control()
endfunction
private struct Sub
unit u
lightning l
Main root
vector dist
effect model
method onDestroy takes nothing returns nothing
call DestroyEffect( .model )
set .model = null
call KillUnit( .u )
set .u = null
call DestroyLightning( .l )
set .l = null
call .dist.destroy()
endmethod
method turn takes nothing returns nothing
call .dist.rotate( AXIS, SUB_TURN_SPEED * TIMER_INTERVAL * bj_DEGTORAD )
call SetUnitX( .u, .root.posi.x + .dist.x )
call SetUnitY( .u, .root.posi.y + .dist.y )
if GetUnitZ( .root.target ) != GetUnitZ( .u ) then
call SetUnitZ( .u, .root.posi.z )
endif
endmethod
method setLightning takes integer i returns nothing
local real x = 0.00
local real y = 0.00
local real z = .root.posi.z
local real tx = .dist.x + .root.posi.x
local real ty = .dist.y + .root.posi.y
if i >= SUB_MAX - 1 then
set x = .root.sub[0].dist.x + .root.posi.x
set y = .root.sub[0].dist.y + .root.posi.y
else
set x = .root.sub[i + 1].dist.x + .root.posi.x
set y = .root.sub[i + 1].dist.y + .root.posi.y
endif
call MoveLightningEx( .l, false, tx, ty, z, x, y, z )
endmethod
static method create takes Main root, integer count returns thistype
local thistype this = thistype.allocate()
local real angle = 360.00 / SUB_MAX * count * bj_DEGTORAD
set .root = root
set .dist = vector.create( Cos( angle ) * SUB_DISTANCE, Sin( angle ) * SUB_DISTANCE, 0.00 )
set .u = CreateUnit( GetOwningPlayer( .root.caster ), DUMMY_ID, .root.posi.x + .dist.x, .root.posi.y + .dist.x, 0.00 )
set .model = AddSpecialEffectTarget( SUB_MODEL, .u, "origin" )
call SetUnitVertexColor( .u, SUB_COLOR_RED, SUB_COLOR_GREEN, SUB_COLOR_BLUE, SUB_COLOR_ALPHA )
call SetUnitScale( .u, SUB_SIZE, SUB_SIZE, SUB_SIZE )
set .l = AddLightningEx( LIGHT_ID, false, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 )
call SetLightningColor( .l, LIGHT_COLOR_RED, LIGHT_COLOR_GREEN, LIGHT_COLOR_BLUE, LIGHT_COLOR_ALPHA )
return this
endmethod
endstruct
private struct Main
unit target = null
unit caster = null
Sub array sub[SUB_MAX]
vector posi = 0
vector start = 0
real shield = 0.00
real damage = 0.00
real interval = MAIN_DAMAGE_INT
integer level = 1
integer number = 1
boolean jumping = false
boolean friend = false
timer t = null
method onDestroy takes nothing returns nothing
local integer i = 0
loop
exitwhen i >= SUB_MAX
call .sub[i].destroy()
set i = i + 1
endloop
call SaveInteger( HASH, GetHandleId( .target ), 0, .number - 1 )
call SaveInteger( HASH, GetHandleId( .target ), .number, 0 )
set .target = null
set .caster = null
call .posi.destroy()
call .start.destroy()
call ReleaseTimer( .t )
set .t = null
endmethod
method control takes nothing returns nothing
local integer i = 0
local real z
local real x
local real y
local real dist
local real angle
set .interval = .interval - TIMER_INTERVAL
if GetWidgetLife( .target ) <= 0.405 then
call .destroy()
return
endif
//Main move
if .jumping then
if DistanceBetweenCoordinates( .posi.x, GetUnitX( .target ), .posi.y, GetUnitY( .target ) ) <= MAIN_COL then
if not HaveSavedInteger( HASH, GetHandleId( .target ), 0 ) then
set .number = 1
call SaveInteger( HASH, GetHandleId( .target ), 0, 1 )
else
set .number = LoadInteger( HASH, GetHandleId( .target ), 0 ) + 1
call SaveInteger( HASH, GetHandleId( .target ), 0, .number )
endif
call SaveInteger( HASH, GetHandleId( .target ), .number, this )
call .start.destroy()
set .jumping = false
set .posi.x = GetUnitX( .target )
set .posi.y = GetUnitY( .target )
set .posi.z = GetUnitZ( .target ) + MAIN_HEIGHT * .number
set .shield = SHIELD( .level )
set .damage = DAMAGE( .level )
else
set angle = AngleBetweenCoordinates( .posi.x, GetUnitX( .target ), .posi.y, GetUnitY( .target ) ) * bj_DEGTORAD
set dist = DistanceBetweenCoordinates( .start.x, GetUnitX( .target ), .start.y, GetUnitY( .target ) )
set x = .posi.x + Cos( angle ) * MAIN_SPEED * TIMER_INTERVAL
set y = .posi.y + Sin( angle ) * MAIN_SPEED * TIMER_INTERVAL
set z = ParabolaZ2( .start.z, GetUnitZ( .target ), dist * MAIN_FLY_HEIGHT, dist, DistanceBetweenCoordinates( .start.x, x, .start.y, y ) )
set .posi.x = x
set .posi.y = y
set .posi.z = z
endif
else
set .posi.x = GetUnitX( .target )
set .posi.y = GetUnitY( .target )
set .posi.z = GetUnitZ( .target ) + MAIN_HEIGHT * .number
endif
//Turn
loop
exitwhen i >= SUB_MAX
call .sub[i].turn()
set i = i + 1
endloop
set i = 0
loop
exitwhen i >= SUB_MAX
call .sub[i].setLightning( i )
set i = i + 1
endloop
endmethod
method TookDamage takes unit damager, real damage returns nothing
local real r
local timer t
if .friend and not .jumping then
if damage >= .shield then
set damage = damage - .shield
call .destroy()
else
set .shield = .shield - damage
endif
set r = GetUnitState( .target, UNIT_STATE_MAX_LIFE ) - GetWidgetLife( .target )
if damage > r then
call SetWidgetLife( .target, GetWidgetLife( .target ) + r )
set TEMPREAL = damage - r
set TEMPUNIT = .target
set t = CreateTimer()
call TimerStart( t, 0.00, false, function Heal )
set t = null
else
call SetWidgetLife( .target, GetWidgetLife( .target ) + damage )
endif
else
if .interval <= 0.00 then
set .interval = MAIN_DAMAGE_INT
set .damage = .damage - DAMAGE( .level ) * MAIN_DMG_PERCENT
call DisableTrigger( DAMAGE_TRIG )
call UnitDamageTarget( .caster, .target, DAMAGE( .level ) * MAIN_DMG_PERCENT, true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, null )
call EnableTrigger( DAMAGE_TRIG )
call DestroyEffect( AddSpecialEffectTarget( MAIN_DMG_SFX, .target, "chest" ) )
if .damage <= 0.00 then
call .destroy()
endif
endif
endif
endmethod
method NewTarget takes unit target returns nothing
call SaveInteger( HASH, GetHandleId( .target ), 0, .number - 1 )
call SaveInteger( HASH, GetHandleId( .target ), .number, 0 )
set .target = target
set .start = vector.create( .posi.x, .posi.y, .posi.z )
set .jumping = true
if IsUnitEnemy( target, GetOwningPlayer( .caster ) ) then
set .friend = false
else
set .friend = true
endif
endmethod
static method create takes unit caster, unit target returns thistype
local thistype this = thistype.allocate()
local integer i = 0
set .caster = caster
set .target = target
if not HaveSavedInteger( HASH, GetHandleId( target ), 0 ) then
set .number = 1
call SaveInteger( HASH, GetHandleId( target ), 0, 1 )
else
set .number = LoadInteger( HASH, GetHandleId( target ), 0 ) + 1
call SaveInteger( HASH, GetHandleId( target ), 0, .number )
endif
call SaveInteger( HASH, GetHandleId( target ), .number, this )
set .posi = vector.create( GetUnitX( target ), GetUnitY( target ), GetUnitZ( target ) + MAIN_HEIGHT * .number )
set .level = GetUnitAbilityLevel( caster, SPELL_ID )
set .shield = SHIELD( .level )
set .damage = DAMAGE( .level )
loop
exitwhen i >= SUB_MAX
set .sub[i] = Sub.create( this, i )
set i = i + 1
endloop
set i = 0
loop
exitwhen i >= SUB_MAX
call .sub[i].setLightning( i )
set i = i + 1
endloop
if IsUnitEnemy( target, GetOwningPlayer( caster ) ) then
set .friend = false
else
set .friend = true
endif
set .t = NewTimer()
call SetTimerData( .t, this )
call TimerStart( .t, TIMER_INTERVAL, true, function OuterControl )
return this
endmethod
endstruct
private function UnderFence takes nothing returns boolean
if HaveSavedInteger( HASH, GetHandleId( GetSpellTargetUnit() ), 0 ) then
set TEMPMAIN = LoadInteger( HASH, GetHandleId( GetSpellTargetUnit() ), LoadInteger( HASH, GetHandleId( GetSpellTargetUnit() ), 0 ) )
call TEMPMAIN.NewTarget( GetTriggerUnit() )
endif
return false
endfunction
private function TakesDamage takes nothing returns boolean
if HaveSavedInteger( HASH, GetHandleId( GetTriggerUnit() ), 0 ) then
set TEMPMAIN = LoadInteger( HASH, GetHandleId( GetTriggerUnit() ), LoadInteger( HASH, GetHandleId( GetTriggerUnit() ), 0 ) )
call TEMPMAIN.TookDamage( GetEventDamageSource(), GetEventDamage() )
endif
return false
endfunction
private function IsSpell takes nothing returns nothing
if GetSpellAbilityId() == SPELL_ID then
call DisableTrigger( SPELL_TRIG )
call Main.create( GetTriggerUnit(), GetSpellTargetUnit() )
call PolledWait( 0.4 )
call EnableTrigger( SPELL_TRIG )
endif
endfunction
private function AddToTakesDamage takes nothing returns nothing
call TriggerRegisterUnitEvent( DAMAGE_TRIG, GetTriggerUnit(), EVENT_UNIT_DAMAGED )
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
local trigger t3 = CreateTrigger()
local group g = CreateGroup()
local unit u
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddAction( t, function IsSpell )
call TriggerRegisterAnyUnitEventBJ( SPELL_TRIG, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( SPELL_TRIG, Condition( function UnderFence ) )
call TriggerRegisterEnterRectSimple( t3, GetWorldBounds() )
call TriggerAddAction( t3, function AddToTakesDamage )
call TriggerAddCondition( DAMAGE_TRIG, Condition( function TakesDamage ) )
call GroupEnumUnitsInRange( g, 0.00, 0.00, 9999999.00, null )
loop
set u = FirstOfGroup( g )
exitwhen u == null
call TriggerRegisterUnitEvent( DAMAGE_TRIG, u, EVENT_UNIT_DAMAGED )
call GroupRemoveUnit( g, u )
set u = null
endloop
call DestroyGroup( g )
set g = null
set AXIS = vector.create( 0.00, 0.00, 1.00 )
set t = null
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Revive_Units_Conditions takes nothing returns boolean
return IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == false
endfunction
function Trig_Revive_Units_Actions takes nothing returns nothing
call TriggerSleepAction( 10.00 )
call CreateUnit( GetOwningPlayer( GetTriggerUnit() ), GetUnitTypeId( GetTriggerUnit() ), GetUnitX( GetTriggerUnit() ), GetUnitY( GetTriggerUnit() ), GetUnitFacing( GetTriggerUnit() ) )
endfunction
//===========================================================================
function InitTrig_Revive_Units takes nothing returns nothing
set gg_trg_Revive_Units = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Revive_Units, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddCondition( gg_trg_Revive_Units, Condition( function Trig_Revive_Units_Conditions ) )
call TriggerAddAction( gg_trg_Revive_Units, function Trig_Revive_Units_Actions )
endfunction