• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[vJASS] What does this even mean?

Status
Not open for further replies.
Line 878: C is not of a type that allows . syntax

If I fix or remove it then everything else starts blowing up too, I tried to set new variables as well.

[jass=]
function InitTrig_vectorsystem takes nothing returns nothing
endfunction


//===========================================================================
library vectorsystem initializer init



// **********************
// ** VECTOR SYSTEM **
// **********************

// Original concept by iNfraNe
// Then Made by Anitarf
// ported to structs by vexorian (actually just copied the math)
globals
private location stupid
endglobals


struct vector
real x=0.
real y=0.
real z=0.



private boolean safety=true

private method onDestroy takes nothing returns nothing
set this.safety=false
endmethod

method created takes nothing returns boolean
return this.safety
endmethod

method length takes nothing returns real
return SquareRoot(this.x*this.x + this.y*this.y+this.z*this.z)
endmethod

method add takes vector B returns nothing
set this.x=this.x+B.x
set this.y=this.y+B.y
set this.z=this.z+B.z
endmethod


method add_factored takes vector B, real fc returns nothing
set this.x=this.x+fc*B.x
set this.y=this.y+fc*B.y
set this.z=this.z+fc*B.z
endmethod

method substract takes vector B returns nothing
set this.x=this.x-B.x
set this.y=this.y-B.y
set this.z=this.z-B.z
endmethod

static method sum takes vector A, vector B returns vector
local vector C=vector.create()

set C.x=A.x+B.x
set C.y=A.y+B.y
set C.z=A.z+B.z
return C
endmethod

static method difference takes vector A, vector B returns vector
local vector C=vector.create()

set C.x=A.x-B.x
set C.y=A.y-B.y
set C.z=A.z-B.z
return C
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

static method amplify takes vector A, real factor returns vector
local vector C=vector.create()
set C.x=A.x*factor
set C.y=A.y*factor
set C.z=A.z*factor
return C
endmethod

static method productScalar takes vector A, vector B returns real
return A.x*B.x+A.y*B.y+A.z*B.z
endmethod

method dot takes vector B returns real
return this.x*B.x+this.y*B.y+this.z*B.z
endmethod

static method productVector takes vector A, vector B returns vector
local vector C=vector.create()

set C.x= A.y*B.z - A.z*B.y
set C.y= A.z*B.x - A.x*B.z
set C.z= A.x*B.y - A.y*B.x
return C
endmethod

method project takes vector B returns vector
local vector C=vector.create()
local real r=this.dot(B)
local real l=B.dot(B)
if (l==0.) then
return 0
endif
return vector.amplify(B,r/l)
endmethod

method projectPlane takes vector planeNormal returns vector
local vector vect= this.project(planeNormal)
local vector vect2= vector.difference(this,vect)
call vect.destroy()
return vect2
endmethod


method setLength takes real length returns boolean
local real l=this.length()
if (l==0) then
return false
endif
call this.scale(length/l)
return true
endmethod

method clone takes nothing returns vector
local vector C=vector.create()
set C.x=this.x
set C.y=this.y
set C.z=this.z
return C
endmethod

static method angle takes vector A, vector B returns real
local real l1=A.length()
local real l2=B.length()
if (l1==0) or (l2==0) then
return 0.
endif
return Acos(vector.productScalar(A,B)/(l1*l2) )
endmethod


static method distance takes vector A, vector B returns real
return SquareRoot((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z))
endmethod

static method distanceSquare takes vector A, vector B returns real
return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z)
endmethod


method rotate takes vector axis, real angle returns vector
local vector locX
local vector locY
local vector locZ= this.project(axis)
local vector result

if locZ == 0 then
return 0
endif
set locX = vector.difference(this,locZ)
set locY = vector.productVector(this, locX)
call locY.setLength(locX.length())
call locX.scale(Cos(angle))
call locY.scale(Sin(angle))
set result= vector.sum(locX,locY)
call result.add(locZ)

call locX.destroy()
call locY.destroy()
call locZ.destroy()

return result
endmethod


static method createFrom takes real x, real y, real z returns vector
local vector C=vector.create()
set C.x=x
set C.y=y
set C.z=z
return C
endmethod

static method getTerrainPosition takes real x, real y returns vector
local integer C=vector.create()
call MoveLocation(stupid,x,y)
set C.x=x
set C.y=y
set C.z=GetLocationZ(stupid)
return C
endmethod

static method getTerrainNormal takes real x, real y, real sampleRadius returns vector

local real z1
local real z2
local real z3
local real z4
local vector xvect
local vector yvect
local vector normvect
call MoveLocation(stupid, x-sampleRadius, y)
set z1=GetLocationZ(stupid)
call MoveLocation(stupid, x+sampleRadius, y)
set z2=GetLocationZ(stupid)
call MoveLocation(stupid, x, y-sampleRadius)
set z3=GetLocationZ(stupid)
call MoveLocation(stupid, x, y+sampleRadius)
set z4=GetLocationZ(stupid)

set xvect = vector.createFrom(2*sampleRadius, 0., z2-z1)
set yvect = vector.createFrom(0., 2*sampleRadius, z4-z3)
set normvect = vector.productVector(xvect, yvect)
call xvect.destroy()
call yvect.destroy()
return normvect
endmethod

method inCylinder takes vector cylinderOriginV, vector cylinderHeightV, real cylinderRadius returns boolean
local vector v1
local vector v2
local vector v3
local boolean b = false
local real l = cylinderHeightV.length()
if (l > 0.) then
set v1=vector.difference(this, cylinderOriginV)
set v2=vector.difference(v1, cylinderHeightV)
set v3=v1.projectPlane( cylinderHeightV)
if vector.productScalar(v1, cylinderHeightV)>=0 and vector.productScalar(v2, cylinderHeightV)<=0 and vector.productScalar(v3, v3)<=cylinderRadius*cylinderRadius then
set b = true
endif
call v1.destroy()
call v2.destroy()
call v3.destroy()
endif
return b
endmethod

method move takes real x, real y, real z returns nothing
set this.x=x
set this.y=y
set this.z=z
endmethod

method inCone takes vector coneOriginV, vector coneHeightV, vector coneRadius returns boolean
local vector v1
local vector v2
local vector v3
local vector v4
local boolean b = false
local real r
local real l = coneHeightV.length()
if (l>0.0) then
set v1=vector.difference(this, coneOriginV)
set v2=vector.difference(v1, coneHeightV)
set v3=v1.project( coneHeightV)
set v4=vector.difference(v1,v3)
set r = 1.0-( v3.length()/l )
if vector.productScalar(v1, coneHeightV)>=0 and v4.length()<=(coneRadius*r) then
set b = true
endif
call v1.destroy()
call v2.destroy()
call v3.destroy()
call v4.destroy()
endif
return b
endmethod

method inSphere takes vector sphereOriginV, real sphereRadius returns boolean
local vector v
local boolean b

set v=vector.difference(this, sphereOriginV)
set b= (vector.productScalar(v,v)<= sphereRadius*sphereRadius)
call v.destroy()
return b
endmethod





endstruct

private function init takes nothing returns nothing
set stupid=Location(0.,0.)
endfunction


endlibrary




[/code]

I am actually attempting to fix a certain map. =)

Hope I can get info/help on what's going wrong.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
[jass=Line]
set C.x=x
[/code]

So it's been duplicated IcemanBo and that is why it is failing?

No the reason it is failing is in the above answer.
This
JASS:
   static method getTerrainPosition takes real x, real y returns vector
    local integer C=vector.create()
       call MoveLocation(stupid,x,y)
       set C.x=x
       set C.y=y
       set C.z=GetLocationZ(stupid)
    return C
   endmethod
Needs to get changed to this.

JASS:
   static method getTerrainPosition takes real x, real y returns vector
    local vector C=vector.create()
       call MoveLocation(stupid,x,y)
       set C.x=x
       set C.y=y
       set C.z=GetLocationZ(stupid)
    return C
   endmethod
or this.
JASS:
   static method getTerrainPosition takes real x, real y returns vector
    local thistype C=thistype.create()
       call MoveLocation(stupid,x,y)
       set C.x=x
       set C.y=y
       set C.z=GetLocationZ(stupid)
    return C
   endmethod
 
Okay now that was fixed, thanks guys however more problems just popped up. . . =(

Can't believe I yet again missed such a big mistake. Dat syntax...

By any chance would you guys help me with the other errors?

The problems are undeclared functions which I am sure are from a system that can't work anymore, some type of storage system for arrays. I don't quite know though.

Messing up lines -
[jass=]
call DestroyEffect(GetArrayEffect(g , i * 2 - 1))
set m = GetArrayUnit(g , i * 2)
call DestroyEffect(GetArrayEffect(g , i * 2 - 1))
if ( GetArrayUnit(g , i * 2) == u ) then
call SetArrayObject(g , n * 2 - 1 , AddSpellEffectTargetById(s , EFFECT_TYPE_AREA_EFFECT , u , GetAbilityEffectById(s , EFFECT_TYPE_AREA_EFFECT , 1)))
call SetArrayObject(g , n * 2 , u)
[/code]


[jass=Undeclared functions of some sort]
//********************************************************************************************************
//* A JESP Spell by Vexorian
//* Codename: RagingCharge
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//* Requirements:
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯
//* - The RagingCharge ability
//* - The Caster System ( http://wc3campaigns.net/vexorian ) >=14.0
//* - JASSHelper or other global merger preprocessor ( http://wc3campaigns.net/vexorian/jasshelper/ )
//* - This Trigger (MAKE SURE TO change the rawcodes in the trigger to the correct ones of your map)
//*
//* Object Editor fields
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//* - Duration : Duration of the ability determines how much the charge lasts.
//* - Art - Caster : After charge Animation
//* - Art - Special (1) : Hero charge effect
//* - Art - Special (2) : Hero charge effect attachment point
//* - Art - Area Effect (1) : Knockback effect
//* - Art - Area Effect (2) : Knockback effect attachment point
//* - Art - Target (1) : Impact effect
//* - Art - Target (2) : Impact effect attachment point
//*
//********************************************************************************************************

//========================================================================================================
// RagingCharge Spell Configuration:
//
//
////
// SpellId
// ¯¯¯¯¯¯¯
// Make sure to replace A007 with the correct Rawcode in your map.
//
constant function RagingCharge_SpellId takes nothing returns integer
return 'A001'
endfunction

////
// Animation Stuff:
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// _AnimationIndex : The sequence index of the animation you want to be played during the charge,
// (Depends on the model used, see next trigger for more info)
// _AnimationDuration: Duration of the animation (Period of time before playing it again)
// _AnimationSpeed : Speed factor for the animation
//
constant function RagingCharge_AnimationIndex takes integer level returns integer
return 5
endfunction
constant function RagingCharge_AnimationDuration takes integer level returns real
return 0.466
endfunction
constant function RagingCharge_AnimationSpeed takes real level returns real
return 1.+level*0
endfunction
constant function RagingCharge_Speed takes real level returns real
return 800.0+level*0
endfunction

////
// Balance Stuff:
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
// _Damage : Damage done to units that are hit by RagingCharge
// _DamagePerSecond : Damage per second units get during knockback
// _ImpactRange : How close must a unit be to be hit by RagingCharge?
// _FrontAngle : Angle in Deg, less than 180.0 that determines the front of the hero
//
constant function RagingCharge_Damage takes real level returns real
return 0.0
// return -5 + (85-5*level)*level
endfunction
constant function RagingCharge_DamagePerSecond takes real level returns real
return 0.
endfunction
constant function RagingCharge_ImpactRange takes real level returns real
return 128.0 //256.0
endfunction
constant function RagingCharge_FrontAngle takes real level returns real
return 179.0
endfunction
constant function RagingCharge_MaxKnockbackTargets takes integer level returns integer
return 5+level
// Keep this number small, it is also used for array allocation, so using
//10000 might mean infinite but it would cause a lot of problems, it is not like
// you really need more than 50 for this value.
endfunction


////
// Targetting options:
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
function RagingCharge_DamageOptions takes integer level returns integer
//** Damage options for impact damage:
return DamageTypes(ATTACK_TYPE_NORMAL,DAMAGE_TYPE_FIRE) + DamageOnlyEnemies() + DamageException(UNIT_TYPE_FLYING,0)
//
// Will do fire spell damage, won't damage allies, and will only affect ground units.
// other damage options can be used, check caster system readme for more information.
//
// (This is for the Impact damage)
//
endfunction
function RagingCharge_KnockbackOptions takes integer level returns integer
//** Damage options for knockback:
return DamageOnlyEnemies() + DamageException(UNIT_TYPE_FLYING,0)
//
// Will knockback enemy ground units
// other damage options can be used, check caster system readme for more information.
//
// (This is for the Knockback, meaning that only in case these damage options determine an unit is
// immune, it won't be affected by the knockback, this has nothing to do with damage
//
endfunction
function RagingCharge_KillTrees takes integer level returns boolean
//** true == kill trees ; false == don't kill trees
return true
endfunction

////
// Other:
// ¯¯¯¯¯
constant function RagingCharge_Timer takes nothing returns real
//** Timer Period:
return 0.04
//
// This is the timer period, a low value (0.01) will look better but will be worse lag-wise, a high
// value (1.0) would be faster lag-wise but will surelly look bad. I think 0.04 is the perfect value.
endfunction




//========================================================================================================
// RagingCharge code:
//
// Why RagingCharge_ItemCheck instead of IsTerrainPathable?
// IsTerrainPathable doesn't consider pathing blockers, destructables nor buildings
//

struct RagingCharge_data
unit u=null //casting hero
integer g=0 //arrayid of the knockback array
integer l=0 // level of the spell
real f=0. // direction of the charge
trigger ran=null //range eent trigger
trigger endt=null //stop casts event
triggeraction ac=null //action of range event
effect fx=null //charge fx
integer times=0 // number of cycles done
real next=0 //next time to play animation

endstruct

function RagingCharge_GetI takes nothing returns nothing
set bj_rescueChangeColorUnit = bj_rescueChangeColorUnit or (GetEnumItem()!=bj_itemRandomCurrentPick)
endfunction
function RagingCharge_ItemCheck takes item p, real x, real y returns boolean
local integer i=50
local rect r
call SetItemPosition(p,x,y)
if ((Pow(GetItemX(p)-x,2)+Pow(GetItemY(p)-y,2))<=100) then
return true
endif
set r=Rect(x-i,y-i,x+i,y+i)
set bj_itemRandomCurrentPick=p
set bj_rescueChangeColorUnit=false
call EnumItemsInRect(r,null,function RagingCharge_GetI)
call RemoveRect(r)

set r=null
return bj_rescueChangeColorUnit
endfunction
function RagingCharge_CheckPathability takes real x, real y returns boolean
return true
// local item it=CreateItem('ciri',x,y)
// local boolean b =RagingCharge_ItemCheck(it,x,y)
// call SetItemVisible(it,false)
// call RemoveItem(it)

// set it=null
// return b
endfunction

function RagingCharge_OrbMov takes unit m,integer l, timer t, RagingCharge_data k returns boolean
local real x=GetUnitX(m)
local real y=GetUnitY(m)
local real kf
local integer kl
local unit ku
local real f=kf
local real d=RagingCharge_Speed(l)*RagingCharge_Timer()
local real nx=x+d*Cos(f*bj_DEGTORAD)
local real ny=y+d*Sin(f*bj_DEGTORAD)
local boolean b
local integer error
local integer n = k.times+1
local real nex

set k.times=n



call SetUnitFacing(m,f)
set nex=k.next

if (n * RagingCharge_Timer() >= nex) then
set k.next=nex+RagingCharge_AnimationDuration(l)
call SetUnitAnimationByIndex(m,RagingCharge_AnimationIndex(l))
endif


if ((RagingCharge_CheckPathability(nx,ny)) and (CS_MoveUnit(m,nx,ny))) then
return true
endif

call SetUnitPosition(m,x,y)
call TriggerEvaluate( k.endt)
return false
endfunction

function RagingCharge_Mov takes nothing returns nothing
local timer t=GetExpiredTimer()
local RagingCharge_data k= GetCSData(t)
local unit m
local unit o
local real f
local real sf=k.f
local real h
local real dir
local real inc
local real x
local real y
local real nx
local real ny
local real px
local real py
local real mina
local real maxa
local integer kg
local integer tms
local integer l= k.l
local trigger tg=k.endt

local integer g=kg
local integer i
local integer n=GetArrayInt(g,0)

set o=k.u
if (GetTriggerEvalCount(tg)>0) then

set i=1
set x=GetUnitX(o)
set y=GetUnitY(o)
loop
exitwhen (i>n)
// set m=GetArrayUnit(g,i*2)
// set nx=GetUnitX(m)
// set ny=GetUnitY(m)
// set f= Angles_GetMidAngle(Angles_GetMidAngle(Atan2(ny-y,nx-x)*bj_RADTODEG,sf),sf)*bj_DEGTORAD
//
// call buffs_addKnockback(m,RagingCharge_Speed(l),f)
call DestroyEffect(GetArrayEffect(g,i*2-1))
set i=i+1
endloop
call DestroyArray(g)
call DestroyTrigger(tg)
set tg=k.ran
call TriggerRemoveAction(tg, k.ac )
call DestroyTrigger(tg)
call ReleaseTimer(t)
set m=k.u
call DestroyEffect(k.fx)
if (GetWidgetLife(m)>0.405) then
call QueueUnitAnimation(m,GetAbilityEffectById(RagingCharge_SpellId(),EFFECT_TYPE_CASTER,0))
endif
call SetUnitTimeScale(m,1)
call k.destroy()
set o=null
set t=null
set m=null
return
endif
set tg=null



set x=GetUnitX(o)
set y=GetUnitY(o)

set inc=RagingCharge_Speed(l)*RagingCharge_Timer()

if (RagingCharge_KillTrees(l)) then
call DamageTreesInCircle(x,y,RagingCharge_ImpactRange(l))
endif
set h=RagingCharge_DamagePerSecond(l)*RagingCharge_Timer()
set i=1
loop
exitwhen (i>n)
set m=GetArrayUnit(g,i*2)
set nx=GetUnitX(m)
set ny=GetUnitY(m)

if (IsUnitInRange(m,o,RagingCharge_ImpactRange(l))) and (GetWidgetLife(m)>0.405) then
call DamageUnitByOptions(o,m,h,RagingCharge_DamageOptions(l))
//set f= Angles_GetMidAngle(Angles_GetMidAngle(Atan2(ny-y,nx-x)*bj_RADTODEG,sf),sf)*bj_DEGTORAD
//set f= Atan2(ny-y,nx-x)
set f= Angles_GetMidAngle((Atan2(ny-y,nx-x)*bj_RADTODEG),sf)*bj_DEGTORAD
set px=nx+inc*Cos(f)
set py=ny+inc*Sin(f)
call buffs_addKnockback(m,RagingCharge_Speed(l),f)
// call SetUnitPosition(m,px,py)
// call CS_MoveUnit(m,px,py)
call SetUnitFacing(m,GetRandomReal(0,360))
//if (Pow(GetUnitX(m)-px,2)+Pow(GetUnitY(m)-py,2))>400 then
// call SetUnitPosition(m,nx,ny)
//endif
else
// Destroy the effect, remove from array.
call DestroyEffect( GetArrayEffect(g,i*2-1) )
call SetArrayInt(g,i*2,GetArrayInt(g,n*2))
call SetArrayInt(g,i*2-1,GetArrayInt(g,n*2-1))
set n=n-1
call SetArrayInt(g,0,n)
endif
set i=i+1
endloop

call RagingCharge_OrbMov(o,l,t,k)


set t=null
set m=null
endfunction

function RagingCharge_InGArray takes unit u, integer g, integer n returns boolean
local integer i=0
loop
exitwhen i>n
if (GetArrayUnit(g,i*2)==u) then
return true
endif
set i=i+1
endloop
return false
endfunction

function RagingCharge_OrbImpact takes nothing returns nothing
local integer k=GetCSData( GetTriggeringTrigger() )
local unit u
local unit m
local unit ku
local integer kg
local integer kl
local integer g=kg
local integer l=kl
local real kf
local real f
local real dt
local integer s=RagingCharge_SpellId()
local integer i=0
local integer n=GetArrayInt(g,0)



if (n>=RagingCharge_MaxKnockbackTargets(l)) then
return //why even bother?
endif

set u=GetTriggerUnit()
set m=ku


if not( RagingCharge_InGArray(u,g,n)) and (GetWidgetLife(u)>0) and not(IsUnitType(u,UNIT_TYPE_DEAD)) and not(IsUnitType(u,UNIT_TYPE_STRUCTURE)) then

set f = kf
set dt=RagingCharge_FrontAngle(l)/2
if (Angles_IsAngleBetweenAngles( Atan2BJ(GetUnitY(u)-GetUnitY(m),GetUnitX(u)-GetUnitX(m)),f-dt,f+dt)) then
if (GetDamageFactorByOptions(m,u,RagingCharge_KnockbackOptions(l))!=0) then
call DestroyEffect( AddSpellEffectTargetById(s,EFFECT_TYPE_TARGET,u,GetAbilityEffectById(s,EFFECT_TYPE_TARGET,1)) )
set n=n+1
call SetArrayObject(g,n*2-1, AddSpellEffectTargetById(s,EFFECT_TYPE_AREA_EFFECT,u,GetAbilityEffectById(s,EFFECT_TYPE_AREA_EFFECT,1)) )
call SetArrayObject(g,n*2, u )
call SetArrayInt(g,0,n)
endif
endif

call DamageUnitByOptions(m,u,RagingCharge_Damage(l),RagingCharge_DamageOptions(l))
endif

set u=null
set m=null
endfunction

function RagingCharge_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local integer s=GetSpellAbilityId()
local integer l=GetUnitAbilityLevel(u,s)
local location loc
local real x=GetUnitX(u)
local real y=GetUnitY(u)
local real f
local timer t=NewTimer()
local integer g=NewArray(1+RagingCharge_MaxKnockbackTargets(l)*2,false)
local trigger tg=CreateTrigger()
local RagingCharge_data data= RagingCharge_data.create()

call SetArrayInt(g,0,0) //number of units in the array.

set data.ac=TriggerAddAction(tg,function RagingCharge_OrbImpact)

call SetCSData(t,data)
call SetCSData(tg,data)



if (GetSpellTargetUnit()!=null) then
set loc=GetUnitLoc(GetSpellTargetUnit())
else
set loc=GetSpellTargetLoc()
endif
set f=Atan2(GetLocationY(loc)-y,GetLocationX(loc)-x) * bj_RADTODEG
call RemoveLocation(loc)

set data.l=l
set data.f=f


set data.u=u
set data.g=g
set data.ran=tg


set data.fx=AddSpellEffectTargetById(s,EFFECT_TYPE_SPECIAL,u,GetAbilityEffectById(s,EFFECT_TYPE_SPECIAL,1))



call TriggerRegisterUnitInRange(tg,u,RagingCharge_ImpactRange(l),null)


set tg=CreateTrigger()
call TriggerRegisterUnitEvent(tg,u,EVENT_UNIT_SPELL_ENDCAST)
set data.endt=tg



call TimerStart(t,RagingCharge_Timer(),true,function RagingCharge_Mov)
call SetUnitTimeScale(u,RagingCharge_AnimationSpeed(l))
call SetUnitAnimationByIndex(u,RagingCharge_AnimationIndex(l))

set tg=null
set u=null
set loc=null
set t=null

endfunction
function InitTrig_RagingCharge takes nothing returns nothing
local integer s=RagingCharge_SpellId()
call OnAbilityEffect(s,"RagingCharge_Actions" )
call Preload(GetAbilityEffectById(s,EFFECT_TYPE_SPECIAL,0))
call Preload(GetAbilityEffectById(s,EFFECT_TYPE_TARGET,0))
call Preload(GetAbilityEffectById(s,EFFECT_TYPE_AREA_EFFECT,0))
endfunction
[/code]
 
Post it in sections.


Then it'd get confusing since its just one trigger, what are you banned from Pastebin or something? It's much easier clicking it and viewing it there

However fine.


[jass=]
library CasterSystem initializer InitCasterSystem requires CSSafeCache, GroupUtils, TimerUtils

//***************************************************************************
//* *
//* Caster System 16.0 *
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ http://wc3campaigns.net/vexorian *
//* Requires: *
//* ¯¯¯¯¯¯¯¯¯ *
//* - Jasshelper / Newgen pack *
//* *
//* - The CSSafeCache Module *
//* - The CSData Module *
//* - The CSSafety Module *
//* *
//* - The caster unit from this map Can be found in this map's unit editor *
//* ( Custom Units\Neutral Passive\Units\Caster ) *
//* *
//* ( Update the cs_CasterUnitId constant next:) *
//* *
//* - the war3mapImported\dummy.mdx imported file (find it in this map) *
//* *
//***************************************************************************

//====================================================================================================================================================================
// Caster System Configuration constants :
//
globals
//
// Caster Unit type rawcode (changes betwen maps, always use it inside '')
//
constant integer cs_CasterUnitId = 'e000'

// cs_TIMER_CYCLE : Cycle value for the projectile movement in seconds (Each 0.04 the projectiles get moved)
// 0.01 looks smooth but is lag friendly
// 0.025 looks smooth and probably matches wc3's frame rate (so in theory, lower values than it are not needed)
// 0.1 looks horrible but is not laggy
// 0.04 is decent for the human eye and very efficient.
// 0.035 is ... well, a little smoother than 0.04
// 0.05 would be an improvement in efficiency but probably doesn't look too well )
//
constant real cs_TIMER_CYCLE = 0.035

//
// The eat tree ability, don't need to change this rawcode unless you modiffied that ability in your map, in that case copy it, reset the copied one and use its rawcode here.
//
constant integer cs_DamageTreeDetectorId = 'Aeat'

//
// Medivh's Crow form ability, don't need to change this rawcode unless you
// modiffied that ability in your map, in that case copy it, reset the copied one and use its rawcode here:
//
constant integer cs_FlyingHeightHack = 'Amrf'

//
// This must point to an inventory ability with 6 slots that does not add bonuses, you don't need one unless
// the caster system item hiding functions are used in your map
//
constant integer cs_DummyInventory_Id = 'null'

//
//Maximum collision size in your map - Affects the caster system's area cast/damage functions
//
constant real cs_MaxUnitCollisionSize = 55.0

//
// Next are default attack and damage types for the old caster system functions or when using 0 as damageoptions
//
constant attacktype cs_DefaultAttackType = ATTACK_TYPE_CHAOS
constant damagetype cs_DefaultDamageType = DAMAGE_TYPE_UNIVERSAL

//
// cs_InitialCastersNumber: Number of casters to create on map init:
//
constant integer cs_InitialCastersNumber = 12

endglobals
//


//=================================================================================================
// Caster System script:
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

//=================================================================================================
// main Caster System global variables:
//
globals
//old ones (udg_ preffix forced for compat ( )
unit udg_currentcaster = null
real array udg_castervars
group udg_casters = null
integer udg_currentabi = 0
unit udg_currenthurter = null
real udg_delayhack = 0.
location udg_sourcehack = null

//--
integer array cs_missiles
integer cs_missilecount = 0
timer cs_movementtimer = CreateTimer()
boolean cs_movementtimer_active = false

endglobals

//=================================================================================================
function CS_CopyGroup takes group g returns group
set bj_groupAddGroupDest=NewGroup()
call ForGroup(g, function GroupAddGroupEnum)
return bj_groupAddGroupDest
endfunction

globals
constant real cs_RectLimitOffSet = 50.0
real cs_game_maxx
real cs_game_maxy
real cs_game_miny
real cs_game_minx
endglobals

function CS_SafeXY_Init takes nothing returns nothing
set cs_game_maxx=GetRectMaxX(bj_mapInitialPlayableArea)-cs_RectLimitOffSet
set cs_game_maxy=GetRectMaxY(bj_mapInitialPlayableArea)-cs_RectLimitOffSet
set cs_game_miny=GetRectMinY(bj_mapInitialPlayableArea)+cs_RectLimitOffSet
set cs_game_minx=GetRectMinX(bj_mapInitialPlayableArea)+cs_RectLimitOffSet
endfunction

function CS_SafeX takes real x returns real
if (x<cs_game_minx) then
return cs_game_minx
elseif (x>cs_game_maxx) then
return cs_game_maxx
endif
return(x)
endfunction

function CS_SafeY takes real y returns real
if (y<cs_game_miny) then
return cs_game_minx
elseif (y>cs_game_maxy) then
return cs_game_maxy
endif
return(y)
endfunction

//Deprecated, since patch 1.21 there is no crash anymore, it is possibly
// still mildly useful since it does bound checking.
function CS_MoveUnit takes unit u, real x, real y returns boolean
local boolean b=true
if (x<cs_game_minx) then
set b=false
elseif (x>cs_game_maxx) then
set b=false
elseif (y>cs_game_maxy) then
set b=false
elseif (y<cs_game_miny) then
set b=false
endif

if (b) then
call SetUnitX(u, x)
call SetUnitY(u, y)
endif
return b
endfunction
function CS_MoveUnitLoc takes unit u, location loc returns boolean
return CS_MoveUnit(u,GetLocationX(loc),GetLocationY(loc))
endfunction

//==================================================================================================
function CS_EnumUnitsInAOE_Filter takes nothing returns boolean
return IsUnitInRangeLoc(GetFilterUnit(), bj_enumDestructableCenter ,bj_enumDestructableRadius)
endfunction

//==================================================================================================
// Use this version when you only have coordinates of the point.
//
function CS_EnumUnitsInAOE takes group g, real x, real y, real area, boolexpr bx returns nothing
local boolexpr cond
local boolexpr aux=Condition(function CS_EnumUnitsInAOE_Filter)

if (bx==null) then
set cond=aux
else
set cond=And(aux,bx)
endif
set bj_enumDestructableCenter=Location(x,y)
set bj_enumDestructableRadius=area
call GroupEnumUnitsInRange(g,x,y,cs_MaxUnitCollisionSize+area,cond)
if (bx!=null) then
call DestroyBoolExpr(cond)
endif
call RemoveLocation(bj_enumDestructableCenter)
set aux=null
set cond=null
endfunction

//==================================================================================================
// Use this version whenever you already have a location for that point, to save some steps
//
function CS_EnumUnitsInAOELoc takes group g, location loc, real area, boolexpr bx returns nothing
local boolexpr cond
local boolexpr aux=Condition(function CS_EnumUnitsInAOE_Filter)

if (bx==null) then
set cond=aux
else
set cond=And(aux,bx)
endif
set bj_enumDestructableCenter=loc
set bj_enumDestructableRadius=area
call GroupEnumUnitsInRangeOfLoc(g,loc,cs_MaxUnitCollisionSize+area,cond)
call DestroyBoolExpr(cond)
if (bx!=null) then
call DestroyBoolExpr(aux)
endif
set aux=null
set cond=null
endfunction




//==================================================================================================
// Angle Calculations
//
// I decided to add them to the caster system, because I found myself using them everytime, I am
// trying to convert the caster system into a Spell Development Framework (hehe)
//
//=================================================================================================
// Returns the angle distance between angles a1 and a2 (For example: a1=30 , a2=60 , return= 30 )
//
function Angles_GetAngleDifference takes real a1, real a2 returns real
local real x
set a1=ModuloReal(a1,360)
set a2=ModuloReal(a2,360)
if a1>a2 then
set x=a1
set a1=a2
set a2=x
endif
set x=a2-360
if a2-a1 > a1-x then
set a2=x
endif
set x=a1-a2
if (x<0) then
return -x
endif
return x
endfunction

//=================================================================================================
// Returns the mid angle between a1 and a2 (For example: a1=30 , a2=60 , return= 45 )
//
function Angles_GetMidAngle takes real a1, real a2 returns real
local real x
set a1=ModuloReal(a1,360)
set a2=ModuloReal(a2,360)
if a1>a2 then
set x=a1
set a1=a2
set a2=x
endif
set x=a2-360
if a2-a1 > a1-x then
set a2=x
endif
return (a1+a2)/2
endfunction

//=================================================================================================
// Makes angle a1 advance i units towards angle a2 (For Example: a1=30, a2=60, i=10, return=40 )
//
function Angles_MoveAngleTowardsAngle takes real a1, real a2, real i returns real
local real x
set a1=ModuloReal(a1,360)
set a2=ModuloReal(a2,360)
if a1>a2 then
set x=a1-360
if a1-a2 > a2-x then
set a1=x
endif
else
set x=a2-360
if a2-a1 > a1-x then
set a2=x
endif
endif
if a1>a2 then
set x=a1-i
if x<=a2 then
return a2
endif
return x
endif
set x=a1+i
if x>=a2 then
return a2
endif
return x
endfunction

//=================================================================================================
// Returns true if the angle 'angle' is between 'angle1' and 'angle2'
//
function Angles_IsAngleBetweenAngles takes real angle, real angle1, real angle2 returns boolean
local real x
set angle=ModuloReal(angle,360)
set angle1=ModuloReal(angle1,360)
set angle2=ModuloReal(angle2,360)
if (angle1>angle2) then
set x=angle1
set angle1=angle2
set angle2=x
endif
if (angle2-angle1)>(angle1 - (angle2-360)) then
set angle2=angle2-360
if angle > 180 then
set angle=angle-360
endif
return angle>=angle2 and angle<=angle1
endif
return (angle>=angle1) and (angle<=angle2)
endfunction

//====================================================================================================================================================================
function CreateCaster takes real fac, real x , real y returns unit
local unit m
if (x!=0) then
set x=CS_SafeX(x)
endif
if (y!=0) then
set y=CS_SafeY(y)
endif
set m=CreateUnit( Player(15), cs_CasterUnitId, x ,y ,fac)


call UnitAddAbility(m, 'Aloc')
call UnitAddAbility(m, cs_FlyingHeightHack)
call UnitRemoveAbility(m, cs_FlyingHeightHack )
set udg_currentcaster=m
set m=null
return udg_currentcaster
endfunction



function AddCasterFacing takes real fac returns unit
return CreateCaster(fac,0,0)
endfunction

function AddCaster takes nothing returns unit
return CreateCaster(0,0,0)
endfunction


//====================================================================================================================================================================
function CreateCasters takes integer n returns nothing
local integer a=0
local unit c
loop
exitwhen a>=n
set c=CreateCaster(0,0,0)
call GroupAddUnit( udg_casters, c)
set a=a+1
endloop
set c=null
endfunction

private function InitCasterSystem takes nothing returns nothing
set udg_casters=NewGroup()
call CS_SafeXY_Init()
call CreateCasters(cs_InitialCastersNumber)
set udg_castervars[100]=-1
set udg_castervars[101]=-1
set udg_castervars[102]=-1
set udg_castervars[103]=-1
set udg_castervars[104]=-1

set cs_dmg_caster=CreateCaster(0.,0.,0.)
call UnitRemoveAbility(cs_dmg_caster,'Aloc') //Otherwise the units would flee like crazy

endfunction



//====================================================================================================================================================================
function GetACaster takes nothing returns unit
set udg_currentcaster=FirstOfGroup( udg_casters)
if udg_currentcaster == null then
set udg_currentcaster=CreateCaster(0,0,0)
endif
call GroupRemoveUnit( udg_casters,udg_currentcaster)
call SetUnitState( udg_currentcaster, UNIT_STATE_MANA, 1000)
return udg_currentcaster
endfunction

//====================================================================================================================================================================
function Caster_SetZAngle takes unit caster, real ang returns nothing
local real a=(ModuloReal(GetUnitFacing(caster),360)*bj_DEGTORAD)
local real x
set ang=ModuloReal(ang,360)
if ( ang == 90 ) then
set ang = 89
endif
if ( ang == 270 ) then
set ang = 271
endif
if (ang>90) and (ang<270) then
set x=-1
else
set x=1
endif
set ang=ang*bj_DEGTORAD
call SetUnitLookAt(caster,"Bone_Chest",caster, 10000.0*Cos(a)*Cos(ang), 10000.0*Sin(a)*Cos(ang), x*(10000.0*Tan(ang)+90.0) )
endfunction

//====================================================================================================================================================================
function Caster_SetZAngle2 takes unit caster, integer ang returns nothing
call SetUnitAnimationByIndex(caster,ang+90) //Thanks infrane!
endfunction

//====================================================================================================================================================================
function RecycleCaster takes unit caster returns nothing
if GetWidgetLife(caster)>=0.405 then
call ResetUnitLookAt(caster)
call SetUnitOwner( caster, Player(15), true)
call SetUnitVertexColor( caster, 255,255,255,255)
call SetUnitScale( caster, 1,1,1)
call SetUnitTimeScale( caster, 1)
call SetUnitMoveSpeed( caster, 522)
call SetUnitFlyHeight( caster, 0,0)
call UnitAddAbility(caster, 'Aloc')
call SetUnitTurnSpeed( caster, 0.6)
call GroupAddUnit( udg_casters, caster)
endif
endfunction

function RecycleCaster_Light takes unit caster returns nothing
if GetWidgetLife(caster)>=0.405 then
call SetUnitOwner( caster, Player(15), true)
call GroupAddUnit( udg_casters, caster)
endif
endfunction
function RecicleCaster takes unit caster returns nothing
call RecycleCaster(caster)
endfunction
function RecicleCaster_Light takes unit caster returns nothing
call RecycleCaster_Light(caster)
endfunction

private struct csrecy
unit caster
integer abil
endstruct

function CasterRecycleTimed_X takes nothing returns nothing
local timer t=GetExpiredTimer()
local csrecy k=GetCSData(t)
if (k.abil!=0) then
call UnitRemoveAbility(k.caster,k.abil)
endif
call RecycleCaster(k.caster)
call k.destroy()
call ReleaseTimer(t)
endfunction

function CasterRecycleTimed takes unit caster, integer abi, real delay returns nothing
local timer t=NewTimer()
local csrecy k= csrecy.create()
set k.caster=caster
set k.abil=abi
call SetCSData(t,k)

call TimerStart(t,delay,false,function CasterRecycleTimed_X)
endfunction

function CasterWaitForEndCast takes nothing returns nothing
local unit caster=udg_currentcaster
local integer abilid=udg_currentabi
local real delay=udg_castervars[0]
local boolean activeability=(udg_castervars[1]>0)
loop
exitwhen GetUnitCurrentOrder(caster) == 0
call TriggerSleepAction(0)
endloop
if (delay>0) then
if activeability then
call CasterRecycleTimed(caster,abilid,delay)
else
call UnitRemoveAbility( caster, abilid)
call CasterRecycleTimed(caster,0,delay)
endif
else
call UnitRemoveAbility( caster, abilid)
call RecycleCaster(caster)
endif
set caster=null
endfunction

function RecycleCasterAfterCastEx takes unit caster, real delaytime, integer abilid, boolean activeability returns nothing
set udg_castervars[0]=delaytime
set udg_castervars[1]=IntegerTertiaryOp(activeability,1,0)
set udg_currentabi=abilid
set udg_currentcaster=caster
call ExecuteFunc("CasterWaitForEndCast" )
endfunction
function RecicleCasterAfterCastEx takes unit caster, real delaytime, integer abilid, boolean activeability returns nothing
call RecycleCasterAfterCastEx(caster,delaytime,abilid,activeability)
endfunction

function CasterWaitForEndCast_Light takes nothing returns nothing
local unit caster=udg_currentcaster
local integer abilid=udg_currentabi
local real delay=udg_castervars[0]
local boolean activeability=(udg_castervars[1]>0)
loop
exitwhen GetUnitCurrentOrder(caster) == 0
call TriggerSleepAction(0)
endloop
if (delay>0) then
if activeability then
call CasterRecycleTimed(caster,abilid,delay)
else
call UnitRemoveAbility( caster, abilid)
call CasterRecycleTimed(caster,0,delay)
endif
else
call UnitRemoveAbility( caster, abilid)
call RecycleCaster_Light(caster)
endif
set caster=null
endfunction

function RecycleCasterAfterCastEx_Light takes unit caster, real delaytime, integer abilid, boolean activeability returns nothing
set udg_castervars[0]=delaytime
set udg_castervars[1]=IntegerTertiaryOp(activeability,1,0)
set udg_currentabi=abilid
set udg_currentcaster=caster
call ExecuteFunc("CasterWaitForEndCast_Light" )
endfunction


function RecicleCasterAfterCastEx_Light takes unit caster, real delaytime, integer abilid, boolean activeability returns nothing
call RecycleCasterAfterCastEx_Light(caster,delaytime,abilid,activeability)
endfunction
function RecicleCasterAfterCast takes unit caster, integer abilid returns nothing
call RecycleCasterAfterCastEx(caster,udg_delayhack,abilid,false)
endfunction
function RecycleCasterAfterCast takes unit caster, integer abilid returns nothing
call RecycleCasterAfterCastEx(caster,udg_delayhack,abilid,false)
endfunction


//====================================================================================================================================================================
function PreloadAbility takes integer abilid returns integer
local unit u=FirstOfGroup(udg_casters)
if u==null then
set u=GetACaster()
call UnitAddAbility(u, abilid)
call UnitRemoveAbility(u, abilid)
call RecycleCaster_Light( u)
else
call UnitAddAbility(u, abilid)
call UnitRemoveAbility(u, abilid)
endif
set u=null
return abilid
endfunction

//====================================================================================================================================================================
function CasterCastAbilityEx takes player owner, real x, real y, real z, integer abilid, integer level, string order, widget target, real delay returns unit
local unit caster=GetACaster()
local boolean done=false
call SetUnitOwner( caster, owner, false)
call UnitAddAbility( caster, abilid)
call SetUnitAbilityLevel(caster,abilid,level)
call SetUnitX(caster,x)
call SetUnitY(caster,y)
call SetUnitFlyHeight(caster,z,0)
if S2I(order) != 0 then
set done=IssueTargetOrderById( caster, S2I(order), target )
else
set done=IssueTargetOrder( caster, order, target )
endif
if (delay<=0) or not(done) then
call UnitRemoveAbility( caster, abilid)
call RecycleCaster_Light( caster)
else
call RecycleCasterAfterCastEx_Light(caster, delay, abilid, true)
endif
set udg_currentcaster=caster
set caster=null
return udg_currentcaster
endfunction

//====================================================================================================================================================================
function CasterCastAbilityExLoc takes player owner, location loc, real z, integer abilid, integer level, string order, widget target, real delay returns unit
return CasterCastAbilityEx(owner,GetLocationX(loc),GetLocationY(loc),z,abilid,level,order,target,delay)
endfunction

//====================================================================================================================================================================
function CasterCastAbilityLevel takes player owner, integer abilid, integer level, string order, widget target, boolean instant returns unit
local real x
local real y
local real d
if udg_sourcehack!=null then
set x=GetLocationX(udg_sourcehack)
set y=GetLocationY(udg_sourcehack)
else
set x=GetWidgetX(target)
set y=GetWidgetY(target)
endif
if not(instant) then
set d=udg_delayhack+0.01
else
set d=0
endif
return CasterCastAbilityEx(owner,x,y,0,abilid,level,order,target,d)
endfunction

//====================================================================================================================================================================
function CasterCastAbility takes player owner, integer abilid, string order, widget target, boolean instant returns unit
return CasterCastAbilityLevel( owner, abilid, 1, order, target, instant )
endfunction

//====================================================================================================================================================================
function CasterCastAbilityPointEx takes player owner, real x1, real y1, real z1, integer abilid, integer level, string order, real x2, real y2, real delay returns unit
local unit caster=GetACaster()
call SetUnitOwner( caster, owner, false)
call UnitAddAbility( caster, abilid)
call SetUnitAbilityLevel(caster,abilid,level)
call SetUnitX(caster,x1)
call SetUnitY(caster,y1)
call SetUnitFlyHeight(caster,z1,0)
if S2I(order) != 0 then
if not IssuePointOrderById( caster, S2I(order), x2,y2 ) then
call IssueImmediateOrderById( caster, S2I(order) )
endif
else
if not IssuePointOrder( caster, order, x2,y2 ) then
call IssueImmediateOrder( caster, order )
endif
endif
if (delay<=0) then
call UnitRemoveAbility( caster, abilid)
call RecycleCaster_Light( caster)
else
call RecicleCasterAfterCastEx_Light(caster, delay, abilid, true)
endif
set udg_currentcaster=caster
set caster=null
return udg_currentcaster
endfunction

//====================================================================================================================================================================
function CasterCastAbilityPointExLoc takes player owner, location loc1, real z1, integer abilid, integer level, string order, location loc2, real delay returns unit
return CasterCastAbilityPointEx(owner,GetLocationX(loc1),GetLocationY(loc1),z1,abilid,level,order,GetLocationX(loc2),GetLocationY(loc2),delay)
endfunction

//====================================================================================================================================================================
function CasterCastAbilityLevelPoint takes player owner, integer abilid, integer level, string order, real x, real y, boolean instant returns unit
local real sx
local real sy
local real d
if udg_sourcehack!=null then
set sx=GetLocationX(udg_sourcehack)
set sy=GetLocationY(udg_sourcehack)
else
set sx=x
set sy=y
endif
if instant then
set d=0
else
set d=udg_delayhack+0.01
endif
return CasterCastAbilityPointEx(owner,sx,sy,0,abilid,level,order,x,y,d)
endfunction

function CasterCastAbilityPoint takes player owner, integer abilid, string order, real x, real y, boolean instant returns unit
return CasterCastAbilityLevelPoint(owner,abilid,1,order,x,y,instant)
endfunction

function CasterCastAbilityPointLoc takes player owner, integer abilid, string order, location loc, boolean instant returns unit
return CasterCastAbilityLevelPoint( owner, abilid, 1,order, GetLocationX(loc), GetLocationY(loc), instant )
endfunction

function CasterCastAbilityLevelPointLoc takes player owner, integer abilid, integer level, string order, location loc, boolean instant returns unit
return CasterCastAbilityLevelPoint( owner, abilid, level,order, GetLocationX(loc), GetLocationY(loc), instant )
endfunction

//====================================================================================================================================================================
private struct cssabi
effect fx
unit caster
integer abil
endstruct

function CasterUseAbilityLevelStatic_Rec takes nothing returns nothing
local timer t=GetExpiredTimer()
local cssabi k=GetCSData(t)
call RecycleCaster(k.caster)
call k.destroy()
call ReleaseTimer(t)
endfunction

function CasterUseAbilityLevelStatic_X takes nothing returns nothing
local timer t=GetExpiredTimer()
local cssabi k=GetCSData(t)

call DestroyEffect(k.fx)
call UnitRemoveAbility( k.caster, k.abil)
call TimerStart(t,2,false, function CasterUseAbilityLevelStatic_Rec)
endfunction

function CasterUseAbilityLevelStatic takes player owner, string modelpath, integer abilityid, integer level, real duration, real x, real y returns unit
local timer t=NewTimer()
local unit c=GetACaster()
local cssabi k= cssabi.create()


call SetUnitPosition( c, x, y)
set k.fx= AddSpecialEffectTarget( modelpath, c,"origin" )
set k.caster = c
set k.abil=abilityid

call SetUnitOwner(c, owner, true)
call UnitAddAbility(c, abilityid)
call SetUnitAbilityLevel(c, abilityid, level)

call SetCSData(t,k)
call TimerStart(t,duration,false,function CasterUseAbilityLevelStatic_X)


set udg_currentcaster=c
set c=null
return udg_currentcaster
endfunction

function CasterUseAbilityStatic takes player owner, string modelpath, integer abilityid, real duration, real x, real y returns unit
return CasterUseAbilityLevelStatic(owner,modelpath,abilityid,1,duration,x,y)
endfunction

function CasterUseAbilityStaticLoc takes player owner, string modelpath, integer abilityid, real duration, location loc returns unit
return CasterUseAbilityLevelStatic(owner,modelpath,abilityid,1,duration, GetLocationX(loc), GetLocationY(loc))
endfunction

function CasterUseAbilityLevelStaticLoc takes player owner, string modelpath, integer abilityid, integer level,real duration, location loc returns unit
return CasterUseAbilityLevelStatic(owner,modelpath,abilityid,level,duration, GetLocationX(loc), GetLocationY(loc))
endfunction

//====================================================================================================================================================================
function CasterCastAbilityLevelGroup takes player owner, integer abilid, integer level,string order, group targetgroup, boolean instant returns nothing
local group affected
local unit tempunit
local unit caster=null
if bj_wantDestroyGroup then
set bj_wantDestroyGroup=false
set affected=targetgroup
else
set affected=NewGroup()
call GroupAddGroup( targetgroup, affected)
endif
loop
set tempunit=FirstOfGroup(affected)
exitwhen tempunit == null
if instant then
if caster==null then
set caster=GetACaster()
call SetUnitOwner( caster, owner, false)
call UnitAddAbility( caster, abilid)
call SetUnitAbilityLevel( caster, abilid,level)
endif
if udg_sourcehack != null then
call SetUnitX(caster,GetLocationX(udg_sourcehack))
call SetUnitY(caster,GetLocationY(udg_sourcehack))

else
call SetUnitX(caster,GetUnitX(tempunit))
call SetUnitY(caster,GetUnitY(tempunit))
endif

if S2I(order) != 0 then
call IssueTargetOrderById( caster, S2I(order), tempunit )
else
call IssueTargetOrder( caster, order, tempunit )
endif
else
call CasterCastAbilityLevel( owner, abilid,level, order, tempunit, false)
endif
call GroupRemoveUnit(affected, tempunit)
endloop
if caster != null then
call UnitRemoveAbility( caster, abilid)
call RecycleCaster(caster)
endif
call ReleaseGroup(affected)
set affected=null
set tempunit=null
set caster=null
endfunction

function CasterCastAbilityGroup takes player owner, integer abilid, string order, group targetgroup, boolean instant returns nothing
call CasterCastAbilityLevelGroup(owner,abilid,1,order,targetgroup,instant)
endfunction

//====================================================================================================================================================================
function CasterAOE_IsFilterEnemy takes nothing returns boolean
return IsUnitEnemy( GetFilterUnit(), bj_groupEnumOwningPlayer ) and ( GetWidgetLife(GetFilterUnit()) > 0.405)
endfunction

function CasterAOE_IsFilterAlly takes nothing returns boolean
return IsUnitAlly( GetFilterUnit(), bj_groupEnumOwningPlayer ) and ( GetWidgetLife(GetFilterUnit()) > 0.405)
endfunction

//====================================================================================================================================================================
function CasterCastAbilityLevelAOE takes player owner, integer abilid, integer level, string order, real x, real y, real radius, boolean goodeffect, boolean instant returns nothing
local boolexpr b
local group aoe=NewGroup()
set bj_groupEnumOwningPlayer=owner
if goodeffect then
set b=Condition(function CasterAOE_IsFilterAlly)
else
set b=Condition(function CasterAOE_IsFilterEnemy)
endif
call CS_EnumUnitsInAOE(aoe, x,y, radius, b)
set bj_wantDestroyGroup=true
call CasterCastAbilityLevelGroup( owner, abilid, level, order, aoe, instant)
call DestroyBoolExpr(b)
set b=null
set aoe=null
endfunction

function CasterCastAbilityAOE takes player owner, integer abilid, string order, real x, real y, real radius, boolean goodeffect, boolean instant returns nothing
call CasterCastAbilityLevelAOE(owner,abilid,1,order,x,y,radius,goodeffect,instant)
endfunction

function CasterCastAbilityAOELoc takes player owner, integer abilid, string order, location center, real radius, boolean goodeffect, boolean instant returns nothing
call CasterCastAbilityLevelAOE(owner, abilid,1, order, GetLocationX(center), GetLocationY(center), radius, goodeffect, instant)
endfunction

function CasterCastAbilityLevelAOELoc takes player owner, integer abilid, integer level, string order, location center, real radius, boolean goodeffect, boolean instant returns nothing
call CasterCastAbilityLevelAOE(owner, abilid,level, order, GetLocationX(center), GetLocationY(center), radius, goodeffect, instant)
endfunction

//====================================================================================================================================================================
globals
timer cs_sourcehacktimer = CreateTimer()
timer cs_delayhacktimer = CreateTimer()
endglobals

function ResetSourceHack takes nothing returns nothing
if (udg_sourcehack!=null) then
call RemoveLocation(udg_sourcehack)
set udg_sourcehack=null
endif
endfunction

function CasterSetCastSource takes real x, real y returns nothing
if (udg_sourcehack==null) then
set udg_sourcehack=Location(x,y)
else
call MoveLocation(udg_sourcehack,x,y)
endif
call TimerStart(cs_sourcehacktimer,0.,false,function ResetSourceHack)
endfunction

function CasterSetCastSourceLoc takes location loc returns nothing
call CasterSetCastSource( GetLocationX(loc), GetLocationY(loc) )
endfunction

function ResetDelayHack takes nothing returns nothing
set udg_delayhack=0.
endfunction

function CasterSetRecycleDelay takes real Delay returns nothing
set udg_delayhack=Delay
call TimerStart(cs_delayhacktimer,0.,false,function ResetDelayHack)
endfunction

//====================================================================================================================================================================


//Super DamageOptions structure!
globals
attacktype cs_dopt_Atype = null
damagetype cs_dopt_Dtype = null
unittype cs_dopt_ExceptionUtype = null
real cs_dopt_ExceptionFct = 1.0

unittype cs_dopt_OnlyUtype = null
unittype cs_dopt_IgnoreUtype = null



integer cs_dopt_EnemyAlly = 0 //[ 0 = onlyenemies, 1= forceall, 2=onlyallies]
integer cs_dopt_dfab1 = 'null'
real cs_dopt_dfab1_fc = 1.0
integer cs_dopt_dfab2 = 'null'
real cs_dopt_dfab2_fc = 1.
integer cs_dopt_dfab3 = 'null'
real cs_dopt_dfab3_fc = 1.

real cs_dopt_Ally_fc = 1.
endglobals


function DamageTypes takes attacktype attT, damagetype dmgT returns integer
// set udg_castervars[100] = CS_H2I(attT)
// set udg_castervars[101] = CS_H2I(dmgT)
set cs_dopt_Atype=attT
set cs_dopt_Dtype=dmgT
return 1
endfunction

function DamageException takes unittype Exception, real ExceptionFactor returns integer
set cs_dopt_ExceptionUtype=Exception
set cs_dopt_ExceptionFct = ExceptionFactor
// set udg_castervars[102] = CS_H2I(Exception)
// set udg_castervars[103] = ExceptionFactor
return 2
endfunction

function DamageOnlyTo takes unittype ThisUnitType returns integer
set cs_dopt_OnlyUtype = ThisUnitType
// set udg_castervars[104] = CS_H2I(ThisUnitType)
return 4
endfunction

constant function DontDamageSelf takes nothing returns integer
return 8
endfunction

constant function DamageTrees takes nothing returns integer
return 16
endfunction

constant function DamageOnlyVisibles takes nothing returns integer
return 32
endfunction

function DamageOnlyEnemies takes nothing returns integer
set cs_dopt_EnemyAlly=0
// ouch, forgot what it was
return 64
endfunction

function ForceDamageAllies takes nothing returns integer
set cs_dopt_EnemyAlly=1
return 64
endfunction

function DamageOnlyAllies takes nothing returns integer
set cs_dopt_EnemyAlly=2
return 64
endfunction

function DamageFactorAbility1 takes integer spellid, real factor returns integer
set cs_dopt_dfab1=spellid
set cs_dopt_dfab1_fc=factor
return 128
endfunction

function DamageFactorAbility2 takes integer spellid, real factor returns integer
set cs_dopt_dfab2=spellid
set cs_dopt_dfab2_fc=factor

return 256
endfunction

function DamageFactorAbility3 takes integer spellid, real factor returns integer
set cs_dopt_dfab3=spellid
set cs_dopt_dfab3_fc=factor

return 512
endfunction

function DamageIgnore takes unittype ThisUnitType returns integer
set cs_dopt_IgnoreUtype = ThisUnitType
// set udg_castervars[112] = CS_H2I(ThisUnitType)
return 1024
endfunction

function DamageAlliedFactor takes real fct returns integer
set cs_dopt_Ally_fc = fct
// set udg_castervars[113] = fct
return 2048
endfunction

constant function ConsiderOnlyDeadUnits takes nothing returns integer
return 4096
endfunction

constant function IgnoreDeadState takes nothing returns integer
return 8192
endfunction


//===============================================================================================
function IsDamageOptionIncluded takes integer DamageOptions, integer whichDamageOption returns boolean
local integer i=8192
if (DamageOptions==0) then
return false
endif
loop
exitwhen (i<=whichDamageOption)
if (DamageOptions>=i) then
set DamageOptions=DamageOptions-i
endif
set i=i/2
endloop
return (DamageOptions>=whichDamageOption)
endfunction


//=================================================================================================
globals
unit cs_dmg_caster=null
endglobals

function GetDamageFactor takes unit u,attacktype a, damagetype d returns real
local real hp=GetWidgetLife(u)
local real mana=GetUnitState(u,UNIT_STATE_MANA)
local real r

//Since a unit is in that point, we don't need checks.
call SetUnitX(cs_dmg_caster,GetUnitX(u))
call SetUnitY(cs_dmg_caster,GetUnitY(u))

call SetUnitOwner(cs_dmg_caster,GetOwningPlayer(u),false)
set r=hp
if (hp<1) then
call SetWidgetLife(u,1)
set r=1
endif
call UnitDamageTarget(cs_dmg_caster,u,0.01,true,false,a,d,null)
call SetUnitOwner(cs_dmg_caster,Player(15),false)
if (mana>GetUnitState(u,UNIT_STATE_MANA)) then
//Unit had mana shield, return 1 and restore mana too.
call SetUnitState(u,UNIT_STATE_MANA,mana)
set r=1
else
set r= (r-GetWidgetLife(u))*100
endif
call SetWidgetLife(u,hp)

return r
endfunction

//======================================================================================================
// Fix for the unit type bugs from blizzard, amphibious units aren't considered ground for some reason
// so this considers any non flying unit as ground.
//
// Also heroes are resistant too, so in case UNIT_TYPE_RESISTANT is used it will return true in case the
// unit is a hero too.
//
function CS_IsUnitType takes unit u, unittype ut returns boolean
if (ut==UNIT_TYPE_GROUND) then
return not(IsUnitType(u,UNIT_TYPE_FLYING))
elseif (ut==UNIT_TYPE_RESISTANT) then
return IsUnitType(u,ut) or IsUnitType(u,UNIT_TYPE_HERO)
endif
return IsUnitType(u,ut)
endfunction

function GetDamageFactorByOptions takes unit hurter, unit target, integer d returns real
local real r=1

if (d>=8192) then
set d=d-8192
elseif (d>=4096) then
if (GetWidgetLife(target)>0.405) then
return 0.0
endif
set d=d-4096
elseif (GetWidgetLife(target)<=0.405) then
return 0.0
endif

if d>=2048 then
if IsUnitAlly(target,GetOwningPlayer(hurter)) then
set r=r* cs_dopt_Ally_fc
endif
set d=d-2048
endif
if d>=1024 then
if CS_IsUnitType(target, cs_dopt_IgnoreUtype ) then
return 0.0
endif
set d=d-1024
endif
if d>=512 then
if GetUnitAbilityLevel(target, cs_dopt_dfab1 )>0 then
set r=r*cs_dopt_dfab1_fc
endif
set d=d-512
endif
if d>=256 then
if GetUnitAbilityLevel(target, cs_dopt_dfab2 )>0 then
set r=r*cs_dopt_dfab2_fc
endif
set d=d-256
endif
if d>=128 then
if GetUnitAbilityLevel(target, cs_dopt_dfab3 )>0 then
set r=r*cs_dopt_dfab3_fc
endif
set d=d-128
endif
if d>=64 then
if (cs_dopt_EnemyAlly==0) and IsUnitAlly(target,GetOwningPlayer(hurter)) then
return 0.0
elseif (cs_dopt_EnemyAlly==2) and IsUnitEnemy(target,GetOwningPlayer(hurter)) then
return 0.0
endif
set d=d-64
endif
if d>=32 then
set d=d-32
if not IsUnitVisible(target,GetOwningPlayer(hurter)) then
return 0.0
endif
endif
if d>=16 then
set d=d-16
endif
if d>=8 then
set d=d-8
if hurter==target then
return 0.0
endif
endif
if d>=4 then
set d=d-4
if not CS_IsUnitType( target,cs_dopt_OnlyUtype) then
return 0.0
endif
endif
if d>=2 then
set d=d-2
if CS_IsUnitType( target, cs_dopt_ExceptionUtype ) then
set r=r* cs_dopt_ExceptionFct
endif
endif
if d>=1 then
set d=d-1
set r=r*GetDamageFactor(target,cs_dopt_Atype,cs_dopt_Dtype)
endif
return r
endfunction

//======================================================================================================================
// This used to be needed because in 1.17 UnitDamageTarget didn't consider the damagetype argument, this bug
// was fixed in 1.18, and we no longer need this function, left for compatibility.
//
function DamageUnitByTypes takes unit hurter, unit target, real dmg, attacktype attT, damagetype dmgT returns boolean
return UnitDamageTarget(hurter,target,dmg,true,false,attT,dmgT,null)
endfunction

//=============================================================================================================================
function DamageUnitByOptions takes unit hurter, unit target, real dmg, integer DamageOptions returns boolean
local real f=GetDamageFactorByOptions(hurter,target,DamageOptions)
if (f==0) then
return false
endif
return UnitDamageTarget(hurter,target,dmg*f,true,false,null,null,null)
endfunction

//=============================================================================================================================
function DamageUnit takes player hurter, real damage, unit victim returns boolean
call SetUnitX(cs_dmg_caster,GetUnitX(victim))
call SetUnitY(cs_dmg_caster,GetUnitY(victim))

call SetUnitOwner(cs_dmg_caster,hurter,false)
call DamageUnitByTypes(cs_dmg_caster,victim,damage,cs_DefaultAttackType,cs_DefaultDamageType)
call SetUnitOwner(cs_dmg_caster,Player(15),false)

return GetWidgetLife(victim)<=0 // I thought UnitDamageTarget returned true when it killed the unit, but nope, it returns true when it was able to do the damage.
endfunction

//====================================================================================================================================================================
function UnitDamageUnitTimed_Child takes nothing returns nothing
local real damage = udg_castervars[0]
local real damageperiod= udg_castervars[2]
local effect fx=bj_lastCreatedEffect
local timer t=NewTimer()
local unit hurter=udg_currenthurter
local real next=0
local integer i=0
local real c
local unit target=udg_currentcaster
local damagetype dmgT=ConvertDamageType(R2I(udg_castervars[4]))
local attacktype attT=ConvertAttackType(R2I(udg_castervars[3]))

call TimerStart(t, udg_castervars[1]-0.01, false,null)
loop
if TimerGetElapsed(t) >= next then
exitwhen not UnitDamageTarget(hurter, target, damage,true,false, attT, dmgT,null)
exitwhen GetWidgetLife(target)<=0.405
set i=i+1
set next=i*damageperiod
endif
exitwhen (TimerGetRemaining(t) <= 0) or GetWidgetLife(target)<=0.405
call TriggerSleepAction(0)
endloop
call DestroyEffect(fx)
call ReleaseTimer(t)
set fx=null
set dmgT=null
set attT=null
endfunction

function UnitDamageUnitTimed takes unit hurter, real damageps, real damageperiod, real duration, unit target, string modelpath, string attachPointName, attacktype attT, damagetype dmgT returns nothing
local unit c=udg_currentcaster
set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, target,attachPointName )
set udg_currentcaster=target
set udg_castervars[0]=damageps
set udg_castervars[1]=duration
set udg_castervars[2]=damageperiod
set udg_castervars[3]=CS_H2I(attT)
set udg_castervars[4]=CS_H2I(dmgT)
set udg_currenthurter=hurter
call ExecuteFunc("UnitDamageUnitTimed_Child")
set udg_currentcaster=c
set c=null
endfunction

//=============================================================================================================
// Left for compatibility
//
function DamageUnitTimedEx_Child takes nothing returns nothing
local real damage = udg_castervars[0]
local real damageperiod= udg_castervars[2]
local effect fx=bj_lastCreatedEffect
local timer t=NewTimer()
local integer id=udg_currentabi
local real next=0
local integer i=0
local real c
local unit target=udg_currentcaster
call TimerStart(t, udg_castervars[1]-0.01, false,null)
loop
if TimerGetElapsed(t) >= next then
exitwhen DamageUnit( Player(id), damage, target)
set i=i+1
set next=i*damageperiod
endif
exitwhen (TimerGetRemaining(t) <= 0) or GetWidgetLife(target)<=0.405
call TriggerSleepAction(0)
endloop
call DestroyEffect(fx)
call ReleaseTimer(t)
set fx=null
endfunction

function DamageUnitTimedEx takes player owner, real damageps, real damageperiod, real duration, unit target, string modelpath, string attachPointName returns nothing
local unit c=udg_currentcaster
set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, target,attachPointName )
set udg_currentcaster=target
set udg_castervars[0]=damageps
set udg_castervars[1]=duration
set udg_castervars[2]=damageperiod
set udg_currentabi=GetPlayerId( owner )
call ExecuteFunc("DamageUnitTimedEx_Child")
set udg_currentcaster=c
set c=null
endfunction

function DamageUnitTimed takes player owner, real damageps, real duration, unit target, string modelpath, string attachPointName returns nothing
call DamageUnitTimedEx(owner , damageps, 1, duration, target, modelpath, attachPointName )
endfunction

//[
private struct dostruct
integer value
attacktype attt
damagetype dmgt
unittype excp
real excf
unittype only
integer allied
integer dfab1
real dfab1_fc
integer dfab2
real dfab2_fc
integer dfab3
real dfab3_fc
unittype ign
real ally_fc
endstruct

// integer k used to point to a table in gamecache, this is the reason I am not using dostruct directly
// the evil backwards compatibility... You shall find out why OOP guys like encapsullation so much...
//
// It's fun, it was first an integer pointing to a mission in gamecache, then it was a dynamic array
// and now it is a struct... so much history.
function SetDamageOptions_i takes integer k, integer DamageOptions returns nothing
local integer d=DamageOptions
set dostruct(k).value=d
if (d>=8192) then
set d=d-8192
endif
if (d>=4096) then
set d=d-4096
endif

if d>=2048 then
set dostruct(k).ally_fc=cs_dopt_Ally_fc
set d=d-2048
endif
if d>=1024 then
set dostruct(k).ign = cs_dopt_IgnoreUtype
set d=d-1024
endif
if d>=512 then
set dostruct(k).dfab3=cs_dopt_dfab3
set dostruct(k).dfab3_fc=cs_dopt_dfab3_fc
set d=d-512
endif
if d>=256 then
set dostruct(k).dfab2=cs_dopt_dfab2
set dostruct(k).dfab2_fc=cs_dopt_dfab2_fc
set d=d-256
endif
if d>=128 then
set dostruct(k).dfab1=cs_dopt_dfab1
set dostruct(k).dfab1_fc=cs_dopt_dfab1_fc
set d=d-128
endif
//[0 integer value][1 integer attT][2 integer dmgT][3 integer excp][4 real excf][5 integer only]
//[6 integer allied][7 integer ab1][8 real fc1][9 integer ab2][10 real fc2][11 integer ab3][12 real fc3]
//[13 integer ign][14 real allf]

if d >= 64 then
set d=d-64
set dostruct(k).allied=cs_dopt_EnemyAlly //[6=allied]
endif
if d >= 32 then
set d=d-32
endif
if d >= 16 then
set d=d-16
endif
if d >= 8 then
set d=d-8
endif
if d >= 4 then
set dostruct(k).only=cs_dopt_OnlyUtype
set d=d-4
endif
if d >= 2 then
set dostruct(k).excp= cs_dopt_ExceptionUtype
set dostruct(k).excf= cs_dopt_ExceptionFct
set d=d-2
endif
if d >= 1 then
set dostruct(k).attt=cs_dopt_Atype
set dostruct(k).dmgt=cs_dopt_Dtype
endif
endfunction


// inline friendly:)
function SetDamageOptions takes integer id, integer DamageOptions returns nothing
call SetDamageOptions_i(id,DamageOptions)
endfunction

function CreateDamageOptions takes integer DamageOptions returns integer
local integer n =integer(dostruct.create())

call SetDamageOptions_i(n,DamageOptions)

return n
endfunction

function DestroyDamageOptions takes integer id returns nothing
call dostruct(id).destroy()
endfunction

function LoadDamageOptions takes integer id returns integer
local integer opt=dostruct(id).value
local integer v=opt

if v>=8192 then
set v=v-8192
endif
if v>=4096 then
set v=v-4096
endif
if v>=2048 then
set cs_dopt_Ally_fc = dostruct(id).ally_fc
set v=v-2028
endif
if v>=1024 then
set cs_dopt_IgnoreUtype = dostruct(id).ign
set v=v-1024
endif
if v>=512 then
set cs_dopt_dfab3 =dostruct(id).dfab3
set cs_dopt_dfab3_fc=dostruct(id).dfab3_fc
set v=v-512
endif
if v>=256 then
set cs_dopt_dfab2 =dostruct(id).dfab2
set cs_dopt_dfab2_fc=dostruct(id).dfab2_fc
set v=v-256
endif
if v>=128 then
set cs_dopt_dfab1 =dostruct(id).dfab1
set cs_dopt_dfab1_fc=dostruct(id).dfab1_fc
set v=v-128
endif
if v >= 64 then
set v=v-64
set cs_dopt_EnemyAlly= dostruct(id).allied
endif
if v >= 32 then
set v=v-32
endif
if v >= 16 then
set v=v-16
endif
if v >= 8 then
set v=v-8
endif
if v >= 4 then
set cs_dopt_OnlyUtype = dostruct(id).only
set v=v-4
endif
if v >= 2 then
set cs_dopt_ExceptionUtype= dostruct(id).excp
set cs_dopt_ExceptionFct= dostruct(id).excf
set v=v-2
endif
if v >= 1 then
set cs_dopt_Atype= dostruct(id).attt
set cs_dopt_Dtype= dostruct(id).dmgt
endif

return opt
endfunction

//==================================================================================================
function IsDestructableTree_withcs takes destructable d returns boolean

local boolean b
local boolean i=IsDestructableInvulnerable(d)

call SetUnitX(cs_dmg_caster,GetWidgetX(d))
call SetUnitY(cs_dmg_caster,GetWidgetY(d))

if i then
call SetDestructableInvulnerable(d,false)
endif
call UnitAddAbility(cs_dmg_caster,cs_DamageTreeDetectorId)

set b=(IssueTargetOrder(cs_dmg_caster,"eattree",d))
call UnitRemoveAbility(cs_dmg_caster,cs_DamageTreeDetectorId)

if i then
call SetDestructableInvulnerable(d,true)
endif
return b
endfunction

function IsDestructableTree takes destructable d returns boolean
local string k=I2S(GetDestructableTypeId(d))
local boolean b

if HaveStoredBoolean(cs_cache,"trees",k) then
set b=GetStoredBoolean(cs_cache,"trees",k)
return b
else
set b=IsDestructableTree_withcs(d)
call StoreBoolean(cs_cache,"trees",k,b)
endif
return b
endfunction

//===============================================================================================
function DamageDestructablesInCircleEnum takes nothing returns nothing
local destructable d=GetEnumDestructable()
local unit u=udg_currentcaster
if (GetWidgetLife(d)>0) and not(IsDestructableInvulnerable(d)) and ((Pow(GetDestructableX(d)-udg_castervars[200],2)+Pow(GetDestructableY(d)-udg_castervars[201],2)) <= udg_castervars[202]) then
call SetWidgetLife(d,GetWidgetLife(d)-udg_castervars[203])
endif
set udg_currentcaster=u
set u=null
set d=null
endfunction

function DamageDestructablesInCircle takes real x, real y, real radius, real dmg returns nothing
local rect r=Rect(x - radius,y - radius,x + radius,y + radius)
set udg_castervars[200]=x
set udg_castervars[201]=y
set udg_castervars[202]=radius*radius
set udg_castervars[203]=dmg
call EnumDestructablesInRect(r,null,function DamageDestructablesInCircleEnum)
call RemoveRect(r)
set r=null
endfunction

function DamageDestructablesInCircleLoc takes location loc, real radius, real dmg returns nothing
call DamageDestructablesInCircle(GetLocationX(loc),GetLocationY(loc),radius,dmg)
endfunction

function DamageTreesInCircleEnum takes nothing returns nothing
local destructable d=GetEnumDestructable()
if (GetWidgetLife(d)>0) and not(IsDestructableInvulnerable(d)) and ((Pow(GetDestructableX(d)-udg_castervars[200],2)+Pow(GetDestructableY(d)-udg_castervars[201],2)) <= udg_castervars[202]) and (IsDestructableTree(d)) then
call KillDestructable(d)
endif
set d=null
endfunction

function DamageTreesInCircle takes real x, real y, real radius returns nothing
local rect r=Rect(x - radius,y - radius,x + radius,y + radius)
set udg_castervars[200]=x
set udg_castervars[201]=y
set udg_castervars[202]=radius*radius
call EnumDestructablesInRect(r,null,function DamageTreesInCircleEnum)
call RemoveRect(r)
set r=null
endfunction

function DamageTreesInCircleLoc takes location loc, real radius returns nothing
call DamageTreesInCircle(GetLocationX(loc),GetLocationY(loc),radius)
endfunction

function DamageUnitGroupEx takes unit hurter, real damage, group targetgroup, integer DamageOptions returns nothing
local group affected
local unit p
if bj_wantDestroyGroup then
set bj_wantDestroyGroup=false
set affected=targetgroup
else
set affected=NewGroup()
call GroupAddGroup( targetgroup, affected)
endif
loop
set p=FirstOfGroup(affected)
exitwhen p==null
call DamageUnitByOptions(hurter,p,damage,DamageOptions)
call GroupRemoveUnit(affected,p)
endloop
call ReleaseGroup(affected)
set affected=null
set p=null
endfunction

function DamageUnitsInAOEEx takes unit hurter, real damage, real x, real y, real radius, boolean affectallied, integer DamageOptions returns nothing
local boolexpr b=null
local group aoe=NewGroup()
local integer d=DamageOptions
set bj_groupEnumOwningPlayer=GetOwningPlayer(hurter)
if d>=8192 then
set d=d-8192
endif
if d>=4096 then
set d=d-4096
endif

if d>=2048 then
set d=d-2048
endif
if d>=1024 then
set d=d-1024
endif
if d>=512 then
set d=d-512
endif
if d>=256 then
set d=d-256
endif
if d>=128 then
set d=d-128
endif
if d>=64 then
if (cs_dopt_EnemyAlly==2) then
set b=Condition(function CasterAOE_IsFilterAlly)
elseif (cs_dopt_EnemyAlly==1) then
else
set b=Condition(function CasterAOE_IsFilterEnemy)
endif
set d=d-64
elseif not(affectallied) then
set b=Condition(function CasterAOE_IsFilterEnemy)
endif
if d>=32 then
set d=d-32
endif
if d>=16 then
call DamageTreesInCircle(x,y,radius)
endif
call CS_EnumUnitsInAOE(aoe, x,y, radius, b)
set bj_wantDestroyGroup=true
call DamageUnitGroupEx( hurter, damage, aoe,DamageOptions)
//call DestroyBoolExpr(b)
set b=null
set aoe=null
endfunction

function DamageUnitsInAOEExLoc takes unit hurter, real damage, location loc, real radius, boolean affectallied, integer DamageOptions returns nothing
call DamageUnitsInAOEEx(hurter,damage, GetLocationX(loc), GetLocationY(loc), radius, affectallied,DamageOptions)
endfunction

function DamageUnitGroup takes player hurter, real damage, group targetgroup returns nothing
call SetUnitOwner(cs_dmg_caster,hurter,false)
call DamageUnitGroupEx(cs_dmg_caster,damage,targetgroup,0)
call SetUnitOwner(cs_dmg_caster,Player(15),false)
endfunction

//====================================================================================================================================================================
function DamageUnitsInAOE takes player hurter, real damage, real x, real y, real radius, boolean affectallied returns nothing
call SetUnitOwner(cs_dmg_caster,hurter,false)
call DamageUnitsInAOEEx(cs_dmg_caster,damage,x,y,radius,affectallied,0)
call SetUnitOwner(cs_dmg_caster,Player(15),false)
endfunction

function DamageUnitsInAOELoc takes player hurter, real damage, location loc, real radius, boolean affectallied returns nothing
call DamageUnitsInAOE( hurter, damage, GetLocationX(loc), GetLocationY(loc), radius, affectallied)
endfunction

//====================================================================================================================================================================
function AddAreaDamagerForUnit_Child takes nothing returns nothing
local real D
local real damageps = udg_castervars[0]
local real area = udg_castervars[2]
local real damageperiod = udg_castervars[3]
local real excd=udg_castervars[8]
local boolean affectallies = (udg_castervars[4]>=1)
local boolean onlyallies = (udg_castervars[4]==2)
local boolean self = (udg_castervars[5]==1)
local unit hurter=udg_currenthurter
local unit fire = udg_currentcaster
local player owner = GetOwningPlayer(fire)
local timer t = NewTimer()
local real next = 0
local integer a = 0
local group inrange = NewGroup()
local string c
local string art=bj_lastPlayedMusic
local string attach=""
local unit picked
local boolean recicled=false
local unittype only=null
local unittype ign=null
local unittype exce=null
local attacktype attT
local damagetype dmgT
local boolean trees=(udg_castervars[11]==1)
local boolean inv=(udg_castervars[12]==1)
local integer a1=0
local integer a2=0
local integer a3=0
local real f1=cs_dopt_dfab1_fc
local real f2=cs_dopt_dfab2_fc
local real f3=cs_dopt_dfab3_fc
local real allf=udg_castervars[113]
local effect array fx
local integer deadcond=R2I(udg_castervars[114])
local boolean deadeval=false
local integer fxn=0
set fx[0]=bj_lastCreatedEffect

if f1!=1 then
set a1=cs_dopt_dfab1
endif
if f2!=1 then
set a2=cs_dopt_dfab2
endif
if f3!=1 then
set a3=cs_dopt_dfab3
endif
if udg_castervars[112]!=-1 then
set ign=ConvertUnitType(R2I(udg_castervars[112]))
endif
if udg_castervars[6]!=-1 then
set only=ConvertUnitType(R2I(udg_castervars[6]))
endif
if udg_castervars[7]!=-1 then
set exce=ConvertUnitType(R2I(udg_castervars[7]))
endif
if udg_castervars[9]!=-1 then
set attT=ConvertAttackType(R2I(udg_castervars[9]))
else
set attT=cs_DefaultAttackType
endif
if udg_castervars[10]!=-1 then
set dmgT=ConvertDamageType(R2I(udg_castervars[10]))
else
set dmgT=cs_DefaultDamageType
endif
loop
set c=SubString(art,a,a+1)
exitwhen c=="!" or c==""
set attach=attach+c
set a=a+1
endloop
set art=SubString(art,a+1,10000)
call TimerStart(t, udg_castervars[1]-0.01, false,null)
set a=0
loop
loop
exitwhen fxn<=0
call DestroyEffect(fx[fxn])
set fx[fxn]=null
set fxn=fxn-1
endloop
if IsUnitInGroup( fire, udg_casters) then
set recicled=true
call GroupRemoveUnit( udg_casters,fire)
endif
exitwhen recicled
if TimerGetElapsed(t) >= next then
set a=a+1
set next=a*damageperiod
call CS_EnumUnitsInAOE(inrange, GetUnitX(fire), GetUnitY(fire), area, null )
if trees then
call DamageTreesInCircle(GetUnitX(fire), GetUnitY(fire), area)
endif
loop
set picked=FirstOfGroup(inrange)
exitwhen picked==null
if (deadcond==0) then
set deadeval=(GetWidgetLife(picked)>0.405)
elseif(deadcond==1)then
set deadeval=(GetWidgetLife(picked)<=0.405)
else
set deadeval=true
endif
if (self or picked!=hurter) and not(GetWidgetLife(picked)<=0.405) and ( ((affectallies or onlyallies) and IsUnitAlly(picked, owner)) or (not(onlyallies) and IsUnitEnemy(picked, owner)) ) and (only==null or CS_IsUnitType(picked,only)) and (ign==null or not(CS_IsUnitType(picked,ign))) then
set D=damageps
if (allf!=1) and IsUnitAlly(picked, owner) then
set D=D*allf
endif
if (exce!=null) and CS_IsUnitType(picked,exce) then
set D=D*excd
endif
if inv and not(IsUnitVisible(picked,owner)) then
set D=0
endif
if (a1!=0) and (GetUnitAbilityLevel(picked,a1)>0) then
set D=D*f1
endif
if (a2!=0) and (GetUnitAbilityLevel(picked,a2)>0) then
set D=D*f2
endif
if (a3!=0) and (GetUnitAbilityLevel(picked,a3)>0) then
set D=D*f3
endif
if D!=0 then
call DamageUnitByTypes(hurter,picked,D,attT,dmgT )
if (art!="") and (art!=null) then
set fxn=fxn+1
set fx[fxn]=AddSpecialEffectTarget(art,picked,attach)
endif
endif
endif
call GroupRemoveUnit(inrange,picked)
endloop
endif
exitwhen TimerGetRemaining(t)<=0
call TriggerSleepAction(0)
endloop
call ReleaseGroup(inrange)
call DestroyEffect(fx[0])
call TriggerSleepAction(2)
call RecicleCaster(fire)
call ReleaseTimer(t)
set inrange=null
set fire=null
set owner=null
set fx[0]=null
set picked=null
set hurter=null
set only=null
set ign=null
set exce=null
set attT=null
set dmgT=null
endfunction

function AddAreaDamagerForUnit takes unit hurter, string modelpath, string targetart, string targetattach, real x, real y, real damage , real damageperiod, real duration, real area, boolean affectallies, integer DamageOptions returns unit
local string s=bj_lastPlayedMusic
local integer v=DamageOptions
set bj_lastPlayedMusic=targetattach+"!"+targetart
set udg_currentcaster=GetACaster()
call SetUnitPosition( udg_currentcaster, x, y)
set bj_lastCreatedEffect = AddSpecialEffectTarget( modelpath, udg_currentcaster,"origin" )
set udg_castervars[0]=damage
set udg_castervars[1]=duration
set udg_castervars[2]=area
set udg_castervars[3]=damageperiod

if(v>=8192)then
set udg_castervars[114]=2
set v=v-8192
elseif (v>=4096)then
set udg_castervars[114]=1
set v=v-4096
else
set udg_castervars[114]=0
endif

if v>=2048 then
set v=v-2048
else
set udg_castervars[113]=1
endif
if v >= 1024 then
set v=v-1024
else
set udg_castervars[112]=-1
endif
if v >= 512 then
set v=v-512
else
set udg_castervars[111]=0
endif
if v >= 256 then
set v=v-256
else
set udg_castervars[109]=0
endif
if v >= 128 then
set v=v-128
else
set udg_castervars[107]=0
endif
if v >= 64 then
set v=v-64
set udg_castervars[4]=cs_dopt_EnemyAlly
else
set udg_castervars[4]=IntegerTertiaryOp(affectallies,1,0)
endif
if v >= 32 then
set udg_castervars[12]=1
set v=v-32
else
set udg_castervars[12]=0
endif
if v >= 16 then
set udg_castervars[11]=1
set v=v-16
else
set udg_castervars[11]=0
endif
if v >= 8 then
set udg_castervars[5]=0
set v=v-8
else
set udg_castervars[5]=1
endif
if v >= 4 then
set udg_castervars[6]=CS_H2I(cs_dopt_OnlyUtype)
set v=v-4
else
set udg_castervars[6]=-1
endif
if v >= 2 then
set udg_castervars[7]=CS_H2I(cs_dopt_ExceptionUtype)
set udg_castervars[8]=damage*cs_dopt_ExceptionFct
set v=v-2
else
set udg_castervars[7]=-1
set udg_castervars[8]=-1
endif
if v >= 1 then
set udg_castervars[9]= CS_H2I(cs_dopt_Atype)
set udg_castervars[10]= CS_H2I(cs_dopt_Dtype)
else
set udg_castervars[9]=-1
set udg_castervars[10]=-1
endif
set udg_currenthurter=hurter
call SetUnitOwner( udg_currentcaster, GetOwningPlayer(hurter), true)
call ExecuteFunc("AddAreaDamagerForUnit_Child")
set bj_lastPlayedMusic=s
return udg_currentcaster
endfunction

function AddAreaDamagerForUnitLoc takes unit hurter, string modelpath, string targetart, string targetattach, location loc, real damage , real damageperiod, real duration, real area, boolean affectallies, integer DamageOptions returns unit
return AddAreaDamagerForUnit(hurter,modelpath,targetart,targetattach,GetLocationX(loc),GetLocationY(loc), damage , damageperiod, duration, area,affectallies, DamageOptions)
endfunction

function AddDamagingEffectEx takes player owner, string modelpath, string targetart, string targetattach, real x, real y, real damage , real damageperiod, real duration, real area, boolean affectallies returns unit
local string s=bj_lastPlayedMusic
set bj_lastPlayedMusic=targetattach+"!"+targetart
set udg_currentcaster=GetACaster()
call SetUnitPosition( udg_currentcaster, x, y)
set bj_lastCreatedEffect = AddSpecialEffectTarget( modelpath, udg_currentcaster,"origin" )
set udg_castervars[0]=damage
set udg_castervars[1]=duration
set udg_castervars[2]=area
set udg_castervars[3]=damageperiod
set udg_castervars[4]=IntegerTertiaryOp(affectallies,1,0)
set udg_castervars[5]=1
set udg_castervars[6]=-1
set udg_castervars[7]=-1
set udg_castervars[8]=-1
set udg_castervars[9]=-1
set udg_castervars[10]=-1
set udg_castervars[107]=0
set udg_castervars[109]=0
set udg_castervars[111]=0
set udg_castervars[112]=-1
set udg_castervars[113]=1
set udg_currenthurter=udg_currentcaster
call SetUnitOwner( udg_currentcaster, owner, true)
call ExecuteFunc("AddAreaDamagerForUnit_Child")
set bj_lastPlayedMusic=s
return udg_currentcaster
endfunction

function AddDamagingEffectExLoc takes player owner, string modelpath, string targetart, string targetattach, location loc, real damage , real damageperiod, real duration, real area, boolean affectallies returns unit
return AddDamagingEffectEx( owner, modelpath, targetart, targetattach, GetLocationX(loc), GetLocationY(loc), damage , damageperiod, duration, area, affectallies )
endfunction

function AddDamagingEffect takes player owner, string modelpath, real x, real y, real damageps , real duration, real area, boolean affectallies returns unit
return AddDamagingEffectEx( owner, modelpath, "", "", x, y, damageps , 1, duration, area, affectallies )
endfunction

function AddDamagingEffectLoc takes player owner, string modelpath, location loc, real damageps , real duration, real area, boolean affectallies returns unit
return AddDamagingEffectEx( owner, modelpath, "", "", GetLocationX(loc), GetLocationY(loc), damageps ,1, duration, area, affectallies)
endfunction

//============================================================================================================
function UnitMoveToAsProjectileAnySpeed_Move takes unit m, csprojectile k returns boolean
local boolean tounit = k.tounit
local unit tg
local real x2
local real y2
local real z2
local real x1=GetUnitX(m)
local real y1=GetUnitY(m)
local real z1=GetUnitFlyHeight(m)
local real g
local real d
local real od
local real v
local real time
local integer n
local boolean done=false
local effect fx

if tounit then
set tg=k.target
if (GetWidgetLife(tg)<=0.405) then
set tounit=false
set k.tounit=false
else
set x2=GetUnitX(tg)
set y2=GetUnitY(tg)
set z2=GetUnitFlyHeight(tg)+k.z2o
set n=k.N
if (n==0) then
//Using the counter prevents us to save z2,x2,y2 too much times and saves speed
set k.z2=z2
set k.x2=x2 // Backup stuff just in case
set k.y2=y2
elseif (n==25) then
set n=0
else
set n=n+1
endif
set k.N=n
endif
set tg=null
endif

if not(tounit) then
set z2=k.z2
set x2=k.x2
set y2=k.y2
endif

set g=Atan2(y2-y1,x2-x1)
call SetUnitFacing(m,g*bj_RADTODEG)


set v=k.speed
set d= v * cs_TIMER_CYCLE

set od=SquareRoot(Pow(x1-x2,2) + Pow(y1-y2,2))
if( od <=d )then
call SetUnitX(m,x2)
call SetUnitY(m,y2)
set done=true
else
call SetUnitX(m,x1+d*Cos(g))
call SetUnitY(m,y1+d*Sin(g))
endif



set g=k.acel
set time= od / v
set d=v
set v=(z2-z1+0.5*g*time*time)/time //z speed
if (GetUnitTypeId(m)==cs_CasterUnitId) then
call SetUnitAnimationByIndex(m,R2I(Atan2(v,d)* bj_RADTODEG)+90) //Thanks infrane!
endif
call SetUnitFlyHeight(m,z1+v*cs_TIMER_CYCLE,0)
set d=( Pow(GetUnitX(m)-x2,2) + Pow(GetUnitY(m)-y2,2) )
if (done or (d<=400)) then //So the actual distance is less than or equal to 20
set done=true
set k.done=true
set fx=k.fx
if (fx!=null) then
call SetUnitAnimationByIndex(m,91)
call DestroyEffect(fx)
set fx=null
endif
endif
return done
endfunction

interface csmissile
integer mtype=0
unit m //the missile
endinterface
globals
constant integer cs_TYPE_COLLISIONMISSILE=2
constant integer cs_TYPE_PROJECTILE=1
endglobals


struct cscollisionmissile extends csmissile
integer state //state of the collision missile
trigger t
triggeraction ac
real collision
real speed
real aspeed //angle speed
real f //facing of collisionmissile

real maxd

integer ttype=0 //target type
static constant integer ttype_widget=2
static constant integer ttype_point=1
static constant integer ttype_none=0

real tx //homing target x
real ty //homing target y
widget tw //homing target widget

boolean pfx=false //periodic fx mode
real pfx_current //current pfx (timer)
real pfx_dur //duration of a periodic effect
string pfx_path //path for the periodix fx

boolean new //Was it a new collision missile or must be recycled?
effect fx

integer tag=0 //custom tag for the user.
endstruct

function CollisionMissile_Destroyer takes unit m, cscollisionmissile k, trigger T returns nothing
local trigger tr = T
local triggeraction ta = k.ac

if (k.fx!=null) then
call DestroyEffect(k.fx)
endif


if (k.new) then
call ExplodeUnitBJ(m)
else
call RecicleCasterAfterCastEx(m,4,0,true)
endif

call TriggerRemoveAction(tr,ta)
//call TriggerRemoveAction(T,GetArrayTriggerAction(k,18)) //[18=triggeraction]

call k.destroy()

//call Hostage(CS_H2I(tr))

call DestroyTrigger(tr)
//call CleanAttachedVars(T)
//call DestroyTrigger(T)

set tr = null
set ta = null

endfunction



function GetTriggerCollisionMissile takes nothing returns unit
return s__csmissile_m[GetCSData(GetTriggeringTrigger()) ]
endfunction



function CollisionMissile_Move takes unit m, cscollisionmissile k returns boolean
local integer state= k.state
local boolean done
local real d
local real F
local real asp
local real x
local real nx
local real y
local real ny
local integer tt
local widget wd

local trigger TTT


if (state==2) then
set TTT=k.t
call TriggerExecute(TTT)
set TTT=null
set k.state=3
return false
elseif (state==3) then
call CollisionMissile_Destroyer(m,k,k.t)
return true
else
if (state==1) then
call TriggerRegisterUnitInRange(k.t,m,k.collision,null)
set k.state=0
endif
set d=k.speed * cs_TIMER_CYCLE
set F=k.f
set asp=k.aspeed
set x=GetUnitX(m)
set y=GetUnitY(m)
if (asp!=0) then
set tt=k.ttype
if (tt==cscollisionmissile.ttype_point) or (tt==cscollisionmissile.ttype_widget ) then
if (tt==cscollisionmissile.ttype_point) then
set nx=k.tx
set ny=k.ty
set F=Angles_MoveAngleTowardsAngle(F,Atan2(ny-y,nx-x)*bj_RADTODEG, asp * cs_TIMER_CYCLE)
else
set wd=k.tw
if (GetWidgetLife(wd)<=0.405) then
set k.ttype=cscollisionmissile.ttype_none
set nx=x+0.001
set ny=y+0.001
set F=F+ asp * cs_TIMER_CYCLE
else
set nx=GetWidgetX(wd)
set ny=GetWidgetY(wd)
set F=Angles_MoveAngleTowardsAngle(F,Atan2(ny-y,nx-x)*bj_RADTODEG, asp * cs_TIMER_CYCLE)
endif
set wd=null
endif
else
set F=F+ asp * cs_TIMER_CYCLE
endif
set k.f=F
call SetUnitFacing(m,F)
endif
set F=F*bj_DEGTORAD
set nx=x+d*Cos(F)
set ny=y+d*Sin(F)
set d=k.maxd-d
set k.maxd=d
set done=(d<=0)
if (not done) then
if not(CS_MoveUnit(m,nx,ny)) then
set done=true
elseif (k.pfx) then
set F= k.pfx_current+cs_TIMER_CYCLE
if (F>=k.pfx_dur) then
call DestroyEffect(AddSpecialEffectTarget(k.pfx_path, m, "origin" ))
set k.pfx_current=0.
else
set k.pfx_current=F
endif
endif
endif
endif
if done then
call DisableTrigger(k.t)
call DestroyEffect(k.fx)
set k.fx=null
set k.state=2
return false
endif
return false
endfunction

function CasterSystemMovementTimer takes nothing returns nothing
local timer ti
local integer n=cs_missilecount
local integer i=1
local unit p

local csmissile k


loop
exitwhen (i>n)
set k=cs_missiles

if (k.mtype==cs_TYPE_COLLISIONMISSILE) then

set p=k.m

if not(CollisionMissile_Move(p,k)) then
set i=i+1
else
set cs_missiles=cs_missiles[n]
set n=n-1
endif
elseif (k.mtype==cs_TYPE_PROJECTILE) then
set p=k.m
if not(UnitMoveToAsProjectileAnySpeed_Move(p,k )) then
set i=i+1
else
set cs_missiles=cs_missiles[n]
set n=n-1
endif
else
set i=i+1
call BJDebugMsg("Caster System: Unexpected Error (1) Wrong Array:"+I2S(k)+" ; "+I2S(k.mtype))
endif

endloop

if (n==0) then
call PauseTimer(cs_movementtimer)
set cs_movementtimer_active=false
endif
set cs_missilecount=n

set p=null
endfunction

struct csprojectile extends csmissile
boolean tounit //Is it directed towards a unit?
unit target //if so, what target?
real z2
real x2
real y2

real speed
real acel

boolean done=false
effect fx

real z2o // offset for z2, useful for flyers
integer N=0
endstruct


function UnitMoveToAsProjectileAnySpeed_Effect takes unit m, effect fx, real speed, real arc, real x2, real y2, unit target, real z2 returns nothing
//
// The internal projectile system used by all the projectile functions
//
local timer t //=GetTableTimer("CasterSystem","MOVEMENT_TIMER")


local string km
local csprojectile k

set km=I2S(CS_H2I(m))
set k=GetTableInt("MOVEMENT_TABLES",km)
if (k>0) then
set k.done=true
endif
set k=csprojectile.create()
set k.m=m

call StoreInteger(cs_cache,"MOVEMENT_TABLES",km,k)


set cs_missilecount=cs_missilecount+1
set cs_missiles[cs_missilecount]=k

if (not cs_movementtimer_active) then
call TimerStart(cs_movementtimer,cs_TIMER_CYCLE,true,function CasterSystemMovementTimer)
set cs_movementtimer_active=true
endif

set k.mtype=cs_TYPE_PROJECTILE

if (target!=null) then
set k.tounit=true
set k.target=target
set k.x2=GetUnitX(target)
set k.y2=GetUnitY(target)
set k.z2o=z2
else
set k.tounit=false
set k.x2=x2
set k.y2=y2
endif

set k.z2=z2
set k.speed=speed

set k.acel=arc*8000
if (fx!=null) then
set k.fx=fx
set fx=null
endif
loop
exitwhen k.done
call TriggerSleepAction(0)
endloop
call FlushStoredInteger(cs_cache,"MOVEMENT_TABLES",km)
call k.destroy()

endfunction

function UnitMoveToAsProjectileAnySpeed takes unit m, real speed, real arc, real x2, real y2, unit target, real z2 returns nothing
//Left for compat
call UnitMoveToAsProjectileAnySpeed_Effect(m,null,speed,arc,x2,y2,target,z2)
endfunction


//========================================================================================================================
function UnitMoveToAsProjectileGen takes unit m, real arc, real x2, real y2, unit target, real z2 returns nothing
//
// The internal projectile system used by all the projectile functions
//
local real x1=GetUnitX(m)
local real y1=GetUnitY(m)
local real acel=arc*1600
local real speed=GetUnitMoveSpeed(m)
local real z1=GetUnitFlyHeight(m)
local real d
local real d1
local real d2
local real t
local real vel
local real dif=0
local boolean tounit= (target!=null)
local boolean b=false
local boolean mode=false
if tounit then
set x2=GetUnitX(target)
set y2=GetUnitY(target)
set z2=GetUnitFlyHeight(target)+z2
endif
set mode=(z2>z1)
set d=SquareRoot(Pow(x2-x1,2)+Pow(y2-y1,2))
set d1=1000000
set d2=0
set t=d/speed
if t==0 then
set t=0.001
endif
set vel=(z2-z1+0.5*acel*t*t)/t
call SetUnitFacing( m, Atan2BJ(y2 - y1, x2 - x2) )
call IssuePointOrder( m, "move", x2,y2)
set t=0
loop
set d2=d1
if tounit then
if (GetWidgetLife(target)<=0.405) then
set tounit=false
else
set x2=GetUnitX(target)
set y2=GetUnitY(target)
endif
endif
set d1=SquareRoot(Pow(x2-GetUnitX(m),2)+Pow(y2-GetUnitY(m),2))
exitwhen b or d1==0
set b=(d1<=speed*(t-dif))
exitwhen (mode and b) or (GetUnitCurrentOrder(m) != OrderId("move"))
if tounit then
call IssuePointOrder( m, "move", x2,y2)
endif
set dif=t
if dif==0.001 then
set t=0.1
else
set t= (d-d1)/speed
endif
set t= 2*t-dif
call SetUnitFlyHeight( m, z1+(vel*t-0.5*acel*t*t), RAbsBJ( vel-acel*(t+dif)/2) )
set t=(t+dif)/2
call TriggerSleepAction(0)
endloop
if tounit then
set x2=GetUnitX(target)
set y2=GetUnitY(target)
endif
call SetUnitFlyHeight( m,z2,0)
call SetUnitX(m,x2)
call SetUnitY(m,y2)
endfunction

function UnitMoveToAsProjectile takes unit m, real arc, real x2, real y2, real z2 returns nothing
call UnitMoveToAsProjectileGen(m, arc,x2,y2,null,z2)
endfunction

//============================================================================================================
function ProjectileLaunchEx takes player owner, string modelpath, real scale, integer red, integer green, integer blue, integer alpha, real speed, real arc,real x1, real y1, real z1, real x2, real y2, real z2 returns nothing
local unit m=CreateCaster( Atan2BJ(y2 - y1, x2 - x1),x1,y1 )
local effect fx=null

call SetUnitScale( m, scale, scale, scale)
call SetUnitVertexColor(m, red, green, blue, alpha)

call SetUnitFlyHeight( m, z1, 0)
set fx= AddSpecialEffectTarget( modelpath, m,"origin" )
call SetUnitOwner( m, owner, true)

if (speed<=522) then
call SetUnitMoveSpeed(m, speed)
call UnitMoveToAsProjectile(m, arc, x2, y2, z2)
call DestroyEffect(fx)
else
call UnitMoveToAsProjectileAnySpeed_Effect(m,fx,speed,arc,x2,y2,null,z2)
endif
call ExplodeUnitBJ(m)
set owner=null
set fx=null
set m=null
endfunction

function ProjectileLaunchExLoc takes player owner, string modelpath, real scale, integer red, integer green, integer blue, integer alpha, real speed, real arc, location loc1, real z1, location loc2, real z2 returns nothing
call ProjectileLaunchEx( owner, modelpath, scale, red, green, blue, alpha, speed, arc,GetLocationX(loc1), GetLocationY(loc1), z1, GetLocationX(loc2), GetLocationY(loc2), z2)
endfunction


[/code]
 
[jass=]

//============================================================================================================
function ProjectileLaunch takes string modelpath, real speed, real arc,real x1, real y1, real z1, real x2, real y2, real z2 returns nothing
call ProjectileLaunchEx( Player(15), modelpath, 1, 255, 255, 255, 255, speed, arc,x1,y1,z1,x2,y2,z2)
endfunction

function ProjectileLaunchLoc takes string modelpath, real speed, real arc, location loc1, real z1, location loc2, real z2 returns nothing
call ProjectileLaunchExLoc( Player(15), modelpath, 1,255,255,255,255,speed,arc,loc1,z1,loc2,z2)
endfunction

//============================================================================================================
function DamagingProjectileLaunchAOE_Child takes nothing returns nothing
local unit m=udg_currentcaster
local effect fx=bj_lastCreatedEffect
local real x2=udg_castervars[0]
local real y2=udg_castervars[1]
local real aoeradius=udg_castervars[3]
local real damage=udg_castervars[4]
local boolean affectallied=bj_isUnitGroupInRectResult
local integer V=CreateDamageOptions(R2I(udg_castervars[5]))
local unit hurter=udg_currenthurter
local real speed=udg_castervars[6]
if (speed<=522) then
call SetUnitMoveSpeed(m, speed)
call UnitMoveToAsProjectile(m, bj_meleeNearestMineDist, udg_castervars[0], udg_castervars[1], udg_castervars[2])
call DestroyEffect(fx)
else
call UnitMoveToAsProjectileAnySpeed_Effect(m,fx,speed,bj_meleeNearestMineDist, udg_castervars[0], udg_castervars[1],null, udg_castervars[2])
endif

call DamageUnitsInAOEEx(hurter,damage,x2,y2,aoeradius,affectallied,LoadDamageOptions(V))
call DestroyDamageOptions(V)
call ExplodeUnitBJ(m)
set m=null
set fx=null
endfunction

function DamagingProjectileLaunchAOE takes unit hurter, string modelpath, real speed, real arc, real x1, real y1, real z1, real x2, real y2, real z2, real aoeradius, real damage, boolean affectallied, integer DamageOptions returns unit
local unit m=CreateCaster( Atan2BJ(y2 - y1, x2 - x1) ,x1,y1)

call SetUnitFlyHeight( m, z1, 0)
set udg_currentcaster=m
set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, m,"origin" )
call SetUnitOwner( m, GetOwningPlayer(hurter), true)
set bj_meleeNearestMineDist = arc
set udg_castervars[0] = x2
set udg_castervars[1] = y2
set udg_castervars[2] = z2
set udg_castervars[3] =aoeradius
set udg_castervars[4] =damage
set udg_castervars[5] =DamageOptions
set udg_castervars[6] =speed
set udg_currenthurter=hurter
set bj_isUnitGroupInRectResult=affectallied
call ExecuteFunc("DamagingProjectileLaunchAOE_Child")
set m=null
return udg_currentcaster
endfunction

function DamagingProjectileLaunchAOELoc takes unit hurter, string modelpath, real speed, real arc, location loc1, real z1, location loc2, real z2, real aoeradius, real damage, boolean affectallied, integer DamageOptions returns unit
return DamagingProjectileLaunchAOE(hurter,modelpath,speed,arc,GetLocationX(loc1),GetLocationY(loc1),z1,GetLocationX(loc2),GetLocationY(loc2),z2, aoeradius, damage, affectallied, DamageOptions )
endfunction

function ProjectileLaunchDamage takes player owner, string modelpath, real speed, real arc, real x1, real y1, real z1, real x2, real y2, real z2, real aoeradius, real damage, boolean affectallied returns unit
local unit m=CreateCaster( Atan2BJ(y2 - y1, x2 - x1) ,x1,y1 )

call SetUnitFlyHeight( m, z1, 0)
set udg_currentcaster=m
set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, m,"origin" )
call SetUnitOwner( m, owner, true)
set bj_meleeNearestMineDist = arc
set udg_castervars[0] = x2
set udg_castervars[1] = y2
set udg_castervars[2] = z2
set udg_castervars[3] =aoeradius
set udg_castervars[4] =damage
set udg_castervars[5] =0
set udg_castervars[6]= speed

set bj_isUnitGroupInRectResult=affectallied
set udg_currenthurter=m
call ExecuteFunc("DamagingProjectileLaunchAOE_Child")
set m=null
return udg_currentcaster
endfunction

function ProjectileLaunchDamageLoc takes player owner, string modelpath, real speed, real arc, location loc1, real z1, location loc2, real z2, real aoeradius, real damage, boolean affectallied returns unit
return ProjectileLaunchDamage( owner, modelpath, speed, arc, GetLocationX(loc1), GetLocationY(loc1), z1, GetLocationX(loc2), GetLocationY(loc2), z2, aoeradius, damage, affectallied)
endfunction

//============================================================================================================
function ProjectileLaunchKill_Child takes nothing returns nothing
local unit m=udg_currentcaster
local effect fx=bj_lastCreatedEffect
local real x2=udg_castervars[0]
local real y2=udg_castervars[1]
local real speed=udg_castervars[3]

if (speed<=522) then
call SetUnitMoveSpeed( m, speed)
call UnitMoveToAsProjectile(m, bj_meleeNearestMineDist, udg_castervars[0], udg_castervars[1], udg_castervars[2])
call DestroyEffect( fx)
else
call UnitMoveToAsProjectileAnySpeed_Effect(m,fx,speed, bj_meleeNearestMineDist, udg_castervars[0], udg_castervars[1], null, udg_castervars[2])
endif

call ExplodeUnitBJ(m)

set m=null
set fx=null
endfunction

function ProjectileLaunchKill takes player owner, string modelpath, real speed, real arc, real x1, real y1, real z1, real x2, real y2, real z2 returns unit
local unit m=CreateCaster( Atan2BJ(y2 - y1, x2 - x1),x1,y1 )


call SetUnitFlyHeight( m, z1, 0)
set udg_currentcaster=m
set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, m,"origin" )
call SetUnitOwner( m, owner, true)
set bj_meleeNearestMineDist = arc
set udg_castervars[0] = x2
set udg_castervars[1] = y2
set udg_castervars[2] = z2
set udg_castervars[3] = speed
call ExecuteFunc("ProjectileLaunchKill_Child")
set m=null
return udg_currentcaster
endfunction

function ProjectileLaunchKillLoc takes player owner, string modelpath, real speed, real arc, location loc1, real z1, location loc2, real z2 returns unit
return ProjectileLaunchKill( owner, modelpath, speed, arc, GetLocationX(loc1), GetLocationY(loc1), z1, GetLocationX(loc2), GetLocationY(loc2), z2)
endfunction

//====================================================================================================================================================================
function UnitMoveToUnitAsProjectile takes unit m, real arc, unit target, real zoffset returns nothing
call UnitMoveToAsProjectileGen(m, arc,0,0,target,zoffset)
endfunction

//====================================================================================================================================================================
function ProjectileLaunchToUnitEx takes player owner, string modelpath, real scale, integer red, integer green, integer blue, integer alpha, real speed, real arc, real x1, real y1, real z1, unit target, real zoffset returns nothing
local unit m=CreateCaster( Atan2BJ(GetUnitY(target) - y1, GetUnitX(target) - x1),x1,y1 )
local effect fx=null

call SetUnitFlyHeight( m, z1, 0)
call SetUnitScale( m, scale, scale, scale)
call SetUnitVertexColor(m, red, green, blue, alpha)
set fx=AddSpecialEffectTarget( modelpath, m,"origin" )
call SetUnitOwner( m , owner, true)

if (speed<=522) then
call SetUnitMoveSpeed( m, speed)
call UnitMoveToUnitAsProjectile(m,arc,target, zoffset)
call DestroyEffect(fx)
else
call UnitMoveToAsProjectileAnySpeed_Effect(m,fx,speed, arc,0,0,target,zoffset)
endif

call ExplodeUnitBJ(m)
set m=null
set fx=null
endfunction

function ProjectileLaunchToUnitExLoc takes player owner, string modelpath, real scale, integer red, integer green, integer blue, integer alpha, real speed, real arc, location loc1, real z1, unit target, real zoffset returns nothing
call ProjectileLaunchToUnitEx( owner, modelpath, scale, red, green, blue, alpha, speed, arc, GetLocationX(loc1),GetLocationY(loc1), z1, target, zoffset)
endfunction

function ProjectileLaunchToUnit takes string modelpath, real speed, real arc,real x1, real y1, real z1, unit target, real zoffset returns nothing
call ProjectileLaunchToUnitEx( Player(15), modelpath, 1, 255,255,255,255,speed,arc,x1,y1,z1,target,zoffset)
endfunction

function ProjectileLaunchToUnitLoc takes string modelpath, real speed, real arc, location loc1, real z1, unit target, real zoffset returns nothing
call ProjectileLaunchToUnitExLoc( Player(15), modelpath, 1, 255,255,255,255, speed, arc, loc1, z1, target,zoffset)
endfunction

//====================================================================================================================================================================
function DamagingProjectileLaunchTarget_Child takes nothing returns nothing
local unit m=udg_currentcaster
local unit target=bj_meleeNearestMine
local effect fx=bj_lastCreatedEffect
local real damage=udg_castervars[4]
local damagetype dmgT=ConvertDamageType(R2I(udg_castervars[6]))
local attacktype attT=ConvertAttackType(R2I(udg_castervars[5]))
local unit hurter=udg_currenthurter
local real speed=udg_castervars[7]
if (speed<=522) then
call SetUnitMoveSpeed( m, speed)
call UnitMoveToUnitAsProjectile(m, bj_meleeNearestMineDist, target, udg_castervars[2])
call DestroyEffect( fx)
else
call UnitMoveToAsProjectileAnySpeed_Effect(m,fx,speed, bj_meleeNearestMineDist,0,0,target,udg_castervars[2])
endif

call DamageUnitByTypes(hurter,target,damage,attT,dmgT)
call ExplodeUnitBJ(m)
set m=null
set hurter=null
set target=null
set fx=null
set dmgT=null
set attT=null
endfunction

function DamagingProjectileLaunchTarget takes unit hurter, string modelpath, real speed, real arc, real x1, real y1, real z1, unit target, real zoffset, real damage, attacktype attT, damagetype dmgT returns unit
local unit m=CreateCaster( Atan2BJ(GetUnitY(target) - y1, GetUnitX(target) - x1),x1,y1 )

set udg_castervars[7]=speed
call SetUnitFlyHeight( m, z1, 0)
set udg_currentcaster=m
set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, m,"origin" )
call SetUnitOwner( m, GetOwningPlayer(hurter), true)
set bj_meleeNearestMineDist = arc
set udg_castervars[2]= zoffset
set bj_meleeNearestMine=target
set udg_castervars[4]=damage
set udg_castervars[5]=CS_H2I(attT)
set udg_castervars[6]=CS_H2I(dmgT)
set udg_currenthurter=hurter
call ExecuteFunc("DamagingProjectileLaunchTarget_Child")
set m=null
return udg_currentcaster
endfunction

function DamagingProjectileLaunchTargetLoc takes unit hurter, string modelpath, real speed, real arc, location loc, real z1, unit target, real zoffset, real damage, attacktype attT, damagetype dmgT returns unit
return DamagingProjectileLaunchTarget(hurter,modelpath,speed,arc,GetLocationX(loc),GetLocationY(loc), z1, target, zoffset, damage, attT, dmgT)
endfunction

function ProjectileLaunchToUnitDamage takes player owner, string modelpath, real speed, real arc, real x1, real y1, real z1, unit target, real zoffset, real damage returns unit
local unit m=CreateCaster( Atan2BJ(GetUnitY(target) - y1, GetUnitX(target) - x1),x1,y1 )

set udg_castervars[7]=speed
call SetUnitFlyHeight( m, z1, 0)
set udg_currentcaster=m
set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, m,"origin" )
call SetUnitOwner( m, owner, true)
set bj_meleeNearestMineDist = arc
set udg_castervars[2]= zoffset
set bj_meleeNearestMine=target
set udg_castervars[4]=damage
set udg_castervars[5]=CS_H2I(cs_DefaultAttackType)
set udg_castervars[6]=CS_H2I(cs_DefaultDamageType)
set udg_currenthurter=m
call ExecuteFunc("DamagingProjectileLaunchTarget_Child")
set m=null
return udg_currentcaster
endfunction

function ProjectileLaunchToUnitDamageLoc takes player owner, string modelpath, real speed, real arc, location loc1, real z1, unit target, real zoffset, real damage returns unit
return ProjectileLaunchToUnitDamage( owner, modelpath, speed, arc,GetLocationX(loc1),GetLocationY(loc1),z1,target,zoffset,damage)
endfunction



//==============================================================================================================================================================================
// Caster System Class: CollisionMissile
//
function CollisionMissile_Destroy takes unit m returns nothing
local cscollisionmissile k=GetUnitUserData(m)


if (k.fx!=null) then
call DestroyEffect(k.fx)
set k.fx=null
endif

//For convenience, always wait for next tic to destroy the thing. But destroy the effect so
//players don't ever notice it.
set k.state=2
call DisableTrigger(k.t)

endfunction

function CollisionMissile_Create takes string MissileModelPath, real x, real y, real dirangle, real speed, real AngleSpeed, real MaxDist, real height, boolean UseNewCaster, real Collision, code OnImpact returns unit
local timer t
local cscollisionmissile k
local trigger R

local unit m


set k=cscollisionmissile.create()

if UseNewCaster then
set m=CreateCaster(dirangle,x,y)
set k.new=true
else
set m=GetACaster()
call SetUnitFacing(m,dirangle)
call SetUnitPosition(m,CS_SafeX(x),CS_SafeY(y))
set k.new=false
endif
set cs_missilecount=cs_missilecount+1
set cs_missiles[cs_missilecount]=k

if (not cs_movementtimer_active) then
call TimerStart(cs_movementtimer,cs_TIMER_CYCLE,true,function CasterSystemMovementTimer)
set cs_movementtimer_active=true
endif

call SetUnitUserData(m,k)

set k.mtype=cs_TYPE_COLLISIONMISSILE

set k.speed=speed
set k.aspeed=AngleSpeed

set k.f=dirangle

set k.maxd=MaxDist

call SetUnitFlyHeight(m,height,0)



set R=CreateTrigger()

set k.collision=Collision

set k.state=1
set k.t=R
call SetCSData(R,k)

set k.fx = AddSpecialEffectTarget(MissileModelPath,m,"origin")
set k.m=m
set k.ac=TriggerAddAction(R,OnImpact)

set R=null
set udg_currentcaster=m
set m=null

return udg_currentcaster
endfunction

function CollisionMissile_CreateLoc takes string MissileModelPath, location loc, real dirangle, real speed, real AngleSpeed, real MaxDist, real height, boolean UseNewCaster, real Collision, code OnImpact returns unit
return CollisionMissile_Create(MissileModelPath,GetLocationX(loc),GetLocationY(loc),dirangle,speed,AngleSpeed,MaxDist,height,UseNewCaster,Collision,OnImpact)
endfunction
//! CollisionMissile_CreateLoc(MissileModelPath,loc,dirangle,speed,AngleSpeed,MaxDist,height,UseNewCaster,Collision,OnImpact) CollisionMissile_Create(MissileModelPath,GetLocationX(loc),GetLocationY(loc),dirangle,speed,AngleSpeed,MaxDist,height,UseNewCaster,Collision,OnImpact)

//=========================================================================================================================================================
function CollisionMissile_SetAngleSpeed takes unit m, real newAspeed returns nothing
local cscollisionmissile k=GetUnitUserData(m)
set k.aspeed=newAspeed
endfunction

//=========================================================================================================================================================
function CollisionMissile_SetSpeed takes unit m, real newspeed returns nothing
local cscollisionmissile k=GetUnitUserData(m)
set k.speed=newspeed
endfunction


//=========================================================================================================================================================
function CollisionMissile_SetTargetPoint takes unit m, real tx, real ty returns nothing
local cscollisionmissile k= GetUnitUserData(m)
set k.tx=tx
set k.ty=ty
set k.ttype=cscollisionmissile.ttype_point
endfunction
function CollisionMissile_SetTargetPointLoc takes unit m, location tloc returns nothing
call CollisionMissile_SetTargetPoint(m,GetLocationX(tloc),GetLocationY(tloc))
endfunction

//=========================================================================================================================================================
function CollisionMissile_SetTarget takes unit m, widget Target returns nothing
local cscollisionmissile k= GetUnitUserData(m)
set k.tw=Target
set k.ttype=cscollisionmissile.ttype_widget
endfunction

//=========================================================================================================================================================
function CollisionMissile_ForgetTarget takes unit m returns nothing
set cscollisionmissile(GetUnitUserData(m)).ttype=cscollisionmissile.ttype_none
endfunction



//=========================================================================================================================================================
function CollisionMissile_SetDirAngle takes unit m, real f returns nothing
set cscollisionmissile(GetUnitUserData(m)).f=f
call SetUnitFacing(m,f)
endfunction

//=========================================================================================================================================================
function CollisionMissile_ResetMaxDist takes unit m, real maxdist returns nothing
set cscollisionmissile(GetUnitUserData(m)).maxd=maxdist
endfunction

//=========================================================================================================================================================
function CollisionMissile_PeriodicFX takes unit m, string fx, real dur returns nothing
// [1 integer state][2 trigger T][3 real collision][4 real speed][5 real F][6 real aspeed][7 integer TType]
// [8 real Tx][9 real Ty][10 widget Tw][11 real F][12 real maxd][13 boolean pfx][14 real pfx_current][15 real pfx_dur][16 pfx_path]
// [17 fx][18 ac][19 boolean new][20 m]

local cscollisionmissile k= cscollisionmissile(GetUnitUserData(m))
set k.pfx=true
set k.pfx_path=fx
set k.pfx_dur=dur
set k.pfx_current=0.
endfunction

//=========================================================================================================================================================
function CollisionMissile_SetTag takes unit m, integer tag returns nothing
set cscollisionmissile(GetUnitUserData(m)).tag=tag
endfunction

//=========================================================================================================================================================
function CollisionMissile_GetTag takes unit m returns integer
return cscollisionmissile(GetUnitUserData(m)).tag
endfunction


//**************************************************************************************************
//*
//* Caster System Special Events:
//*
//*
//**************************************************************************************************



globals
private boolean eventhandlers_passives=false
private trigger events_probablytemp_learntrig=null
private triggeraction events_probablytemp_learntriga=null
endglobals

//==================================================================================================
// Event: OnAbilityLearn
//
function Event_OnLearn1 takes nothing returns nothing

local integer s=GetLearnedSkill()
local string k=I2S(s)
if HaveStoredString( cs_cache, "events_onlearn",k) then
call ExecuteFunc( GetStoredString( cs_cache, "events_onlearn",k) )
endif

endfunction

function Event_OnLearn2 takes nothing returns nothing

local integer s=GetLearnedSkill()
local string k=I2S(s)
if HaveStoredString( cs_cache, "events_onlearn",k) then
call StoreInteger(cs_cache,"events_variables","unit",CS_H2I(GetTriggerUnit()))
call StoreInteger(cs_cache,"events_variables","current",s)
call ExecuteFunc( GetStoredString( cs_cache, "events_onlearn",k) )
endif

endfunction

function InitLearnEvent takes gamecache g, integer i returns nothing
local trigger t=CreateTrigger()
local integer j=0
loop
call TriggerRegisterPlayerUnitEvent(t, Player(j),EVENT_PLAYER_HERO_SKILL, null)
set j=j+1
exitwhen j==bj_MAX_PLAYER_SLOTS
endloop
if (i==1) then
set events_probablytemp_learntrig=t
set events_probablytemp_learntriga=TriggerAddAction(t, function Event_OnLearn1)
else
call TriggerAddAction(t, function Event_OnLearn2)
endif
call StoreInteger(g,"eventhandlers","learn",i)

set t=null
endfunction

function OnAbilityLearn takes integer abilid, string funcname returns nothing


if (not HaveStoredInteger(cs_cache,"eventhandlers","learn")) then
call InitLearnEvent(cs_cache,1)
endif

call StoreString(cs_cache,"events_onlearn", I2S(abilid), funcname)


endfunction

//==================================================================================================
// Event: OnAbilityGet
//
globals
private unit acquiringunit
private integer acquiredabil
endglobals
function GetAbilityAcquiringUnit takes nothing returns unit
return acquiringunit
endfunction

function GetAcquiredAbilityId takes nothing returns integer
return acquiredabil
endfunction


function UnitAddAbility_ConsiderEvent takes unit whichUnit, integer abilid, integer level returns nothing
local string k=I2S(abilid)
call UnitAddAbility(whichUnit,abilid)
call SetUnitAbilityLevel(whichUnit,abilid,level)
if (HaveStoredString(cs_cache,"events_onlearn",k)) then
set acquiringunit = whichUnit
set acquiredabil = abilid
call ExecuteFunc(GetStoredString(cs_cache,"events_onlearn",k))
endif
endfunction


function Event_OnPassive_Browse takes unit u, string k returns nothing
local integer n=GetStoredInteger(cs_cache,"events_passives","n")
local integer un=0
local integer i=1
local integer s

loop
exitwhen (i>n)
set s=GetStoredInteger(cs_cache,"events_passives",I2S(i))
if (GetUnitAbilityLevel(u,s)>0) then
if (un==0) then
set un=1
call StoreInteger(cs_cache,"events_variables","unit",CS_H2I(u))
else
set un=un+1
endif
call StoreInteger(cs_cache,"events_unit_passive"+I2S(un),k,s)
call StoreInteger(cs_cache,"events_variables","current",s)
call ExecuteFunc(GetStoredString(cs_cache,"events_onlearn",I2S(s)))
endif
set i=i+1
endloop
if (un==0) then
set un=-1
endif
call StoreInteger(cs_cache,"events_unit_passives",k,un)
endfunction

function Event_OnPassive_Do takes unit u, string k, integer n returns nothing
local integer i=1
local integer s
call StoreInteger(cs_cache,"events_variables","unit",CS_H2I(u))
loop
exitwhen (i>n)
set s=GetStoredInteger(cs_cache,"events_unit_passive"+I2S(i),k)
if (GetUnitAbilityLevel(u,s)>0) then
call StoreInteger(cs_cache,"events_variables","current",s)
call ExecuteFunc(GetStoredString(cs_cache,"events_onlearn",I2S(s)))
endif
set i=i+1
endloop
endfunction


function Event_OnPassive_EnterRect takes nothing returns nothing

local unit u=GetTriggerUnit()
local string k=I2S(GetUnitTypeId(u))
local integer n=GetStoredInteger(cs_cache,"events_unit_passives",k)
if (n>0) then
call Event_OnPassive_Do(u,k,n)
elseif (n==0) then
call Event_OnPassive_Browse(u,k)
endif

set u=null
endfunction

function Event_OnPassive_NoCasters takes nothing returns boolean
return (GetUnitTypeId(GetTriggerUnit())!=cs_CasterUnitId)
endfunction
function Event_OnPassive_InitEnum takes nothing returns nothing
local trigger t
local integer n=GetStoredInteger(cs_cache,"events_passives","n")
local integer i=1
local integer array p
local string array s
local unit u
local group a=NewGroup()
local boolean saved
call ReleaseTimer(GetExpiredTimer())
loop
exitwhen (i>n)
set p=GetStoredInteger(cs_cache,"events_passives",I2S(i))
set s=GetStoredString(cs_cache,"events_onlearn", I2S(p))
set i=i+1
endloop
call GroupEnumUnitsInRect(a,bj_mapInitialPlayableArea,null)
loop
set u=FirstOfGroup(a)
exitwhen (u==null)
set i=1
set saved=false

loop
exitwhen (i>n)
if (GetUnitAbilityLevel(u,p)>0) then
if (not saved) then
set saved=true
call StoreInteger(cs_cache,"events_variables","unit",CS_H2I(u))
endif
call StoreInteger(cs_cache,"events_variables","current",p)
call ExecuteFunc(s)
endif
set i=i+1
endloop
call GroupRemoveUnit(a,u)
endloop
set t=CreateTrigger()
call TriggerRegisterEnterRectSimple(t,bj_mapInitialPlayableArea)
call TriggerAddAction(t,function Event_OnPassive_EnterRect)
call TriggerAddCondition(t,Condition(function Event_OnPassive_NoCasters))
call ReleaseGroup(a)

set t=null
set a=null
endfunction


function InitPassiveEvent takes nothing returns nothing
local trigger t
call TimerStart(NewTimer(),0,false,function Event_OnPassive_InitEnum)
set eventhandlers_passives=true

if (not HaveStoredInteger(cs_cache,"eventhandlers","learn")) then
call InitLearnEvent(cs_cache,2)
else
set t=events_probablytemp_learntrig
call TriggerRemoveAction(t,events_probablytemp_learntriga)
call TriggerAddAction(t, function Event_OnLearn2)
call StoreInteger(cs_cache,"eventhandlers","learn",2)
set t=null
endif
endfunction


function OnAbilityGet takes integer abilid, string funcname returns nothing
local integer n=GetStoredInteger(cs_cache,"events_passives","n")+1

if (not eventhandlers_passives) then
call InitPassiveEvent()
endif

call StoreString( cs_cache,"events_onlearn", I2S(abilid), funcname)
call StoreInteger(cs_cache,"events_passives","n",n)
call StoreInteger(cs_cache,"events_passives",I2S(n),abilid)
endfunction

//==================================================================================================
// Event: OnAbilityEffect
//
function Event_OnEffect takes nothing returns nothing
local string k=I2S(GetSpellAbilityId())

if HaveStoredString(cs_cache, "events_oneffect",k) then
call ExecuteFunc( GetStoredString(cs_cache, "events_oneffect",k))
endif
endfunction

function InitEffectEvent takes gamecache g returns nothing
local trigger t=CreateTrigger()
local integer i = 0
loop
call TriggerRegisterPlayerUnitEvent(t, Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
set i=i+1
exitwhen i==bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddAction(t,function Event_OnEffect)
call StoreInteger(g,"eventhandlers","effect",1)
set t=null
endfunction

function OnAbilityEffect takes integer abilid, string funcname returns nothing

if (not HaveStoredInteger(cs_cache,"eventhandlers","effect")) then
call InitEffectEvent(cs_cache)
endif
call StoreString(cs_cache,"events_oneffect",I2S(abilid),funcname)
endfunction

//==================================================================================================
// Event: OnAbilityCast
//
function Event_OnCast takes nothing returns nothing
local string k=I2S(GetSpellAbilityId())
if HaveStoredString(cs_cache, "events_oncast",k) then
call ExecuteFunc( GetStoredString(cs_cache, "events_oncast",k))
endif

endfunction

function InitCastEvent takes nothing returns nothing
local trigger t=CreateTrigger()
local integer i = 0
loop
call TriggerRegisterPlayerUnitEvent(t, Player(i),EVENT_PLAYER_UNIT_SPELL_CAST, null)
set i=i+1
exitwhen i==bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddAction(t,function Event_OnCast)
call StoreInteger(cs_cache,"eventhandlers","cast",1)
set t=null
endfunction

function OnAbilityPreCast takes integer abilid, string funcname returns nothing
if (not HaveStoredInteger(cs_cache,"eventhandlers","cast")) then
call InitCastEvent()
endif
call StoreString(cs_cache,"events_oncast",I2S(abilid),funcname)
endfunction

//==================================================================================================
// Event: OnAbilityEndCast
//
function Event_OnEndCast takes nothing returns nothing
local string k=I2S(GetSpellAbilityId())

if HaveStoredString(cs_cache, "events_onendcast",k) then
call ExecuteFunc( GetStoredString(cs_cache, "events_onendcast",k))
endif

endfunction

function InitEndCastEvent takes nothing returns nothing
local trigger t=CreateTrigger()
local integer i = 0
loop
call TriggerRegisterPlayerUnitEvent(t, Player(i),EVENT_PLAYER_UNIT_SPELL_ENDCAST, null)
set i=i+1
exitwhen i==bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddAction(t,function Event_OnEndCast)
call StoreInteger(cs_cache,"eventhandlers","endcast",1)
set t=null
endfunction

function OnAbilityEndCast takes integer abilid, string funcname returns nothing

if (not HaveStoredInteger(cs_cache,"eventhandlers","endcast")) then
call InitEndCastEvent()
endif
call StoreString(cs_cache,"events_onendcast",I2S(abilid),funcname)

endfunction


//==================================================================================================
// Spell Helpers
//
function IsPointWater takes real x, real y returns boolean
return IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) and not(IsTerrainPathable(x,y,PATHING_TYPE_AMPHIBIOUSPATHING))
endfunction

function IsPointWaterLoc takes location loc returns boolean
return IsPointWater(GetLocationX(loc),GetLocationY(loc))
endfunction

//==================================================================================================
function IsUnitSpellImmune takes unit u returns boolean
return IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE)
endfunction

function IsUnitImmuneToPhisical takes unit u returns boolean
return (GetDamageFactor(u,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_DEMOLITION)==0)
endfunction

function IsUnitInvulnerable takes unit u returns boolean
return (GetDamageFactor(u,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL)==0)
endfunction

//## Utility functions ##
//====================================================================================================
// Mimic an interface error message
// ForPlayer : The player to show the error
// msg : The error
//
function CS_Error takes player ForPlayer, string msg returns nothing
local sound error=CreateSoundFromLabel( "InterfaceError",false,false,false,10,10)
if (GetLocalPlayer() == ForPlayer) then
if (msg!="") and (msg!=null) then
call ClearTextMessages()
call DisplayTimedTextToPlayer( ForPlayer, 0.52, -1.00, 2.00, "|cffffcc00"+msg+"|r" )
endif
call StartSound( error )
endif
call KillSoundWhenDone( error)
set error=null
endfunction

//## Safe item hiding system ##
//===============================
// Hides an item, it keeps it safe while leaving other units unable to use it
// (unless an (attached) variable / table field points to it and user does
// something with it) - THIS IS HIGHLY DISCOURAGED
//
// * Don't use it with tomes that increase hero stats
// * Make triggers with item acquire/lose events ignore when a
// Caster is triggering unit.
//
globals
private group CSItemStorage_gr=null
endglobals

//If your map got more than 8191 items, you are crazy.
private struct itemholder
unit s
item it
endstruct

function CS_HideItem takes item i returns integer
local unit s
local group gr=CSItemStorage_gr
local itemholder r

if (gr==null) then
set gr=NewGroup()
set CSItemStorage_gr=gr
endif
set s=FirstOfGroup(gr)
if (s==null) then
set s=CreateCaster(0,0,0)
call UnitAddAbility(s,cs_DummyInventory_Id)
if (UnitInventorySize(s)<bj_MAX_INVENTORY) then
call BJDebugMsg("CASTER SYSTEM ERROR: Please use a correct ability for cs_DummyInventory_Id ")
loop //crash the thread
endloop
endif

call GroupAddUnit(gr,s)
endif
call UnitAddItem(s,i)
set r=itemholder.create()
set r.it=i
set r.s=s

if(UnitInventorySize(s)==UnitInventoryCount(s)) then
call GroupRemoveUnit(gr,s)
endif
set s=null
set gr=null
return integer(r)
endfunction


//===============================
// Restores an item
//
globals
private item returnitem
endglobals
function CS_RestoreItem takes integer hiddenindex, real x, real y returns item
local group gr=CSItemStorage_gr
local itemholder r=itemholder(hiddenindex)
local unit s=r.s
local item i=r.it
local integer c
call r.destroy()

call UnitRemoveItem(s,i)
set c=UnitInventoryCount(s)
if (c==0) then
call UnitRemoveAbility(s,cs_DummyInventory_Id)
call GroupRemoveUnit(gr,s)
call ExplodeUnitBJ(s)
else
call GroupAddUnit(gr,s)
endif
call SetItemPosition(i,x,y)
set returnitem=i
set i=null
set s=null
return returnitem
endfunction

function CS_RestoreItemLoc takes integer hiddenindex, location loc returns item
return CS_RestoreItem(hiddenindex,GetLocationX(loc),GetLocationY(loc))
endfunction


//=============================================================================================================
// More convenient than CS_HideItem not compatible with CS_HideItem / CS_RestoreItem(loc)
//
function CS_SetItemVisible takes item it, boolean flag returns nothing
local itemholder r
local unit s
local string k=I2S(CS_H2I(it))
local group gr
local integer x
if (flag) then
if (HaveStoredInteger(cs_cache,"CSItemStorage",k )) then
//DO SHOW:
set r=itemholder(GetStoredInteger(cs_cache,"CSItemStorage",k))
set s=r.s
set gr=CSItemStorage_gr
if (gr==null) then
set gr=NewGroup()
set CSItemStorage_gr=gr
endif
call FlushStoredInteger(cs_cache,"CSItemStorage",k)
call UnitRemoveItem(s,it)
call SetItemVisible(it,true) //Just in case
set x=GetUnitUserData(s)-1
if (x==0) then
call UnitRemoveAbility(s,cs_DummyInventory_Id)
call GroupRemoveUnit(gr,s)
call ExplodeUnitBJ(s)
else
call SetUnitUserData(s,x)
call GroupAddUnit(gr,s)
endif
call r.destroy()
set s=null
set gr=null
else //What? Trying to show an item that was not hidden using this method?
endif


elseif (HaveStoredInteger(cs_cache,"CSItemStorage",k )) then
//What? Trying to hide an item that was already hidden by this method?

else //DO HIDE:
set gr=CSItemStorage_gr
if (gr==null) then
set gr=NewGroup()
set CSItemStorage_gr=gr
endif
set s=FirstOfGroup(gr)

if (s==null) then
set s=CreateCaster(0,0,0)
call UnitAddAbility(s,cs_DummyInventory_Id)
if (UnitInventorySize(s)<bj_MAX_INVENTORY) then
call BJDebugMsg("CASTER SYSTEM ERROR: Please use a correct ability for cs_DummyInventory_Id ")
set x=x
endif
call SetUnitUserData(s,0) //UserData will now hold total items
call GroupAddUnit(gr,s)
endif
call UnitAddItem(s,it)
set r=itemholder.create()
set r.s=s
set r.it=it
call StoreInteger(cs_cache,"CSItemStorage",k,integer(r))
set x=GetUnitUserData(s)+1
call SetUnitUserData(s,x)
if (x==bj_MAX_INVENTORY) then
call GroupRemoveUnit(gr,s)
endif
set s=null
set gr=null
endif
endfunction

function CS_IsItemVisible takes item it returns boolean
return not HaveStoredInteger(cs_cache,"CSItemStorage",I2S(CS_H2I(it)) )
endfunction


//=============================================================================================================
// Obsolette functions: (Left for compatibility)
//
constant function WaterDetectorId takes nothing returns integer
return 'Asb2'
endfunction
function SpellEffectModelPath takes integer abilityid, effecttype t returns string
return GetAbilityEffectById(abilityid,t, 0)
endfunction
constant function Caster_DefaultAttackType takes nothing returns attacktype
return cs_DefaultAttackType
endfunction
constant function Caster_DefaultDamageType takes nothing returns damagetype
return cs_DefaultDamageType
endfunction
constant function Caster_UnitId takes nothing returns integer
return cs_CasterUnitId
endfunction
constant function DamageTreeDetectorId takes nothing returns integer
return cs_DamageTreeDetectorId
endfunction
constant function ChangeableFlyingHeightAllowerId takes nothing returns integer
return cs_FlyingHeightHack
endfunction
constant function CS_MaxCollisionSize takes nothing returns real
return cs_MaxUnitCollisionSize
endfunction
constant function CS_Cycle takes nothing returns real
return cs_TIMER_CYCLE
endfunction
constant function CS_InventoryId takes nothing returns integer
return cs_DummyInventory_Id
endfunction
constant function CS_RectLimitOffSet takes nothing returns real
return cs_RectLimitOffSet
endfunction
function CS_IsUnitVisible takes unit u, player p returns boolean
return IsUnitVisible(u,p)
endfunction

endlibrary



[/code]
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
undeclared objects GetArrayeffect/unit and SetArrayobject
That's not a common syntax error so I'm not sure that the problem is in the code. If you have CasterSystem's demo code, try to disable it. Probably it's related to one or two pre-placed objects in the terrain editor. For better idea, try to do what dimf have just said:
Can you post a picture of the exact error ?

Another thing you can try is to switch between cJassHelper and vJassHelper. Afaik, cJass can't compile some of vJass codes.

Good luck...
 
Status
Not open for further replies.
Top