1. Are you planning to upload your awesome map to Hive? Please review the rules here.
    Dismiss Notice
  2. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  3. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still haven't received your rank award? Then please contact the administration.
    Dismiss Notice
  4. Lead your forces to battle in the 15th Techtree Contest. The call is yours, commander!
    Dismiss Notice
  5. The reforging of the races is complete. Come see the 14th Techtree Contest Results.
    Dismiss Notice
  6. It's time to choose your horse in the race - the 32nd Modeling Contest Poll is up!
    Dismiss Notice
  7. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Trigger Viewer

SupCom Paradise v21.w3x
Variables
Initialization
Initialization
Class Config
Cine Cam
Choose Mode
Start Game
AI
Initialize AI
Start AI
AI Loop
Team Defense
Initialize Team Defense
Spawn Waves
Core
Bullets
Attack
Range Refresh
Unit Refresh
Resources
Tree Dies
Volcanos
Music
Units
Unit Takes Item
Unit Index
Unit Train Start
Unit Train Abort
Unit Train Finish
Unit Upgrade Start
Unit Upgrade Abort
Unit Upgrade Finish
Unit Transported
Build Structures Start
Build Structures Abort
Build Structures Finish
Order Target
Order Point
Order Immediate
Unit Dies
Spells
Fire Strategic Missile
Fire Tactical Missile
Unit Start Repair
Unit Stop Repair
Unit Start Capture
Unit Stop Capture
Enable Ressource Production
Disable Ressource Production
Enable Auto Production
Disable Auto Production
Submerge
Support
Translocate
Overcharge Check
Overcharge
Explode
Controller
Camera
Zoom In
Zoom Out
Reset Camera
Lock Camera Target
Free Fly
Eco Display On
Eco Display Off
Range Display On
Range Display Off
Destroy
Players
Debug
Arrows
Ally
Nap
War
Create
FPS
Esc
Unit Info
Unit Transfer
General Hints
Player Leaves
//TESH.scrollpos=30
//TESH.alwaysfold=0
//***************************************************************************
//*
//*  Debug API
//*
//***************************************************************************

function BugMsg takes string s returns nothing
	call DisplayTextToPlayer(GetLocalPlayer(),0,0,"[|cffff0000Debug|r] "+s+"")
endfunction

function ThreadStart takes string ThreadName returns nothing
	local integer ThreadId = 1
	loop
		exitwhen ThreadId>udg_threadMax
		if udg_threadName[ThreadId]==ThreadName then
			call BugMsg("Attempting to start an existent Thread (\""+ThreadName+"\").")
			return
		endif
		set ThreadId = ThreadId + 1
	endloop
	set udg_threadName[ThreadId] = ThreadName
	set udg_threadMax = ThreadId
endfunction

function ThreadClose takes string ThreadName returns nothing
	local integer ThreadId = 1
	loop
		if ThreadId>udg_threadMax then
			call BugMsg("Attempting to close non-existent Thread (\""+ThreadName+"\").")
			return
		endif
		exitwhen udg_threadName[ThreadId]==ThreadName
		set ThreadId = ThreadId + 1
	endloop
	set udg_threadName[ThreadId] = udg_threadName[udg_threadMax]
	set udg_threadMax = udg_threadMax-1
endfunction

//***************************************************************************
//*
//*  Systems
//*
//***************************************************************************

function H2I takes handle h returns integer
	return GetHandleId(h)
	return 0
endfunction

function NewGroup takes nothing returns group
	if udg_GroupStackN<=0 then
		return CreateGroup()
	endif
	set udg_GroupStackN=udg_GroupStackN-1
	return udg_GroupStack[udg_GroupStackN]
endfunction

function ReleaseGroup takes group g returns nothing
	if udg_GroupStackN>8191 then
		call DestroyGroup(g)
	else
		call GroupClear(g)
		set udg_GroupStack[udg_GroupStackN]=g
		set udg_GroupStackN=udg_GroupStackN+1
	endif
endfunction

function InitTimers takes integer Count returns nothing
	local timer array TimersReference
	set udg_Timers[Count] = null
	set udg_Timers[0] = CreateTimer()
	set TimersReference[0] = udg_Timers[0]
	set udg_TimersBase = H2I(udg_Timers[0])
	set udg_TimersN = 1
	loop
		exitwhen udg_TimersN >= Count
		set udg_Timers[udg_TimersN] = CreateTimer()
		set TimersReference[udg_TimersN] = udg_Timers[udg_TimersN]
		set udg_TimersN = udg_TimersN + 1
	endloop
endfunction

function GetTimerId takes timer t returns integer
	return H2I(t)-udg_TimersBase
endfunction

function NewTimer takes nothing returns timer
	set udg_TimersN = udg_TimersN - 1
	return udg_Timers[udg_TimersN]
endfunction

function ReleaseTimer takes timer t returns nothing
	call PauseTimer(t)
	set udg_Timers[udg_TimersN] = t
	set udg_TimersN = udg_TimersN + 1
endfunction

function StringReplace takes string find, string replace, string subject returns string
	local integer pos = 0
	local integer findlen = StringLength(find)
	local integer replacelen = StringLength(replace)
	local integer subjectlen = StringLength(subject)
	loop
		exitwhen pos>subjectlen-findlen
		if SubString(subject,pos,pos+findlen)==find then
			set subject = SubString(subject,0,pos)+replace+SubString(subject,pos+findlen,subjectlen)
			set subjectlen = subjectlen - findlen + replacelen
			set pos = pos + replacelen
		else
			set pos = pos + 1
		endif
	endloop
	return subject
endfunction

function StringPos takes string searchIn, string searchFor returns integer
	local integer pos = 0
	local integer searchInL = StringLength(searchIn)
	local integer searchForL = StringLength(searchFor)
	local string firstchar = SubString(searchFor,0,1)
	loop
		exitwhen pos > searchInL-searchForL
		if SubString(searchIn,pos,pos+1)==firstchar then
			if SubString(searchIn,pos,pos+searchForL)==searchFor then
				return pos
			endif
		endif
		set pos = pos + 1
	endloop
	return -1
endfunction

//***************************************************************************
//*
//*  Misc API
//*
//***************************************************************************

function GetColoredProgressBar takes real progress, integer length, string color1, string color2 returns string
	local integer DivideAt = R2I(length*progress+0.5)*2
	if DivideAt<0 then
		set DivideAt = 0
	elseif DivideAt>length*2 then
		set DivideAt = length*2
	endif
	return "|c"+color1+SubString(udg_progressBarBase,0,DivideAt)+"|r|c"+color2+SubString(udg_progressBarBase,0,length*2-DivideAt)+"|r"
endfunction

function SetAbilityAvailable takes integer abilid, boolean avail returns nothing
	local integer i = 0
	loop
		exitwhen i > 15
		call SetPlayerAbilityAvailable(Player(i), abilid, avail)
		set i = i + 1
	endloop
endfunction

function AngleDifferenceDeg takes real Angle1, real Angle2 returns real
	local real diff
	set Angle1 = Angle1-I2R(R2I(Angle1/360))*360
	if Angle1<0 then
		set Angle1 = Angle1 + 360
	endif
	set Angle2 = Angle2-I2R(R2I(Angle2/360))*360
	if Angle2<0 then
		set Angle2 = Angle2 + 360
	endif
	set diff = Angle2-Angle1
	if diff<0 then
		set diff = diff + 360
	endif
	if diff>180 then
		return 360-diff
	endif
	return diff
endfunction

function GridRealCross takes real X, real grid returns real
	if X>0 then
		return R2I(X/grid+.5)*grid
	endif
	return R2I(X/grid-.5)*grid
endfunction

function GridRealCenter takes real X, real grid returns real
	if X>0 then
		return R2I(X/grid)*grid+grid*.5
	endif
	return R2I(X/grid)*grid-grid*.5
endfunction

function IsGroundUnitNearby takes real X, real Y, real Range returns boolean
	local group G = NewGroup()
	local unit U
	call GroupEnumUnitsInRange(G,X,Y,Range,null)
	loop
		set U = FirstOfGroup(G)
		exitwhen U==null
		if GetUnitAbilityLevel(U,'Aloc')==0 and (IsUnitType(U,UNIT_TYPE_FLYING)==false) and GetUnitState(U,UNIT_STATE_LIFE)>0 then
			call ReleaseGroup(G)
			set U = null
			return true
		endif
		call GroupRemoveUnit(G,U)
	endloop
	call ReleaseGroup(G)
	return false
endfunction

function IsTerrainBlockPathable takes real MinX, real MinY, real MaxX, real MaxY returns boolean
	local real CurX
	local real CurY
	set CurX = MinX+32
	loop
		exitwhen CurX > MaxX
		set CurY = MinY+32
		loop
			exitwhen CurY > MaxY
			if IsTerrainPathable(CurX+16,CurY+16,PATHING_TYPE_WALKABILITY) then
				return false
			endif
			if IsTerrainPathable(CurX-16,CurY+16,PATHING_TYPE_WALKABILITY) then
				return false
			endif
			if IsTerrainPathable(CurX-16,CurY-16,PATHING_TYPE_WALKABILITY) then
				return false
			endif
			if IsTerrainPathable(CurX+16,CurY-16,PATHING_TYPE_WALKABILITY) then
				return false
			endif
			set CurY = CurY + 64
		endloop
		set CurX = CurX + 64
	endloop
	return true
endfunction

function SetUnitInGroup takes unit whichUnit, group whichGroup, boolean inside returns nothing
	if inside then
		//if not IsUnitInGroup(whichUnit,whichGroup) then
			call GroupAddUnit(whichGroup,whichUnit)
		//endif
	else
		//if IsUnitInGroup(whichUnit,whichGroup) then
			call GroupRemoveUnit(whichGroup,whichUnit)
		//endif
	endif
endfunction

function SetAlliance takes player sourcePlayer, player otherPlayer, integer State returns nothing
	set udg_playerAlliance[GetPlayerId(sourcePlayer)+GetPlayerId(otherPlayer)*16] = State
	call SetPlayerAlliance(sourcePlayer, otherPlayer, ALLIANCE_PASSIVE,       State<2)
	call SetPlayerAlliance(sourcePlayer, otherPlayer, ALLIANCE_HELP_REQUEST,  State==0)
	call SetPlayerAlliance(sourcePlayer, otherPlayer, ALLIANCE_HELP_RESPONSE, State==0)
	call SetPlayerAlliance(sourcePlayer, otherPlayer, ALLIANCE_SHARED_XP,     State==0)
	call SetPlayerAlliance(sourcePlayer, otherPlayer, ALLIANCE_SHARED_SPELLS, State==0)
	call SetPlayerAlliance(sourcePlayer, otherPlayer, ALLIANCE_SHARED_VISION, State==0)
	if State!=0 then
		call SetPlayerAlliance(sourcePlayer, otherPlayer, ALLIANCE_SHARED_CONTROL, false)
	endif
endfunction

function GetAllianceById takes integer sourcePlayerId, integer otherPlayerId returns integer
	return udg_playerAlliance[sourcePlayerId+otherPlayerId*16]
endfunction

function GetAllianceByUnit takes unit sourceUnit, unit otherUnit returns integer
	return udg_playerAlliance[GetPlayerId(GetOwningPlayer(sourceUnit))+GetPlayerId(GetOwningPlayer(otherUnit))*16]
endfunction

function GetAllianceByPlayer takes player sourcePlayer, player otherPlayer returns integer
	return udg_playerAlliance[GetPlayerId(sourcePlayer)+GetPlayerId(otherPlayer)*16]
endfunction

function GetAllianceByIdAndUnit takes integer sourcePlayerId, unit otherUnit returns integer
	return udg_playerAlliance[sourcePlayerId+GetPlayerId(GetOwningPlayer(otherUnit))*16]
endfunction

function GroupWasFull takes group G returns boolean
	local boolean containsUnit = (FirstOfGroup(G)!=null)
	call ReleaseGroup(G)
	return containsUnit
endfunction

function GetNearestUnitWhichWasInGroup takes group G, real X, real Y returns unit
	local unit U
	local real nearestdist = 0
	local real currentdist
	set bj_meleeNearestMine = null
	loop
		set U = FirstOfGroup(G)
		exitwhen U==null
		set currentdist = Pow(GetUnitX(U)-X,2)+Pow(GetUnitY(U)-Y,2)
		if bj_meleeNearestMine==null or currentdist<nearestdist then
			set nearestdist = currentdist
			set bj_meleeNearestMine = U
		endif
		call GroupRemoveUnit(G,U)
	endloop
	call ReleaseGroup(G)
	return bj_meleeNearestMine
endfunction

function GetHelpStamp takes nothing returns string
	return "[|cff1E90FFHint|r]"
endfunction

function GetTimeStamp takes nothing returns string
	local integer totalsecs = R2I(TimerGetElapsed(udg_GameTimer))
	local integer hours = totalsecs/3600
	local integer minutes = (totalsecs-hours*3600)/60
	local integer secs = totalsecs-hours*3600-minutes*60
	local string s = "[|cff999999"+I2S(hours)
	if minutes<10 then
		set s = s + ":0"+I2S(minutes)
	else
		set s = s + ":"+I2S(minutes)
	endif
	if secs<10 then
		set s = s + ":0"+I2S(secs)+"|r]"
	else
		set s = s + ":"+I2S(secs)+"|r]"
	endif
	return s
endfunction

function SetUnitManaDelayed_Child takes nothing returns nothing
	local timer t = GetExpiredTimer()
	local integer i = GetTimerId(t)
	call SetUnitState(udg_AV_Units[i], UNIT_STATE_MANA, udg_AV_X[i])
	call ReleaseTimer(t)
endfunction

function SetUnitManaDelayed takes unit U, real Mana returns nothing
	local timer t = NewTimer()
	local integer i = GetTimerId(t)
	set udg_AV_Units[i] = U
	set udg_AV_X[i] = Mana
	call TimerStart(t,0.00,false,function SetUnitManaDelayed_Child)
endfunction

function GetUnitTypeClass takes integer UnitType returns integer
	return UnitType-(UnitType/8192)*8192
endfunction

function GetUnitClass takes unit U returns integer
	return GetUnitTypeClass(GetUnitTypeId(U))
endfunction

function InitClass takes integer UnitType, integer CollisionShape, real CollisionDim1, real CollisionDim2, real CollisionDim3, real CollisionZOffset, integer BuildingSquares, integer VeterancyKills, integer ProducedMass, integer ProducedEnergy, integer CostsMass, integer CostsEnergy, integer StorageMass, integer StorageEnergy, real BuildTimeReal, real BuildTimeBase, real DeathDmg, real DeathAOE, integer BigExplosion, integer R, integer G, integer B returns integer
	local integer i = GetUnitTypeClass(UnitType)
	if i < 0 then
		call BugMsg("Class Id is smaller than 0.")
	elseif i > 8191 then
		call BugMsg("Class Id is bigger than 8191.")
	elseif udg_classUnitType[i]!=0 then
		call BugMsg("Class Id is already used."+I2S(udg_classUnitType[i]))
	endif
	set udg_classUnitType[i] = UnitType
	set udg_classCollisionShape[i] = CollisionShape
	set udg_classCollisionDim1[i] = CollisionDim1
	set udg_classCollisionDim2[i] = CollisionDim2
	set udg_classCollisionDim3[i] = CollisionDim3
	set udg_classCollisionZOffset[i] = CollisionZOffset
	if udg_classCollisionShape[i]==1 then
		set udg_classCollisionRadius[i] = CollisionDim1
		set udg_classCollisionRadius2d[i] = CollisionDim1
		if CollisionDim1*2>CollisionDim3 then
			set udg_classCollisionDim3[i]=CollisionDim1*2
		endif
	elseif udg_classCollisionShape[i]==2 then
		set udg_classCollisionRadius[i] = SquareRoot(CollisionDim1*CollisionDim1+CollisionDim3*CollisionDim3/4)
		set udg_classCollisionRadius2d[i] = CollisionDim1
	elseif udg_classCollisionShape[i]==3 then
		set udg_classCollisionRadius[i] = SquareRoot(CollisionDim1*CollisionDim1+CollisionDim2*CollisionDim2+CollisionDim3*CollisionDim3)/2
		set udg_classCollisionRadius2d[i] = SquareRoot(CollisionDim1*CollisionDim1+CollisionDim2*CollisionDim2)/2
	endif
	set udg_classBuildingSquares[i] = BuildingSquares
	set udg_classVeterancyKills[i] = VeterancyKills
	set udg_classProducedMass[i] = ProducedMass
	set udg_classProducedEnergy[i] = ProducedEnergy
	set udg_classCostsMass[i] = CostsMass
	set udg_classCostsEnergy[i] = CostsEnergy
	set udg_classStorageMass[i] = StorageMass
	set udg_classStorageEnergy[i] = StorageEnergy
	set udg_classBuildTimeReal[i] = BuildTimeReal
	set udg_classBuildTimeBase[i] = BuildTimeBase
	set udg_classDeathDmg[i] = DeathDmg
	set udg_classDeathDmgAOE[i] = DeathAOE
	set udg_classBigExplosion[i] = (BigExplosion!=0)
	set udg_classColorR[i] = R
	set udg_classColorG[i] = G
	set udg_classColorB[i] = B
	set udg_classBuildSpeed[i] = 0
	set udg_classManaRegeneration[i] = 0
	set udg_classRadarRange[i] = 0
	set udg_classAdjEnergyCostFactor[i] = 1
	set udg_classAdjMassCostFactor[i] = 1
	set udg_classAdjEnergyIncomeFactor[i] = 1
	set udg_classAdjMassIncomeFactor[i] = 1
	return i
endfunction

function AddClassAttack takes integer UnitType, integer Bind, integer SalvoSize, real SalvoReloadTime, real ManaCosts, real Speed, real SpeedMinFactor, real Acceleration, real Friction, real ShadowSize, real AimingOrCruiseZ, real AimingTimeout, real Interception, real LiftFactor, real Randomness, real AngleZ, real TurretAngle, real TurretAngleRange, real Damage, real AOE, real Range, real Cooldown, string Targets, real XOffset, real YOffset, real ZOffset, integer Special, real Scale, integer BigExplosion, string Effect, string Effect2 returns integer
	local integer i
	local integer pos = 0
	local integer attackLoop
	set udg_attackCount = udg_attackCount + 1
	set udg_attackBind[udg_attackCount] = (Bind!=0)
	set udg_attackSalvoSize[udg_attackCount] = SalvoSize
	set udg_attackSalvoReloadTime[udg_attackCount] = SalvoReloadTime
	set udg_attackManaCosts[udg_attackCount] = ManaCosts
	set udg_attackSpeed[udg_attackCount] = Speed
	set udg_attackSpeedMinFactor[udg_attackCount] = SpeedMinFactor
	set udg_attackShadowSize[udg_attackCount] = ShadowSize
	if AimingOrCruiseZ>100 then
		set udg_attackAiming[udg_attackCount] = 1
		set udg_attackCruiseZ[udg_attackCount] = AimingOrCruiseZ
	else
		set udg_attackAiming[udg_attackCount] = AimingOrCruiseZ
		set udg_attackCruiseZ[udg_attackCount] = 0
	endif
	set udg_attackAimingTimeout[udg_attackCount] = AimingTimeout
	set udg_attackInterception[udg_attackCount] = Interception
	set udg_attackLiftFactor[udg_attackCount] = LiftFactor
	set udg_attackDamage[udg_attackCount] = Damage
	set udg_attackAOE[udg_attackCount] = AOE
	set udg_attackEffect[udg_attackCount] = Effect
	set udg_attackEffect2[udg_attackCount] = Effect2
	set udg_attackRange[udg_attackCount] = Range
	set udg_attackCooldown[udg_attackCount] = Cooldown
	set udg_attackXOffset[udg_attackCount] = XOffset
	set udg_attackYOffset[udg_attackCount] = YOffset
	set udg_attackZOffset[udg_attackCount] = ZOffset
	set udg_attackSpecial[udg_attackCount] = Special
	set udg_attackRandomness[udg_attackCount] = Randomness
	set udg_attackAcceleration[udg_attackCount] = Acceleration
	set udg_attackFriction[udg_attackCount] = Friction
	set udg_attackAngleZ[udg_attackCount] = AngleZ
	set udg_attackScale[udg_attackCount] = Scale
	set udg_attackBigExplosion[udg_attackCount] = (BigExplosion!=0)
	set udg_attackTurretAngle[udg_attackCount] = TurretAngle
	set udg_attackTurretAngleRange[udg_attackCount] = TurretAngleRange
	loop
		exitwhen pos >= StringLength(Targets)
		if SubString(Targets,pos,pos+1)=="a" then
			set udg_attackAntiAir[udg_attackCount] = true
		endif
		if SubString(Targets,pos,pos+1)=="g" then
			set udg_attackAntiGround[udg_attackCount] = true
		endif
		if SubString(Targets,pos,pos+1)=="w" then
			set udg_attackAntiWater[udg_attackCount] = true
		endif
		if SubString(Targets,pos,pos+1)=="s" then
			set udg_attackAntiStrategic[udg_attackCount] = true
		endif
		if SubString(Targets,pos,pos+1)=="t" then
			set udg_attackAntiTactical[udg_attackCount] = true
		endif
		if SubString(Targets,pos,pos+1)=="p" then
			set udg_attackAntiTorpedo[udg_attackCount] = true
		endif
		set pos = pos + 1
	endloop
	if UnitType!=0 then
		set i = GetUnitTypeClass(UnitType)
		set attackLoop = udg_classFirstAttack[i]
		if attackLoop == 0 then
			set udg_classFirstAttack[i] = udg_attackCount
		else
			loop
				exitwhen udg_attackNext[attackLoop]==0
				set attackLoop = udg_attackNext[attackLoop]
			endloop
			set udg_attackNext[attackLoop] = udg_attackCount
		endif
	endif
	return udg_attackCount
endfunction

function IsStrategicAttack takes integer Attack returns boolean
	return ((udg_attackSpecial[Attack]==3) or (udg_attackSpecial[Attack]==5))
endfunction

function IsTorpedoAttack takes integer Attack returns boolean
	return (udg_attackSpecial[Attack]==1) and not udg_attackAntiTorpedo[Attack]
endfunction

function IsTacticalAttack takes integer Attack returns boolean
	return (udg_attackSpecial[Attack]==9) or ((udg_attackAiming[Attack]!=0) and (udg_attackAntiGround[Attack]) and not (IsStrategicAttack(Attack) or IsTorpedoAttack(Attack)))
endfunction

function SetClassBuildSpeed takes integer UnitType, real r returns nothing
	set udg_classBuildSpeed[GetUnitTypeClass(UnitType)] = r
endfunction

function SetClassManaRegeneration takes integer UnitType, real r, boolean isShield returns nothing
	local integer i = GetUnitTypeClass(UnitType)
	set udg_classManaRegeneration[i] = r
	set udg_classIsShield[i] = isShield
endfunction

function SetClassRadarRange takes integer UnitType, real r returns nothing
	set udg_classRadarRange[GetUnitTypeClass(UnitType)] = r
endfunction

function SetClassStealthRange takes integer UnitType, real r returns nothing
	set udg_classStealthRange[GetUnitTypeClass(UnitType)] = r
endfunction

function SetClassEnergyAbility takes integer UnitType, integer abilid returns nothing
	set udg_classEnergyAbility[GetUnitTypeClass(UnitType)] = abilid
endfunction

function SetClassAdjecencyEnergyCostFactor takes integer UnitType, real r returns nothing
	set udg_classAdjEnergyCostFactor[GetUnitTypeClass(UnitType)] = r
endfunction

function SetClassAdjecencyMassCostFactor takes integer UnitType, real r returns nothing
	set udg_classAdjMassCostFactor[GetUnitTypeClass(UnitType)] = r
endfunction

function SetClassAdjecencyEnergyIncomeFactor takes integer UnitType, real r returns nothing
	set udg_classAdjEnergyIncomeFactor[GetUnitTypeClass(UnitType)] = r
endfunction

function SetClassAdjecencyMassIncomeFactor takes integer UnitType, real r returns nothing
	set udg_classAdjMassIncomeFactor[GetUnitTypeClass(UnitType)] = r
endfunction

function InitVeterancy takes nothing returns nothing
	set udg_hitpointAbility[0] = 'A010'
	set udg_hitpointAbility[1] = 'A011'
	set udg_hitpointAbility[2] = 'A012'
	set udg_hitpointAbility[3] = 'A013'
	set udg_hitpointAbility[4] = 'A014'
	set udg_hitpointAbility[5] = 'A015'
	set udg_hitpointAbility[6] = 'A016'
	set udg_hitpointAbility[7] = 'A017'
	set udg_hitpointAbility[8] = 'A018'
	set udg_hitpointAbility[9] = 'A019'
	set udg_hitpointAbility[10] = 'A01A'
	set udg_hitpointAbility[11] = 'A01B'
	set udg_hitpointAbility[12] = 'A01C'
	set udg_hitpointAbility[13] = 'A01D'
	set udg_hitpointAbility[14] = 'A01E'
	set udg_hitpointAbility[15] = 'A01F'
	set udg_hitpointAbility[16] = 'A01G'
	set udg_hitpointAbility[17] = 'A01H'
endfunction

function UnitAddVeterancyLevel takes unit U, integer newLevel returns nothing
	local integer i = 0
	local integer addThisLevel = 131072
	local integer KillerId = GetUnitUserData(U)
	local real currentHP = GetUnitState(U,UNIT_STATE_LIFE)
	local real maxHPold = GetUnitState(U,UNIT_STATE_MAX_LIFE)
	local real maxHP
	local real factor = newLevel*.1
	local integer addHP
	call SetUnitState(U,UNIT_STATE_LIFE,maxHPold)
	loop
		exitwhen i > 17
		if GetUnitAbilityLevel(U,udg_hitpointAbility[i])!=0 then
			call UnitRemoveAbility(U,udg_hitpointAbility[i])
		endif
		set i = i + 1
	endloop
	set maxHP = GetUnitState(U,UNIT_STATE_MAX_LIFE)
	set addHP = R2I(maxHP*factor+0.5)
	set maxHP = maxHP + addHP
	set i = 17
	loop
		exitwhen i < 0
		if addHP>=addThisLevel then
			set addHP = addHP-addThisLevel
			call UnitAddAbility(U,udg_hitpointAbility[i])
		endif
		set addThisLevel = addThisLevel/2
		set i = i - 1
	endloop
	call SetUnitState(U,UNIT_STATE_LIFE,currentHP+(maxHP-maxHPold)*2)
	call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Items\\AIlm\\AIlmTarget.mdl",U,"origin"))
endfunction

function UnitAddKill takes unit U returns nothing
	local integer KillerId = GetUnitUserData(U)
	if KillerId>0 then
		set udg_unitKills[KillerId] = udg_unitKills[KillerId]+1
		if udg_unitKills[KillerId]<=9999 then
			call SetUnitAbilityLevel(U,'A00P',udg_unitKills[KillerId]/100+1)
			call SetUnitAbilityLevel(U,'A00Q',udg_unitKills[KillerId]-(udg_unitKills[KillerId]/100)*100+1)
		endif
		if udg_classVeterancyKills[udg_unitClass[KillerId]]!=0 then
			if (udg_unitKills[KillerId]/udg_classVeterancyKills[udg_unitClass[KillerId]])*udg_classVeterancyKills[udg_unitClass[KillerId]]==udg_unitKills[KillerId] and udg_unitKills[KillerId]/udg_classVeterancyKills[udg_unitClass[KillerId]]<=5 then
				call UnitAddVeterancyLevel(U,udg_unitKills[KillerId]/udg_classVeterancyKills[udg_unitClass[KillerId]])
			endif
		endif
	endif
endfunction

function NewWeapon takes integer Attack returns integer
	local integer i
	if udg_weaponStackN==0 then
		set udg_weaponStackMax = udg_weaponStackMax + 1
		set i = udg_weaponStackMax
	else
		set i = udg_weaponStack[udg_weaponStackN]
		set udg_weaponStackN = udg_weaponStackN-1
	endif
	set udg_weaponAttack[i] = Attack
	set udg_weaponCooldown[i] = 0
	set udg_weaponTarget[i] = null
	set udg_weaponNext[i] = 0
	return i
endfunction

function RemoveWeapon takes integer i returns nothing
	set udg_weaponStackN=udg_weaponStackN+1
	set udg_weaponStack[udg_weaponStackN] = i
endfunction

function SetUnitTarget_Enum takes nothing returns nothing
	local unit U = GetEnumUnit()
	local integer weapon = udg_unitFirstWeapon[GetUnitUserData(GetEnumUnit())]
	loop
		exitwhen weapon==0
		if (bj_forLoopBIndex==0) or (GetAllianceByUnit(U,udg_weaponTarget[weapon])!=2) then
			set udg_weaponTarget[weapon] = bj_lastCreatedUnit
		endif
		set weapon = udg_weaponNext[weapon]
	endloop
	set U = null
endfunction

function SetUnitTarget takes unit U, unit Target, boolean onlyResetAllies returns nothing
	local integer Id = GetUnitUserData(U)
	local integer weapon = udg_unitFirstWeapon[Id]
	loop
		exitwhen weapon==0
		if (not onlyResetAllies) or (GetAllianceByUnit(U,udg_weaponTarget[weapon])!=2) then
			set udg_weaponTarget[weapon] = Target
		endif
		set weapon = udg_weaponNext[weapon]
	endloop
	if udg_unitTransportedUnits[Id]!=null then
		set bj_lastCreatedUnit = Target
		if onlyResetAllies then
			set bj_forLoopBIndex = 1
		else
			set bj_forLoopBIndex = 0
		endif
		call ForGroup(udg_unitTransportedUnits[Id],function SetUnitTarget_Enum)
	endif
endfunction

function CheckTorpedoTarget takes unit U returns nothing
	local integer Id = GetUnitUserData(U)
	call MoveLocation(udg_tempLoc,GetUnitX(U), GetUnitY(U))
	if GetUnitFlyHeight(U)+GetLocationZ(udg_tempLoc)+udg_classCollisionZOffset[udg_unitClass[Id]]-udg_classCollisionDim3[udg_unitClass[Id]]/2<=udg_waterHeight then
		if IsUnitType(U,UNIT_TYPE_ANCIENT)==false then
			call UnitAddType(U,UNIT_TYPE_ANCIENT)
		endif
	elseif IsUnitType(U,UNIT_TYPE_ANCIENT)==true then
		call UnitRemoveType(U,UNIT_TYPE_ANCIENT)
	endif
endfunction

function UnitRemoveWeapons takes integer i returns nothing
	local integer weapon = udg_unitFirstWeapon[i]
	local integer weaponNext
	loop
		exitwhen weapon==0
		set weaponNext = udg_weaponNext[weapon]
		call RemoveWeapon(weapon)
		set weapon = weaponNext
	endloop
	set udg_unitFirstWeapon[i] = 0
endfunction

function UnitRefreshWeapons takes integer i returns nothing
	local integer attack
	local integer weapon
	local real lastCooldown = 0.
	call UnitRemoveWeapons(i)
	if udg_classFirstAttack[udg_unitClass[i]]==0 then
		set udg_unitFirstWeapon[i] = 0
	else
		set udg_unitFirstWeapon[i] = NewWeapon(udg_classFirstAttack[udg_unitClass[i]])
		set attack = udg_classFirstAttack[udg_unitClass[i]]
		set weapon = udg_unitFirstWeapon[i]
		loop
			set attack = udg_attackNext[attack]
			exitwhen attack==0
			set udg_weaponNext[weapon] = NewWeapon(attack)
			if GetRandomInt(0,1)==0 then
				set lastCooldown = lastCooldown-R2I(lastCooldown/udg_attackCooldown[attack])*udg_attackCooldown[attack]
			else
				set lastCooldown = lastCooldown+udg_attackCooldown[attack]*GetRandomReal(0.25,0.75)
				set lastCooldown = lastCooldown-R2I(lastCooldown/udg_attackCooldown[attack])*udg_attackCooldown[attack]
			endif
			set udg_weaponCooldown[weapon] = lastCooldown
			set weapon = udg_weaponNext[weapon]
		endloop
	endif
endfunction

function NewIndex takes unit U returns integer
	local integer i
	local integer weapon
	local integer attack
	if udg_unitStackN==0 then
		set udg_unitStackMax = udg_unitStackMax + 1
		set i = udg_unitStackMax
	else
		set i = udg_unitStack[udg_unitStackN]
		set udg_unitStackN = udg_unitStackN-1
	endif
	call SetUnitUserData(U,i)
	set udg_unitClass[i] = GetUnitClass(U)
	if udg_classUnitType[udg_unitClass[i]]==0 then
		set udg_unitClass[i] = InitClass(GetUnitTypeId(U),1,32,0,0,16,0,6,0,0,100,500,0,0,10,10,0,0,0,255,255,255)
	endif
	set udg_unitUsedMass[i] = 0
	set udg_unitUsedEnergy[i] = 0
	set udg_unitPaused[i] = false
	set udg_unitSupporters[i] = null
	set udg_unitSupportsUnit[i] = null
	set udg_unitChannelTarget[i] = null
	set udg_unitAdjEnergyCostFactor[i] = 1
	set udg_unitAdjMassCostFactor[i] = 1
	set udg_unitAdjEnergyIncomeFactor[i] = 1
	set udg_unitAdjMassIncomeFactor[i] = 1
	set udg_unitUpgradesTo[i] = 0
	set udg_unitUpgradeState[i] = 0
	set udg_unitProducesUnit[i] = 0
	set udg_unitProducesUnitState[i] = 0
	set udg_unitProductionOn[i] = true
	set udg_unitConstructionState[i] = 11
	set udg_unitCaptureState[i] = 0
	set udg_unitCaptureFinished[i] = false
	set udg_unitLastX[i] = GetUnitX(U)
	set udg_unitLastY[i] = GetUnitY(U)
	call MoveLocation(udg_tempLoc,udg_unitLastX[i],udg_unitLastY[i])
	set udg_unitLastZ[i] = GetUnitFlyHeight(U)+GetLocationZ(udg_tempLoc)
	set udg_unitSpeedX[i] = 0
	set udg_unitSpeedY[i] = 0
	set udg_unitSpeedZ[i] = 0
	set udg_unitSpecialWorks[i] = false
	set udg_unitMaxSpeed[i] = GetUnitMoveSpeed(U)
	set udg_unitKills[i] = 0
	set udg_unitLastDamaged[i] = -1
	set udg_unitTransportedBy[i] = null
	set udg_unitTransportedUnits[i] = null
	set udg_unitHasShield[i] = false
	if udg_unitLastZ[i]+udg_classCollisionZOffset[udg_unitClass[i]]-udg_classCollisionDim3[udg_unitClass[i]]/2<=udg_waterHeight and (IsUnitType(U,UNIT_TYPE_FLYING)==false) and GetLocationZ(udg_tempLoc)<=udg_waterHeight then
		call UnitAddType(U,UNIT_TYPE_ANCIENT)
	endif
	if GetUnitDefaultMoveSpeed(U)!=0 then
		call GroupAddUnit(udg_groupMeasureSpeed,U)
	endif
	if udg_classCollisionRadius2d[udg_unitClass[i]]>udg_maxCollision2dLimit then
		call GroupAddUnit(udg_groupBigColliders,U)
	elseif udg_classCollisionRadius2d[udg_unitClass[i]]>udg_maxCollision2d then
		set udg_maxCollision2d = udg_classCollisionRadius2d[udg_unitClass[i]]
	endif
	call UnitRefreshWeapons(i)
	return i
endfunction

function GetUnitModuleBuildSpeed takes unit U returns real
	local integer i = 0
	local integer imax = UnitInventorySize(U)-1
	local real r = 0.
	loop
		exitwhen i > imax
		if GetItemTypeId(UnitItemInSlot(U,i))=='I003' then
			set r = r + 3.
		endif
		set i = i + 1
	endloop
	return r
endfunction

function ResetShieldCheckTimes takes nothing returns nothing
	local integer i = udg_bulletLoopNext[0]
	loop
		exitwhen i==0
		set udg_bulletShieldCheckTime[i] = 0
		set i = udg_bulletLoopNext[i]
	endloop
endfunction

function DisableShieldById takes integer i returns nothing
	call DestroyEffect(udg_shieldEffect[i])
	set udg_unitHasShield[GetUnitUserData(udg_shieldUnit[i])] = false
	set udg_shieldUnit[i] = udg_shieldUnit[udg_shieldCount]
	set udg_shieldX[i] = udg_shieldX[udg_shieldCount]
	set udg_shieldY[i] = udg_shieldY[udg_shieldCount]
	set udg_shieldZ[i] = udg_shieldZ[udg_shieldCount]
	set udg_shieldMobile[i] = udg_shieldMobile[udg_shieldCount]
	set udg_shieldRange[i] = udg_shieldRange[udg_shieldCount]
	set udg_shieldEffect[i] = udg_shieldEffect[udg_shieldCount]
	set udg_shieldAbsorbed[i] = udg_shieldAbsorbed[udg_shieldCount]
	set udg_shieldAlreadyDamaged[i] = udg_shieldAlreadyDamaged[udg_shieldCount]
	set udg_shieldCount = udg_shieldCount-1
endfunction

function DisableShield takes unit U returns nothing
	local integer i = 1
	loop
		exitwhen i > udg_shieldCount
		if udg_shieldUnit[i]==U then
			call DisableShieldById(i)
			exitwhen true
		endif
		set i = i + 1
	endloop
endfunction

function EnableShield takes unit U returns nothing
	local integer id = GetUnitUserData(U)
	if udg_unitHasShield[id] then
		call DisableShield(U)
	endif

	set udg_shieldCount = udg_shieldCount+1
	set udg_shieldUnit[udg_shieldCount] = U
	if GetUnitTypeId(udg_shieldUnit[udg_shieldCount])=='h006' then
		set udg_shieldEffect[udg_shieldCount] = AddSpecialEffectTarget("war3mapImported\\ShieldBig.mdx",U,"origin")
		set udg_shieldRange[udg_shieldCount] = 485*0.6*1.3
	elseif GetUnitTypeId(udg_shieldUnit[udg_shieldCount])=='h00B' then
		set udg_shieldEffect[udg_shieldCount] = AddSpecialEffectTarget("war3mapImported\\ShieldSmallZOff.mdx",U,"origin")
		set udg_shieldRange[udg_shieldCount] = 485*1.3/2
	elseif GetUnitTypeId(udg_shieldUnit[udg_shieldCount])=='h014' then
		set udg_shieldEffect[udg_shieldCount] = AddSpecialEffectTarget("war3mapImported\\ShieldBig.mdx",U,"origin")
		set udg_shieldRange[udg_shieldCount] = 485*1.3
	elseif GetUnitTypeId(udg_shieldUnit[udg_shieldCount])=='h025' then
		set udg_shieldEffect[udg_shieldCount] = AddSpecialEffectTarget("war3mapImported\\Shield.mdx",U,"origin")
		set udg_shieldRange[udg_shieldCount] = 485*1.2
	elseif GetUnitTypeId(udg_shieldUnit[udg_shieldCount])=='h02A' then
		set udg_shieldEffect[udg_shieldCount] = AddSpecialEffectTarget("war3mapImported\\ShieldBig.mdx",U,"origin")
		set udg_shieldRange[udg_shieldCount] = 485*0.8*1.3
	elseif GetUnitTypeId(udg_shieldUnit[udg_shieldCount])=='H00C' then
		set udg_shieldEffect[udg_shieldCount] = AddSpecialEffectTarget("war3mapImported\\Shield.mdx",U,"origin")
		set udg_shieldRange[udg_shieldCount] = 485*0.85
	elseif GetUnitTypeId(udg_shieldUnit[udg_shieldCount])=='h01L' then
		set udg_shieldEffect[udg_shieldCount] = AddSpecialEffectTarget("war3mapImported\\Shield.mdx",U,"origin")
		set udg_shieldRange[udg_shieldCount] = 485*0.6
	else
		set udg_shieldEffect[udg_shieldCount] = AddSpecialEffectTarget("war3mapImported\\Shield.mdx",U,"origin")
		set udg_shieldRange[udg_shieldCount] = 485
	endif
	set udg_shieldMobile[udg_shieldCount] = GetUnitDefaultMoveSpeed(udg_shieldUnit[udg_shieldCount])!=0
	set udg_shieldX[udg_shieldCount] = GetUnitX(udg_shieldUnit[udg_shieldCount])
	set udg_shieldY[udg_shieldCount] = GetUnitY(udg_shieldUnit[udg_shieldCount])
	call MoveLocation(udg_tempLoc,udg_shieldX[udg_shieldCount],udg_shieldY[udg_shieldCount])
	set udg_shieldZ[udg_shieldCount] = GetLocationZ(udg_tempLoc)+GetUnitFlyHeight(udg_shieldUnit[udg_shieldCount])
	set udg_unitHasShield[id] = true
	call ResetShieldCheckTimes()
endfunction

function ItemDropInvalid takes unit U, item DropItem returns nothing
	local real ItemX = GetItemX(DropItem)
	local real ItemY = GetItemY(DropItem)
	local real DistX = ItemX-GetUnitX(U)
	local real DistY = ItemY-GetUnitY(U)
	if DistX*DistX+DistY*DistY <= 40000 then
		call SetItemPosition(DropItem, GetItemX(DropItem), GetItemY(DropItem))
	else
		call SetItemPosition(DropItem, GetUnitX(U), GetUnitY(U))
	endif
endfunction

//***************************************************************************
//*
//*  Effect API
//*
//***************************************************************************

function ReleaseDummy takes unit U returns nothing
	call GroupAddUnit(udg_bulletUnitPools[9],U)
endfunction

function NewDummy takes real X, real Y, real Angle returns unit
	local unit U = FirstOfGroup(udg_bulletUnitPools[0])
	if U!=null then
		call GroupRemoveUnit(udg_bulletUnitPools[0],U)
		call SetUnitFacing(U,bj_RADTODEG * Angle)
		call SetUnitPosition(U,X,Y)
		call SetUnitX(U,X)
		call SetUnitY(U,Y)
	else
		set U = CreateUnit(Player(11),'h003',X,Y,bj_RADTODEG * Angle)
		call UnitAddAbility(U,'Amrf')
		call UnitRemoveAbility(U,'Amrf')
		call SetUnitBlendTime(U,0)
		call SetUnitTimeScale(U,100)
		call SetUnitPathing(U,false)
		call SetUnitX(U,X)
		call SetUnitY(U,Y)
		call RemoveGuardPosition(U)
	endif
	return U
endfunction

function AddLightningExTimed_Child takes nothing returns nothing
	local timer t = GetExpiredTimer()
	local integer i = GetTimerId(t)
	call DestroyLightning(udg_AV_L[i])
	set udg_AV_L[i] = null
	call ReleaseTimer(t)
endfunction

function AddLightningExTimed takes string codeName, real duration, real x1, real y1, real z1, real x2, real y2, real z2 returns lightning
	local timer t = NewTimer()
	local integer i = GetTimerId(t)
	set udg_AV_L[i] = AddLightningEx(codeName, true, x1, y1, z1, x2, y2, z2)
	call TimerStart(t,duration,false,function AddLightningExTimed_Child)
	return udg_AV_L[i]
endfunction

function AddScaledEffectWithFlyHeight takes string Model, real Scale, real X, real Y, real Z returns nothing
	local unit Effect = NewDummy(X,Y,270)
	call SetUnitAnimationByIndex(Effect,90)
	call SetUnitFlyHeight(Effect,Z,0)
	call SetUnitX(Effect,X)
	call SetUnitY(Effect,Y)
	call SetUnitScale(Effect,Scale,Scale,Scale)
	call DestroyEffect(AddSpecialEffectTarget( Model, Effect,"origin" ))
	call ReleaseDummy(Effect)
	set Effect = null
endfunction

function DestroyTreesInRange_Enum takes nothing returns nothing
	local destructable D = GetEnumDestructable()
	local integer typeId = GetDestructableTypeId(D)
	if typeId!='B002' and typeId!='B006' and typeId!='B007' and Pow(GetDestructableX(D)-bj_cineFadeContinueTrans,2)+Pow(GetDestructableY(D)-bj_cineFadeContinueDuration,2)<=bj_enumDestructableRadius and GetDestructableLife(D)>0 then
		set udg_treeDestroy = D
		call TriggerExecute(gg_trg_Tree_Dies)
	endif
	set D = null
endfunction

function DestroyTreesInRange takes real X, real Y, real Range returns nothing
	call SetRect(udg_tempRect,X-Range,Y-Range,X+Range,Y+Range)
	set bj_cineFadeContinueTrans = X
	set bj_cineFadeContinueDuration = Y
	set bj_enumDestructableRadius = Range*Range
	call EnumDestructablesInRect(udg_tempRect, null, function DestroyTreesInRange_Enum)
endfunction

function DestroyTreesInRangeTimed_Child takes nothing returns nothing
	local timer t = GetExpiredTimer()
	local integer tid = GetTimerId(t)
	set udg_AV_Z[tid] = udg_AV_Z[tid]+0.1
	if udg_AV_Z[tid]>=udg_AV_Damage[tid] then
		call DestroyTreesInRange(udg_AV_X[tid],udg_AV_Y[tid],udg_AV_AOE[tid])
		call ReleaseTimer(t)
	else
		call DestroyTreesInRange(udg_AV_X[tid],udg_AV_Y[tid],udg_AV_AOECurrent[tid]+(udg_AV_AOE[tid]-udg_AV_AOECurrent[tid])*udg_AV_Z[tid])
	endif
endfunction

function DestroyTreesInRangeTimed takes real X, real Y, real MinRange, real MaxRange, real duration returns nothing
	local timer t = NewTimer()
	local integer tid = GetTimerId(t)
	set udg_AV_X[tid] = X
	set udg_AV_Y[tid] = Y
	set udg_AV_Z[tid] = 0
	set udg_AV_AOECurrent[tid] = MinRange
	set udg_AV_AOE[tid] = MaxRange
	set udg_AV_Damage[tid] = duration
	call TimerStart(t,0.1,true,function DestroyTreesInRangeTimed_Child)
endfunction

function RemoveUnitTimed_Child takes nothing returns nothing
	local timer t = GetExpiredTimer()
	local unit U = udg_AV_Units[GetTimerId(t)]
	call ReleaseTimer(t)
	call RemoveUnit(U)
	set U = null
endfunction

function RemoveUnitTimed takes unit U, real duration returns nothing
	local timer t = NewTimer()
	set udg_AV_Units[GetTimerId(t)] = U
	call TimerStart(t,duration,false,function RemoveUnitTimed_Child)
endfunction

function FadeAndRemoveUnit_Child takes nothing returns nothing
	local timer t = GetExpiredTimer()
	local integer id = GetTimerId(t)
	local integer Class = GetUnitClass(udg_AV_Units[id])
	set udg_AV_X[id] = udg_AV_X[id] - 0.1
	if udg_AV_X[id]<=0 then
		call ReleaseTimer(t)
		call RemoveUnit(udg_AV_Units[id])
	else
		call SetUnitVertexColor(udg_AV_Units[id],udg_classColorR[Class]/4,udg_classColorG[Class]/4,udg_classColorB[Class]/4,R2I(255*udg_AV_X[id]/udg_AV_Y[id]))
	endif
endfunction

function FadeAndRemoveUnit takes unit U, real duration returns nothing
	local timer t = NewTimer()
	local integer id = GetTimerId(t)
	set udg_AV_Units[id] = U
	set udg_AV_X[id] = duration
	set udg_AV_Y[id] = duration
	call TimerStart(t,0.1,true,function FadeAndRemoveUnit_Child)
endfunction

function CreateExplosionEffect takes real X, real Y, real Z, real AOE returns nothing
	local unit Effect
	local real Scale = AOE/160
	if Z<=udg_waterHeight+1 then
		call DestroyEffect(AddSpecialEffect( "war3mapImported\\IceSparks.mdx", X, Y ))
	endif
	if Scale<1.4 and Z-GetLocationZ(udg_tempLoc)<75 then
		call DestroyEffect(AddSpecialEffect( "war3mapImported\\NewGroundEX.mdx", X, Y ))
	else
		call MoveLocation(udg_tempLoc,X,Y)
		set Effect = NewDummy(X,Y,270)
		call SetUnitAnimationByIndex(Effect,90)
		call SetUnitFlyHeight(Effect,Z-GetLocationZ(udg_tempLoc),0)
		call SetUnitX(Effect,X)
		call SetUnitY(Effect,Y)
		call SetUnitScale(Effect,Scale,Scale,Scale)
		call DestroyEffect(AddSpecialEffectTarget( "war3mapImported\\NewGroundEX.mdx", Effect, "origin" ))
		call ReleaseDummy(Effect)
		set Effect = null
	endif
endfunction

//***************************************************************************
//*
//*  Damage And Projectile Functions
//*
//***************************************************************************

function DoAOEDamageEx takes unit Source, player p, real Damage, real AOE, real X, real Y, real Z, boolean AntiWater, real MaxRange, group AlreadyDamaged, integer Special returns nothing
	local group G = NewGroup()
	local real X2
	local real Y2
	local real Z2
	local real Dist
	local real dX
	local real dY
	local real Facing
	local integer j = 1
	local unit U
	local integer Absorbers = 0
	local unit Damager = Source
	local real thisDmg
	local real Now = TimerGetElapsed(udg_GameTimer)
	local integer Id
	local real AbsorbedDmg
	local real r
	call ThreadStart("DoAOEDamageEx")
	if GetUnitState(Source,UNIT_STATE_MAX_LIFE)<=0 then
		set Damager = udg_playerACU[GetPlayerId(p)]
	endif
	call MoveLocation(udg_tempLoc,X,Y)
	set r = Z-GetLocationZ(udg_tempLoc)-50
	if r<0 then
		set r = 0
	endif
	if AOE<MaxRange then
		set r = SquareRoot(AOE*AOE-r*r)
	else
		set r = SquareRoot(MaxRange*MaxRange-r*r)
	endif
	if r > 0 then
		call DestroyTreesInRange(X,Y,r)
	endif
	if AOE<12 then
		set AOE = 12
	endif
	if MaxRange<12 then
		set MaxRange = 12
	endif

	call GroupEnumUnitsInRange(G,X,Y,AOE+udg_maxCollision2d+32,null)
	call GroupAddGroup(udg_groupBigColliders, G)

	loop
		exitwhen j > udg_shieldCount
		set udg_shieldOutside[j] = ((udg_shieldX[j]-X)*(udg_shieldX[j]-X)+(udg_shieldY[j]-Y)*(udg_shieldY[j]-Y)+(udg_shieldZ[j]-Z)*(udg_shieldZ[j]-Z)>(udg_shieldRange[j]*udg_shieldRange[j]))
		set udg_shieldAbsorbed[j] = false
		set udg_shieldAlreadyDamaged[j] = (AlreadyDamaged!=null) and IsUnitInGroup(udg_shieldUnit[j],AlreadyDamaged)
		set j = j + 1
	endloop
	loop
		set U = FirstOfGroup(G)
		exitwhen U == null
		set Id = GetUnitUserData(U)
		if (Id>0) and ((AlreadyDamaged==null) or not IsUnitInGroup(U,AlreadyDamaged)) then
			set j = udg_unitClass[Id]
			set X2 = GetUnitX(U)
			set Y2 = GetUnitY(U)
			call MoveLocation(udg_tempLoc,X2,Y2)
			set Z2 = GetUnitFlyHeight(U)+GetLocationZ(udg_tempLoc)+udg_classCollisionZOffset[j]
			set Dist = SquareRoot((X2-X)*(X2-X)+(Y2-Y)*(Y2-Y)+(Z2-Z)*(Z2-Z))-udg_classCollisionRadius[j]
			if Dist<=AOE and Dist<=MaxRange then
				if udg_classCollisionShape[j]==3 then
					set Facing = GetUnitFacing(U)*bj_DEGTORAD
					set dX = (X-X2)*Cos(Facing)+(Y-Y2)*Sin(Facing)
					set dY = (X-X2)*Sin(Facing)-(Y-Y2)*Cos(Facing)
					if (Z-Z2)>udg_classCollisionDim3[j]/2 then
						set Dist = Pow((Z-Z2)-udg_classCollisionDim3[j]/2,2)
					elseif (Z2-Z)>udg_classCollisionDim3[j]/2 then
						set Dist = Pow((Z2-Z)-udg_classCollisionDim3[j]/2,2)
					else
						set Dist = 0
					endif
					if dX>udg_classCollisionDim1[j]/2 then
						set Dist = Dist + Pow(dX-udg_classCollisionDim1[j]/2,2)
					elseif -dX>udg_classCollisionDim1[j]/2 then
						set Dist = Dist + Pow(-dX-udg_classCollisionDim1[j]/2,2)
					endif
					if dY>udg_classCollisionDim2[j]/2 then
						set Dist = Dist + Pow(dY-udg_classCollisionDim2[j]/2,2)
					elseif -dY>udg_classCollisionDim2[j]/2 then
						set Dist = Dist + Pow(-dY-udg_classCollisionDim2[j]/2,2)
					endif
					set Dist = SquareRoot(Dist)
				elseif udg_classCollisionShape[j]==2 then
					set Dist = SquareRoot((X2-X)*(X2-X)+(Y2-Y)*(Y2-Y))-udg_classCollisionDim1[j]
					if Dist<0 then
						set Dist = 0
					endif
					if (Z2-Z)*(Z2-Z)>udg_classCollisionDim3[j]*udg_classCollisionDim3[j]/4 then
						if Z>Z2 then
							set Dist = SquareRoot(Dist*Dist+((Z-Z2)-udg_classCollisionDim3[j]/2)*((Z-Z2)-udg_classCollisionDim3[j]/2))
						else
							set Dist = SquareRoot(Dist*Dist+((Z2-Z)-udg_classCollisionDim3[j]/2)*((Z2-Z)-udg_classCollisionDim3[j]/2))
						endif
					endif
				elseif Dist<0 then
					set Dist = 0
				endif
			endif
			if Dist<=AOE and Dist<=MaxRange then
				set j = 1
				set AbsorbedDmg = 0
				loop
					exitwhen j > udg_shieldCount
					if GetAllianceByUnit(udg_shieldUnit[j],U)==0 then
						if udg_shieldOutside[j] and (udg_shieldX[j]-X2)*(udg_shieldX[j]-X2)+(udg_shieldY[j]-Y2)*(udg_shieldY[j]-Y2)+(udg_shieldZ[j]-Z2)*(udg_shieldZ[j]-Z2)<Pow(udg_shieldRange[j]-udg_classCollisionRadius[udg_unitClass[Id]],2) then
							set AbsorbedDmg = AbsorbedDmg + GetUnitState(udg_shieldUnit[j],UNIT_STATE_MANA)
							if not udg_shieldAbsorbed[j] then
								set Absorbers = Absorbers + 1
								set udg_shieldAbsorbed[j] = true
							endif
						endif
					endif
					set j = j + 1
				endloop
				set thisDmg = 0
				if Dist<=AOE/2 then
					set thisDmg = Damage
				elseif Dist<=AOE then
					set thisDmg = Damage*2*(1-Dist/AOE)
				endif
				set thisDmg = thisDmg - AbsorbedDmg
				if (IsUnitType(U,UNIT_TYPE_MECHANICAL)==true) and not AntiWater then
					set thisDmg = thisDmg/4
				endif
				if thisDmg>0 then
					set udg_unitLastDamaged[Id] = Now
					if GetUnitTypeId(U)=='H00C' and GetLocalPlayer()==GetOwningPlayer(U) and (udg_lastCommanderWarning==0 or Now-udg_lastCommanderWarning>60) then
						if udg_German then
							call StartSound( gg_snd_commanderattacked )
						else
							call StartSound( gg_snd_commanderattackedEnglish )
						endif
						call SetCameraQuickPosition(X2,Y2)
						set udg_lastCommanderWarning = Now
					endif
					set udg_DamageSource = Source
					if Special==6 then
						if IsUnitType(U,UNIT_TYPE_STRUCTURE)==true or GetUnitTypeId(U)=='H00C' then
							set thisDmg = thisDmg*500/12000
						endif
					endif
					call UnitDamageTarget(Damager, U, thisDmg, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
				endif
				if AlreadyDamaged!=null then
					call GroupAddUnit(AlreadyDamaged, U)
				endif
			endif
		endif
		call GroupRemoveUnit(G,U)
	endloop
	if Absorbers!=0 then
		set j = 1
		loop
			exitwhen j > udg_shieldCount
			if udg_shieldAbsorbed[j] and not udg_shieldAlreadyDamaged[j] then
				set udg_unitLastDamaged[GetUnitUserData(udg_shieldUnit[j])] = Now
				set udg_shieldAbsorbed[j] = false
				if Damage/Absorbers < GetUnitState(udg_shieldUnit[j],UNIT_STATE_MANA) then
					call SetUnitState(udg_shieldUnit[j],UNIT_STATE_MANA,GetUnitState(udg_shieldUnit[j],UNIT_STATE_MANA)-Damage/Absorbers)
					if (AlreadyDamaged!=null) and not IsUnitInGroup(udg_shieldUnit[j],AlreadyDamaged) then
						call GroupAddUnit(AlreadyDamaged, udg_shieldUnit[j])
					endif
				else
					call SetUnitState(udg_shieldUnit[j],UNIT_STATE_MANA,0)
					call DisableShieldById(j)
					set j = j - 1
				endif
			endif
			set j = j + 1
		endloop
	endif
	call ReleaseGroup(G)
	set Damager = null
	call ThreadClose("DoAOEDamageEx")
endfunction

function DoAOEDamage takes unit Source, player p, real Damage, real AOE, real X, real Y, real Z, boolean AntiWater, integer Special returns nothing
	call DoAOEDamageEx(Source,p,Damage,AOE,X,Y,Z,AntiWater,AOE,null,Special)
endfunction

function BulletAddShadow takes integer i returns image
	local real size
	if udg_bulletAttackId[i]==0 then
		set size = udg_classCollisionRadius2d[GetUnitClass(udg_bulletUnit[i])]
	else
		set size = udg_attackShadowSize[udg_bulletAttackId[i]]
	endif
	if size<1. then
		return null
	endif
	set udg_bulletShadow[i] = CreateImage("ReplaceableTextures\\Shadows\\ShadowFlyer.blp", size, size, size, udg_bulletX[i]-size*.5, udg_bulletY[i]-size*.5, 0, 0, 0, 0, 2)
	call SetImageColor(udg_bulletShadow[i],255,255,255,192)
	call SetImageRenderAlways( udg_bulletShadow[i], IsUnitVisible(udg_bulletUnit[i],GetLocalPlayer()) )
	call ShowImage(udg_bulletShadow[i], true)
	return udg_bulletShadow[i]
endfunction

function BulletAddEffects takes integer i returns nothing
	local integer Attack = udg_bulletAttackId[i]
	if StringLength(udg_attackEffect[Attack])<=4 then
		set udg_bulletEffect[i] = null
		set udg_bulletEffect2[i] = null
	else
		set udg_bulletEffect[i] = AddSpecialEffectTarget(udg_attackEffect[Attack],udg_bulletUnit[i],"origin")
		if StringLength(udg_attackEffect2[Attack])<=4 then
			set udg_bulletEffect2[i] = null
		else
			set udg_bulletEffect2[i] = AddSpecialEffectTarget(udg_attackEffect2[Attack],udg_bulletUnit[i],"origin")
		endif
	endif
endfunction

function NewBulletId takes nothing returns integer
	local integer i
	if udg_bulletStackN==0 then
		set udg_bulletStackMax = udg_bulletStackMax + 1
		set i = udg_bulletStackMax
	else
		set i = udg_bulletStack[udg_bulletStackN]
		set udg_bulletStackN = udg_bulletStackN-1
	endif
	set udg_bulletLoopNext[i] = udg_bulletLoopNext[0]
	set udg_bulletLoopPrevious[udg_bulletLoopNext[0]] = i
	set udg_bulletLoopNext[0] = i
	set udg_bulletLoopPrevious[i] = 0
	return i
endfunction

function AirCrash takes unit U, real SpeedX, real SpeedY, real SpeedZ returns integer
	local real DeviationAngleDirection
	local real DeviationSpeed
	local integer i = NewBulletId()
	local integer Class = GetUnitClass(U)
	local real SourceX = GetUnitX(U)
	local real SourceY = GetUnitY(U)
	local real SourceZ = GetUnitFlyHeight(U)
	call MoveLocation(udg_tempLoc,SourceX,SourceY)
	set SourceZ = SourceZ+GetLocationZ(udg_tempLoc)

	set udg_bulletUnit[i] = U

	set DeviationAngleDirection = bj_DEGTORAD+GetRandomReal(0,2*bj_PI)
	set DeviationSpeed = GetRandomReal(0,100)

	set udg_bulletX[i] = SourceX
	set udg_bulletY[i] = SourceY
	set udg_bulletZ[i] = SourceZ
	set udg_bulletTargetX[i] = 0
	set udg_bulletTargetY[i] = 0
	set udg_bulletTargetZ[i] = 0
	set udg_bulletStartTargetX[i] = 0
	set udg_bulletStartTargetY[i] = 0
	set udg_bulletStartTargetZ[i] = 10000
	set udg_bulletTargetSpeedX[i] = 0
	set udg_bulletTargetSpeedY[i] = 0
	set udg_bulletTargetSpeedZ[i] = 0
	set udg_bulletTargetTime[i] = 1000.
	set udg_bulletTargetLastTime[i] = -udg_bulletRefreshCalc*.5
	set udg_bulletShieldCheckTime[i] = 0
	set udg_bulletAttackId[i] = 0
	set udg_bulletTorpedo[i] = false
	set udg_bulletInWater[i] = false
	set udg_bulletCruiseZ[i] = 0
	set udg_bulletSpeedX[i] = SpeedX+DeviationSpeed*Cos(DeviationAngleDirection)
	set udg_bulletSpeedY[i] = SpeedY+DeviationSpeed*Sin(DeviationAngleDirection)
	set udg_bulletSpeedZ[i] = SpeedZ
	set udg_bulletTempSpeedXY[i] = SquareRoot(udg_bulletSpeedX[i]*udg_bulletSpeedX[i]+udg_bulletSpeedY[i]*udg_bulletSpeedY[i])
	set udg_bulletTempSpeed[i] = SquareRoot(udg_bulletTempSpeedXY[i]*udg_bulletTempSpeedXY[i]+udg_bulletSpeedZ[i]*udg_bulletSpeedZ[i])
	set udg_bulletRemoveTime[i] = 5
	set udg_bulletExplodeTime[i] = 4
	set udg_bulletAOE[i] = udg_classDeathDmgAOE[Class]
	set udg_bulletDamage[i] = udg_classDeathDmg[Class]
	set udg_bulletAiming[i] = 0
	set udg_bulletAimTime[i] = 0
	set udg_bulletEffect[i] = AddSpecialEffectTarget("Environment\\LargeBuildingFire\\LargeBuildingFire2.mdl",udg_bulletUnit[i],"chest")
	set udg_bulletEffect2[i] = AddSpecialEffectTarget("Environment\\LargeBuildingFire\\LargeBuildingFire2.mdl",udg_bulletUnit[i],"head")
	set udg_bulletSource[i] = U
	set udg_bulletPlayer[i] = GetOwningPlayer(U)
	set udg_bulletTargetUnit[i] = null
	set udg_bulletTargetClass[i] = 0
	set udg_bulletCollisionCheckTime[i] = 1000
	set udg_bulletTime[i] = 0
	set udg_bulletActive[i] = true
	call SetUnitUserData(udg_bulletUnit[i],-i)
	call SetUnitPathing(udg_bulletUnit[i],false)
	call SetUnitTimeScale(udg_bulletUnit[i],0.01)
	return i
endfunction

function DoAttackVectorSingle takes unit Source, real SourceX, real SourceY, real SourceZ, real SpeedX, real SpeedY, real SpeedZ, integer Attack returns integer
	local integer i = NewBulletId()
	local real Angle
	local real AngleZ
	local real DeviationAngleDirection
	local real DeviationAngle

	
	set Angle = Atan2(SpeedY,SpeedX)

	set udg_bulletUnit[i] = NewDummy(SourceX,SourceY,Angle)
	call SetUnitScale(udg_bulletUnit[i],udg_attackScale[Attack],udg_attackScale[Attack],udg_attackScale[Attack])

	set udg_bulletTorpedo[i] = false
	if udg_attackSpecial[Attack]==1 then
		set udg_bulletTorpedo[i] = true
	endif
	set udg_bulletX[i] = SourceX
	set udg_bulletY[i] = SourceY
	set udg_bulletZ[i] = SourceZ
	set udg_bulletTargetX[i] = 0
	set udg_bulletTargetY[i] = 0
	set udg_bulletTargetZ[i] = 0
	set udg_bulletStartTargetX[i] = 0
	set udg_bulletStartTargetY[i] = 0
	set udg_bulletStartTargetZ[i] = 0
	set udg_bulletTargetSpeedX[i] = 0
	set udg_bulletTargetSpeedY[i] = 0
	set udg_bulletTargetSpeedZ[i] = 0
	set udg_bulletTargetTime[i] = 1000.
	set udg_bulletTargetLastTime[i] = -udg_bulletRefreshCalc*.5
	set udg_bulletShieldCheckTime[i] = 0
	set udg_bulletAttackId[i] = Attack
	set udg_bulletCollisionCheckTime[i] = 1000
	set udg_bulletCruiseZ[i] = 0
	set udg_bulletSpeedX[i] = SpeedX
	set udg_bulletSpeedY[i] = SpeedY
	set udg_bulletSpeedZ[i] = SpeedZ+udg_bulletAccelerationZ[i]*udg_bulletRefreshCalc*.5
	set udg_bulletTempSpeedXY[i] = SquareRoot(SpeedX*SpeedX+SpeedY*SpeedY)
	set udg_bulletTempSpeed[i] = SquareRoot(SpeedX*SpeedX+SpeedY*SpeedY+SpeedZ*SpeedZ)
	set udg_bulletRemoveTime[i] = 30
	if Attack==udg_Salva1Split then
		set udg_bulletRemoveTime[i] = .8
	endif
	set udg_bulletExplodeTime[i] = 31
	if udg_attackRandomness[Attack]!=0 then
		set DeviationAngleDirection = GetRandomReal(0,2*bj_PI)
		set DeviationAngle = GetRandomReal(0,udg_attackRandomness[Attack]*bj_DEGTORAD)
		set Angle = Angle+DeviationAngle*Cos(DeviationAngleDirection)
		set AngleZ = Atan2(udg_bulletSpeedZ[i],udg_bulletTempSpeedXY[i])+DeviationAngle*Sin(DeviationAngleDirection)
		set udg_bulletTempSpeedXY[i] = udg_bulletTempSpeed[i]*Cos(AngleZ)
		set udg_bulletSpeedX[i] = udg_bulletTempSpeedXY[i]*Cos(Angle)
		set udg_bulletSpeedY[i] = udg_bulletTempSpeedXY[i]*Sin(Angle)
		set udg_bulletSpeedZ[i] = udg_bulletTempSpeed[i]*Sin(AngleZ)
	endif
	set udg_bulletAOE[i] = udg_attackAOE[Attack]
	set udg_bulletDamage[i] = udg_attackDamage[Attack]
	set udg_bulletAiming[i] = udg_attackAiming[Attack]
	set udg_bulletAimTime[i] = udg_attackAimingTimeout[Attack]
	set udg_bulletInWater[i] = false
	if IsStrategicAttack(Attack) then
		call GroupAddUnit(udg_groupStrategicMissiles,udg_bulletUnit[i])
	elseif IsTorpedoAttack(Attack) then
		if udg_bulletInWater[i] then
			call GroupAddUnit(udg_groupTorpedoes,udg_bulletUnit[i])
		endif
	elseif IsTacticalAttack(Attack) then
		call GroupAddUnit(udg_groupTacticalMissiles,udg_bulletUnit[i])
	endif
	set udg_bulletSource[i] = Source
	set udg_bulletPlayer[i] = GetOwningPlayer(Source)
	set udg_bulletTargetUnit[i] = null
	set udg_bulletTargetClass[i] = 0
	set udg_bulletTime[i] = 0
	call SetUnitUserData(udg_bulletUnit[i],-i)
	if udg_bulletTempSpeedXY[i]>0. then
		call SetUnitLookAt(udg_bulletUnit[i],"Bone_Head",udg_bulletUnit[i],udg_bulletSpeedX[i]/udg_bulletTempSpeedXY[i]*1000.+250.,udg_bulletSpeedY[i]/udg_bulletTempSpeedXY[i]*1000.,0.)
	endif
	call SetUnitFlyHeight(udg_bulletUnit[i],SourceZ-GetLocationZ(udg_tempLoc),0)
	call SetUnitAnimationByIndex(udg_bulletUnit[i],R2I(Atan2(udg_bulletSpeedZ[i],SquareRoot(udg_bulletSpeedX[i]*udg_bulletSpeedX[i]+udg_bulletSpeedY[i]*udg_bulletSpeedY[i]))*bj_RADTODEG)+90)
	return i
endfunction

function DoAttackSplit takes integer FromBullet, integer Attack returns integer
	local integer count = 0
	local integer i = 0
	loop
		exitwhen (count>=udg_attackSalvoSize[Attack]) or ((udg_bulletStackMax-udg_bulletStackN)>=udg_bulletLimit)
		set i = DoAttackVectorSingle(udg_bulletSource[FromBullet],udg_bulletX[FromBullet],udg_bulletY[FromBullet],udg_bulletZ[FromBullet],udg_bulletSpeedX[FromBullet],udg_bulletSpeedY[FromBullet],udg_bulletSpeedZ[FromBullet], Attack)
		set udg_bulletPlayer[i] = udg_bulletPlayer[FromBullet]
		set udg_bulletTargetUnit[i] = udg_bulletTargetUnit[FromBullet]
		set udg_bulletTargetClass[i] = udg_bulletTargetClass[FromBullet]
		set udg_bulletTargetX[i] = udg_bulletTargetX[FromBullet]
		set udg_bulletTargetY[i] = udg_bulletTargetY[FromBullet]
		set udg_bulletTargetZ[i] = udg_bulletTargetZ[FromBullet]
		set udg_bulletStartTargetX[i] = udg_bulletStartTargetX[FromBullet]
		set udg_bulletStartTargetY[i] = udg_bulletStartTargetY[FromBullet]
		set udg_bulletStartTargetZ[i] = udg_bulletStartTargetZ[FromBullet]
		set udg_bulletCollisionCheckTime[i] = udg_bulletCollisionCheckTime[FromBullet]-udg_bulletTime[FromBullet]
		set count = count + 1
	endloop
	return i
endfunction

function DoAttackXYZSingle takes unit Source, real TargetX, real TargetY, real TargetZ, integer Attack returns integer
	local real Speed = udg_attackSpeed[Attack]
	local real Aiming = udg_attackAiming[Attack]
	local real AngleZ = udg_attackAngleZ[Attack]
	local real Damage = udg_attackDamage[Attack]
	local real AOE = udg_attackAOE[Attack]
	local real XOffset = udg_attackXOffset[Attack]
	local real YOffset = udg_attackYOffset[Attack]
	local real ZOffset = udg_attackZOffset[Attack]
	local real SourceFacing = GetUnitFacing(Source)*bj_DEGTORAD
	local real SourceX = GetUnitX(Source)
	local real SourceY = GetUnitY(Source)
	local real SourceZ = GetUnitFlyHeight(Source)
	local integer SourceId = GetUnitUserData(Source)
	local integer SourceClass = udg_unitClass[SourceId]
	local integer i
	local real Angle
	local real FlightTime
	local real DistXY
	local real DeviationAngleDirection
	local real DeviationAngle
	local real AverageSpeed
	local boolean OnBoardCannon = GetUnitAbilityLevel(Source,'Achd')==0
	if udg_attackBind[Attack] and IsUnitType(Source,UNIT_TYPE_STRUCTURE)==true then
		set SourceFacing = Atan2(TargetY-SourceY,TargetX-SourceX)
	endif
	if not OnBoardCannon then
		set i = udg_classFirstAttack[SourceClass]
		loop
			exitwhen i == 0 or OnBoardCannon
			set OnBoardCannon = (i==Attack)
			set i = udg_attackNext[i]
		endloop
	endif
	if OnBoardCannon then
		if udg_attackSpecial[Attack]==5 and GetRandomInt(0,1)==0 then
			set YOffset = -YOffset
		endif
		set SourceX = SourceX+XOffset*Cos(SourceFacing)+YOffset*Cos(SourceFacing+90*bj_DEGTORAD)
		set SourceY = SourceY+XOffset*Sin(SourceFacing)+YOffset*Sin(SourceFacing+90*bj_DEGTORAD)
		set SourceZ = SourceZ+ZOffset
	else
		set DeviationAngle = GetRandomReal(0,2*bj_PI)
		set AverageSpeed = GetRandomReal(0,udg_classCollisionRadius2d[SourceClass]/2)
		set SourceX = SourceX+AverageSpeed*Cos(DeviationAngle)
		set SourceY = SourceY+AverageSpeed*Sin(DeviationAngle)
		set SourceZ = SourceZ + udg_classCollisionZOffset[SourceClass]
	endif
	call MoveLocation(udg_tempLoc,SourceX,SourceY)
	set SourceZ = SourceZ+GetLocationZ(udg_tempLoc)

	set DistXY = SquareRoot((SourceX-TargetX)*(SourceX-TargetX)+(SourceY-TargetY)*(SourceY-TargetY))
	if udg_attackRange[Attack]!=0 then
		set Speed = Speed*(udg_attackSpeedMinFactor[Attack]+SquareRoot(DistXY/udg_attackRange[Attack])*(1-udg_attackSpeedMinFactor[Attack]))*GetRandomReal(1-udg_attackRandomness[Attack]/100,1+udg_attackRandomness[Attack]/100)
	endif
	if udg_attackAcceleration[Attack]!=0. or udg_attackFriction[Attack]!=0. then
		set Speed = (Speed + udg_attackAcceleration[Attack]*udg_bulletRefreshCalc*.5)
		set AverageSpeed = (Speed + udg_attackAcceleration[Attack]*.1)*Pow(1-udg_attackFriction[Attack]*.001,100*.1)
		set AverageSpeed = (AverageSpeed + udg_attackAcceleration[Attack]*.1)*Pow(1-udg_attackFriction[Attack]*.001,100*.1)
		set AverageSpeed = (AverageSpeed + udg_attackAcceleration[Attack]*.1)*Pow(1-udg_attackFriction[Attack]*.001,100*.1)
		set AverageSpeed = (AverageSpeed + udg_attackAcceleration[Attack]*.1)*Pow(1-udg_attackFriction[Attack]*.001,100*.1)
	else
		set AverageSpeed = Speed
	endif


	set i = NewBulletId()

	if udg_attackSpecial[Attack]==7 then
		set Angle = Atan2(YOffset,XOffset)+SourceFacing
	else
		set Angle = Atan2(TargetY-SourceY,TargetX-SourceX)
	endif

	if DistXY < 1 then
		set FlightTime = 1/AverageSpeed
	else
		set FlightTime = DistXY/AverageSpeed
	endif
	set FlightTime = FlightTime + udg_attackAimingTimeout[Attack]*2

	set udg_bulletUnit[i] = NewDummy(SourceX,SourceY,Angle)
	call SetUnitScale(udg_bulletUnit[i],udg_attackScale[Attack],udg_attackScale[Attack],udg_attackScale[Attack])

	set udg_bulletTorpedo[i] = false
	if udg_attackSpecial[Attack]==1 then
		set udg_bulletTorpedo[i] = true
	endif
	set udg_bulletX[i] = SourceX
	set udg_bulletY[i] = SourceY
	set udg_bulletZ[i] = SourceZ
	set udg_bulletTargetX[i] = TargetX
	set udg_bulletTargetY[i] = TargetY
	set udg_bulletTargetZ[i] = TargetZ
	set udg_bulletStartTargetX[i] = TargetX
	set udg_bulletStartTargetY[i] = TargetY
	set udg_bulletStartTargetZ[i] = TargetZ
	set udg_bulletTargetSpeedX[i] = 0
	set udg_bulletTargetSpeedY[i] = 0
	set udg_bulletTargetSpeedZ[i] = 0
	set udg_bulletTargetTime[i] = 0
	set udg_bulletTargetLastTime[i] = -udg_bulletRefreshCalc*.5
	set udg_bulletShieldCheckTime[i] = 0
	set udg_bulletAttackId[i] = Attack
	set udg_bulletCollisionCheckTime[i] = 0
	if Aiming!=0 then
		if udg_attackCruiseZ[Attack]==0 then
			set udg_bulletCruiseZ[i] = 0
		else
			set udg_bulletCruiseZ[i] = udg_attackCruiseZ[Attack]+SourceZ
			if udg_bulletCruiseZ[i]<TargetZ+400 then
				set udg_bulletCruiseZ[i] = TargetZ+400
			endif
		endif
		if AngleZ==-1 then
			set AngleZ = Atan2(TargetZ-SourceZ,DistXY)
		else
			set AngleZ = AngleZ*bj_DEGTORAD
		endif
		set udg_bulletTempSpeedXY[i] = Speed*Cos(AngleZ)
		set udg_bulletSpeedX[i] = udg_bulletTempSpeedXY[i]*Cos(Angle)
		set udg_bulletSpeedY[i] = udg_bulletTempSpeedXY[i]*Sin(Angle)
		set udg_bulletSpeedZ[i] = Speed*Sin(AngleZ)
		set udg_bulletTempSpeed[i] = Speed
		set udg_bulletRemoveTime[i] = FlightTime*2+(2000+udg_attackCruiseZ[Attack]*2)/AverageSpeed
		if udg_attackAntiTactical[Attack] or udg_attackAntiStrategic[Attack] then
			set udg_bulletRemoveTime[i] = udg_bulletRemoveTime[i]+5
		endif
	elseif AngleZ==-1 then
		set udg_bulletCruiseZ[i] = 0
		set udg_bulletSpeedX[i] = Speed*Cos(Angle)
		set udg_bulletSpeedY[i] = Speed*Sin(Angle)
		set udg_bulletSpeedZ[i] = (TargetZ-SourceZ)/FlightTime+udg_Gravity*FlightTime/2
		set udg_bulletTempSpeedXY[i] = Speed
		set udg_bulletTempSpeed[i] = SquareRoot(Speed*Speed+udg_bulletSpeedZ[i]*udg_bulletSpeedZ[i])
		set Speed = Speed*Speed/udg_bulletTempSpeed[i]
		if DistXY < 1 then
			set FlightTime = 1/Speed
		else
			set FlightTime = DistXY/Speed
		endif
		set udg_bulletSpeedX[i] = Speed*Cos(Angle)
		set udg_bulletSpeedY[i] = Speed*Sin(Angle)
		set udg_bulletSpeedZ[i] = (TargetZ-SourceZ)/FlightTime+udg_Gravity*FlightTime/2
		set udg_bulletTempSpeedXY[i] = Speed
		set udg_bulletTempSpeed[i] = SquareRoot(Speed*Speed+udg_bulletSpeedZ[i]*udg_bulletSpeedZ[i])
		set udg_bulletRemoveTime[i] = FlightTime+1000/Speed
		if udg_attackSpecial[Attack]==4 then
			set udg_bulletRemoveTime[i] = FlightTime-1.2
		elseif udg_attackSpecial[Attack]==10 then
			set udg_bulletRemoveTime[i] = FlightTime-1.6
		elseif udg_attackSpecial[Attack]==13 then
			set udg_bulletRemoveTime[i] = FlightTime-1.2
		endif
		if udg_bulletRemoveTime[i]<1 then
			set udg_bulletRemoveTime[i] = 1
		endif
	else
		set udg_bulletCruiseZ[i] = 0
		set udg_bulletTempSpeed[i] = Speed
		set udg_bulletTempSpeedXY[i] = Speed*Cos(AngleZ*bj_DEGTORAD)
		set udg_bulletSpeedX[i] = udg_bulletTempSpeedXY[i]*Cos(Angle)
		set udg_bulletSpeedY[i] = udg_bulletTempSpeedXY[i]*Sin(Angle)
		set udg_bulletSpeedZ[i] = Speed*Sin(AngleZ*bj_DEGTORAD)
		set udg_bulletRemoveTime[i] = 5
	endif
	set udg_bulletExplodeTime[i] = 1000.
	set udg_bulletInWater[i] = (SourceZ+udg_bulletSpeedZ[i]*udg_bulletRefreshCalc)<=udg_waterHeight
	if udg_attackRandomness[Attack]!=0 then
		if udg_bulletInWater[i] then
			set DeviationAngleDirection = 0
		else
			set DeviationAngleDirection = GetRandomReal(0,2*bj_PI)
		endif
		if SourceId!=0 and (udg_unitSpeedX[SourceId]!=0 or udg_unitSpeedY[SourceId]!=0 or udg_unitSpeedZ[SourceId]!=0) then
			set DeviationAngle = GetRandomReal(0,2*udg_attackRandomness[Attack]*bj_DEGTORAD)
		else
			set DeviationAngle = GetRandomReal(0,udg_attackRandomness[Attack]*bj_DEGTORAD)
		endif
		set Angle = Angle+DeviationAngle*Cos(DeviationAngleDirection)
		set AngleZ = Atan2(udg_bulletSpeedZ[i],udg_bulletTempSpeedXY[i])+DeviationAngle*Sin(DeviationAngleDirection)
		set udg_bulletTempSpeedXY[i] = udg_bulletTempSpeed[i]*Cos(AngleZ)
		set udg_bulletSpeedX[i] = udg_bulletTempSpeedXY[i]*Cos(Angle)
		set udg_bulletSpeedY[i] = udg_bulletTempSpeedXY[i]*Sin(Angle)
		set udg_bulletSpeedZ[i] = udg_bulletTempSpeed[i]*Sin(AngleZ)
	endif
	if udg_bulletTempSpeedXY[i]<0 then
		set udg_bulletTempSpeedXY[i] = -udg_bulletTempSpeedXY[i]
	endif
	set udg_bulletAOE[i] = AOE
	set udg_bulletDamage[i] = Damage
	set udg_bulletAiming[i] = Aiming
	set udg_bulletAimTime[i] = udg_attackAimingTimeout[Attack]
	if IsStrategicAttack(Attack) then
		call GroupAddUnit(udg_groupStrategicMissiles,udg_bulletUnit[i])
	elseif IsTorpedoAttack(Attack) then
		if udg_bulletInWater[i] then
			call GroupAddUnit(udg_groupTorpedoes,udg_bulletUnit[i])
		endif
	elseif IsTacticalAttack(Attack) then
		call GroupAddUnit(udg_groupTacticalMissiles,udg_bulletUnit[i])
	endif
	set udg_bulletSource[i] = Source
	set udg_bulletPlayer[i] = GetOwningPlayer(Source)
	set udg_bulletTargetUnit[i] = null
	set udg_bulletTargetClass[i] = 0
	set udg_bulletTime[i] = 0
	call SetUnitUserData(udg_bulletUnit[i],-i)
	if udg_bulletTempSpeedXY[i]>0. then
		call SetUnitLookAt(udg_bulletUnit[i],"Bone_Head",udg_bulletUnit[i],udg_bulletSpeedX[i]/udg_bulletTempSpeedXY[i]*1000.,udg_bulletSpeedY[i]/udg_bulletTempSpeedXY[i]*1000.,0.)
	endif
	call SetUnitFlyHeight(udg_bulletUnit[i],SourceZ-GetLocationZ(udg_tempLoc),0)
	call SetUnitAnimationByIndex(udg_bulletUnit[i],R2I(Atan2(udg_bulletSpeedZ[i],SquareRoot(udg_bulletSpeedX[i]*udg_bulletSpeedX[i]+udg_bulletSpeedY[i]*udg_bulletSpeedY[i]))*bj_RADTODEG)+90)
	return i
endfunction

function DoAttackXYSingle takes unit Source, real TargetX, real TargetY, integer Attack returns integer
	call MoveLocation(udg_tempLoc,TargetX,TargetY)
	return DoAttackXYZSingle(Source, TargetX, TargetY, GetLocationZ(udg_tempLoc), Attack)
endfunction

function DoAttackTargetSingle takes unit Source, unit Target, integer Attack returns integer
	local integer TargetClass = GetUnitClass(Target)
	local real TargetX
	local real TargetY
	local real TargetZ
	local real TargetZMin
	local real TargetZMax
	local integer i
	local integer Id = GetUnitUserData(Target)
	local integer TargetPid = GetPlayerId(GetOwningPlayer(Target))
	local real FinishTime
	if Id<0 then
		set TargetX = udg_bulletX[-Id]
		set TargetY = udg_bulletY[-Id]
		set TargetZ = udg_bulletZ[-Id]
		set TargetZMin = TargetZ
		set TargetZMax = TargetZ
	else
		set TargetX = GetUnitX(Target)
		set TargetY = GetUnitY(Target)
		set TargetZ = GetUnitFlyHeight(Target)+udg_classCollisionZOffset[TargetClass]
		set TargetZMin = TargetZ-udg_classCollisionDim3[TargetClass]*.5
		set TargetZMax = TargetZ+udg_classCollisionDim3[TargetClass]*.5
	endif
	call MoveLocation(udg_tempLoc,TargetX,TargetY)
	if TargetZMin<0 then
		set TargetZMin=0
	endif
	set TargetZ = (TargetZMin+TargetZMax)*.5+GetLocationZ(udg_tempLoc)

	set i = DoAttackXYZSingle(Source,TargetX,TargetY,TargetZ,Attack)

	set FinishTime = TimerGetElapsed(udg_GameTimer)+udg_bulletRemoveTime[i]
	if FinishTime>udg_playerInvolvedUntil[TargetPid] then
		set udg_playerInvolvedUntil[TargetPid] = FinishTime
	endif

	set udg_bulletTargetUnit[i] = Target
	set udg_bulletStartTargetZ[i] = TargetZ
	set udg_bulletTargetClass[i] = GetUnitClass(Target)
	if (udg_attackInterception[Attack]!=0) and (udg_attackAiming[Attack]==0) then
		if Id>0 then
			set udg_bulletTargetSpeedX[i] = udg_unitSpeedX[Id]
			set udg_bulletTargetSpeedY[i] = udg_unitSpeedY[Id]
			set udg_bulletTargetSpeedZ[i] = udg_unitSpeedZ[Id]
		elseif Id<0 then
			set udg_bulletTargetSpeedX[i] = udg_bulletSpeedX[-Id]
			set udg_bulletTargetSpeedY[i] = udg_bulletSpeedY[-Id]
			set udg_bulletTargetSpeedZ[i] = udg_bulletSpeedZ[-Id]
		endif
		set udg_bulletSpeedX[i] = udg_bulletSpeedX[i] + udg_bulletTargetSpeedX[i]*udg_attackInterception[Attack]
		set udg_bulletSpeedY[i] = udg_bulletSpeedY[i] + udg_bulletTargetSpeedY[i]*udg_attackInterception[Attack]
		set udg_bulletSpeedZ[i] = udg_bulletSpeedZ[i] + udg_bulletTargetSpeedZ[i]*udg_attackInterception[Attack]
		set udg_bulletTempSpeedXY[i] = SquareRoot(udg_bulletSpeedX[i]*udg_bulletSpeedX[i]+udg_bulletSpeedY[i]*udg_bulletSpeedY[i])
		set udg_bulletTempSpeed[i] = SquareRoot(udg_bulletTempSpeed[i]*udg_bulletTempSpeed[i]+udg_bulletSpeedZ[i]*udg_bulletSpeedZ[i])
		if udg_bulletTempSpeedXY[i]>0. then
			call SetUnitLookAt(udg_bulletUnit[i],"Bone_Head",udg_bulletUnit[i],udg_bulletSpeedX[i]/udg_bulletTempSpeedXY[i]*1000.,udg_bulletSpeedY[i]/udg_bulletTempSpeedXY[i]*1000.,0.)
		endif
	endif
	return i
endfunction

function DoAttackXYZ_Loop takes nothing returns nothing
	local timer t = GetExpiredTimer()
	local integer i = GetTimerId(t)
	if GetUnitState(udg_AV_Units[i],UNIT_STATE_LIFE)<=0 then
		call ReleaseTimer(t)
		return
	endif
	set udg_AV_I[i] = udg_AV_I[i] - 1
	if udg_AV_I[i]<=0 then
		call ReleaseTimer(t)
	endif
	call DoAttackXYZSingle(udg_AV_Units[i], udg_AV_X[i], udg_AV_Y[i], udg_AV_Z[i], udg_AV_Attack[i])
endfunction

function DoAttackXYZ takes unit Source, real TargetX, real TargetY, real TargetZ, integer Attack returns integer
	local timer t
	local integer i
	if udg_attackSalvoSize[Attack]>1 then
		set t = NewTimer()
		set i = GetTimerId(t)
		set udg_AV_Units[i] = Source
		set udg_AV_X[i] = TargetX
		set udg_AV_Y[i] = TargetY
		set udg_AV_Z[i] = TargetZ
		set udg_AV_I[i] = udg_attackSalvoSize[Attack]-1
		set udg_AV_Attack[i] = Attack
		call TimerStart(t,udg_attackSalvoReloadTime[Attack],true,function DoAttackXYZ_Loop)
	endif
	return DoAttackXYZSingle(Source, TargetX, TargetY, TargetZ, Attack)
endfunction

function DoAttackXY takes unit Source, real TargetX, real TargetY, integer Attack returns integer
	call MoveLocation(udg_tempLoc,TargetX,TargetY)
	return DoAttackXYZ(Source, TargetX, TargetY, GetLocationZ(udg_tempLoc), Attack)
endfunction

function DoAttackTarget_Loop takes nothing returns nothing
	local timer t = GetExpiredTimer()
	local integer i = GetTimerId(t)
	if GetUnitState(udg_AV_Units[i],UNIT_STATE_LIFE)<=0 then
		call ReleaseTimer(t)
		return
	endif
	if GetUnitState(udg_AV_Target[i],UNIT_STATE_LIFE)<=0 then
		if GetUnitState(udg_AV_Target[i],UNIT_STATE_MAX_LIFE)>0 then
			set udg_AV_X[i] = GetUnitX(udg_AV_Target[i])
			set udg_AV_Y[i] = GetUnitY(udg_AV_Target[i])
			call MoveLocation(udg_tempLoc,udg_AV_X[i],udg_AV_Y[i])
			set udg_AV_Z[i] = GetUnitFlyHeight(udg_AV_Target[i])+udg_classCollisionZOffset[GetUnitClass(udg_AV_Target[i])]+GetLocationZ(udg_tempLoc)
			set udg_AV_I[i] = udg_AV_I[i] - 1
			if udg_AV_I[i]<=0 then
				call ReleaseTimer(t)
			else
				call TimerStart(t, udg_attackSalvoReloadTime[udg_AV_Attack[i]],true,function DoAttackXYZ_Loop)
			endif
			call DoAttackXYZSingle(udg_AV_Units[i], udg_AV_X[i], udg_AV_Y[i], udg_AV_Z[i], udg_AV_Attack[i])
		else
			call ReleaseTimer(t)
			return
		endif
	else
		set udg_AV_I[i] = udg_AV_I[i] - 1
		if udg_AV_I[i]<=0 then
			call ReleaseTimer(t)
		endif
		call DoAttackTargetSingle(udg_AV_Units[i], udg_AV_Target[i], udg_AV_Attack[i])
	endif
endfunction

function DoAttackTarget takes unit Source, unit Target, integer Attack returns integer
	local timer t
	local integer i
	if udg_attackSalvoSize[Attack]>1 then
		set t = NewTimer()
		set i = GetTimerId(t)
		set udg_AV_Units[i] = Source
		set udg_AV_Target[i] = Target
		set udg_AV_I[i] = udg_attackSalvoSize[Attack]-1
		set udg_AV_Attack[i] = Attack
		call TimerStart(t,udg_attackSalvoReloadTime[Attack],true,function DoAttackTarget_Loop)
	endif
	return DoAttackTargetSingle(Source, Target, Attack)
endfunction

function Nuke_End takes nothing returns nothing
	local timer t = GetExpiredTimer()
	local integer timerid = GetTimerId(t)
	call DestroyFogModifier(udg_AV_FogMod[timerid])
	set udg_AV_FogMod[timerid] = null
	call ReleaseTimer(t)
endfunction

function Nuke_Loop takes nothing returns nothing
	local timer t = GetExpiredTimer()
	local integer timerid = GetTimerId(t)
	set udg_AV_AOECurrent[timerid] = udg_AV_AOECurrent[timerid] + 500*0.25
	if udg_AV_AOECurrent[timerid]>udg_AV_AOE[timerid] then
		call TimerStart(t,12,false,function Nuke_End)
		call DestroyGroup(udg_AV_G[timerid])
		set udg_AV_G[timerid] = null
	else
		call DoAOEDamageEx(udg_AV_Units[timerid], udg_AV_Player[timerid], udg_AV_Damage[timerid], udg_AV_AOE[timerid], udg_AV_X[timerid],udg_AV_Y[timerid],udg_AV_Z[timerid],false,udg_AV_AOECurrent[timerid],udg_AV_G[timerid],0)
	endif
endfunction

function Nuke takes unit Source, player p, real X, real Y, real Z, real dmg, real aoe returns nothing
	local timer t = NewTimer()
	local integer timerid = GetTimerId(t)
	set udg_AV_FogMod[timerid] = CreateFogModifierRadius(p, FOG_OF_WAR_VISIBLE, X, Y, 200, true, false)
	call FogModifierStart(udg_AV_FogMod[timerid])
	set udg_AV_Units[timerid] = Source
	set udg_AV_Player[timerid] = p
	set udg_AV_X[timerid] = X
	set udg_AV_Y[timerid] = Y
	set udg_AV_Z[timerid] = Z
	set udg_AV_Damage[timerid] = dmg
	set udg_AV_AOECurrent[timerid] = 750
	set udg_AV_AOE[timerid] = aoe
	set udg_AV_G[timerid] = NewGroup()
	call AddSpecialEffect( "war3mapImported\\NuclearExplosion.mdx", X, Y )
	call TimerStart(t,0.25,true,function Nuke_Loop)
endfunction


//***************************************************************************
//*
//*  Terrain API
//*
//***************************************************************************

function SetTerrainPathable2x2 takes real X, real Y, pathingtype p, boolean b returns nothing
	call SetTerrainPathable(X+16,Y-16,p,b)
	call SetTerrainPathable(X+16,Y+16,p,b)
	call SetTerrainPathable(X-16,Y+16,p,b)
	call SetTerrainPathable(X-16,Y-16,p,b)
endfunction

function UpdateTerrainPathing_AdjustForPlatform takes real X, real Y returns nothing
	call SetTerrainPathable2x2(X+160,Y-160,PATHING_TYPE_WALKABILITY,false)
	call SetTerrainPathable2x2(X+160,Y-160,PATHING_TYPE_FLOATABILITY,false)
	call SetTerrainPathable2x2(X+160,Y-160,PATHING_TYPE_AMPHIBIOUSPATHING,false)

	call SetTerrainPathable2x2(X-160,Y-160,PATHING_TYPE_WALKABILITY,false)
	call SetTerrainPathable2x2(X-160,Y-160,PATHING_TYPE_FLOATABILITY,false)
	call SetTerrainPathable2x2(X-160,Y-160,PATHING_TYPE_AMPHIBIOUSPATHING,false)

	call SetTerrainPathable2x2(X-160,Y+160,PATHING_TYPE_WALKABILITY,false)
	call SetTerrainPathable2x2(X-160,Y+160,PATHING_TYPE_FLOATABILITY,false)
	call SetTerrainPathable2x2(X-160,Y+160,PATHING_TYPE_AMPHIBIOUSPATHING,false)

	call SetTerrainPathable2x2(X+160,Y+160,PATHING_TYPE_WALKABILITY,false)
	call SetTerrainPathable2x2(X+160,Y+160,PATHING_TYPE_FLOATABILITY,false)
	call SetTerrainPathable2x2(X+160,Y+160,PATHING_TYPE_AMPHIBIOUSPATHING,false)
endfunction

function UpdateTerrainPathing_AdjustForMass takes real X, real Y returns nothing
	call SetTerrainPathable2x2(X,Y,PATHING_TYPE_WALKABILITY,false)
	call SetTerrainPathable2x2(X,Y,PATHING_TYPE_FLOATABILITY,false)
	call SetTerrainPathable2x2(X,Y,PATHING_TYPE_AMPHIBIOUSPATHING,false)
	call SetTerrainPathable2x2(X,Y,PATHING_TYPE_BUILDABILITY,true)
endfunction

function UpdateTerrainPathing_AdjustForHydrocarbon_Child takes real X, real Y returns nothing
	call SetTerrainPathable2x2(X,Y,PATHING_TYPE_WALKABILITY,false)
	call SetTerrainPathable2x2(X,Y,PATHING_TYPE_FLOATABILITY,false)
	call SetTerrainPathable(X+16,Y-16,PATHING_TYPE_BUILDABILITY,true)
	call SetTerrainPathable(X+16,Y+16,PATHING_TYPE_BUILDABILITY,false)
	call SetTerrainPathable(X-16,Y+16,PATHING_TYPE_BUILDABILITY,true)
	call SetTerrainPathable(X-16,Y-16,PATHING_TYPE_BUILDABILITY,false)
	//call SetTerrainPathable2x2(X,Y,PATHING_TYPE_AMPHIBIOUSPATHING,true)
endfunction

function UpdateTerrainPathing_AdjustForHydrocarbon takes real X, real Y returns nothing
	call UpdateTerrainPathing_AdjustForHydrocarbon_Child(X-32,Y+32)
	call UpdateTerrainPathing_AdjustForHydrocarbon_Child(X-32,Y-32)
	call UpdateTerrainPathing_AdjustForHydrocarbon_Child(X+32,Y+32)
	call UpdateTerrainPathing_AdjustForHydrocarbon_Child(X+32,Y-32)
	call SetTerrainPathable2x2(X,Y,PATHING_TYPE_AMPHIBIOUSPATHING,false)
	call SetTerrainPathable(X+48,Y-48,PATHING_TYPE_AMPHIBIOUSPATHING,false)
	call SetTerrainPathable(X+48,Y+48,PATHING_TYPE_AMPHIBIOUSPATHING,false)
	call SetTerrainPathable(X-48,Y+48,PATHING_TYPE_AMPHIBIOUSPATHING,false)
	call SetTerrainPathable(X-48,Y-48,PATHING_TYPE_AMPHIBIOUSPATHING,false)
endfunction

function UpdateTerrainPathing_Destructables takes nothing returns nothing
	local destructable d = GetEnumDestructable()
	local real X = GetDestructableX(d)
	local real Y = GetDestructableY(d)
	if GetDestructableTypeId(d)=='B002' then
		call UpdateTerrainPathing_AdjustForMass(X,Y)
	elseif GetDestructableTypeId(d)=='B006' then
		call UpdateTerrainPathing_AdjustForHydrocarbon(X,Y)
	elseif GetDestructableTypeId(d)=='B007' then
		call UpdateTerrainPathing_AdjustForPlatform(X,Y)
	endif
	set d = null
endfunction

function UpdateTerrainPathing_Child takes nothing returns nothing
	local real X = GetLocationX(udg_tempLoc)
	local real Y = GetLocationY(udg_tempLoc)
	local real Z1
	local real Z2
	local real Z3
	local real Z4
	local real Z
	local boolean UPDATE_TEXTURE = (bj_forLoopAIndex>0)
	local integer i = 0

	call ThreadStart("UpdateTerrainPathing_Child")

	call MoveLocation(udg_tempLoc,X-32.,Y-32.)
	set Z2 = GetLocationZ(udg_tempLoc)
	call MoveLocation(udg_tempLoc,X+32.,Y-32.)
	set Z3 = GetLocationZ(udg_tempLoc)

	loop
			set Z1 = Z2
			set Z4 = Z3
			call MoveLocation(udg_tempLoc,X-32.,Y+32.)
			set Z2 = GetLocationZ(udg_tempLoc)
			call MoveLocation(udg_tempLoc,X+32.,Y+32.)
			set Z3 = GetLocationZ(udg_tempLoc)
			set Z = (Z2+Z4)*.5

			if udg_maxPathableInclineHelper>128*128/((Z4-Z2+Z3-Z1)*(Z4-Z2+Z3-Z1)+(Z3-Z1-Z4+Z2)*(Z3-Z1-Z4+Z2)+128.*128.) then
				call SetTerrainPathable2x2(X,Y,PATHING_TYPE_WALKABILITY,false)
				if Z>udg_waterHeight then
					call SetTerrainPathable2x2(X,Y,PATHING_TYPE_FLOATABILITY,false)
					call SetTerrainPathable2x2(X,Y,PATHING_TYPE_AMPHIBIOUSPATHING,false)
				else
					call SetTerrainPathable2x2(X,Y,PATHING_TYPE_FLOATABILITY,true)
					call SetTerrainPathable2x2(X,Y,PATHING_TYPE_AMPHIBIOUSPATHING,true)
				endif
				if UPDATE_TEXTURE then
					call SetTerrainType( X, Y, udg_tileCliff, -1, 1, 0 )
				endif
			elseif Z<=udg_waterHeight then
				if UPDATE_TEXTURE then
					call SetTerrainType( X, Y, udg_tileBeach, 0, 1, 0 )
				endif
				call SetTerrainPathable2x2(X,Y,PATHING_TYPE_WALKABILITY,false)
				call SetTerrainPathable2x2(X,Y,PATHING_TYPE_FLOATABILITY,true)
				call SetTerrainPathable2x2(X,Y,PATHING_TYPE_AMPHIBIOUSPATHING,true)
			else
				if UPDATE_TEXTURE and (Z<=udg_waterHeight+25) then
					call SetTerrainType( X, Y, udg_tileBeach, -1, 1, 0 )
				endif
				call SetTerrainPathable2x2(X,Y,PATHING_TYPE_WALKABILITY,true)
				call SetTerrainPathable2x2(X,Y,PATHING_TYPE_FLOATABILITY,false)
				call SetTerrainPathable2x2(X,Y,PATHING_TYPE_AMPHIBIOUSPATHING,true)
			endif
			if X > udg_mapMaxX-udg_mapBorderWidth or Y > udg_mapMaxY-udg_mapBorderWidth or X < udg_mapMinX+udg_mapBorderWidth or Y < udg_mapMinY+udg_mapBorderWidth then
				call SetTerrainPathable2x2(X,Y,PATHING_TYPE_ANY,false)
			else
				call SetTerrainPathable2x2(X,Y,PATHING_TYPE_BUILDABILITY,false)
			endif


			set i = i + 1


			set Y = Y + 64.
			if Y > GetRectMaxY(udg_tempRect) then
				set Y = GetRectMinY(udg_tempRect)+32.
				set X = X + 64.
				if X > GetRectMaxX(udg_tempRect) then
					set udg_Done = true
					exitwhen true
					// finished
				endif

				call MoveLocation(udg_tempLoc,X-32.,Y-32.)
				set Z2 = GetLocationZ(udg_tempLoc)
				call MoveLocation(udg_tempLoc,X+32.,Y-32.)
				set Z3 = GetLocationZ(udg_tempLoc)
			endif

		exitwhen i > 350
	endloop
	call MoveLocation(udg_tempLoc,X,Y)

	call ThreadClose("UpdateTerrainPathing_Child")
endfunction

function UpdateTerrainPathing takes rect R, boolean UpdateTextures returns nothing
	if udg_trg_Terrain_Update==null then
		set udg_maxPathableInclineHelper = Pow(Cos(udg_maxPathableInclineDeg*bj_DEGTORAD),2)
		set udg_trg_Terrain_Update = CreateTrigger()
		call TriggerAddAction(udg_trg_Terrain_Update,function UpdateTerrainPathing_Child)
	endif

	if UpdateTextures then
		set bj_forLoopAIndex = 1
	else
		set bj_forLoopAIndex = 0
	endif

	set udg_Done = false
	call MoveLocation(udg_tempLoc,GetRectMinX(R)+32,GetRectMinY(R)+32)
	call SetRect(udg_tempRect,GetRectMinX(R),GetRectMinY(R),GetRectMaxX(R),GetRectMaxY(R))
	loop
		exitwhen udg_Done
		call TriggerExecute(udg_trg_Terrain_Update)
	endloop
	call SetRect(udg_tempRect,GetRectMinX(R)-160,GetRectMinY(R)-160,GetRectMaxX(R)+160,GetRectMaxY(R)+160)
	call EnumDestructablesInRect(udg_tempRect, null, function UpdateTerrainPathing_Destructables)
endfunction

//***************************************************************************
//*
//*  Misc API
//*
//***************************************************************************

function GetPlayerFromString takes string playerstr returns player
	local integer pid = -1
	local integer minPos = 1000
	local integer curPos
	local integer i = 0
	if playerstr=="" or playerstr==null then
		return null
	endif
	set playerstr = StringCase(playerstr,false)
	loop
		exitwhen i > udg_maxPlayer
		set curPos = -1
		if (playerstr==I2S(i+1) or playerstr==udg_playerColorWord[i]) then
			set pid = i
			set minPos = 0
		endif
		set i = i + 1
	endloop
	if minPos!=0 then
		set i = 0
		loop
			exitwhen i > udg_maxPlayer
			set curPos = StringPos(StringCase(udg_playerName[i],false),playerstr)
			if curPos!=-1 and curPos<minPos then
				set pid = i
				set minPos = curPos
			endif
			set i = i + 1
		endloop
	endif
	if pid==-1 then
		return null
	endif
	return Player(pid)
endfunction

function GetUnitClassFromString_Child takes nothing returns nothing
	local integer curPos
	local integer iend = bj_forLoopBIndex+1024
	loop
		exitwhen bj_forLoopBIndex>iend
		if udg_classUnitType[bj_forLoopBIndex]!=0 and udg_classUnitType[bj_forLoopBIndex]!='h003' then
			set curPos = StringPos(StringCase(GetObjectName(udg_classUnitType[bj_forLoopBIndex]),false),bj_cineFadeContinueTex)
			if curPos!=-1 and curPos<bj_forLoopBIndexEnd then
				set bj_forLoopAIndexEnd = bj_forLoopBIndex
				set bj_forLoopBIndexEnd = curPos
			endif
		endif
		set bj_forLoopBIndex = bj_forLoopBIndex + 1
	endloop
endfunction

function GetUnitClassFromString takes string unitstr returns integer
	set bj_forLoopBIndex = 0
	set bj_forLoopAIndexEnd = 0
	set bj_forLoopBIndexEnd = 1000
	set bj_cineFadeContinueTex = unitstr
	if unitstr=="" or unitstr==null then
		return 0
	endif
	set bj_cineFadeContinueTex = StringCase(unitstr,false)
	call ExecuteFunc("GetUnitClassFromString_Child")
	call ExecuteFunc("GetUnitClassFromString_Child")
	call ExecuteFunc("GetUnitClassFromString_Child")
	call ExecuteFunc("GetUnitClassFromString_Child")
	call ExecuteFunc("GetUnitClassFromString_Child")
	call ExecuteFunc("GetUnitClassFromString_Child")
	call ExecuteFunc("GetUnitClassFromString_Child")
	call ExecuteFunc("GetUnitClassFromString_Child")
	return bj_forLoopAIndexEnd
endfunction

function Mode_GetBooleanOnOff takes boolean b returns string
	if b then
		return "On"
	endif
	return "Off"
endfunction

function Mode_GetMode takes nothing returns string
	if udg_modeValMode==0 then
		return "Assasination"
	elseif udg_modeValMode==1 then
		return "Annihilation"
	elseif udg_modeValMode==2 then
		return "Defense"
	endif
	return "Phantom"
endfunction

function Mode_GetPrebuilt takes nothing returns string
	if udg_modeValPrebuilt==1 then
		return "Base (T1)"
	elseif udg_modeValPrebuilt==2 then
		return "Base (T2)"
	elseif udg_modeValPrebuilt==3 then
		return "Base (T3)"
	elseif udg_modeValPrebuilt==4 then
		return "Base (T4)"
	endif
	return "Off"
endfunction

function Mode_GetNoRush takes nothing returns string
	if udg_modeValNoRush==1 then
		return "5 min"
	elseif udg_modeValNoRush==2 then
		return "15 min"
	elseif udg_modeValNoRush==3 then
		return "30 min"
	endif
	return "Off"
endfunction

function RefreshModeDialog takes nothing returns nothing
	call DialogClear(udg_modeDialog)
	call DialogSetMessage(udg_modeDialog, "|cffffffffSelect Options|r")
	set udg_modeBtMode = DialogAddButton(udg_modeDialog, "|cffffffffM|rode: "+Mode_GetMode(), 'M')
	set udg_modeBtPrebuilt = DialogAddButton(udg_modeDialog, "|cffffffffP|rrebuilt: "+Mode_GetPrebuilt(), 'P')
	set udg_modeBtTeamSize = DialogAddButton(udg_modeDialog, "|cffffffffT|ream Size: "+I2S(udg_modePossibleTeamSizes[udg_modeValTeamSize]), 'T')
	set udg_modeBtLockTeams = DialogAddButton(udg_modeDialog, "|cffffffffL|rock Teams: "+Mode_GetBooleanOnOff(udg_modeValLockTeams), 'L')
	set udg_modeBtNoRush = DialogAddButton(udg_modeDialog, "No |cffffffffR|rush: "+Mode_GetNoRush(), 'R')
	set udg_modeBtLeaverAI = DialogAddButton(udg_modeDialog, "Leaver |cffffffffA|rI: "+Mode_GetBooleanOnOff(udg_modeValLeaverAI), 'A')
	set udg_modeBtGo = DialogAddButton(udg_modeDialog, "|cffffffffO|rk", 'O')
endfunction

function FadeToMusic_Child takes nothing returns nothing
	local timer t = GetExpiredTimer()
	local integer tid = GetTimerId(t)
	local real fadeOut = udg_AV_X[tid]
	local real fadeIn = udg_AV_Y[tid]
	set udg_AV_Z[tid]=udg_AV_Z[tid]+0.02
	if udg_AV_A[tid] then
		if udg_AV_Z[tid]<fadeOut then
			call SetMusicVolume(R2I(udg_AV_I[tid]-udg_AV_I[tid]*udg_AV_Z[tid]/fadeOut))
		else
			if not udg_AV_B[tid] then
				set udg_AV_B[tid] = true
				call PlayMusic(udg_AV_S[tid])
			endif
			if udg_AV_Z[tid]<fadeOut+fadeIn then
				call SetMusicVolume(R2I(udg_AV_J[tid]*(udg_AV_Z[tid]-fadeOut)/fadeIn))
			else
				call SetMusicVolume(udg_AV_J[tid])
				call ReleaseTimer(t)
			endif
		endif
	elseif udg_AV_Z[tid]>=fadeOut+fadeIn then
		call ReleaseTimer(t)
	endif
endfunction

function FadeToMusic takes string NewMusic, integer OldVolume, integer NewVolume, real fadeOut, real fadeIn, boolean Do returns nothing
	local timer t = NewTimer()
	local integer tid = GetTimerId(t)
	set udg_AV_S[tid] = NewMusic
	set udg_AV_I[tid] = OldVolume
	set udg_AV_J[tid] = NewVolume
	set udg_AV_X[tid] = fadeOut
	set udg_AV_Y[tid] = fadeIn
	set udg_AV_Z[tid] = 0
	set udg_AV_A[tid] = Do
	set udg_AV_B[tid] = false
	call TimerStart(t,0.02,true,function FadeToMusic_Child)
endfunction

function UnitRefreshColor takes unit U returns nothing
	local integer Class = udg_unitClass[GetUnitUserData(U)]
	if Class==0 then
		set Class = GetUnitClass(U)
	endif
	if GetUnitState(U,UNIT_STATE_LIFE)>0 then
		call SetUnitVertexColor(U,udg_classColorR[Class],udg_classColorG[Class],udg_classColorB[Class],255-(GetUnitAbilityLevel(U,'Apiv')*127))
	else
		call SetUnitVertexColor(U,udg_classColorR[Class]/4,udg_classColorG[Class]/4,udg_classColorB[Class]/4,255)
	endif
endfunction

function UnitProvidesAdjecency takes unit U returns boolean
	local integer Class = GetUnitClass(U)
	return udg_classAdjEnergyCostFactor[Class]!=1 or udg_classAdjMassCostFactor[Class]!=1 or udg_classAdjMassIncomeFactor[Class]!=1 or udg_classAdjEnergyIncomeFactor[Class]!=1
endfunction

function UnitRefreshEnergyAbility takes unit U returns nothing
	local integer Id = GetUnitUserData(U)
	local integer Class = udg_unitClass[Id]
	if udg_unitSpecialWorks[Id] then
		if udg_classEnergyAbility[Class]!=0 and GetUnitAbilityLevel(U,udg_classEnergyAbility[Class])==0 then
			call UnitAddAbility(U,udg_classEnergyAbility[Class])
		endif
	else
		if udg_classEnergyAbility[Class]!=0 and GetUnitAbilityLevel(U,udg_classEnergyAbility[Class])!=0 then
			call UnitRemoveAbility(U,udg_classEnergyAbility[Class])
		endif
	endif
endfunction

function CheckUnitVisibility takes unit U returns nothing
	local group G
	local unit EnumU
	local integer Id = GetUnitUserData(U)
	local boolean visible = true
	if (udg_unitProducesUnit[Id]!=0) or (udg_unitConstructionState[Id]<10) or (udg_unitUpgradesTo[Id]!=0) then
		set visible = true
	elseif udg_unitSpecialWorks[Id] and (udg_classStealthRange[udg_unitClass[Id]]>0) then
		set visible = false
	else
		set G = NewGroup()
		call GroupEnumUnitsInRange(G,GetUnitX(U),GetUnitY(U),1000,null)
		loop
			set EnumU = FirstOfGroup(G)
			exitwhen EnumU==null
			set Id = GetUnitUserData(EnumU)
			if Id>0 and udg_unitSpecialWorks[Id] and (udg_classStealthRange[udg_unitClass[Id]]>10) and (GetAllianceByUnit(EnumU,U)==0) then
				if IsUnitInRangeXY(U,GetUnitX(EnumU),GetUnitY(EnumU),udg_classStealthRange[udg_unitClass[Id]]) then
					set visible = false
				endif
			endif
			call GroupRemoveUnit(G,EnumU)
		endloop
	endif
	if GetUnitAbilityLevel(U,'Apiv')!=0 then
		if visible then
			call UnitRemoveAbility(U,'Apiv')
			call UnitRefreshColor(U)
		endif
	else
		if not visible then
			call UnitAddAbility(U,'Apiv')
			call UnitRefreshColor(U)
		endif
	endif
	call SetUnitInGroup(U,udg_groupStealth,not visible)
endfunction

function CheckRessourceUnit takes unit U returns nothing
	local integer Id = GetUnitUserData(U)
	local integer Class = udg_unitClass[Id]
	call SetUnitInGroup(U, udg_groupRessOnlyIncome, udg_unitProductionOn[Id] and ((udg_classProducedMass[Class]>=0) and (udg_classProducedEnergy[Class]>=0)))
	call SetUnitInGroup(U, udg_groupRessIncomeWithFee,udg_unitProductionOn[Id] and ((udg_classProducedMass[Class]>0) or (udg_classProducedEnergy[Class]>0)) and ((udg_classProducedMass[Class]<0) or (udg_classProducedEnergy[Class]<0)))
	call SetUnitInGroup(U, udg_groupRessUpgradeAndTrain,udg_unitUpgradesTo[Id]!=0 or udg_unitProducesUnit[Id]!=0)
	call SetUnitInGroup(U, udg_groupRessUse,((udg_classProducedMass[Class]<=0) and (udg_classProducedEnergy[Class]<=0) and (udg_classProducedMass[Class]+udg_classProducedEnergy[Class]<0)) or (udg_classRadarRange[Class]!=0) or (udg_classStealthRange[Class]!=0) or (udg_classManaRegeneration[Class]!=0))
endfunction

function CheckAutoFire takes unit U returns nothing
	local integer Id = GetUnitUserData(U)
	local boolean HasAutoFireWeapon = false
	local integer weapon = udg_unitFirstWeapon[Id]
	local integer attack
	local boolean IsLoaded = IsUnitLoaded(U)
	if (udg_unitConstructionState[Id]>10) and (udg_unitUpgradesTo[Id]==0) then
		loop
			exitwhen (weapon==0) or HasAutoFireWeapon
			set attack = udg_weaponAttack[weapon]
			set HasAutoFireWeapon = ((udg_attackSpecial[attack]==8) or not IsLoaded) and (((not udg_attackBind[attack]) or ((udg_attackSpecial[attack]==8) and IsLoaded)) and (udg_attackAntiGround[attack] or udg_attackAntiWater[attack] or udg_attackAntiAir[attack] or udg_attackAntiStrategic[attack] or udg_attackAntiTactical[attack] or udg_attackAntiTorpedo[attack]))
			set weapon = udg_weaponNext[weapon]
		endloop
	endif
	call SetUnitInGroup(U, udg_groupAutoFire,HasAutoFireWeapon)
endfunction

function NewRangeUnit takes real X, real Y, real FlyHeight, real range returns unit
	local unit U
	if udg_rangeUnitStackN<=0 then
		set U = CreateUnit(Player(15),'h01Y',X,Y,270)
		call UnitAddAbility(U,'Amrf')
		call SetUnitPathing(U,false)
		call SetUnitVertexColor(U,255,255,255,0)
	else
		set udg_rangeUnitStackN=udg_rangeUnitStackN-1
		set U = udg_rangeUnitStack[udg_rangeUnitStackN]
	endif
	if FlyHeight<0 then
		set FlyHeight = 0
	endif
	call SetUnitFlyHeight(U,FlyHeight,0)
	call SetUnitX(U,X)
	call SetUnitY(U,Y)
	call SetUnitScale(U,range*.0286,range*.0286,range*.0286)
	return U
endfunction

function ReleaseRangeUnit takes unit U returns nothing
	if udg_rangeUnitStackN>20 then
		call RemoveUnit(U)
	else
		call SetUnitVertexColor(U,255,255,255,0)
		set udg_rangeUnitStack[udg_rangeUnitStackN]=U
		set udg_rangeUnitStackN=udg_rangeUnitStackN+1
	endif
endfunction

function CheckUnitRangeDisplay takes unit U returns nothing
	local integer id = GetUnitUserData(U)
	local integer pid = GetPlayerId(GetOwningPlayer(U))
	local boolean Display = udg_playerRangeDisplay[pid] and (id>0) and (udg_classFirstAttack[udg_unitClass[id]]!=0) and IsUnitInGroup(U,udg_playerUnitsSelected[pid]) and (not IsUnitLoaded(U))
	local integer i
	local real r
	if Display then
		set r = udg_attackRange[udg_classFirstAttack[udg_unitClass[id]]]
		set udg_unitRangeDisplay[id] = true
		set i = 1
		loop
			exitwhen i > udg_rangeCount
			if udg_rangeFollowUnit[i]==U and udg_rangePlayerId[i]==pid then
				set udg_rangeFadeout[i] = (udg_rangeRadius[i]!=r) or (not Display)
				if not udg_rangeFadeout[i] then
					set Display = false
				endif
			endif
			set i = i + 1
		endloop
		if Display then
			set udg_rangeCount = udg_rangeCount + 1
			set udg_rangeRadius[udg_rangeCount] = r
			set udg_rangeUnit[udg_rangeCount] = NewRangeUnit(GetUnitX(U),GetUnitY(U),GetUnitFlyHeight(U)+udg_classCollisionZOffset[udg_unitClass[id]],r)
			set udg_rangeFollowUnit[udg_rangeCount] = U
			set udg_rangeAlpha[udg_rangeCount] = 0
			set udg_rangePlayerId[udg_rangeCount] = pid
			set udg_rangeFadeout[udg_rangeCount] = false
		endif
	elseif id>0 then
		set udg_unitRangeDisplay[id] = false
	endif
endfunction

function GetUnitEcoString takes unit U returns string
	local string s = null
	local real dps = 0.
	local real dpsa = 0.
	local real dpsg = 0.
	local real dpsn = 0.
	local integer Id = GetUnitUserData(U)
	local integer Class = udg_unitClass[Id]
	local integer weapon = udg_unitFirstWeapon[Id]
	local integer attack
	local real massinc = 0.
	local real energyinc = 0.
	local integer buildthis
	local real r
	local real buildspeed
	loop
		exitwhen weapon==0
		set attack = udg_weaponAttack[weapon]
		if (udg_attackCooldown[attack]>0) then
			set r = udg_attackSalvoSize[attack]*udg_attackDamage[attack]/udg_attackCooldown[attack]
			if (udg_attackAntiGround[attack]) then
				set dpsg = dpsg + r
			endif
			if (udg_attackAntiAir[attack]) then
				set dpsa = dpsa + r
			endif
			if (udg_attackAntiWater[attack]) then
				set dpsn = dpsn + r
			endif
			if (udg_attackAntiGround[attack] or udg_attackAntiAir[attack] or udg_attackAntiWater[attack]) then
				set dps = dps + r
			endif
		endif
		set weapon = udg_weaponNext[weapon]
	endloop
	if udg_unitProductionOn[Id] then
		if udg_classProducedMass[Class]>=0 then
			set massinc = udg_unitAdjMassIncomeFactor[Id]*udg_classProducedMass[Class]
		else
			set massinc = udg_unitAdjMassCostFactor[Id]*udg_classProducedMass[Class]
		endif
		if udg_classProducedEnergy[Class]>=0 then
			set energyinc = udg_unitAdjEnergyIncomeFactor[Id]*udg_classProducedEnergy[Class]
		else
			set energyinc = udg_unitAdjEnergyCostFactor[Id]*udg_classProducedEnergy[Class]
		endif
	endif
	set buildthis = udg_unitUpgradesTo[Id]
	if udg_unitProducesUnit[Id]!=0 then
		set buildthis = GetUnitTypeClass(udg_unitProducesUnit[Id])
	endif
	if buildthis!=0 then
		set massinc = massinc - udg_unitAdjMassCostFactor[Id]*udg_classCostsMass[buildthis]/udg_classBuildTimeReal[buildthis]
		set energyinc = energyinc - udg_unitAdjEnergyCostFactor[Id]*udg_classCostsEnergy[buildthis]/udg_classBuildTimeReal[buildthis]
	endif
	if udg_unitChannelTarget[Id]!=null and IsUnitInGroup(U,udg_groupBuildingUnits) then
		set buildthis = GetUnitClass(udg_unitChannelTarget[Id])
		if udg_unitConstructionState[GetUnitUserData(udg_unitChannelTarget[Id])]<10 then
			set r = 1.
		else
			set r = udg_repairCostFactor/udg_repairTimeFactor
		endif
		if buildthis!=0 then
			set buildspeed = udg_classBuildSpeed[udg_unitClass[Id]]+GetUnitModuleBuildSpeed(U)
			set massinc = massinc - buildspeed*udg_classCostsMass[buildthis]/udg_classBuildTimeBase[buildthis]*r
			set energyinc = energyinc - buildspeed*udg_classCostsEnergy[buildthis]/udg_classBuildTimeBase[buildthis]*r
		endif
	endif
	if (R2I(massinc)!=0) then
		if s!=null then
			set s = s + " / "
		else
			set s = "("
		endif
		set s = s+"|cffffcc00"
		if massinc>=0. then
			set s = s + "+"
		endif
		set s = s + I2S(R2I(massinc))+"|r"
	endif
	if (R2I(energyinc)!=0) then
		if s!=null then
			set s = s + " / "
		else
			set s = "("
		endif
		set s = s+"|cff5555ff"
		if energyinc>=0. then
			set s = s + "+"
		endif
		set s = s + I2S(R2I(energyinc))+"|r"
	endif
	if dpsg!=0. then
		if s!=null then
			set s = s + " / "
		else
			set s = "("
		endif
		set s = s + "|cffff0000G "+I2S(R2I(dpsg))+"|r"
	endif
	if dpsn!=0. then
		if s!=null then
			set s = s + " / "
		else
			set s = "("
		endif
		set s = s + "|cffff0000N "+I2S(R2I(dpsn))+"|r"
	endif
	if dpsa!=0. then
		if s!=null then
			set s = s + " / "
		else
			set s = "("
		endif
		set s = s + "|cffff0000A "+I2S(R2I(dpsa))+"|r"
	endif
	if s!=null then
		return s+")"
	endif
	return ""
endfunction

function CheckUnitEcoDisplay takes unit U, boolean refreshText returns nothing
	local integer id = GetUnitUserData(U)
	local integer pid = GetPlayerId(GetOwningPlayer(U))
	local boolean Display = udg_playerEcoDisplay[pid] and (id>0) and IsUnitInGroup(U,udg_playerUnitsSelected[pid]) and (not IsUnitLoaded(U))
	local integer i
	if Display then
		set udg_unitEcoDisplay[id] = true
		set i = 1
		loop
			exitwhen i > udg_ecoCount
			if udg_ecoFollowUnit[i]==U and udg_ecoPlayerId[i]==pid then
				if refreshText then
					set udg_ecoString[i] = GetUnitEcoString(U)
					call SetTextTagText(udg_ecoTag[i], udg_ecoString[i] ,  0.023)
				endif
				set udg_ecoFadeout[i] = (not Display)
				set Display = false
			endif
			set i = i + 1
		endloop
		if Display then
			set udg_ecoCount = udg_ecoCount + 1
			set udg_ecoTag[udg_ecoCount] = CreateTextTag()
			set udg_ecoString[udg_ecoCount] = GetUnitEcoString(U)
			call SetTextTagText(udg_ecoTag[udg_ecoCount], udg_ecoString[udg_ecoCount] ,  0.023)
			call SetTextTagPos(udg_ecoTag[udg_ecoCount], GetUnitX(U), GetUnitY(U), GetUnitFlyHeight(U)+udg_classCollisionZOffset[udg_unitClass[id]])
			call SetTextTagVisibility(udg_ecoTag[udg_ecoCount],pid==GetPlayerId(GetLocalPlayer()))
			call SetTextTagPermanent(udg_ecoTag[udg_ecoCount],false)
			call SetTextTagColor(udg_ecoTag[udg_ecoCount], 255, 255, 255, 0)
			set udg_ecoFollowUnit[udg_ecoCount] = U
			set udg_ecoAlpha[udg_ecoCount] = 0
			set udg_ecoPlayerId[udg_ecoCount] = pid
			set udg_ecoFadeout[udg_ecoCount] = false
		endif
	elseif id>0 then
		set udg_unitEcoDisplay[id] = false
	endif
endfunction

function Init_Colors takes nothing returns nothing
	local integer i = 0
	set udg_Color[0] = "|cFFFF0303"
	set udg_Color[1] = "|cFF0042FF"
	set udg_Color[2] = "|cFF1CE6B9"
	set udg_Color[3] = "|cFF540081"
	set udg_Color[4] = "|cFFFFFC01"
	set udg_Color[5] = "|cFFFE8A0E"
	set udg_Color[6] = "|cFF20C000"
	set udg_Color[7] = "|cFFE55BB0"
	set udg_Color[8] = "|cFF959697"
	set udg_Color[9] = "|cFF7EBFF1"
	set udg_Color[10] = "|cFF106246"
	set udg_Color[11] = "|cFF4E2A04"
	loop
		exitwhen i > udg_maxPlayer
		set udg_playerNameColored[i] = udg_Color[i] + udg_playerName[i] + "|r"
		set i = i + 1
	endloop
endfunction

function CheckVictory_Child takes nothing returns nothing
	local integer teamcount = 0
	local integer pid = 0
	local integer pid2
	local boolean GameOver = false
	local player array winners
	local integer winnersCount = 0
	local string s
	call ReleaseTimer(GetExpiredTimer())
	if not udg_GameOver then
		if udg_modeValMode==2 then
			loop
				exitwhen pid>udg_maxPlayer
				if udg_playerAlive[pid] then
					set winnersCount = winnersCount + 1
				endif
				set pid = pid + 1
			endloop
			if winnersCount==0 then
				set GameOver = true
			endif
			set pid = 1
			set winnersCount = 0
			loop
				exitwhen pid > udg_tdspawnMax
				if GetUnitState(udg_tdspawnGate[pid],UNIT_STATE_LIFE)>0 then
					set winnersCount = winnersCount + 1
				endif
				set pid = pid + 1
			endloop
			if winnersCount==0 then
				set GameOver = true
			endif
		elseif udg_Phantom!=null then
			if not udg_playerAlive[GetPlayerId(udg_Phantom)] then
				set GameOver = true
			else
				loop
					exitwhen pid>udg_maxPlayer
					if udg_playerAlive[pid] then
						set winnersCount = winnersCount + 1
					endif
					set pid = pid + 1
				endloop
				if winnersCount==1 then
					set GameOver = true
				endif
			endif
		else
			set GameOver = true
			loop
				exitwhen pid>udg_maxPlayer
				set pid2 = 0
				loop
					exitwhen pid2>udg_maxPlayer
					if udg_playerAlive[pid] and udg_playerAlive[pid2] and (GetAllianceById(pid,pid2)!=0) then
						set GameOver = false
					endif
					set pid2 = pid2 + 1
				endloop
				set pid = pid + 1
			endloop
		endif
	endif
	if GameOver then
		set udg_GameOver = true
		set pid = 0
		set winnersCount = 0
		loop
			exitwhen pid > udg_maxPlayer
			if udg_playerAlive[pid] then
				set winnersCount = winnersCount + 1
				set winners[winnersCount] = Player(pid)
			endif
			set pid = pid + 1
		endloop
		if winnersCount==0 then
			set s = "Nobody is victorious."
		else
			set s = ""
			set pid = 1
			loop
				exitwhen pid>winnersCount
				set s = s + udg_playerNameColored[GetPlayerId(winners[pid])]
				if winnersCount-pid>=2 then
					set s = s + ", "
				elseif winnersCount-pid>=1 then
					set s = s + " and "
				endif
				set pid = pid + 1
			endloop
			if winnersCount>1 then
				set s = s + " are victorious."
			else
				set s = s + " is victorious."
			endif
		endif
		set s = s + "\nVisit |cfffed312supcom.btanks.net|r for more maps."
		call DisplayTimedTextToPlayer( GetLocalPlayer(), 0,0,120,GetTimeStamp()+" "+s )
		call StartSound(gg_snd_GoodJob)
	endif
endfunction

function CheckVictory takes nothing returns nothing
	call TimerStart(NewTimer(),2,false,function CheckVictory_Child)
endfunction

function PlayerDefeat takes player p, real x, real y returns nothing
	local fogmodifier fogmod = CreateFogModifierRect(p, FOG_OF_WAR_VISIBLE, GetWorldBounds(), false, false)
	local integer i = 0
	local group G
	local unit U
	local string s
	set udg_playerAlive[GetPlayerId(p)] = false
	set udg_playerAI[GetPlayerId(p)] = false
	call TriggerSleepAction(0.5)


	loop
		exitwhen i > udg_maxPlayer
		if p!=Player(i) then
			call SetPlayerAlliance(Player(i), p, ALLIANCE_SHARED_VISION, true)
			call SetPlayerAlliance(p, Player(i), ALLIANCE_SHARED_VISION, false)
		endif
		set i = i + 1
	endloop
	call FogModifierStart(fogmod)
	call LeaderboardDisplay(udg_resourceBoard[GetPlayerId(p)],false)
	call SetPlayerState(p,PLAYER_STATE_RESOURCE_GOLD,0)
	call SetPlayerState(p,PLAYER_STATE_RESOURCE_LUMBER,0)

	set G = NewGroup()
	call GroupEnumUnitsOfPlayer(G,p,null)
	loop
		set U = FirstOfGroup(G)
		exitwhen U == null
		if (GetUnitUserData(U)>0) and (GetUnitState(U,UNIT_STATE_LIFE)>0) then
			call KillUnit(U)
		endif
		call GroupRemoveUnit(G,U)
	endloop
	call ReleaseGroup(G)
	set s = GetTimeStamp()+" "+udg_playerNameColored[GetPlayerId(p)]+" has been defeated."
	if udg_Phantom==p then
		set s = s + "\nThe phantom has been detected and erased."
	elseif udg_Phantom!=null and udg_playerAlive[GetPlayerId(udg_Phantom)] then
		set s = s + "\nThe phantom is still alive."
	endif
	call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,s)
	call SetPlayerName(p,udg_playerName[GetPlayerId(p)]+" (Dead)")
	call PingMinimap(x, y, 5)
	call CheckVictory()
endfunction

function CheckPlayerDefeat takes player p, real x, real y returns nothing
	local boolean alive = false
	local group G
	local unit U
	if not udg_playerAlive[GetPlayerId(p)] then
		return
	endif
	if udg_modeValMode==1 then
		set G = NewGroup()
		call GroupEnumUnitsOfPlayer(G,p,null)
		loop
			set U = FirstOfGroup(G)
			exitwhen (U == null) or alive
			if (GetUnitUserData(U)>0) and (GetUnitState(U,UNIT_STATE_LIFE)>0) then
				set alive = true
			endif
			call GroupRemoveUnit(G,U)
		endloop
		call ReleaseGroup(G)
		set U = null
	else
		set alive = GetUnitState(udg_playerACU[GetPlayerId(p)],UNIT_STATE_LIFE)>0
	endif
	if not alive then
		call PlayerDefeat(p,x,y)
	endif
endfunction

function SetUnitOwnerEx takes unit U, player NewOwner, boolean changeColor returns nothing
	local integer OldOwnerId = GetPlayerId(GetOwningPlayer(U))
	local integer NewOwnerId = GetPlayerId(NewOwner)
	local integer Id = GetUnitUserData(U)
	local integer weap = 0
	call SetUnitOwner( U, NewOwner, changeColor )
	call CheckPlayerDefeat(Player(OldOwnerId), GetUnitX(U), GetUnitY(U))
	if Id>0 then
		set udg_calculateAdjecency = true
		set udg_calculateRessourceCaps = true

		if udg_unitProducesUnit[Id]!=0 then
			set udg_playerMass[NewOwnerId] = udg_playerMass[NewOwnerId]+udg_unitUsedMass[Id]
			set udg_playerEnergy[NewOwnerId] = udg_playerEnergy[NewOwnerId]+udg_unitUsedEnergy[Id]
			set udg_unitProducesUnit[Id] = 0
			set udg_unitProducesUnitState[Id] = 0
			set udg_unitUsedMass[Id] = 0
			set udg_unitUsedEnergy[Id] = 0
			call PauseUnit(U,false)
			set udg_unitPaused[Id] = false
			call CheckRessourceUnit(U)
		endif
		set udg_unitRangeDisplay[Id] = false
		call CheckUnitEcoDisplay(U,true)
		call CheckUnitVisibility(U)
		call CheckUnitRangeDisplay(U)
		if GetUnitAbilityLevel(U,'A000')!=0 then
			call ResetShieldCheckTimes()
		endif
	endif
	loop
		exitwhen weap>udg_weaponStackMax
		if udg_weaponTarget[weap]==U then
			set udg_weaponTarget[weap] = null
		endif
		set weap = weap + 1
	endloop
	call IssueImmediateOrder(U,"stop")
endfunction

//***************************************************************************
//*
//*  AI API
//*
//***************************************************************************

function AIGetUnits_Filter takes nothing returns boolean
	return GetUnitAbilityLevel(GetFilterUnit(),'Aloc')==0 and (GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)>0)
endfunction

function AIGetUnits takes player p returns group
	local group G = NewGroup()
	call GroupEnumUnitsOfPlayer(G, p, Filter(function AIGetUnits_Filter))
	return G
endfunction

function AIGetFreeUnits_Filter takes nothing returns boolean
	return GetUnitAbilityLevel(GetFilterUnit(),'Aloc')==0 and (GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)>0) and (GetUnitCurrentOrder(GetFilterUnit())==OrderId("stop") or GetUnitCurrentOrder(GetFilterUnit())==0)
endfunction

function AIGetFreeUnits takes player p returns group
	local group G = NewGroup()
	call GroupEnumUnitsOfPlayer(G, p, Filter(function AIGetFreeUnits_Filter))
	return G
endfunction

function AIGetUnitsOfType_Filter takes nothing returns boolean
	return (GetUnitTypeId(GetFilterUnit())==bj_groupEnumTypeId) and (GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)>0)
endfunction

function AIGetUnitsOfType takes player p, integer typeid returns group
	local group G = NewGroup()
	set bj_groupEnumTypeId = typeid
	call GroupEnumUnitsOfPlayer(G, p, Filter(function AIGetUnitsOfType_Filter))
	return G
endfunction

function AIGetFreeUnitsOfType_Filter takes nothing returns boolean
	return (GetUnitTypeId(GetFilterUnit())==bj_groupEnumTypeId) and (GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)>0) and (GetUnitCurrentOrder(GetFilterUnit())==OrderId("stop") or GetUnitCurrentOrder(GetFilterUnit())==0)
endfunction

function AIGetFreeUnitsOfType takes player p, integer typeid returns group
	local group G = NewGroup()
	set bj_groupEnumTypeId = typeid
	call GroupEnumUnitsOfPlayer(G, p, Filter(function AIGetFreeUnitsOfType_Filter))
	return G
endfunction

function AIGetEnemyUnits_Filter takes nothing returns boolean
	return (GetUnitUserData(GetFilterUnit())>0) and (IsUnitType(GetFilterUnit(),UNIT_TYPE_MECHANICAL)==false)
endfunction

function AIGetEnemyUnits takes player p returns group
	local integer pid = 0
	local group G = NewGroup()
	local group G2 = NewGroup()
	loop
		exitwhen pid>udg_maxPlayer
		if (GetAllianceById(GetPlayerId(p),pid)==2) then
			call GroupEnumUnitsOfPlayer(G2, Player(pid), Filter(function AIGetEnemyUnits_Filter))
			call GroupAddGroup(G2,G)
		endif
		set pid = pid + 1
	endloop
	call ReleaseGroup(G2)
	return G
endfunction

function AIGetNearestFreeMass takes real X, real Y returns integer
	local integer massLoop = 1
	local real nearestdist = 0
	local real currentdist
	local integer massNearest = 0
	loop
		exitwhen massLoop>udg_massCount
		set currentdist = (X-udg_massX[massLoop])*(X-udg_massX[massLoop])+(Y-udg_massY[massLoop])*(Y-udg_massY[massLoop])
		if (massNearest==0 or currentdist<nearestdist) and (not IsGroundUnitNearby(udg_massX[massLoop],udg_massY[massLoop],16)) then
			set nearestdist = currentdist
			set massNearest = massLoop
		endif
		set massLoop = massLoop + 1
	endloop

	return massNearest
endfunction

function AIUnitBuildMassExtractor takes unit U returns boolean
	local integer nearestMass = AIGetNearestFreeMass(GetUnitX(U),GetUnitY(U))
	if nearestMass==0 then
		return false
	endif
	return IssueBuildOrderById(U, 'h00G', udg_massX[nearestMass], udg_massY[nearestMass])
endfunction

function AIUnitBuildUnit takes unit U, integer typeid returns boolean
	local real X
	local real Y
	local real CheckX
	local real CheckY
	local real Offset
	local real OffsetAngle
	local real OffsetAngleStart
	local boolean b = false
	if typeid=='h00G' then
		set b =  AIUnitBuildMassExtractor(U)
	else
		set X = GetUnitX(U)
		set Y = GetUnitY(U)
		set Offset = 256
		set OffsetAngleStart = GetRandomReal(0,360)
		set OffsetAngle = OffsetAngleStart
		loop
			set OffsetAngle = OffsetAngle + 45

			set CheckX = X + Offset*Cos(OffsetAngle*bj_DEGTORAD)
			set CheckY = Y + Offset*Sin(OffsetAngle*bj_DEGTORAD)
			call MoveLocation(udg_tempLoc,CheckX,CheckY)
			if GetLocationZ(udg_tempLoc)>udg_waterHeight and IssueBuildOrderById(U, typeid, CheckX, CheckY) then
				set b = true
				exitwhen true
			endif

			if OffsetAngle>=OffsetAngleStart+360 then
				set OffsetAngle = 0
				set Offset = Offset + 128
				if Offset>2048 then
					set b = false
					exitwhen true
				endif
			endif
		endloop
	endif
	return b
endfunction

function AIWorkerAssist takes unit U returns nothing
	local group G = AIGetUnits(GetOwningPlayer(U))
	local unit EnumU = FirstOfGroup(G)
	local real X = GetUnitX(U)
	local real Y = GetUnitY(U)
	loop
		exitwhen EnumU==null
		if GetUnitState(EnumU,UNIT_STATE_LIFE)<GetUnitState(EnumU,UNIT_STATE_MAX_LIFE) and Pow(GetUnitX(EnumU)-X,2)+Pow(GetUnitY(EnumU)-Y,2)<1000000 then
			call IssueTargetOrder(U,"repair",EnumU)
			call ReleaseGroup(G)
			set EnumU = null
			return
		endif
		call GroupRemoveUnit(G,EnumU)
		set EnumU = FirstOfGroup(G)
	endloop
	call ReleaseGroup(G)
endfunction

function AIGetMassRemain takes player p, integer typeid returns real
	local integer pid = GetPlayerId(p)
	local integer class = GetUnitTypeClass(typeid)
	return udg_playerMass[pid] - udg_classCostsMass[class] + udg_classBuildTimeReal[class]*(udg_playerMassIncome[pid]-udg_playerMassUse[pid])
endfunction

function AIGetEnergyRemain takes player p, integer typeid returns real
	local integer pid = GetPlayerId(p)
	local integer class = GetUnitTypeClass(typeid)
	return udg_playerEnergy[pid] - udg_classCostsEnergy[class] + udg_classBuildTimeReal[class]*(udg_playerEnergyIncome[pid]-udg_playerEnergyUse[pid])
endfunction

function AIGetRandomName takes player p returns string
	local string array names
	local string name
	set names[1] = "EarthAlliance"
	set names[2] = "RisingEmpire"
	set names[3] = "Dominator"
	set names[4] = "Imperium"
	set names[5] = "OuterSpace"
	set names[6] = "ReignOfDarkness"
	set names[7] = "Prediction"
	set names[8] = "HolyForce"
	set names[9] = "Protector"
	set names[10] = "UniversalEmpire"
	set names[11] = "GalacticKingdom"
	set names[12] = "SpaceInvaders"
	set names[13] = "TheChosenArmy"
	set names[14] = "Ambassador"
	set names[15] = "SupremeArmy"
	set names[16] = "Destroyer"
	set names[17] = "Operator"
	set names[18] = "ExMachina"
	set names[19] = "AlphaCentauri"
	set names[20] = "GalaxyForce"
	set name = names[GetRandomInt(1,20)]
	return name + " (AI)"
endfunction
Name Type Is Array Initial Value
AHeavySplit integer No
ai boolean No
aiArmyList unitcode Yes
aiArmyListCount integer No
aiBuildingLastAction real Yes
aiBuildingList unitcode Yes
aiBuildingListCount integer No
aiBuildingListDone boolean Yes
aiBuildingListGroup group No
aiCurId integer No
aiInitialized boolean No
aiTargetLoc location Yes
Ally integer No 0
ArtillSplit integer No
attackAcceleration real Yes
attackAiming real Yes
attackAimingTimeout real Yes
attackAngleZ real Yes
attackAntiAir boolean Yes
attackAntiGround boolean Yes
attackAntiStrategic boolean Yes
attackAntiTactical boolean Yes
attackAntiTorpedo boolean Yes
attackAntiWater boolean Yes
attackAOE real Yes
attackBigExplosion boolean Yes
attackBind boolean Yes
attackCooldown real Yes
attackCount integer No
attackCruiseZ real Yes
attackDamage real Yes
attackEffect string Yes
attackEffect2 string Yes
attackFriction real Yes
attackInterception real Yes
attackLiftFactor real Yes
attackManaCosts real Yes
attackNext integer Yes
attackRandomness real Yes
attackRange real Yes
attackSalvoReloadTime real Yes
attackSalvoSize integer Yes
attackScale real Yes
attackShadowSize real Yes
attackSpecial integer Yes
attackSpeed real Yes
attackSpeedMinFactor real Yes
attackTurretAngle real Yes
attackTurretAngleRange real Yes
attackXOffset real Yes
attackYOffset real Yes
attackZOffset real Yes
AV_A boolean Yes
AV_AOE real Yes
AV_AOECurrent real Yes
AV_Attack integer Yes
AV_B boolean Yes
AV_Damage real Yes
AV_FogMod fogmodifier Yes
AV_G group Yes
AV_I integer Yes
AV_J integer Yes
AV_L lightning Yes
AV_Player player Yes
AV_S string Yes
AV_Target unit Yes
AV_Units unit Yes
AV_X real Yes
AV_Y real Yes
AV_Z real Yes
buildLightnings lightning Yes
buildLightningsCount integer No
bulletAccelerationZ real Yes
bulletActive boolean Yes
bulletAiming real Yes
bulletAimTime real Yes
bulletAOE real Yes
bulletAttackId integer Yes
bulletCollisionCheckTime real Yes
bulletCountered boolean Yes
bulletCruiseZ real Yes
bulletDamage real Yes
bulletEffect effect Yes
bulletEffect2 effect Yes
bulletExplodeTime real Yes
bulletInWater boolean Yes
bulletLastCalc real No
bulletLimit integer No 100
bulletLoopNext integer Yes
bulletLoopPrevious integer Yes
bulletLoopShield integer No
bulletMaxJump real No 50.00
bulletPlayer player Yes
bulletRefreshCalc real No
bulletRefreshMove real No
bulletRemoveTime real Yes
bulletShadow image Yes
bulletShieldCheckTime real Yes
bulletSource unit Yes
bulletSpeedX real Yes
bulletSpeedY real Yes
bulletSpeedZ real Yes
bulletStack integer Yes
bulletStackMax integer No
bulletStackN integer No
bulletStartTargetX real Yes
bulletStartTargetY real Yes
bulletStartTargetZ real Yes
bulletStartX real Yes
bulletStartY real Yes
bulletStartZ real Yes
bulletTargetClass integer Yes
bulletTargetLastTime real Yes
bulletTargetSpeedX real Yes
bulletTargetSpeedY real Yes
bulletTargetSpeedZ real Yes
bulletTargetTime real Yes
bulletTargetUnit unit Yes
bulletTargetX real Yes
bulletTargetY real Yes
bulletTargetZ real Yes
bulletTempSpeed real Yes
bulletTempSpeedXY real Yes
bulletTime real Yes
bulletTimeSinceLastCalc real No
bulletTorpedo boolean Yes
bulletUnit unit Yes
bulletUnitPools group Yes
bulletX real Yes
bulletY real Yes
bulletZ real Yes
calculateAdjecency boolean No
calculateRessourceCaps boolean No
CamAngle real No 90.00
CamAngleZ real No 305.00
CamDistance real No 2300.00
CamMode integer No
CamRefreshComplete boolean No
CamSpeed real No
CamTarget unit Yes
CamX real No
CamY real No
CamZ real No
classAdjEnergyCostFactor real Yes
classAdjEnergyIncomeFactor real Yes
classAdjMassCostFactor real Yes
classAdjMassIncomeFactor real Yes
classBigExplosion boolean Yes
classBuildingSquares integer Yes
classBuildSpeed real Yes
classBuildTimeBase real Yes
classBuildTimeReal real Yes
classCollisionDim1 real Yes
classCollisionDim2 real Yes
classCollisionDim3 real Yes
classCollisionRadius real Yes
classCollisionRadius2d real Yes
classCollisionShape integer Yes
classCollisionZOffset real Yes
classColorB integer Yes
classColorG integer Yes
classColorR integer Yes
classCostsEnergy integer Yes
classCostsMass integer Yes
classDeathDmg real Yes
classDeathDmgAOE real Yes
classEnergyAbility integer Yes
classFirstAttack integer Yes
classIsShield boolean Yes
classManaRegeneration real Yes
classProducedEnergy integer Yes
classProducedMass integer Yes
classRadarRange real Yes
classStealthRange real Yes
classStorageEnergy integer Yes
classStorageMass integer Yes
classUnitType integer Yes
classVeterancyKills integer Yes
Color string Yes
DamageSource unit No
Done boolean No
ecoAlpha integer Yes
ecoCount integer No
ecoFadeout boolean Yes
ecoFollowUnit unit Yes
ecoPlayerId integer Yes
ecoString string Yes
ecoTag texttag Yes
explodeBullet integer Yes
explodeCount integer No
fogModifiers fogmodifier Yes
fogModifiersCount integer No
GameOver boolean No
GameTimer timer No
German boolean No
Gravity real No 450.00
groupAutoFire group No
groupBigColliders group No
groupBuildingUnits group No
groupCapturedUnits group No
groupCapturingUnits group No
groupMeasureSpeed group No
groupRessIncomeWithFee group No
groupRessOnlyIncome group No
groupRessUpgradeAndTrain group No
groupRessUse group No
GroupStack group Yes
GroupStackN integer No
groupStealth group No
groupStealthOld group No
groupStrategicMissiles group No
groupTacticalMissiles group No
groupTorpedoes group No
groupTransportedUnits group No
groupWithRangeDisplay group No
hintsShowed boolean Yes
hitpointAbility integer Yes
Host player No
initialVisibility fogmodifier Yes
lastCommanderWarning real No
LavaRock integer No
mapBorderWidth real No
mapMaxX real No
mapMaxY real No
mapMinX real No
mapMinY real No
massCount integer No
massX real Yes
massY real Yes
maxCollision2d real No
maxCollision2dLimit real No 300.00
maxPathableInclineDeg real No 30.00
maxPathableInclineHelper real No
maxPlayer integer No
maxPlayerCount integer No
modeBtGo button No
modeBtLeaverAI button No
modeBtLockTeams button No
modeBtMode button No
modeBtNoRush button No
modeBtPrebuilt button No
modeBtTeamSize button No
modeDialog dialog No
modePossibleTeamSizes integer Yes
modeValLeaverAI boolean No
modeValLockTeams boolean No true
modeValMode integer No
modeValNoRush integer No
modeValPrebuilt integer No
modeValTeamSize integer No
musicPeace string No Sound\Music\mp3Music\Human1.mp3
musicWar string No war3mapImported\music.mp3
noRush boolean No
noRushBaseRadius real No
noRushCircleEffects effect Yes
Overcharge integer No
Phantom player No
PhantomIncomeFactor real No 2.00
playerACU unit Yes
playerAI boolean Yes
playerAlive boolean Yes
playerAlliance integer Yes
playerColorWord string Yes
playerController unit Yes
playerEcoDisplay boolean Yes
playerEnergy real Yes
playerEnergyCap integer Yes
playerEnergyGathered real Yes
playerEnergyIncome real Yes
playerEnergyOverProd real Yes
playerEnergyOverUse boolean Yes
playerEnergyUse real Yes
playerInGame boolean Yes
playerInvolvedUntil real Yes
playerKeyDown boolean Yes
playerKeyLeft boolean Yes
playerKeyRight boolean Yes
playerKeyUp boolean Yes
playerLastEnergySet integer Yes
playerLastMassSet integer Yes
playerMass real Yes
playerMassCap integer Yes
playerMassGathered real Yes
playerMassIncome real Yes
playerMassOverProd real Yes
playerMassOverUse boolean Yes
playerMassUse real Yes
playerName string Yes
playerNameColored string Yes
playerOrder boolean No true
playerRangeDisplay boolean Yes
playerStartX real Yes
playerStartY real Yes
playerUnitsSelected group Yes
playerWarMusic boolean Yes
Preloader unit No
progressBarBase string No
rangeAlpha integer Yes
rangeCount integer No
rangeFadeout boolean Yes
rangeFollowUnit unit Yes
rangePlayerId integer Yes
rangeRadius real Yes
rangeUnit unit Yes
rangeUnitStack unit Yes
rangeUnitStackN integer No
repairCostFactor real No 0.10
repairTimeFactor real No 1.00
resourceBoard leaderboard Yes
resourceNegativeRed boolean No
resourceRefresh real No 0.36
Salva1Split integer No
Salva2Split integer No
shieldAbsorbed boolean Yes
shieldAlreadyDamaged boolean Yes
shieldcheckBullet integer Yes
shieldcheckN integer No
shieldCount integer No
shieldEffect effect Yes
shieldMobile boolean Yes
shieldOutside boolean Yes
shieldRange real Yes
shieldUnit unit Yes
shieldX real Yes
shieldY real Yes
shieldZ real Yes
supportOrderId integer No
tdspawnGate unit Yes
tdspawnMax integer No
tdspawnTargetX real Yes
tdspawnTargetY real Yes
tdspawnX real Yes
tdspawnY real Yes
tdwaveCountUnits integer Yes
tdwaveCurrent integer No
tdwaveMax integer No
tdwaveTime real Yes
tdwaveUnitType unitcode Yes
tempLoc location No
tempRect rect No
threadMax integer No
threadName string Yes
tileBeach terraintype No TerrainTypeNsnw
tileCliff terraintype No TerrainTypeNsnr
Timers timer Yes
TimersBase integer No
TimersN integer No
treeDestroy destructable No
trg_Bullets_Calculate trigger No
trg_Bullets_Explode trigger No
trg_Bullets_Shields trigger No
trg_Terrain_Update trigger No
unitAdjEnergyCostFactor real Yes
unitAdjEnergyIncomeFactor real Yes
unitAdjMassCostFactor real Yes
unitAdjMassIncomeFactor real Yes
unitCaptureFinished boolean Yes
unitCaptureState real Yes
unitCaptureTag texttag Yes
unitChannelTarget unit Yes
unitClass integer Yes
unitConstructionState real Yes
unitEcoDisplay boolean Yes
unitFirstWeapon integer Yes
unitHasShield boolean Yes
unitIsBeingCaptured boolean Yes
unitKills integer Yes
unitLastDamaged real Yes
unitLastX real Yes
unitLastY real Yes
unitLastZ real Yes
unitLinkedDestructable destructable Yes
unitMaxSpeed real Yes
unitPaused boolean Yes
unitProducesUnit unitcode Yes
unitProducesUnitState real Yes
unitProductionOn boolean Yes
unitRangeDisplay boolean Yes
unitRefresh real No 0.36
unitSpecialWorks boolean Yes
unitSpeedX real Yes
unitSpeedY real Yes
unitSpeedZ real Yes
unitStack integer Yes
unitStackMax integer No
unitStackN integer No
unitSupporters group Yes
unitSupportsUnit unit Yes
unitTransportedBy unit Yes
unitTransportedUnits group Yes
unitUpgradeState real Yes
unitUpgradesTo unitcode Yes
unitUsedEnergy real Yes
unitUsedMass real Yes
waterHeight real No
weaponAttack integer Yes
weaponCooldown real Yes
weaponNext integer Yes
weaponStack integer Yes
weaponStackMax integer No
weaponStackN integer No
weaponTarget unit Yes
weaponTargetX real Yes
weaponTargetY real Yes
function Trig_Initialization_Destructables_Enum takes nothing returns nothing
    local destructable d = GetEnumDestructable()
    if GetDestructableTypeId(d)=='B002' then
        set udg_massCount = udg_massCount + 1
        set udg_massX[udg_massCount] = GetDestructableX(d)
        set udg_massY[udg_massCount] = GetDestructableY(d)
    endif
    set d = null
endfunction

function Trig_Initialization_Destructables takes nothing returns nothing
    call EnumDestructablesInRect(bj_mapInitialPlayableArea, null, function Trig_Initialization_Destructables_Enum)
endfunction

function Trig_Initialization_Units takes nothing returns nothing
    local unit U
    local integer i
    local group G = NewGroup()
    call GroupEnumUnitsInRange(G,0,0,100000,null)
    loop
        set U = FirstOfGroup(G)
        exitwhen U==null
        call GroupRemoveUnit(G,U)
        if GetUnitTypeId(U)=='H00C' then
            set udg_tdspawnMax = udg_tdspawnMax + 1
            set udg_tdspawnX[udg_tdspawnMax] = GetUnitX(U)
            set udg_tdspawnY[udg_tdspawnMax] = GetUnitY(U)
            set udg_tdspawnTargetX[udg_tdspawnMax] = GetStartLocationX(GetPlayerId(GetOwningPlayer(U)))
            set udg_tdspawnTargetY[udg_tdspawnMax] = GetStartLocationY(GetPlayerId(GetOwningPlayer(U)))
            call RemoveUnit(U)
        elseif GetUnitAbilityLevel(U,'Aloc')==0 and GetUnitTypeId(U)!='H02E' then
            set i = NewIndex(U)
            call CheckAutoFire(U)
            call CheckRessourceUnit(U)
            if udg_classManaRegeneration[udg_unitClass[i]]>50 then
                call EnableShield(U)
            elseif GetPlayerId(GetOwningPlayer(U))>udg_maxPlayer then
                if Pow(GetUnitX(U)-GetRectCenterX(gg_rct_CineCamFrom),2)+Pow(GetUnitY(U)-GetRectCenterY(gg_rct_CineCamFrom),2)>Pow(GetUnitX(U)-GetRectCenterX(gg_rct_CineCamTo),2)+Pow(GetUnitY(U)-GetRectCenterY(gg_rct_CineCamTo),2) then
                    call IssuePointOrder(U,"attack",GetRectCenterX(gg_rct_CineCamFrom),GetRectCenterY(gg_rct_CineCamFrom))
                else
                    call IssuePointOrder(U,"attack",GetRectCenterX(gg_rct_CineCamTo),GetRectCenterY(gg_rct_CineCamTo))
                endif
            endif
        endif
    endloop
    call ReleaseGroup(G)
endfunction

function Trig_Initialization_Delayed takes nothing returns nothing
    local integer pid = 0
    call DestroyTimer(GetExpiredTimer())
    call FadeToMusic(udg_musicWar, 0, 127, 0, 1, true)
    loop
        exitwhen pid>udg_maxPlayer
        set udg_playerWarMusic[pid] = true
        set pid = pid + 1
    endloop
endfunction

function Trig_Initialization_ShowDialog takes nothing returns nothing
    local integer Size = 1
    local integer CountTeams
    call DestroyTimer(GetExpiredTimer())
    call RefreshModeDialog()
    call EnableUserControl(GetLocalPlayer()==udg_Host)
    call DialogDisplay( udg_Host, udg_modeDialog, true )
endfunction

function Trig_Initialization_Actions takes nothing returns nothing
    local integer i = 0
    local integer imax = udg_maxPlayer
    local integer j
    call InitTimers(512)
    call InitVeterancy()

    call SetMapFlag( MAP_LOCK_ALLIANCE_CHANGES, true )
    call SetMusicVolume(0)
    call SetSkyModel( "Environment\\Sky\\LordaeronSummerSky\\LordaeronSummerSky.mdl" )
    call SetAmbientDaySound( "" )
    call SetAmbientNightSound( "" )
    call EnableDawnDusk( false )
    call SetTimeOfDay( 12 )
    call SetTimeOfDayScale( 0.00 )

    call SetAbilityAvailable('A01J',false)
    call SetAbilityAvailable('A01K',false)
    call SetAbilityAvailable('A01L',false)
    call SetAbilityAvailable('A01M',false)
    call SetAbilityAvailable('A01N',false)
    call SetAbilityAvailable('A01O',false)
    call SetAbilityAvailable('A01P',false)
    call SetAbilityAvailable('A01Q',false)
    call SetAbilityAvailable('A01Y',false)

    set udg_mapMaxX = GetRectMaxX(bj_mapInitialPlayableArea)
    set udg_mapMaxY = GetRectMaxY(bj_mapInitialPlayableArea)
    set udg_mapMinX = GetRectMinX(bj_mapInitialPlayableArea)
    set udg_mapMinY = GetRectMinY(bj_mapInitialPlayableArea)
    set udg_mapBorderWidth = 128
    set udg_tempLoc = Location(GetRectCenterX(gg_rct_BeachTile), GetRectCenterY(gg_rct_BeachTile))
    set udg_tempRect = Rect(-10,-10,10,10)
    if GetLocationX(udg_tempLoc)>udg_mapMinX+128 or GetLocationY(udg_tempLoc)>udg_mapMinY+128  then
        set udg_waterHeight = GetLocationZ(udg_tempLoc)
    else
        set udg_waterHeight = -2048
    endif

    set i = 1
    loop
        exitwhen i > 20
        set udg_bulletUnitPools[i] = NewGroup()
        set i = i + 1
    endloop

    set udg_Preloader = CreateUnit(Player(15),'h003',10000,10000,270)
    call TriggerExecute(gg_trg_Class_Config)
    call UpdateTerrainPathing(GetWorldBounds(), true)
    call Trig_Initialization_Destructables()
    call Trig_Initialization_Units()
    call DestroyEffect(AddSpecialEffectTarget("Units\\NightElf\\Wisp\\WispExplode.mdl",udg_Preloader,"origin"))
    call DestroyEffect(AddSpecialEffectTarget("war3mapImported\\Flash2.mdx",udg_Preloader,"origin"))
    call RemoveUnit(udg_Preloader)
    set udg_Preloader = null

    set udg_supportOrderId = OrderId("spiritlink")
    set udg_playerColorWord[0] = "red"
    set udg_playerColorWord[1] = "blue"
    set udg_playerColorWord[2] = "teal"
    set udg_playerColorWord[3] = "purple"
    set udg_playerColorWord[4] = "yellow"
    set udg_playerColorWord[5] = "orange"
    set udg_playerColorWord[6] = "green"
    set udg_playerColorWord[7] = "pink"
    set udg_hintsShowed[3] = false
    set udg_progressBarBase = "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"

    call SetWaterBaseColor( 200, 200, 255, 200 )
    set i = 0
    loop
        exitwhen i > 15
        set j = 0
        loop
            exitwhen j > 15
            if IsPlayerEnemy(Player(i),Player(j)) then
                set udg_playerAlliance[i+j*16] = 2
            else
                set udg_playerAlliance[i+j*16] = 0
            endif
            set j = j + 1
        endloop
        set i = i + 1
    endloop
    set i = 0
    loop
        exitwhen i > imax
        if GetPlayerSlotState(Player(i)) != PLAYER_SLOT_STATE_EMPTY then
            if udg_Host==null then
                set udg_Host = Player(i)
            endif
            if GetPlayerController(Player(i))==MAP_CONTROL_COMPUTER then
                set udg_playerName[i] = AIGetRandomName(Player(i))
                call SetPlayerName(Player(i),udg_playerName[i])
                set udg_playerAI[i] = true
                set udg_ai = true
            else
                set udg_playerName[i] = GetPlayerName(Player(i))
            endif
            if SubString(udg_playerName[i],0,StringLength(udg_playerName[i])-7)+" (Dead)"==udg_playerName[i] then
                set udg_playerName[i] = SubString(udg_playerName[i],0,StringLength(udg_playerName[i])-7)
                call SetPlayerName(Player(i),udg_playerName[i])
            endif
            set udg_playerInGame[i] = true
            set udg_playerUnitsSelected[i] = NewGroup()
            set udg_initialVisibility[i] = CreateFogModifierRect(Player(i), FOG_OF_WAR_VISIBLE, GetWorldBounds(), true, false)
            call FogModifierStart(udg_initialVisibility[i])
            set udg_maxPlayer = i
        endif
        set i = i + 1
    endloop

    set i = 1
    set j = 0
    loop
        exitwhen i>udg_maxPlayerCount
        if (udg_maxPlayerCount/i)*i==udg_maxPlayerCount then
            set udg_modePossibleTeamSizes[j] = i
            set j = j + 1
        endif
        set i = i + 1
    endloop

    call Init_Colors()
    call EnableUserControl(false)
    call ShowInterface(false,0)
    call SetCineFilterTexture("ReplaceableTextures\\CameraMasks\\White_mask.blp")
    call SetCineFilterBlendMode(BLEND_MODE_BLEND)
    call SetCineFilterTexMapFlags(TEXMAP_FLAG_NONE)
    call SetCineFilterStartUV(0, 0, 1, 1)
    call SetCineFilterEndUV(0, 0, 1, 1)
    call SetCineFilterStartColor(0, 0, 0, 255)
    call SetCineFilterEndColor(0, 0, 0, 0)
    call SetCineFilterDuration(2)
    call DisplayCineFilter(true)

    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,20,udg_playerNameColored[GetPlayerId(udg_Host)]+" will now choose the game options.")
    call TimerStart(CreateTimer(),0,false,function Trig_Initialization_Delayed)
    call TimerStart(CreateTimer(),2,false,function Trig_Initialization_ShowDialog)
    call TimerStart(udg_GameTimer,100000,true,null)
    call PanCameraToTimed(GetRectCenterX(gg_rct_CineCamFrom),GetRectCenterY(gg_rct_CineCamFrom),0)
    call TriggerExecute(gg_trg_Cine_Cam)
    call TriggerExecute(gg_trg_Volcanos)
    if udg_ai then
        call TriggerExecute(gg_trg_Initialize_AI)
    endif
    call DestroyTrigger(GetTriggeringTrigger())
endfunction

//===========================================================================
function InitTrig_Initialization takes nothing returns nothing
    local unit U = CreateUnit(Player(15),'hgyr',0,0,270)
    local real X
    local real Y
    set udg_maxPlayerCount = S2I(GetLocalizedString("TRIGSTR_2"))
    set udg_tileCliff = GetTerrainType(GetRectCenterX(gg_rct_CliffTile), GetRectCenterY(gg_rct_CliffTile))
    set udg_tileBeach = GetTerrainType(GetRectCenterX(gg_rct_BeachTile), GetRectCenterY(gg_rct_BeachTile))
    set udg_maxPlayer = udg_maxPlayerCount-1
    set udg_German = (GetUnitName(U)=="Flugapparat")
    call RemoveUnit(U)
    set U = null
    set gg_trg_Initialization = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Initialization, function Trig_Initialization_Actions )
endfunction
//TESH.scrollpos=225
//TESH.alwaysfold=0
function Trig_Class_Config_Actions takes nothing returns nothing
    //             Shape             Dimensions
    local integer None   = 0 //      0,     0,     0
    local integer Sphere = 1 // Radius,     0,     0
    local integer Barrel = 2 // Radius, SizeZ,     0
    local integer Box    = 3 // SizeX,  SizeY, SizeZ

    //                      -------Collision-------            Income        Costs        Storage      Time        Death
    //              Type    Shape  Dimensions  ZOff  Adj Vet Mass Energy  Mass Energy   Mass Energy   Real   Base  Dmg  AOE Big  R   G   B
    call InitClass('h000', Sphere, 32,  0,  0,  16,   1,  0,  0,   2,      75,     75,    0,     0,   6.25,  6.25,  25,  96, 1, 255,255,255) // Generator T1
    call InitClass('h001', Sphere, 36,  0,  0,  28,   0,  0,  0,   0,      52,     26,   10,    10,   6.00,  3.00,   0,   0, 0, 255,255,255) // Engineer T1
    call InitClass('h002', Barrel, 25,  0, 96,  48,   1,  6,  0,   0,      50,      0,    0,     0,   2.50, 12.50,   0,   0, 0, 255,255,255) // Turret T1
    call InitClass('h004', Barrel, 96,  0,192,  96,   3,  0,  0, -20,     600,    600,    0,     0,  36.00, 36.00,   0,   0, 0, 255,255,255) // Shield Generator T2
    call InitClass('h005', Sphere, 32,  0,  0,  16,   0,  3,  0,   0,      56,     27,    0,     0,   6.00,  3.00,   0,   0, 0, 255,255,255) // Medium Tank T1
    call InitClass('h006', Sphere, 50,  0,  0,  40,   0,  0,  0, -10,     640,    480,    0,     0,  22.00, 33.00,   0,   0, 0, 100,100,100) // Mobile Shield Generator T3
    call InitClass('h007', Sphere, 40,  0,  0,  30,   0,  3,  0,   0,     200,    150,    0,     0,  10.00, 10.00,   0,   0, 0, 255,255,255) // Rocket Launcher T2
    call InitClass('h008', Sphere, 40,  0,  0,  10,   0,  6,  0,   0,     300,    600,    0,     0,  20.00, 20.00,  10,  48, 1, 255,255,255) // Gunship T2
    call InitClass('h009', Sphere, 32,  0,  0,  16,   0,  2,  0,   0,      28,     14,    0,     0,   3.00,  1.50,   0,   0, 0, 127,195,255) // Anti-Air Tank T1
    call InitClass('h00A', Barrel, 27,  0,106,  53,   1, 12,  0,   0,     260,     40,    0,     0,   3.50, 22.50,   0,   0, 0, 127,127,127) // Turret T2
    call InitClass('h00B', Sphere, 43,  0,  0,   0,   0,  6,  0, -25,    2000,   2800,    0,     0,  50.00, 75.00,   5, 144, 1, 127,127,127) // Heavy Air Transport T3
    call InitClass('H00C', Box,    64,128,200,  94,   0, 20,  2,   2,    9600,  11400,  600,   600, 120.00,120.00,   0,   0, 0, 255,255,255) // ACU
    call InitClass('h00D', Barrel, 95,  0,256, 127,   0, 25,  0, -25,   16000,  20000,    0,     0, 600.00,600.00, 400, 336, 1, 255,255,255) // Monkeylord T4
    call InitClass('h00E', Sphere, 28,  0,  0,  28,   0,  2,  0,   0,      35,     14,    0,     0,   3.00,  1.50,   0,   0, 0, 255,255,255) // Light Assault Bot T1
    call InitClass('h00F', Sphere, 56,  0,  0,   0,   0,  9,  0,   0,     800,    800,    0,     0,  32.00, 48.00,   0,   0, 0, 127,127,127) // Mobile Artillery T3
    call InitClass('h00G', Sphere, 32,  0,  0,  32,   1,  0,  2,   0,      36,     36,    0,     0,   3.00,  3.00,   0,   0, 0, 255,255,255) // Mass Extractor T1
    call InitClass('h00H', Barrel, 27,  0,126,  63,   1,  0,  0,  -2,      80,     72,    0,     0,   4.00,  4.00,   0,   0, 0, 255,255,255) // Radar T1
    call InitClass('h00I', Sphere,100,  0,  0,  35,   3,  0,  0,   0,     240,    210,   60,    60,  15.00, 15.00,   0,   0, 0, 255,255,255) // Land Factory T1
    call InitClass('h00J', Sphere, 95,  0,  0,  55,   3,  0,  0,   0,     210,    240,   60,    60,  15.00, 15.00,   0,   0, 0, 255,255,255) // Air Factory T1
    call InitClass('h00K', Sphere, 32,  0,  0,   0,   0,  2,  0,   0,      12,      8,    0,     0,   2.00,  2.00,   0,   0, 0, 255,255,255) // Land Scout T1
    call InitClass('h00L', Sphere, 80,  0,  0,   0,   0,  2,  0,   0,     120,    480,    0,     0,  16.00,  8.00,  10,  48, 1, 255,255,255) // Air Transporter T1
    call InitClass('h00M', Barrel, 25,  0, 96,  48,   1,  4,  0,   0,       0,      0,    0,     0,   2.50, 12.50,   0,   0, 0, 255,255,255) // Anti-Air Turret T1
    call InitClass('h00N', Sphere, 40,  0,  0,   0,   1,  0,  1,  -8,      50,    250,    0,     0,  15.00, 15.00,  37, 240, 1, 255,255,255) // Mass Fabricator T1
    call InitClass('h00O', Sphere,100,  0,  0,  35,   3,  0,  0,   0,     800,    720,  120,   120,  32.00, 47.00,   0,   0, 0, 195,195,195) // Land Factory T2
    call InitClass('h00P', Sphere, 40,  0,  0,  32,   0,  0,  0,   0,     160,     84,   20,    20,   8.00,  8.00,   0,   0, 0, 210,210,210) // Engineer T2
    call InitClass('h00Q', Sphere, 64,  0,  0,  32,   2,  0,  0,  50,    1200,   1200,    0,     0, 100.00,100.00, 150, 240, 1, 255,255,255) // Generator T2
    call InitClass('h00R', Sphere, 95,  0,  0,  55,   3,  0,  0,   0,     630,   1170,  120,   120,  36.00, 51.00,   0,   0, 0, 195,195,195) // Air Factory T2
    call InitClass('h00S', Barrel, 32,  0, 32,   0,   0,  0,  0,   0,      40,    160,    0,     0,   8.00,  4.00,   2,  48, 1, 255,255,255) // Air Scout T1
    call InitClass('h00T', Sphere, 32,  0,  0,   6,   0,  2,  0,   0,      50,    225,    0,     0,  10.00,  5.00,   5,  48, 1, 255,255,255) // Fighter T1
    call InitClass('h00U', Barrel, 27,  0,126,  63,   1,  0,  0, -25,     180,    360,    0,     0,  30.00, 30.00,   0,   0, 0, 195,195,195) // Radar T2
    call InitClass('h00V', Sphere, 32,  0,  0,  32,   1,  0,  6,  -1,     900,    540,    0,     0,  20.00, 23.00,   0,   0, 0, 195,195,195) // Mass Extractor T2
    call InitClass('h00W', Sphere, 32,  0,  0,  32,   1,  0, 15,  -5,    3200,   2200,    0,     0,  32.00, 55.00,   0,   0, 0, 127,127,127) // Mass Extractor T3
    call InitClass('h00X', Barrel, 27,  0,126,  63,   1,  0,  0,-200,    2400,   3000,    0,     0,  90.00, 90.00,   0,   0, 0, 127,127,127) // Radar T3
    call InitClass('h00Y', Sphere, 48,  0,  0,  40,   0,  0,  0,   0,     490,    315,   40,    40,  14.00, 21.00,   0,   0, 0, 180,180,180) // Engineer T3
    call InitClass('h00Z', Sphere, 96,  0,  0,  48,   3,  0,  0, 250,    3240,   5760,    0,     0, 270.00,270.00, 800, 480, 1, 255,255,255) // Generator T3
    call InitClass('h010', Barrel, 77,  0, 77,   0,   0, 12,  0,   0,    2100,   7000,    0,     0,  56.00, 84.00,  50,  48, 1, 127,127,127) // Strategic Bomber T3
    call InitClass('h011', Sphere, 95,  0,  0,  55,   3,  0,  0,   0,    2520,   4620,  240,   240,  84.00,135.00,   0,   0, 0, 127,127,127) // Air Factory T3
    call InitClass('h012', Sphere,100,  0,  0,  35,   3,  0,  0,   0,    3240,   1134,  240,   240,  84.00,131.00,   0,   0, 0, 127,127,127) // Land Factory T3
    call InitClass('h013', Barrel, 40,  0,110,  55,   0,  9,  0,   0,     480,    540,    0,     0,  16.00, 24.00,   0,   0, 0,  63, 63, 63) // Heavy Bot T3
    call InitClass('h014', Barrel, 96,  0,192,  96,   3,  0,  0, -40,    3000,   5000,    0,     0,  37.50, 73.50,   0,   0, 0, 196,196,196) // Shield Generator T3
    call InitClass('h015', Sphere, 80,  0,  0,   0,   2,  0, 18,-250,    1900,   8250,    0,     0, 187.50,187.50, 450, 672, 1, 127,127,127) // Mass Fabricator T3
    call InitClass('h016', Sphere, 55,  0,  0,   0,   2, 15,  0, -10,    2520,   1800,    0,     0,  90.00, 90.00,   0,   0, 0, 255,255,255) // Artillery Installation T2
    call InitClass('h017', Barrel, 32,  0,100,  50,   0, 12,  0,   0,    1400,   1200,    0,     0,  75.00, 75.00,   0,   0, 0, 255,255,255) // Sam Launcher T3
    call InitClass('h018', Sphere, 32,  0,  0,   0,   0,  3,  0,   0,      36,     18,    0,     0,   4.00,  2.00,   0,   0, 0, 255,255,255) // Mobile Artillery T1
    call InitClass('h019', Sphere,100,  0,  0,  35,   3,  0,  0,   0,     300,    150,   60,    60,  15.00, 15.00,   0,   0, 0, 255,255,255) // Naval Factory T1
    call InitClass('h01A', Sphere, 40,  0,  0,  20,   0,  6,  0,   0,     200,    100,    0,     0,   9.00,  9.00,   0,   0, 0, 127,127,195) // Heavy Tank T2
    call InitClass('h01B', Box,   128, 48, 64,  30,   0,  6,  0,   0,     280,    280,    0,     0,  28.00, 14.00,   0,   0, 0, 255,255,255) // Frigate T1
    call InitClass('h01C', Box,   192, 64, 64,  30,   0, 16,  0,   0,    2000,   1800,    0,     0,  80.00, 80.00,   0,   0, 0, 255,255,255) // Cruiser T2
    call InitClass('h01D', Sphere, 92,  0,  0,   0,   0, 16,  0,   0,    2250,   1500,    0,     0, 100.00,100.00,   0,   0, 0, 255,255,255) // Destroyer T2
    call InitClass('h01E', Sphere,192,  0,  0,   0,   0, 32,  0,   0,   11250,   7500,    0,     0, 298.00,503.25,   0,   0, 0, 127,127,127) // Battleship T3
    call InitClass('h01F', Sphere,100,  0,  0,  65,   3,  0,  0,   0,    5400,   2340,  240,   240,  72.00,123.00,   0,   0, 0, 127,127,127) // Naval Factory T3
    call InitClass('h01G', Sphere,100,  0,  0,  65,   3,  0,  0,   0,    1170,    540,  120,   120,  36.00, 51.00,   0,   0, 0, 195,195,195) // Naval Factory T2
    call InitClass('h01H', Barrel, 27,  0,106,  53,   1,  8,  0,   0,     260,    240,    0,     0,  16.00, 35.00,   0,   0, 0, 127,127,127) // Anti Air Turret T2
    call InitClass('h01I', Box,   128, 45, 45, -22,   0,  4,  0,   0,     400,    320,    0,     0,  32.00, 16.00,   0,   0, 0, 255,255,255) // Submarine T1
    call InitClass('h01J', Sphere, 32,  0,  0,   5,   0,  3,  0,   0,     100,    225,    0,     0,  10.00,  5.00,  14,  48, 1, 255,255,255) // Bomber T1
    call InitClass('h01K', Barrel, 90,  0,256, 128,   3,  0,  0,   0,    3000,   3000,    0,     0, 150.00,150.00,   0,   0, 0, 255,255,255) // Quantum Gateway T4
    call InitClass('h01L', Box,    45, 90,190,  85,   0, 30,  2,   2,    9600,  11400,  380,   380, 120.00,120.00,   0,   0, 0, 127,127,127) // Sub Commander
    call InitClass('h01M', Barrel,128,  0,450, 220,   0, 50,  0,   0,   22500,  28000,    0,     0, 853.75,853.75, 750, 192, 1,  63, 63,127) // Galactic Colossus T4
    call InitClass('h01N', Sphere, 45,  0,  0,  25,   2, 30,-80,-900,   15000,  21000,    0,     0, 450.00,450.00, 600, 288, 1, 255,255,255) // Strategic Missile Launcher T4
    call InitClass('h01O', Sphere,128,  0,  0,   0,   0, 40,  0,   0,   40000,  65000,    0,     0,1500.00,1500.00,500, 192, 1, 200,200,200) // Experimental Gunship T4
    call InitClass('h01P', Sphere, 50,  0,  0,  30,   1,  0,-30, -30,    7500,  10500,    0,     0, 225.00,225.00,   0,   0, 0, 255,255,255) // Strategic Missile Defense T4
    call InitClass('h01R', Sphere, 40,  0,  0,  20,   0,  4,  0,   0,     160,     80,    0,     0,   8.00,  8.00,   0,   0, 0,  97,146,195) // Anti Air Tank T2
    call InitClass('h01Q', Sphere, 54,  0,  0,  10,   0,  6,  0,   0,     400,   2000,    0,     0,  20.00, 30.00,  20,  48, 1, 127,127,127) // Air Superiority Fighter T3
    call InitClass('h01S', Sphere, 40,  0,  0,   0,   1,  0,  0,   0,       2,      1,    0,     0,   0.50,  0.50,   0,   0, 0, 255,255,255) // Wall Section T1
    call InitClass('h01T', Sphere,110,  0,  0,   0,   0,  4,  0,   0,     300,   1200,    0,     0,  24.00, 24.00,  14,  48, 1, 195,195,195) // Air Transporter T2
    call InitClass('h01U', Barrel, 54,  0, 27,   0,   0,  0,  0,   0,     195,    500,    0,     0,   6.00,  9.00,  14,  48, 1, 127,127,127) // Spy Plane T3
    call InitClass('h01V', Box,   128, 45, 45,   0,   0,  4,  0,   0,     400,    320,    0,     0,  32.00, 16.00,   0,   0, 0, 255,255,255) // Submarine T1 (Surfaced)
    call InitClass('h01W', Sphere, 45,  0,  0,   7,   0,  2,  0,   0,     240,    480,    0,     0,  16.00, 16.00,  18,  48, 1, 127,127,255) // Torpedo Bomber T2
    call InitClass('h01X', Sphere, 39,  0,  0,  40,   0,  7,  0,   0,     365,    200,    0,     0,  14.00, 14.00,   0,   0, 0, 127,127,255) // Amphibious Tank T2
    call InitClass('h01Y', Sphere,  0,  0,  0,   0,   0,  0,  0,   0,       0,      0,    0,     0,   0.00,  0.00,   0,   0, 0, 255,255,255) // Range Circle
    call InitClass('h01Z', Sphere,111,  0,  0,   0,   4, 50,  0,-750,  300000, 600000,    0,     0,4500.00,4500.0,   0,   0, 0, 196,128,128) // Experimental Artillery
    call InitClass('h020', Sphere,128,  0,  0,  64,   4,  0,10000,100000,250000,750000,   0,     0,6250.00,6250.0,   0,   0, 0, 255,255,255) // Experimental Generator T4
    call InitClass('h021', Sphere, 40,  0,  0,  10,   1,  0,  0,   0,     160,    195,  180,   180,  11.25, 11.25,   0,   0, 0, 255,255,255) // Storage T1
    call InitClass('h022', Sphere, 35,  0,  0,  35,   0,  6,  0,   0,     200,    100,    0,     0,  10.00, 10.00,   0,   0, 0, 128,128,196) // Gatling Bot T2
    call InitClass('h023', Barrel, 54,  0, 54,   0,   0,  6,  0,   0,     420,    840,    0,     0,  24.00, 24.00,  20,  48, 1, 195,195,195) // Fighter / Bomber T2
    call InitClass('h024', Barrel,342,  0,136,   0,   0, 40,  0,   0,   45000,  75000,    0,     0,1687.50,1687.5,2000, 720, 1, 255,255,255) // CZAR T4
    call InitClass('h025', Box,   256,204,100,  30,   0, 25,  0, -50,   24600,  30750,  150,   150, 922.50,922.50, 400, 336, 1, 255,255,255) // Fatboy T4
    call InitClass('h026', Barrel, 25,  0, 96,  48,   1,  0,  0,   0,       0,      0,    0,     0,   1.00,  1.00,   0,   0, 0, 255,255,255) // Tactical Missile Defense T2
    call InitClass('h027', Sphere, 50,  0,  0,  37,   0,  6,  0,   0,     400,    300,    0,     0,  10.00, 15.00,   0,   0, 0, 127,127,127) // Mobile Missile Platform T3
    call InitClass('h028', Sphere, 57,  0,  0,  10,   0, 12,  0,   0,    1650,   3500,    0,     0,  56.00, 84.00,  30,  48, 1, 127,127,127) // Heavy Gunship T3
    call InitClass('h029', Box,   192, 64, 64,  30,   0,  6,  0,   0,     900,    720,    0,     0,  36.00, 36.00,   0,   0, 0, 255,255,255) // Torpedo Boat T2
    call InitClass('h02A', Box,   192, 64, 64,  30,   0,  0,  0, -15,    1040,   1040,    0,     0,  32.00, 48.00,   0,   0, 0, 100,100,100) // Shield Boat T3
    call InitClass('h02B', Box,   128, 67, 67, -33,   0, 12,-80,-840,   10000,   6000,    0,     0, 200.00,300.00,   0,   0, 0, 127,127,127) // Strategic Missile Submarine T3
    call InitClass('h02C', Box,   128, 67, 67,   0,   0, 12,-80,-840,   10000,   6000,    0,     0, 200.00,300.00,   0,   0, 0, 127,127,127) // Strategic Missile Submarine T3 (Surfaced)
    call InitClass('h02D', Barrel, 90,  0,256, 128,   3,  0,  0,   0,    3000,   3000,    0,     0, 999999,999999, 800, 720, 1, 255,255,255) // Quantum Gateway T4 (TD)
    call InitClass('h02F', Box,   128, 48, 64,  30,   0,  6,  0,   0,     280,    280,    0,     0,  28.00, 14.00,   0,   0, 0, 255,255,255) // Light Naval Transport T1
    call InitClass('h02G', Box,   224, 80, 80,  38,   0, 16,  0,   0,     600,    600,    0,     0,  36.00, 36.00,   0,   0, 0, 195,195,195) // Naval Transport T2
    call InitClass('h02H', Barrel, 25,  0, 96,   0,   1,  6,  0,   0,     250,    160,    0,     0,  12.50, 22.50,   0,   0, 0, 255,255,255) // Torpedo Launcher T1
    call InitClass('h02J', Sphere, 48,  0,  0,  24,   0,  4,  0,   0,     400,    180,    0,     0,  10.00, 15.00,   0,   0, 0,  63, 95,127) // Mobile AA SAM Launcher T3
    call InitClass('h02K', Box,   128, 64, 64,  33,   0,  0,  0,  -5,    1200,   1200,    0,     0,  32.00, 48.00,   0,   0, 0, 255,255,255) // Land Raid Support T3
    call InitClass('h02L', Sphere, 57,  0,  0,  10,   0, 12,  0,   0,    1650,   3500,    0,     0,  56.00,  8.00,  30,  48, 1, 127,127,127) // Missile Carrier T3
    call InitClass('h02M', Sphere, 34,  0,  0,  17,   0,  0,  0,   0,     300,    180,    0,     0,  12.00,  5.00,   0,   0, 0, 255,255,255) // Mobile Bomb T2
    call InitClass('h02N', Barrel, 52,  0,120,  80,   2,  0,  0,  10,     160,     80,    0,     0,  20.00, 20.00,  25,  96, 1, 255,255,255) // Hydrocarbon Power Plant T1
    call InitClass('h02O', Barrel, 25,  0, 96,  48,   1,  0,  0,   0,     200,    200,    0,     0,  10.00, 10.00,   0,   0, 0, 255,255,255) // Defensive Frame T1
    call InitClass('h02P', Barrel, 27,  0,106,  53,   1,  0,  0,   0,     280,    320,    0,     0,  19.00, 19.00,   0,   0, 0, 127,127,127) // Defensive Frame T2
    call InitClass('h02Q', Barrel, 25,  0, 96,   0,   1, 12,  0,   0,     800,    580,    0,     0,  41.00, 60.00,   0,   0, 0, 127,127,127) // Torpedo Launcher T2
    call InitClass('h02R', Sphere, 22,  0,  0,  12,   1,  9, -6, -12,     520,     80,    0,     0,  41.00, 60.00,   0,   0, 0, 255,255,255) // Tactical Missile Launcher T2
    call InitClass('h02S', Sphere, 83,  0,  0,   0,   3, 30,  0,-400,   90000,  90000,    0,     0,1500.00,1500.0,   0,   0, 0, 127,127,127) // Heavy Artillery Installation T3
    call InitClass('h02T', Box,   152, 54, 54, -26,   0,  8,  0,   0,    1100,    880,    0,     0,  44.00, 44.00,   0,   0, 0, 195,195,255) // Submarine Hunter T2
    call InitClass('h02U', Box,   152, 54, 54,   0,   0,  8,  0,   0,    1100,    880,    0,     0,  44.00, 44.00,   0,   0, 0, 195,195,255) // Submarine Hunter T2 (Surfaced)
    call InitClass('h02V', Sphere, 48,  0,  0,  24,   0, 12,  0,   0,     500,    600,    0,     0,  25.00, 37.50,   0,   0, 0, 127,127,127) // Heavy Tank T3
    call InitClass('h02W', Box,   270,140,150,  65,   0, 25,  0,   0,    7500,   6500,    0,     0, 200.00,300.00,  14, 144, 1, 127,127,127) // Battlecruiser T3
    call InitClass('h02X', Barrel, 27,  0,126,  63,   1,  0,  0, -12,      80,    220,    0,     0,  14.00, 33.00,   0,   0, 0, 127,127,127) // Stealth Field Generator T2
    call InitClass('h02Y', Barrel, 54,  0,126,  84,   2,  0,  0, 100,    1600,    600,    0,     0,  40.00, 60.00, 150, 240, 1, 127,127,127) // Hydrocarbon Power Plant T2
    call InitClass('h02Z', Sphere,120,  0,  0, -30,   4, 50,-30,-300,   20000,  50000, 1000,  1000,1000.00,1000.0,   0,   0, 0, 196,128,128) // Bunker

    call InitClass('h030', Sphere,  0,  0,  0,   0,   0,  0,  0,   0,    2000,  12000,    0,     0,  55.00, 55.00,   0,   0, 0, 255,255,255) // Fortified Hull
    call InitClass('h031', Sphere,  0,  0,  0,   0,   0,  0,  0,   0,    3000,  22500,    0,     0,  90.00, 90.00,   0,   0, 0, 255,255,255) // Nano-Repair Module
    call InitClass('h032', Sphere,  0,  0,  0,   0,   0,  0,  0,   0,    3000,  24000,    0,     0,  90.00, 90.00,   0,   0, 0, 255,255,255) // Shield Generator Module
    call InitClass('h033', Sphere,  0,  0,  0,   0,   0,  0,  0,   0,    1000,   2700,    0,     0,  60.00, 60.00,   0,   0, 0, 255,255,255) // Advanced Build Module

    call InitClass('h034', Box,   324,324,100, -48,   4,  0,  0,   0,     200,    200,    0,     0,  10.00, 10.00,   0,   0, 0, 127,127,127) // Platform Area T2
    call InitClass('h035', Sphere, 28,  0,  0,  28,   0,  2,  0,   0,      40,     40,    0,     0,   5.00,  2.50,   0,   0, 0, 255,255,255) // Flame Thrower Recruit T1
    call InitClass('h036', Box,   324,324,100,   0,   4,  0,  0,   0,     200,    200,    0,     0,  10.00, 10.00,   0,   0, 0, 127,127,127) // Platform Area T2 (Construction)

    call InitClass('h003', Sphere, 48,  0,  0,   0,   0,  0,  0,   0,       0,      0,    0,     0,   0.00,  0.00,   0,   0, 0, 255,255,255) // Bullet


    // Target Types
    // g = Ground Units
    // a = Air Units
    // w = Naval Units
    // s = Stratigic Missile
    // t = Tactical Missile
    // p = Torpedoes

    //                              ---Salvo---    --------Speed--------         --Aim--                        ------Facing------                             --Offset--
    //                   Type  Bind Size Reload MP  Base Min Accel Frict  Shade  Aim T/O Intercept Lift Random    Z     XY   Range  Dmg   AOE Range Coold Targ  X   Y   Z  Special Scale Big Model
    call AddClassAttack('h002',  1,   1,    0,   0, 1979,  1,   0,    0,    24,    0,  0,   1.0,    0.0,   3,    -1,    0,    180,   21,    0, 1248, 0.7, "g",  0,  0, 76,    0,    0.6,  0, "Abilities\\Spells\\Other\\HealingSpray\\HealBottleMissile.mdl","")
    call AddClassAttack('h005',  1,   1,    0,   0, 1414,  1,   0,    0,    24,    0,  0,   0.5,    0.0,   3,    -1,    0,    180,    6,    0,  864, 1.2, "g", 20,  0, 48,    0,    0.6,  0, "Abilities\\Weapons\\FaerieDragonMissile\\FaerieDragonMissile.mdl","")
    call AddClassAttack('h006',  0,   1,    0,   0,  600,  1,1300,   17,    16,  4.0,.12,   1.0,    1.0,   0,    90,    0,    360,   .1,    0, 2400, 3.0, "t",  0,  0, 32,    0,    0.3,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h007',  1,   1,    0,   0,  200,  1, 900,   16,    32,  1.6,1.0,   1.0,    1.0,   0,    80,    0,    180,   48,   48, 2880, 6.0, "g",  0,  0, 45,    0,    0.6,  1, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h008',  1,   1,    0,   0, 2262,  1,   0,    0,    24,    0,  0,   0.7,    0.0,   2,    -1,    0,    180,    7,    0, 1056, 0.6, "g",  0,  0, 45,    0,    0.6,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h009',  1,   2, 0.24,   0, 5000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   2,    -1,    0,    180,    4,    0, 1538, 2.4, "a",-17,  0, 43,    0,    0.6,  0, "war3mapImported\\LaserBlue.mdx","")
    call AddClassAttack('h00A',  1,   3, 0.48,   0, 1979,  1,   0,    0,    45,    0,  0,   1.0,    0.0,   2,    -1,    0,    180,   30,   96, 2400, 3.3, "g",  0,  0, 85,    0,    1.0,  1, "Abilities\\Spells\\Undead\\AbsorbMana\\AbsorbManaBirthMissile.mdl","")
    call AddClassAttack('h00B',  1,   1,    0,   0, 1700,  1,   0,    0,    32,    0,  0,   1.0,    0.0,   1,    -1,    0,    180,   64,    0, 1200, 2.0, "g",  0,  0,  0,    0,    0.6,  0, "Abilities\\Spells\\Undead\\OrbOfDeath\\AnnihilationMissile.mdl","")
    call AddClassAttack('h00B',  0,   1,    0,   0, 1000,  1,1300,   17,    24,  2.0,  0,   0.8,    1.0,   0,     0,    0,    360,   25,    0, 2400, 2.4, "a",  0,  0,  0,    0,    0.5,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h00B',  0,   1,    0,   0, 1000,  1,1300,   17,    24,  2.0,  0,   0.8,    1.0,   0,     0,    0,    360,   25,    0, 2400, 2.4, "a",  0,  0,  0,    0,    0.5,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('H00C',  1,   1,    0,   0, 1200,  1,   0,    0,    32,    0,  0,   1.0,    0.0,   1,    -1,    0,    180,   20,    0, 1056, 1.0, "g",  0,-45,108,    0,    0.8,  0, "Abilities\\Spells\\Human\\ManaFlare\\ManaFlareMissile.mdl","")
    call AddClassAttack('h00D',  1,   1,    0,   0,25000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   1,    -1,    0,    180,   80,   48, 1440, 0.1, "g",160,  0,128,    0,    0.6,  0, "AFOD","Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl")
    call AddClassAttack('h00D',  0,   1,    0,   0, 1979,  1,   0,    0,    32,    0,  0,   1.0,    0.0,   2,    -1,    0,    180,   63,    0, 3072, 0.7, "g",140,-100,162,   0,    0.6,  0, "Abilities\\Spells\\Undead\\OrbOfDeath\\AnnihilationMissile.mdl","")
    call AddClassAttack('h00D',  0,   1,    0,   0, 1000,  1,1300,   17,    24,  3.0,  0,   0.8,    1.0,   0,    45,    0,    360,   19,    0, 3072, 2.4, "a", 50,  0, 65,    0,    0.4,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h00D',  0,   1,    0,   0, 1000,  1,1300,   17,    24,  3.0,  0,   0.8,    1.0,   0,    45,    0,    360,   19,    0, 3072, 2.4, "a", 50,  0, 65,    0,    0.4,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h00D',  0,   1,    0,   0,  300,  1,1500,   24,    24,  1.5,1.0,   0.3,    0.0,   0,     0,    0,    360,   36,   48, 2160, 3.6, "w",  0,  0,  0,    1,    0.6,  1, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h00E',  1,   1,    0,   0, 1500,  1,   0,    0,    16,    0,  0,   0.0,    0.0,   6,    -1,    0,    360,    2,    0,  672, 0.47,"g",  0,  0, 35,    8,    0.5,  0, "Abilities\\Weapons\\WardenMissile\\WardenMissile.mdl","")
    call AddClassAttack('h00F',  1,   1,    0,   0, 1244,0.1,   0,    0,    90,    0,  0,   0.5,    0.0,   2,    -1,    0,    180,  180,  192, 4320,12.0, "g",  0,  0, 25,   13,    0.6,  1, "Abilities\\Weapons\\GreenDragonMissile\\GreenDragonMissile.mdl","Abilities\\Spells\\NightElf\\Rejuvenation\\RejuvenationTarget.mdl")
    call AddClassAttack('h00K',  1,   1,    0,   0, 1414,  1,   0,    0,    16,    0,  0,   1.0,    0.0,   1,    -1,    0,    180,    3,    0, 1200, 3.0, "g",  6,  0, 30,    0,    0.4,  0, "Abilities\\Weapons\\WardenMissile\\WardenMissile.mdl","")
    call AddClassAttack('h00M',  1,   4, 0.24,   0, 4000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   3,    -1,    0,    180,    6,    0, 2112, 1.7, "a",  0,  0, 70,    0,    0.4,  0, "Abilities\\Weapons\\WardenMissile\\WardenMissile.mdl","")
    call AddClassAttack('h00T',  1,   2, 0.24,   0, 5000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   4,    -1,    0,    180,    5,    0, 1200, 1.15,"a", 17,  0, 14,    0,    0.4,  0, "war3mapImported\\LaserRed.mdx","")
    call AddClassAttack('h010',  1,   1,    0,   0,  600,  1,   0,    0,    64,    0,  0,   0.0,    0.0,   4,    -1,    0,    180,  288,  288,  500, 9.6, "g",  0,  0,  0,    2,    0.6,  1, "Abilities\\Weapons\\GyroCopter\\GyroCopterMissile.mdl","Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl")
    call AddClassAttack('h010',  0,   2,  0.6,   0,  200,  1,1300,   17,    24,  3.0,  0,   1.0,    0.0,   1,    -1,    0,    360,   18,    0, 2112, 2.4, "a",  0,  0, 65,    0,    0.4,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h013',  1,   4, 0.48,   0, 2000,  1,   0,    0,    24,    0,  0,   1.0,    0.0,   3,    -1,    0,    180,   22,    0, 1200, 2.93,"g",  0,  0, 90,    0,    0.6,  0, "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl","war3mapImported\\LaserBlue.mdx")
    call AddClassAttack('h016',  1,   1,    0,  10, 1400,0.1,   0,    0,    64,    0,  0,   0.6,    0.0,   3,    -1,    0,    180,  192,  144, 6144,12.0, "g",  0,  0, 60,    0,    0.6,  1, "Abilities\\Weapons\\LordofFlameMissile\\LordofFlameMissile.mdl","Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl")
    call AddClassAttack('h017',  1,   1,    0,   0,  600,  1,1300,   17,    32,  3.0,  0,   0.8,    1.0,   0,    45,    0,    180,   67,    0, 2880, 1.0, "a",  0, 20, 70,    5,    0.6,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h018',  1,   1,    0,   0,  600,0.1,   0,    0,    45,    0,  0,   0.0,    0.0,   3,    -1,    0,    180,   60,  128, 1440,10.0, "g",  0,  0, 25,    4,    0.6,  1, "Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl","")
    call AddClassAttack('h01A',  1,   1,    0,   0,  900,  1,   0,    0,    45,    0,  0,   1.0,    0.0,   2,    -1,    0,    180,   18,    0, 1104, 1.56,"g", 12,  0, 40,    0,    0.4,  0, "war3mapImported\\DualWaterElementalMissile.mdx","")
    call AddClassAttack('h01B',  1,   1,    0,   0, 1700,  1,   0,    0,    32,    0,  0,   0.0,    0.0,   2,    -1,    0,    180,   20,   48, 1344, 1.8, "g", 27,  0, 15,    0,    0.9,  1, "Abilities\\Weapons\\DruidoftheTalonMissile\\DruidoftheTalonMissile.mdl","")
    call AddClassAttack('h01B',  0,   2, 0.24,   0, 5000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   1,    -1,    0,    360,    5,    0, 2304, 7.5, "a",  0,  0, 15,    0,    0.4,  0, "Abilities\\Weapons\\WardenMissile\\WardenMissile.mdl","")
    call AddClassAttack('h01C',  1,   1,    0,   0, 1700,  1,   0,    0,    45,    0,  0,   1.0,    0.0,   1,    -1,    0,     60,   56,   48, 2880, 4.0, "g", 40,  0, 15,    0,    0.6,  1, "Abilities\\Spells\\Undead\\OrbOfDeath\\AnnihilationMissile.mdl","")
    call AddClassAttack('h01C',  0,   1,    0,   0,  100,  1,1300,   17,    32,  3.0,  0,   0.8,    1.0,   0,    45,    0,    360,   60,    0, 3600, 2.1, "a", 50,  0, 15,    0,    0.6,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h01C',  0,   1,    0,   0,  100,  1,1300,   17,    32,  3.0,  0,   0.8,    1.0,   0,    45,    0,    360,   60,    0, 3600, 2.1, "a",-50,  0, 30,    0,    0.6,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h01C',  0,   1,    0,   0, 1000,  1,1300,   17,    16,  4.0,  0,   0.8,    1.0,   0,    90,    0,    360,   .1,    0, 2400, 2.4, "t",  0,  0,100,    0,    0.3,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h01D',  1,   1,    0,   0,  200,  1, 900,   16,    32,  1.6,1.5,   1.0,    1.0,   0,    89,    0,    360,  125,   64, 2880,15.0, "g",  0,  0, 20,    0,    0.6,  1, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h01D',  0,   1,    0,   0, 1700,0.2,   0,    0,    64,    0,  0,   0.5,    0.0,   1,    -1,    0,    270,   80,   48, 2880, 4.8, "g", 24,  0, 20,    0,    0.6,  1, "war3mapImported\\DualWaterElementalMissile.mdx","")
    call AddClassAttack('h01D',  0,   1,    0,   0, 1700,0.2,   0,    0,    64,    0,  0,   0.5,    0.0,   1,    -1,    0,    270,   80,   48, 2880, 4.8, "g",-24,  0, 20,    0,    0.6,  1, "war3mapImported\\DualWaterElementalMissile.mdx","")
    call AddClassAttack('h01D',  0,   1,    0,   0,  300,  1,1500,   24,    24,  1.8,1.0,   0.3,    0.0,   0,     0,    0,    270,   36,   48, 2160, 6.0, "w",  0,  0,  0,    1,    0.6,  1, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h01D',  0,   1,    0,   0, 5000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   1,    -1,    0,    360,    7,    0, 2444, 2.47,"a",  0,  0, 15,    0,    0.4,  0, "Abilities\\Weapons\\WardenMissile\\WardenMissile.mdl","")
    call AddClassAttack('h01D',  0,   1,    0,   0, 1000,  1,1500,   24,    16,  4.0,  0,   1.0,    0.0,   0,    -1,    0,    360,   .1,    0, 1440, 8.0, "p",  0,  0,  0,    1,    0.3,  0, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h01E',  0,   2, 0.36,   0, 2100,0.1,   0,    0,    45,    0,  0,   1.0,    0.0,   2,    -1,    0,    180,  150,  144, 7200,10.0, "g",184,  0, 50,    0,    1.2,  1, "Abilities\\Weapons\\Mortar\\MortarMissile.mdl","")
    call AddClassAttack('h01E',  0,   2, 0.36,   0, 2100,0.1,   0,    0,    45,    0,  0,   1.0,    0.0,   2,    -1,   60,    180,  150,  144, 7200,10.0, "g", 48, 90, 50,    0,    1.2,  1, "Abilities\\Weapons\\Mortar\\MortarMissile.mdl","")
    call AddClassAttack('h01E',  0,   2, 0.36,   0, 2100,0.1,   0,    0,    45,    0,  0,   1.0,    0.0,   2,    -1,  -60,    180,  150,  144, 7200,10.0, "g", 48,-90, 50,    0,    1.2,  1, "Abilities\\Weapons\\Mortar\\MortarMissile.mdl","")
    call AddClassAttack('h01E',  0,   1,    0,   0, 5000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   2,    -1,    0,    360,    3,    0, 2444, 2.1, "a", 48,  0, 50,    0,    0.3,  0, "Abilities\\Weapons\\WardenMissile\\WardenMissile.mdl","")
    call AddClassAttack('h01E',  0,   1,    0,   0, 1000,  1,1300,   17,    16,  4.0,  0,   1.0,    1.0,   0,    90,    0,    360,   .1,    0, 2400, 1.2, "t",  0,  0,100,    0,    0.3,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h01H',  1,   1,    0,   0, 4000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   1,    -1,    0,    360,   25,  192, 2112, 0.86,"a",  0,  0, 70,    0,    0.6,  0, "Abilities\\Spells\\NightElf\\FanOfKnives\\FanOfKnivesMissile.mdl","")
    call AddClassAttack('h01I',  0,   1,    0,   0,  300,  1,1500,   24,    24,  1.5,1.0,   0.3,    0.0,   0,     0,    0,    180,   36,   48, 1440, 4.8, "w",  0,  0,  0,    1,    0.6,  1, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h01J',  1,   1,    0,   0,  400,  1,   0,    0,    48,    0,  0,   0.0,    0.0,   4,    -1,    0,    180,   18,  120,  500, 4.8, "g",  0,  0,  0,    0,    0.4,  1, "Abilities\\Weapons\\GyroCopter\\GyroCopterMissile.mdl","")
    call AddClassAttack('h01L',  1,   1,    0,   0, 1200,  1,   0,    0,    32,    0,  0,   1.0,    0.0,   1,    -1,    0,    180,   20,    0, 1200, 1.0, "g",  0,-31, 76,    0,    0.8,  0, "Abilities\\Spells\\Human\\ManaFlare\\ManaFlareMissile.mdl","")
    call AddClassAttack('h01M',  1,   1,    0,   0,25000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   1,    -1,    0,    180,   50,   24, 1920, 0.12,"g", 88,  0,418,   12,    1.2,  0, "CLPB","Abilities\\Spells\\Undead\\OrbOfDeath\\AnnihilationMissile.mdl")
    call AddClassAttack('h01N',  0,   1,    0,   0,   50,  1,1000,   17,    64, 2200,  0,   0.0,    1.0,   0,    90,    0,    360,14000, 2500,99999,60.0, "",   0,  0, 10,    3,    0.9,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","war3mapImported\\nukesign.mdx")
    call AddClassAttack('h01O',  1,   1,    0,   0, 1000,  1,1300,   17,    32,  1.8,  0,   0.8,    0.4,   0,     0,    0,    180,   34,    0, 1440, 0.6, "g", 64,-64, 50,    0,    0.6,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl")
    call AddClassAttack('h01O',  1,   1,    0,   0, 1000,  1,1300,   17,    32,  1.8,  0,   0.8,    0.4,   0,     0,    0,    180,   34,    0, 1440, 0.6, "g", 64, 64, 50,    0,    0.6,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl")
    call AddClassAttack('h01O',  0,   1,    0,   0, 1000,  1,1300,   17,    24,  2.0,  0,   0.8,    1.0,   0,    -1,   60,    270,   46,    0, 3072, 1.9, "a", 50,  0, 65,    0,    0.4,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h01O',  0,   1,    0,   0, 1000,  1,1300,   17,    24,  2.0,  0,   0.8,    1.0,   0,     0,  -60,    270,   46,    0, 3072, 1.9, "a", 50,  0, 65,    0,    0.4,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h01O',  0,   1,    0,   0, 1700,  1,   0,    0,    32,    0,  0,   1.0,    0.0,   2,    -1,   60,    180,  128,    0, 1440, 0.6, "g", 48, 90,  0,    0,    0.6,  0, "Abilities\\Spells\\Undead\\OrbOfDeath\\AnnihilationMissile.mdl","")
    call AddClassAttack('h01O',  0,   1,    0,   0, 1700,  1,   0,    0,    32,    0,  0,   1.0,    0.0,   2,    -1,  -60,    180,  128,    0, 1440, 0.6, "g", 48,-90,  0,    0,    0.6,  0, "Abilities\\Spells\\Undead\\OrbOfDeath\\AnnihilationMissile.mdl","")
    call AddClassAttack('h01P',  0,   1,    0, 100, 1000,  1,1300,   17,    32,  4.0,  0,   0.8,    1.0,   0,    90,    0,    360,   .1,  128, 4320, 2.0, "s",  0,  0,160,    0,    0.5,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h01R',  1,   1,    0,   0, 5000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   1,    -1,    0,    180,   34,  144, 1920, 1.6, "a",-20,  0, 50,    0,    0.8,  0, "Abilities\\Spells\\NightElf\\FanOfKnives\\FanOfKnivesMissile.mdl","")
    call AddClassAttack('h01Q',  1,   1,    0,   0,25000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   0,    -1,    0,    180,   48,    0, 1440, 1.2, "a", 20,  0, 20,    0,    0.8,  0, "CLPB","Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl")
    call AddClassAttack('h01T',  1,   1,    0,   0, 2262,  1,   0,    0,    24,    0,  0,   1.0,    0.0,   2,    -1,    0,    180,    6,    0, 1056, 1.7, "g",  0,  0,  0,    0,    0.6,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h01T',  0,   1,    0,   0, 5000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   3,    -1,    0,    360,    6,    0,  960, 1.24,"a", 17,  0, 14,    0,    0.8,  0, "Abilities\\Weapons\\WardenMissile\\WardenMissile.mdl","")
    call AddClassAttack('h01T',  0,   1,    0,   0, 5000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   3,    -1,    0,    360,    6,    0,  960, 1.24,"a", 17,  0, 14,    0,    0.8,  0, "Abilities\\Weapons\\WardenMissile\\WardenMissile.mdl","")
    call AddClassAttack('h01V',  1,   1,    0,   0, 5000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   1,    -1,    0,    180,    6,    0, 1440, 1.2, "g", 12,  0, 15,    0,    0.4,  0, "war3mapImported\\LaserRed.mdx","")
    call AddClassAttack('h01V',  0,   1,    0,   0,  300,  1,1500,   24,    24,  1.5,1.0,   0.3,    0.0,   0,     0,    0,    180,   36,   48, 1440, 4.8, "w",  0,  0,  0,    1,    0.6,  1, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h01W',  1,   1,    0,   0,  400,  1,1500,   24,    24,  1.5,1.0,   0.3,    0.0,   8,    -1,    0,    180,   58,   48, 1056, 4.8, "w",  0,  0,  0,    1,    0.6,  1, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h01X',  1,   1,    0,   0, 2262,  1,   0,    0,    45,    0,  0,   0.5,    0.0,   2,    -1,    0,    180,    6,    0,  864, 0.37,"g", 12,  0, 60,    0,    0.4,  0, "Abilities\\Weapons\\LichMissile\\LichMissile.mdl","Abilities\\Weapons\\WingedSerpentMissile\\WingedSerpentMissile.mdl")
    call AddClassAttack('h01Z',  1,   1,    0,  10, 4000,  0,   0,    0,    90,    0,  0,   0.1,    0.0,   0,    -1,    0,    360, 1585,  336,40000, 3.1, "g",  0,  0, 60,   10,    1.2,  1, "Abilities\\Weapons\\LordofFlameMissile\\LordofFlameMissile.mdl","Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl")
    call AddClassAttack('h022',  1,   5, 0.36,   0, 3000,  1,   0,    0,    16,    0,  0,   1.0,    0.0,   2,    -1,    0,    180,    5,    0, 1632, 4.0, "g",  0,  0, 70,    0,    0.4,  0, "Abilities\\Weapons\\FaerieDragonMissile\\FaerieDragonMissile.mdl","")
    call AddClassAttack('h022',  0,   1,    0,   0, 1500,  1,   0,    0,    32,    0,  0,   0.5,    0.0,   2,    -1,    0,    180,   16,   96, 1632, 3.07,"g",  0,  0, 70,    0,    0.5,  1, "Abilities\\Weapons\\GyroCopter\\GyroCopterMissile.mdl","Abilities\\Spells\\Undead\\AbsorbMana\\AbsorbManaBirthMissile.mdl")
    call AddClassAttack('h023',  1,   2, 0.48,   0,  400,  1,   0,    0,    45,    0,  0,   0.0,    0.0,   4,    -1,    0,    180,   18,  120,  500, 4.8, "g",  0,  0,  0,    0,    0.4,  1, "Abilities\\Weapons\\GyroCopter\\GyroCopterMissile.mdl","")
    call AddClassAttack('h023',  0,   2,  0.6,   0,  200,  1,1300,   17,    24,  3.0,  0,   1.0,    0.0,   1,    -1,    0,    360,   18,    0, 2112, 2.4, "a",  0,  0, 65,    0,    0.4,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h024',  0,   6, 0.12,   0, 4000,  1,   0,    0,     0,    0,  0,   0.0,    0.0,   1,   -90,    0,    360,   80,  192,  192, 0.72,"g",  0,  0,  0,    0,    1.0,  0, "Abilities\\Weapons\\FrostWyrmMissile\\FrostWyrmMissile.mdl","Abilities\\Weapons\\ZigguratMissile\\ZigguratMissile.mdl")
    call AddClassAttack('h024',  0,   1,    0,   0, 1000,  1,1300,   17,    32,  3.0,0.2,   0.8,    1.0,   0,     0,    0,    215,   86,    0, 3072, 0.6, "a",325,  0,  0,    7,    0.6,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h024',  0,   1,    0,   0, 1000,  1,1300,   17,    32,  3.0,0.2,   0.8,    1.0,   0,     0,  180,    215,   86,    0, 3072, 0.6, "a",-325, 0,  0,    7,    0.6,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h024',  0,   1,    0,   0, 1000,  1,1300,   17,    32,  3.0,0.2,   0.8,    1.0,   0,     0,   90,    215,   86,    0, 3072, 0.6, "a",  0,325,  0,    7,    0.6,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h024',  0,   1,    0,   0, 1000,  1,1300,   17,    32,  3.0,0.2,   0.8,    1.0,   0,     0,  -90,    215,   86,    0, 3072, 0.6, "a",  0,-325, 0,    7,    0.6,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h024',  0,   1,    0,   0,  900,  1, 900,    7,    32,  1.0,  0,   1.0,    1.0,   4,    -1,    0,    360,   36,   72, 2400, 4.8, "w",  0,200, -99,   0,    0.6,  1, "Abilities\\Weapons\\GyroCopter\\GyroCopterMissile.mdl","Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl")
    call AddClassAttack('h024',  0,   1,    0,   0,  900,  1, 900,    7,    32,  1.0,  0,   1.0,    1.0,   4,    -1,    0,    360,   36,   72, 2400, 4.8, "w",  0,-200,-99,   0,    0.6,  1, "Abilities\\Weapons\\GyroCopter\\GyroCopterMissile.mdl","Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl")
    call AddClassAttack('h025',  0,   1,    0,   0, 1700,0.2,   0,    0,    64,    0,  0,   1.0,    0.0,   1,    -1,    0,    120,  180,   72, 4800, 1.2, "g", 28,  0,100,    0,    0.8,  1, "war3mapImported\\DualWaterElementalMissile.mdx","")
    call AddClassAttack('h025',  0,   1,    0,   0, 1700,0.2,   0,    0,    64,    0,  0,   1.0,    0.0,   1,    -1,    0,    120,  180,   72, 4800, 1.2, "g", 80,  0, 65,    0,    0.8,  1, "war3mapImported\\DualWaterElementalMissile.mdx","")
    call AddClassAttack('h025',  0,   1,    0,   0, 1700,0.2,   0,    0,    64,    0,  0,   1.0,    0.0,   1,    -1,   50,    120,  180,   72, 4800, 1.2, "g",-60, 84, 65,    0,    0.8,  1, "war3mapImported\\DualWaterElementalMissile.mdx","")
    call AddClassAttack('h025',  0,   1,    0,   0, 1700,0.2,   0,    0,    64,    0,  0,   1.0,    0.0,   1,    -1,  -50,    120,  180,   72, 4800, 1.2, "g",-60,-84, 65,    0,    0.8,  1, "war3mapImported\\DualWaterElementalMissile.mdx","")
    call AddClassAttack('h025',  0,   1,    0,   0, 2262,  1,   0,    0,    32,    0,  0,   1.0,    0.0,   1,    -1,    0,     90,   54,    0, 2160, 0.6, "g",110, 68, 46,    0,    0.8,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h025',  0,   1,    0,   0, 2262,  1,   0,    0,    32,    0,  0,   1.0,    0.0,   1,    -1,    0,     90,   54,    0, 2160, 0.6, "g",110,-68, 46,    0,    0.8,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h025',  0,   1,    0,   0, 5000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   1,    -1,    0,    360,    7,    0, 2160, 0.58,"a",-60, 84, 65,    0,    0.6,  0, "war3mapImported\\LaserBlue.mdx","")
    call AddClassAttack('h025',  0,   1,    0,   0, 5000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   1,    -1,    0,    360,    7,    0, 2160, 0.58,"a",-60,-84, 65,    0,    0.6,  0, "war3mapImported\\LaserBlue.mdx","")
    call AddClassAttack('h026',  0,   1,    0,   0, 2000,  1,1300,   17,    16,  4.0,  0,   1.0,    1.0,   0,    -1,    0,    360,   .1,    0, 1920, 2.4, "t",  0,  0,100,    0,    0.3,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h027',  1,   3, 0.48,   0,  200,  1, 900,   16,    32,  1.6,1.2,   1.0,    1.0,   0,    80,    0,    180,   95,   48, 3840,15.0, "g",  0,  0, 45,    0,    0.7,  1, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h028',  1,   1,    0,   0, 2262,  1,   0,    0,    32,    0,  0,   0.4,    0.0,   2,    -1,    0,    180,   24,    0, 1200, 0.45,"g",  0,  0, 45,    0,    0.6,  0, "Abilities\\Spells\\Undead\\OrbOfDeath\\AnnihilationMissile.mdl","")
    call AddClassAttack('h029',  1,   1,    0,   0,  300,  1,1000,   24,    24,  1.5,1.0,   0.3,    1.0,   2,     0,   60,    180,   38,   48, 2400, 4.0, "w", 50, 50,  0,    1,    0.6,  1, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h029',  1,   1,    0,   0,  300,  1,1000,   24,    24,  1.5,1.0,   0.3,    1.0,   2,     0,  -60,    180,   38,   48, 2400, 4.0, "w", 50,-50,  0,    1,    0.6,  1, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h029',  0,   1,    0,   0,  300,  1,1000,   24,    24,  1.5,1.0,   0.3,    1.0,   2,     0,   90,    215,   38,   48, 2400, 4.0, "w",-50, 50,  0,    1,    0.6,  1, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h029',  0,   1,    0,   0,  300,  1,1000,   24,    24,  1.5,1.0,   0.3,    1.0,   2,     0,  -90,    215,   38,   48, 2400, 4.0, "w",-50,-50,  0,    1,    0.6,  1, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h029',  0,   1,    0,   0, 1000,  1,1500,   24,    16,  4.0,  0,   1.0,    0.0,   0,    -1,    0,    360,   .1,    0, 1200, 2.5, "p",  0,  0,  0,    1,    0.3,  0, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h02B',  1,   3, 0.24,   0,   50,  1,1500,   22,    32,  0.8,2.0,   0.0,    1.0,   2,    88,    0,    360,  160,  144, 6144,12.0, "g",  0,  0,  1,    9,    0.6,  1, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h02B',  0,   1,    0,   0,   50,  1,1000,   17,    45, 2200,  0,   0.0,    1.0,   0,    90,    0,    360, 5000, 2500,99999,60.0, "",   0,  0,  1,    3,    0.9,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","war3mapImported\\nukesign.mdx")
    call AddClassAttack('h02C',  1,   3, 0.24,   0,   50,  1,1500,   22,    32,  0.8,2.0,   0.0,    1.0,   2,    88,    0,    360,  160,  144, 6144,12.0, "g",  0,  0,  1,    9,    0.6,  1, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h02C',  0,   1,    0,   0,   50,  1,1000,   17,    45, 2200,  0,   0.0,    1.0,   0,    90,    0,    360, 5000, 2500,99999,60.0, "",   0,  0,  1,    3,    0.9,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","war3mapImported\\nukesign.mdx")
    call AddClassAttack('h02G',  1,   1,    0,   0, 2262,  1,   0,    0,    32,    0,  0,   1.0,    0.0,   2,    -1,    0,    180,    6,    0, 1344, 0.94,"g", 40,  0, 15,    0,    0.6,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h02G',  0,   1,    0,   0, 1000,  1,1500,   24,    24,  4.0,  0,   1.0,    0.0,   0,    -1,    0,    360,   .1,    0, 1440, 4.0, "p",  0,  0,  0,    1,    0.3,  0, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h02H',  1,   1,    0,   0,  300,  1,1500,   24,    16,  1.8,1.0,   0.3,    0.0,   0,    45,    0,    360,   30,   48, 2400, 2.0, "w",  0,  0,  0,    1,    0.6,  1, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h02J',  1,   3, 0.24,   0,  600,  1,1300,   19,    32,  1.5,  0,   0.8,    1.0,   6,    45,    0,    180,   40,    0, 2444, 3.6, "a",  0,  0, 60,    0,    0.6,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h02L',  1,   1,    0,   0,  600,  1, 900,   17,    32,  1.8,.12,   1.0,    0.4,   0,     0,    0,    180,   48,   48, 2000, 4.8, "g",  0,-32,  0,    0,    0.6,  1, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h02L',  1,   1,    0,   0,  600,  1, 900,   17,    32,  1.8,.12,   1.0,    0.4,   0,     0,    0,    180,   48,   48, 2000, 4.8, "g",  0, 32,  0,    0,    0.6,  1, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h02Q',  1,   4, 0.48,   0,  300,  1,1500,   24,    24,  1.8,1.0,   0.3,    0.0,   0,    45,    0,    360,   30,   48, 2880, 4.0, "w",  0,  0,  0,    1,    0.6,  1, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h02R',  0,   1,    0,   0,   50,  1,1500,   22,    32,  0.8,3.0,   0.0,    1.0,   0,    90,    0,    360,  200,   96,12288,30.0, "",   0,  0, 10,    9,    0.7,  1, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h02S',  1,   1,    0,  10, 3500,0.1,   0,    0,    64,    0,  0,   0.1,    0.0,   1,    -1,    0,    180, 1100,  240,36000,10.0, "g",  0,  0, 25,    0,    1.0,  1, "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl","Abilities\\Spells\\Undead\\Cripple\\CrippleTarget.mdl")
    call AddClassAttack('h02T',  1,   1,    0,   0,  300,  1,1000,   24,    24,  1.5,1.0,   0.3,    1.0,   2,     0,    0,    180,   36,   48, 2160, 4.0, "w",  0, 30,  0,    1,    0.6,  1, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h02T',  1,   1,    0,   0,  300,  1,1000,   24,    24,  1.5,1.0,   0.3,    1.0,   2,     0,    0,    180,   36,   48, 2160, 4.0, "w",  0,-30,  0,    1,    0.6,  1, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h02T',  0,   1,    0,   0, 1000,  1,1500,   24,    16,  4.0,  0,   1.0,    0.0,   0,    -1,    0,    360,   .1,    0, 1536, 6.0, "p",  0,  0,  0,    1,    0.3,  0, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h02U',  1,   1,    0,   0,  300,  1,1000,   24,    24,  1.5,1.0,   0.3,    1.0,   2,     0,    0,    180,   36,   48, 2160, 4.0, "w",  0, 30,  0,    1,    0.6,  1, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h02U',  1,   1,    0,   0,  300,  1,1000,   24,    24,  1.5,1.0,   0.3,    1.0,   2,     0,    0,    180,   36,   48, 2160, 4.0, "w",  0,-30,  0,    1,    0.6,  1, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h02U',  0,   1,    0,   0, 1000,  1,1500,   24,    16,  4.0,  0,   1.0,    0.0,   0,    -1,    0,    360,   .1,    0, 1536, 6.0, "p",  0,  0,  0,    1,    0.3,  0, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h02V',  1,   2, 0.36,   0, 1000,  1,   0,    0,    24,    0,  0,   1.0,    0.0,   1,    -1,    0,    180,   40,   48, 1536, 6.0, "g",  0,  0, 45,    0,    0.6,  1, "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl","Abilities\\Spells\\Undead\\AbsorbMana\\AbsorbManaBirthMissile.mdl")
    call AddClassAttack('h02V',  0,   4, 0.24,   0, 1414,  1,   0,    0,    24,    0,  0,   0.5,    0.0,   1,    -1,    0,     90,   15,    0, 1536, 5.4, "g", 20, 35, 40,    0,    0.6,  0, "Abilities\\Weapons\\FaerieDragonMissile\\FaerieDragonMissile.mdl","")
    call AddClassAttack('h02W',  1,   5, 0.24,   0,25000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   0,    -1,    0,    180,   38,   48, 3360, 6.7, "g",128, 40, 60,    0,    0.9,  0, "DRAM","Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl")
    call AddClassAttack('h02W',  1,   5, 0.24,   0,25000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   0,    -1,    0,    180,   38,   48, 3360, 6.7, "g",128,-40, 60,    0,    0.9,  0, "DRAM","Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl")
    call AddClassAttack('h02W',  0,   5, 0.24,   0,25000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   0,    -1,   45,    120,   38,   48, 3360, 6.7, "g",  0, 70, 60,    0,    0.9,  0, "DRAM","Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl")
    call AddClassAttack('h02W',  0,   5, 0.24,   0,25000,  1,   0,    0,     0,    0,  0,   1.0,    0.0,   0,    -1,  -45,    120,   38,   48, 3360, 6.7, "g",  0,-70, 60,    0,    0.9,  0, "DRAM","Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl")
    call AddClassAttack('h02W',  0,   1,    0,   0,  300,  1,1500,   24,    24,  1.8,1.0,   0.3,    0.0,   0,     0,    0,    270,   30,   24, 2880, 7.5, "w",  0,  0,  0,    1,    0.6,  1, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h02W',  0,   1,    0,   0, 1000,  1,1500,   24,    16,  4.0,  0,   1.0,    0.0,   0,    -1,    0,    360,   .1,    0, 1440, 5.0, "p",  0,  0,  0,    1,    0.3,  0, "war3mapImported\\Torpedo.mdx","")
    call AddClassAttack('h02W',  0,   1,    0,   0, 1000,  1,1300,   17,    16,  4.0,  0,   1.0,    1.0,   0,    90,    0,    360,   .1,    0, 2400, 2.4, "t",  0,  0,100,    0,    0.3,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h02Z',  0,   1,    0,   0, 1000,  1,1300,   17,    32,  3.0,0.2,   0.8,    1.0,   0,     0,    0,    215,   67,    0, 3072, 4.0, "a",128,  0, 80,    7,    0.6,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h02Z',  0,   1,    0,   0, 1000,  1,1300,   17,    32,  3.0,0.2,   0.8,    1.0,   0,     0,  180,    215,   67,    0, 3072, 4.0, "a",-128, 0, 80,    7,    0.6,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h02Z',  0,   1,    0,   0, 1000,  1,1300,   17,    32,  3.0,0.2,   0.8,    1.0,   0,     0,   90,    215,   67,    0, 3072, 4.0, "a",  0,128, 80,    7,    0.6,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h02Z',  0,   1,    0,   0, 1000,  1,1300,   17,    32,  3.0,0.2,   0.8,    1.0,   0,     0,  -90,    215,   67,    0, 3072, 4.0, "a",  0,-128,80,    7,    0.6,  0, "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl","")
    call AddClassAttack('h02Z',  0,   1,    0,   0, 1979,  1,   0,    0,    45,    0,  0,   1.0,    0.0,   2,    -1,   45,    180,   30,   96, 2400, 2.2, "g", 64, 64, 85,    0,    1.0,  1, "Abilities\\Spells\\Undead\\AbsorbMana\\AbsorbManaBirthMissile.mdl","")
    call AddClassAttack('h02Z',  0,   1,    0,   0, 1979,  1,   0,    0,    45,    0,  0,   1.0,    0.0,   2,    -1,  135,    180,   30,   96, 2400, 2.2, "g",-64, 64, 85,    0,    1.0,  1, "Abilities\\Spells\\Undead\\AbsorbMana\\AbsorbManaBirthMissile.mdl","")
    call AddClassAttack('h02Z',  0,   1,    0,   0, 1979,  1,   0,    0,    45,    0,  0,   1.0,    0.0,   2,    -1, -135,    180,   30,   96, 2400, 2.2, "g",-64,-64, 85,    0,    1.0,  1, "Abilities\\Spells\\Undead\\AbsorbMana\\AbsorbManaBirthMissile.mdl","")
    call AddClassAttack('h02Z',  0,   1,    0,   0, 1979,  1,   0,    0,    45,    0,  0,   1.0,    0.0,   2,    -1,  -45,    180,   30,   96, 2400, 2.2, "g", 64,-64, 85,    0,    1.0,  1, "Abilities\\Spells\\Undead\\AbsorbMana\\AbsorbManaBirthMissile.mdl","")
    call AddClassAttack('h035',  1,   1,    0,   0,  600,  1,   0,    0,     0,    0,  0,   0.0,    0.0,  10,    -1,    0,    360,   10,   24,  160, 0.8, "g",  0,  0, 35,    0,    0.5,  0, "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl","")

    set udg_Overcharge = AddClassAttack(     0,  0,   1,    0,   0, 1200,  1,   0,    0,    64,    0,  0,   1.0,    0.0,   0,    -1,    0,    360, 2400,   96, 1056, 0.0, "g",  0,-45,128,    6,    1.3,  1, "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl","Abilities\\Weapons\\ZigguratMissile\\ZigguratMissile.mdl")
    set udg_LavaRock   = AddClassAttack(     0,  0,   1,    0,   0,  500,  1,   0,    0,    45,    0,  0,   0.0,    0.0,   0,    -1,    0,    360,  120,  144, 2000, 0.0, "g",  0,  0,  0,    0,    1.3,  1, "Abilities\\Spells\\Other\\Volcano\\VolcanoMissile.mdl","Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl")
    set udg_ArtillSplit= AddClassAttack(     0,  0,   5,    0,   0,  600,0.1,   0,    0,    24,    0,  0,   0.0,    0.0,  25,    -1,    0,    180,   24,   48,    0, 0.0, "g",  0,  0,  0,    0,    0.3,  0, "Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl","")
    set udg_Salva1Split= AddClassAttack(     0,  1,   6,    0,   0,  600,0.1,   0,    0,    45,    0,  0,   0.0,    0.0,   8,    -1,    0,    180,  264,  144,    0, 0.0, "g",  0,  0,  0,   11,    1.0,  1, "Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl","")
    set udg_Salva2Split= AddClassAttack(     0,  0,   6,    0,   0,  600,0.1,   0,    0,    24,    0,  0,   0.0,    0.0,   8,    -1,    0,    180,   44,   96,    0, 0.0, "g",  0,  0,  0,    0,    0.5,  1, "Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl","")
    set udg_AHeavySplit= AddClassAttack(     0,  0,   5,    0,   0, 1244,0.1,   0,    0,    45,    0,  0,   0.0,    0.0,  14,    -1,    0,    180,   40,  120,    0, 0.0, "g",  0,  0,  0,    0,    0.3,  1, "Abilities\\Weapons\\GreenDragonMissile\\GreenDragonMissile.mdl","")




    // Additional Abilities

    call SetClassBuildSpeed('h001', 0.5 )
    call SetClassBuildSpeed('h00P', 1.0 )
    call SetClassBuildSpeed('H00C', 1.0 )
    call SetClassBuildSpeed('h00Y', 1.5 )
    call SetClassBuildSpeed('h01L', 6.0 )
    call SetClassBuildSpeed('h02K', 0.5 )

    // Shields

    call SetClassManaRegeneration('h00B',  12.0, true )
    call SetClassManaRegeneration('H00C',  52.0, true )
    call SetClassManaRegeneration('h01L',  52.0, true )
    call SetClassManaRegeneration('h006',  22.0, true )
    call SetClassManaRegeneration('h004',  48.0, true )
    call SetClassManaRegeneration('h014',  52.0, true )
    call SetClassManaRegeneration('h025',  26.0, true )
    call SetClassManaRegeneration('h02A',  32.0, true )

    // Production

    call SetClassManaRegeneration('h01N', 2.0/3, false)
    call SetClassManaRegeneration('h01P',   1.5, false)
    call SetClassManaRegeneration('h02B', 1/2.1, false)
    call SetClassManaRegeneration('h02C', 1/2.1, false)
    call SetClassManaRegeneration('h02R',   1.0, false)
    call SetClassManaRegeneration('h02Z',   1.0, false)

    // Weapon Reload

    call SetClassManaRegeneration('h01Z',10/3.1, false)
    call SetClassManaRegeneration('h016',10/12., false)
    call SetClassManaRegeneration('h02S',10/12., false)

    call SetClassRadarRange('h00X', 22624.0*0.7 )
    call SetClassRadarRange('h00U', 11312.0*0.7 )
    call SetClassRadarRange('h00H',  6504.0*0.7 )
    call SetClassRadarRange('h00K',  2545.0*0.7 )
    call SetClassRadarRange('h00S',  2375.0*0.7 )
    call SetClassRadarRange('h01E',  2828.0*0.7 )
    call SetClassRadarRange('h01U',  5430.0*0.7 )
    call SetClassRadarRange('h01C',  8484.0*0.7 )
    call SetClassRadarRange('h01B',  4524.0*0.7 )
    call SetClassRadarRange('h01M',  2828.0*0.7 )
    call SetClassRadarRange('h010',  3676.0*0.7 )
    call SetClassRadarRange('h01O',  2601.0*0.7 )
    call SetClassRadarRange('h024',  9600.0*0.7 )
    call SetClassRadarRange('h02K',  6504.0*0.7 )

    call SetClassEnergyAbility('h00X','A01Y' )

    call SetClassStealthRange('h00D',    1 )
    call SetClassStealthRange('h02X',  400 )
    call SetClassStealthRange('h02K',  300 )

    call SetClassAdjecencyEnergyCostFactor('h000', 0.75 )
    call SetClassAdjecencyEnergyCostFactor('h00Q', 0.50 )
    call SetClassAdjecencyEnergyCostFactor('h00Z', 0.25 )
    call SetClassAdjecencyEnergyCostFactor('h02N', 0.50 )
    call SetClassAdjecencyEnergyCostFactor('h02Y', 0.75 )

    call SetClassAdjecencyMassCostFactor('h00G', 0.60 )
    call SetClassAdjecencyMassCostFactor('h00V', 0.40 )
    call SetClassAdjecencyMassCostFactor('h00W', 0.20 )
    call SetClassAdjecencyMassCostFactor('h00N', 0.90 )
    call SetClassAdjecencyMassCostFactor('h015', 0.60 )

    call SetClassAdjecencyMassIncomeFactor('h021', 1.50 )

    call SetClassAdjecencyEnergyIncomeFactor('h021', 1.50 )
    call DestroyTrigger(GetTriggeringTrigger())
endfunction

//===========================================================================
function InitTrig_Class_Config takes nothing returns nothing
    set gg_trg_Class_Config = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Class_Config, function Trig_Class_Config_Actions )
endfunction
function Trig_Cine_Cam_Actions takes nothing returns nothing
    local real FromX = GetRectCenterX(gg_rct_CineCamFrom)
    local real FromY = GetRectCenterY(gg_rct_CineCamFrom)
    local real ToX = GetRectCenterX(gg_rct_CineCamTo)
    local real ToY = GetRectCenterY(gg_rct_CineCamTo)
    local real Duration = 22
    local real TimeElapsed = TimerGetElapsed(udg_GameTimer)+0.2
    call PanCameraToTimed(FromX+(ToX-FromX)*TimeElapsed/Duration,FromY+(ToY-FromY)*TimeElapsed/Duration,0.2)
endfunction

//===========================================================================
function InitTrig_Cine_Cam takes nothing returns nothing
    set gg_trg_Cine_Cam = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Cine_Cam, 0.2 )
    call TriggerAddAction( gg_trg_Cine_Cam, function Trig_Cine_Cam_Actions )
endfunction
function Trig_Choose_Mode_Actions takes nothing returns nothing
    local integer pid = 0
    local integer pid2
    local integer Size = 1
    local integer i = 1
    local integer CurTeamSize
    local integer CurTeam
    local integer CountTeams
    local button Clicked = GetClickedButton()
    if Clicked==udg_modeBtMode then
        set udg_modeValMode = udg_modeValMode + 1
        if udg_modeValMode>3 then
            set udg_modeValMode = 0
        endif
    endif
    if Clicked==udg_modeBtPrebuilt then
        set udg_modeValPrebuilt = udg_modeValPrebuilt + 1
        if udg_modeValPrebuilt>4 then
            set udg_modeValPrebuilt = 0
        endif
    endif
    if Clicked==udg_modeBtTeamSize then
        set udg_modeValTeamSize = udg_modeValTeamSize + 1
        if udg_modePossibleTeamSizes[udg_modeValTeamSize]==0 then
            set udg_modeValTeamSize = 0
        endif
    endif
    if Clicked==udg_modeBtLockTeams then
        set udg_modeValLockTeams = not udg_modeValLockTeams
    endif
    set udg_modeValLockTeams = udg_modeValLockTeams and udg_modeValMode!=3
    if Clicked==udg_modeBtNoRush then
        set udg_modeValNoRush = udg_modeValNoRush + 1
        if udg_modeValNoRush>3 then
            set udg_modeValNoRush = 0
        endif
    endif
    if udg_modeValMode==2 then
        set udg_modeValNoRush = 0
    endif
    if Clicked==udg_modeBtLeaverAI then
        set udg_modeValLeaverAI = not udg_modeValLeaverAI
    endif
    if Clicked==udg_modeBtGo then
        call EnableUserControl(false)
        call TriggerExecute(gg_trg_Start_Game)
    else
        call RefreshModeDialog()
        call EnableUserControl(GetLocalPlayer()==udg_Host)
        call DialogDisplay( udg_Host, udg_modeDialog, true )
    endif
endfunction

//===========================================================================
function InitTrig_Choose_Mode takes nothing returns nothing
    set gg_trg_Choose_Mode = CreateTrigger(  )
    call TriggerRegisterDialogEventBJ( gg_trg_Choose_Mode, udg_modeDialog )
    call TriggerAddAction( gg_trg_Choose_Mode, function Trig_Choose_Mode_Actions )
endfunction
function Trig_Start_Game_StopBattle takes nothing returns nothing
    local integer pid = 0
    local integer i = udg_bulletLoopNext[0]
    local unit U
    local group G = NewGroup()
    call DestroyTimer(GetExpiredTimer())
    loop
        exitwhen pid > udg_maxPlayer
        if udg_initialVisibility[pid]!=null then
            call DestroyFogModifier(udg_initialVisibility[pid])
            set udg_initialVisibility[pid] = null
        endif
        set pid = pid + 1
    endloop

    call GroupEnumUnitsOfPlayer(G,Player(8),null)
    loop
        set U = FirstOfGroup(G)
        exitwhen U==null
        call GroupRemoveUnit(G,U)
        if GetUnitUserData(U)>0 then
            set udg_DamageSource = null
            call KillUnit(U)
        endif
    endloop
    call GroupEnumUnitsOfPlayer(G,Player(9),null)
    loop
        set U = FirstOfGroup(G)
        call GroupRemoveUnit(G,U)
        exitwhen U==null
        if GetUnitUserData(U)>0 then
            set udg_DamageSource = null
            call KillUnit(U)
        endif
    endloop
    call ReleaseGroup(G)

    loop
        exitwhen i==0
        set udg_bulletRemoveTime[i] = 0
        set i = udg_bulletLoopNext[i]
    endloop
endfunction

function Trig_Start_Game_FadeOutBattle takes nothing returns nothing
    call SetCineFilterTexture("ReplaceableTextures\\CameraMasks\\White_mask.blp")
    call SetCineFilterBlendMode(BLEND_MODE_BLEND)
    call SetCineFilterTexMapFlags(TEXMAP_FLAG_NONE)
    call SetCineFilterStartUV(0, 0, 1, 1)
    call SetCineFilterEndUV(0, 0, 1, 1)
    call SetCineFilterStartColor(0, 0, 0, 0)
    call SetCineFilterEndColor(0, 0, 0, 255)
    call SetCineFilterDuration(2)
    call DisplayCineFilter(true)
endfunction

function Trig_Start_Game_BuildNearbyExtractor takes real X, real Y, player p, integer tech returns nothing
    local integer massNearest = AIGetNearestFreeMass(X,Y)
    local unit U
    if massNearest==0 then
        return
    endif
    if tech > 2 then
        set U = CreateUnit(p,'h00W',udg_massX[massNearest],udg_massY[massNearest],270)
    elseif tech==2 then
        set U = CreateUnit(p,'h00V',udg_massX[massNearest],udg_massY[massNearest],270)
    else
        set U = CreateUnit(p,'h00G',udg_massX[massNearest],udg_massY[massNearest],270)
    endif
    call DestroyTreesInRange(udg_massX[massNearest],udg_massY[massNearest],udg_classCollisionRadius[GetUnitClass(U)])
    set U = null
endfunction

function Trig_Start_Game_BuildNearbyResourceGenerator takes real X, real Y, real StartAngle, player p returns nothing
    local real CurrentCheckDist = 384
    local real CurrentCheckAngle = StartAngle
    local real CheckX
    local real CheckY
    local unit U
    loop
        set CheckX = GridRealCross(X+CurrentCheckDist*Cos(CurrentCheckAngle*bj_DEGTORAD),64)
        set CheckY = GridRealCross(Y+CurrentCheckDist*Sin(CurrentCheckAngle*bj_DEGTORAD),64)
        if IsTerrainBlockPathable(CheckX-128,CheckY-128,CheckX+128,CheckY+128) then
            set U = CreateUnit(p,'h020',CheckX,CheckY,270)
            call DestroyTreesInRange(CheckX,CheckY,udg_classCollisionRadius[GetUnitClass(U)])
            set U = null
            return
        endif
        set CurrentCheckAngle = CurrentCheckAngle + 45
        if CurrentCheckAngle>=StartAngle+360 then
            set CurrentCheckAngle=StartAngle
            set CurrentCheckDist=CurrentCheckDist+256
        endif
        exitwhen CurrentCheckDist>2048
    endloop
endfunction

function Trig_Start_Game_BuildNearbyDefense takes real X, real Y, real StartAngle, player p, integer tech returns nothing
    local real CurrentCheckDist = 384
    local real CurrentCheckAngle = StartAngle
    local real CheckX
    local real CheckY
    local unit U
    loop
        set CheckX = GridRealCenter(X+CurrentCheckDist*Cos(CurrentCheckAngle*bj_DEGTORAD),64)
        set CheckY = GridRealCenter(Y+CurrentCheckDist*Sin(CurrentCheckAngle*bj_DEGTORAD),64)
        if IsTerrainBlockPathable(CheckX-32,CheckY-32,CheckX+32,CheckY+32) then
            if tech > 2 then
                set U = CreateUnit(p,'h017',CheckX,CheckY,270)
            elseif tech==2 then
                set U = CreateUnit(p,'h02P',CheckX,CheckY,270)
            else
                set U = CreateUnit(p,'h02O',CheckX,CheckY,270)
            endif
            call DestroyTreesInRange(CheckX,CheckY,udg_classCollisionRadius[GetUnitClass(U)])
            set U = null
            return
        endif
        set CurrentCheckAngle = CurrentCheckAngle + 45
        if CurrentCheckAngle>=StartAngle+360 then
            set CurrentCheckAngle=StartAngle
            set CurrentCheckDist=CurrentCheckDist+256
        endif
        exitwhen CurrentCheckDist>2048
    endloop
endfunction

function Trig_Start_Game_BuildNearbyFactoryWithGenerators takes real X, real Y, real StartAngle, player p, integer tech returns nothing
    local real CurrentCheckDist = 384
    local real CurrentCheckAngle = StartAngle
    local real CheckX
    local real CheckY
    local unit U
    loop
        if tech>2 then
            set CheckX = GridRealCenter(X+CurrentCheckDist*Cos(CurrentCheckAngle*bj_DEGTORAD),64)
            set CheckY = GridRealCross(Y+CurrentCheckDist*Sin(CurrentCheckAngle*bj_DEGTORAD),64)
            if IsTerrainBlockPathable(CheckX-96,CheckY-192,CheckX+96,CheckY+192) then
                set U = CreateUnit(p,'h012',CheckX,CheckY+96,270)
                call DestroyTreesInRange(CheckX,CheckY+96,udg_classCollisionRadius[GetUnitClass(U)])
                set U = CreateUnit(p,'h00Z',CheckX,CheckY-96,270)
                call DestroyTreesInRange(CheckX,CheckY-96,udg_classCollisionRadius[GetUnitClass(U)])
                set U = null
                return
            endif
        elseif tech==2 then
            set CheckX = GridRealCenter(X+CurrentCheckDist*Cos(CurrentCheckAngle*bj_DEGTORAD),64)
            set CheckY = GridRealCenter(Y+CurrentCheckDist*Sin(CurrentCheckAngle*bj_DEGTORAD),64)
            if IsTerrainBlockPathable(CheckX-96,CheckY-160,CheckX+96,CheckY+160) then
                set U = CreateUnit(p,'h00O',CheckX,CheckY+64,270)
                call DestroyTreesInRange(CheckX,CheckY+64,udg_classCollisionRadius[GetUnitClass(U)])
                set U = CreateUnit(p,'h00Q',CheckX+32,CheckY-64,270)
                call DestroyTreesInRange(CheckX+32,CheckY-64,udg_classCollisionRadius[GetUnitClass(U)])
                set U = null
                return
            endif
        else
            set CheckX = GridRealCenter(X+CurrentCheckDist*Cos(CurrentCheckAngle*bj_DEGTORAD),64)
            set CheckY = GridRealCenter(Y+CurrentCheckDist*Sin(CurrentCheckAngle*bj_DEGTORAD),64)
            if IsTerrainBlockPathable(CheckX-96,CheckY-160,CheckX+96,CheckY+96) then
                set U = CreateUnit(p,'h00I',CheckX,CheckY,270)
                call DestroyTreesInRange(CheckX,CheckY,udg_classCollisionRadius[GetUnitClass(U)])
                set U = CreateUnit(p,'h000',CheckX-128,CheckY-64,270)
                call DestroyTreesInRange(CheckX-128,CheckY-64,udg_classCollisionRadius[GetUnitClass(U)])
                set U = CreateUnit(p,'h000',CheckX-128,CheckY,270)
                call DestroyTreesInRange(CheckX-128,CheckY,udg_classCollisionRadius[GetUnitClass(U)])
                set U = CreateUnit(p,'h000',CheckX-128,CheckY+64,270)
                call DestroyTreesInRange(CheckX-128,CheckY+64,udg_classCollisionRadius[GetUnitClass(U)])
                set U = null
                return
            endif
        endif
        set CurrentCheckAngle = CurrentCheckAngle + 45
        if CurrentCheckAngle>=StartAngle+360 then
            set CurrentCheckAngle=StartAngle
            set CurrentCheckDist=CurrentCheckDist+256
        endif
        exitwhen CurrentCheckDist>2048
    endloop
endfunction

function Trig_Start_Game_PrebuildForPlayer takes nothing returns nothing
    local integer pid = bj_forLoopAIndex
    local real CenterX = GetRectCenterX(bj_mapInitialPlayableArea)
    local real CenterY = GetRectCenterY(bj_mapInitialPlayableArea)
    local real X = GetUnitX(udg_playerACU[pid])
    local real Y = GetUnitY(udg_playerACU[pid])
    local real a = Atan2(Y-CenterY,X-CenterX)*bj_RADTODEG
    local integer tech = udg_modeValPrebuilt
    call Trig_Start_Game_BuildNearbyDefense(X,Y,a+90,Player(pid),tech)
    call Trig_Start_Game_BuildNearbyDefense(X,Y,a-90,Player(pid),tech)
    call Trig_Start_Game_BuildNearbyExtractor(X,Y,Player(pid),tech)
    call Trig_Start_Game_BuildNearbyExtractor(X,Y,Player(pid),tech)
    call Trig_Start_Game_BuildNearbyExtractor(X,Y,Player(pid),tech)
    call Trig_Start_Game_BuildNearbyExtractor(X,Y,Player(pid),tech)
    if tech==4 then
        call Trig_Start_Game_BuildNearbyResourceGenerator(X,Y,a,Player(pid))
        set a = a + 180
    endif
    call Trig_Start_Game_BuildNearbyFactoryWithGenerators(X,Y,a,Player(pid),tech)
    if tech==4 then
        call CreateUnit(Player(pid),'h01L',X-192,Y,270)
        call CreateUnit(Player(pid),'h00Y',X-96,Y,270)
        call CreateUnit(Player(pid),'h00P',X+96,Y,270)
        call CreateUnit(Player(pid),'h001',X+192,Y,270)
    elseif tech==3 then
        call CreateUnit(Player(pid),'h00Y',X-192,Y,270)
        call CreateUnit(Player(pid),'h00P',X-96,Y,270)
        call CreateUnit(Player(pid),'h00P',X+96,Y,270)
        call CreateUnit(Player(pid),'h001',X+192,Y,270)
    elseif tech==2 then
        call CreateUnit(Player(pid),'h00P',X-192,Y,270)
        call CreateUnit(Player(pid),'h001',X+192,Y,270)
    else
        call CreateUnit(Player(pid),'h001',X-192,Y,270)
        call CreateUnit(Player(pid),'h001',X+192,Y,270)
    endif
endfunction

function Trig_Start_Game_Prebuild takes nothing returns nothing
    local integer pid = 0
    loop
        exitwhen pid > udg_maxPlayer
        if udg_playerACU[pid]!=null then
            set bj_forLoopAIndex = pid
            call ExecuteFunc("Trig_Start_Game_PrebuildForPlayer")
        endif
        set pid = pid + 1
    endloop
endfunction

function Trig_Start_Game_GiveControlBack takes nothing returns nothing
    call DestroyTimer(GetExpiredTimer())
    call DisplayCineFilter( false )
    call EnableUserControl(true)
    call ShowInterface(true,0.0001)
endfunction

function Trig_Start_Game_GetCommanderWelcome takes integer pid returns string
    local string s = "Welcome, Commander "+udg_playerNameColored[pid]+"!\n"
    if udg_Phantom==Player(pid) then
        set s = s + "Your objective in this mission is to defeat all commanders.\nYou are the phantom and have twice the normal income, however you should not show it to other players."
    elseif udg_Phantom!=null then
        set s = s + "Your objective in this mission is to defeat the phantom.\nOnly the phantom knows that he is the one to kill all other players."
    elseif udg_modeValMode==2 then
        set s = s + "Your objective in this mission is to defend your commander and destroy the enemy Quantum Gateways."
    elseif udg_modeValMode==1 then
        set s = s + "Your objective in this mission is to defeat all enemy units and buildings."
    else
        set s = s + "Your objective in this mission is to defeat all enemy commanders."
    endif
    if udg_modeValLockTeams then
        set s = s + "\nThe teams are locked."
    else
        set s = s + "\nThe teams are variable (-ally / -nap / -war)."
    endif
    if udg_modeValNoRush!=0 then
        set s = s + " Rushing is prohibited for "+Mode_GetNoRush()+"."
    endif
    if udg_modeValLeaverAI then
        set s = s + " Leavers will be taken over by the AI."
    endif
    return s
endfunction

function Trig_Start_Game_EndNoRush takes nothing returns nothing
    local integer i = 1
    call ReleaseTimer(GetExpiredTimer())
    call DisplayTimedTextToPlayer( GetLocalPlayer(), 0,0,10,GetTimeStamp()+" No Rush time is over, may the battle begin." )
    loop
        exitwhen udg_noRushCircleEffects[i]==null
        call DestroyEffect(udg_noRushCircleEffects[i])
        set i = i + 1
    endloop
    set udg_noRush = false
endfunction

function Trig_Start_Game_CreateStartingUnits takes nothing returns nothing
    local integer pid
    local real X
    local real Y
    local unit U
    local string s
    local integer CommanderClass = GetUnitTypeClass('H00C')
    local integer StartMass = udg_classStorageMass[CommanderClass]
    local integer StartEnergy = udg_classStorageEnergy[CommanderClass]
    local integer countPlayers = 0
    local integer noRushSFXn = 0
    local real a
    local real w
    local real curX
    local real curY
    call DestroyTrigger(gg_trg_Cine_Cam)
    call DestroyTimer(GetExpiredTimer())
    call DisplayCineFilter( false )
    call EnableUserControl(true)
    call ShowInterface(true,0.0001)
    call ClearTextMessages()

    if udg_modeValNoRush!=0 then
        if udg_modeValNoRush==1 then
            call TimerStart(NewTimer(),5*60,false,function Trig_Start_Game_EndNoRush)
        elseif udg_modeValNoRush==2 then
            call TimerStart(NewTimer(),15*60,false,function Trig_Start_Game_EndNoRush)
        else
            call TimerStart(NewTimer(),30*60,false,function Trig_Start_Game_EndNoRush)
        endif
    endif
    set pid = 0
    loop
        exitwhen pid > udg_maxPlayer
        if udg_playerInGame[pid] then
            set countPlayers = countPlayers + 1
        endif
        set pid = pid + 1
    endloop
    set pid = 0
    loop
        exitwhen pid > udg_maxPlayer
        if udg_playerInGame[pid] then
            set X = udg_playerStartX[pid]
            set Y = udg_playerStartY[pid]
            call SetPlayerState(Player(pid),PLAYER_STATE_RESOURCE_FOOD_CAP,(100/countPlayers)*10)
            call SetPlayerState(Player(pid),PLAYER_STATE_RESOURCE_GOLD,StartMass)
            call SetPlayerState(Player(pid),PLAYER_STATE_RESOURCE_LUMBER,StartEnergy)
            set udg_playerLastMassSet[pid] = StartMass
            set udg_playerLastEnergySet[pid] = StartEnergy
            set udg_playerMass[pid] = StartMass
            set udg_playerEnergy[pid] = StartEnergy
            set udg_playerController[pid] = CreateUnit(Player(pid),'H02E',X,Y,270)
            call SuspendHeroXP(udg_playerController[pid], true)
            set U = CreateUnit(Player(pid),'H00C',X,Y,270)
            call CheckRessourceUnit(U)
            call SuspendHeroXP(U, true)
            call SelectUnit(U,GetLocalPlayer()==Player(pid))
            set udg_playerACU[pid] = U
            set udg_playerAlive[pid] = true
            set U = CreateUnit(Player(15),'h003',X,Y,270)
            call SetUnitPathing(U,false)
            call SetUnitX(U,X)
            call SetUnitY(U,Y)
            call SetUnitScale(U,3,3,3)
            call SetUnitAnimationByIndex(U,90)
            call DestroyEffect(AddSpecialEffectTarget("Units\\NightElf\\Wisp\\WispExplode.mdl",U,"origin"))
            call DestroyEffect(AddSpecialEffectTarget("war3mapImported\\Flash2.mdx",U,"origin"))
            call DestroyTreesInRangeTimed(X,Y,0,600,1)
            call UnitApplyTimedLife(U, 'BTLF',5)
            set s = Trig_Start_Game_GetCommanderWelcome(pid)
            if GetLocalPlayer()==Player(pid) then
                call SetCameraQuickPosition(X,Y)
                call PanCameraToTimed(X,Y,0)
                call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,20,s)
            endif
            set udg_resourceBoard[pid] = CreateLeaderboard()
            call PlayerSetLeaderboard(Player(pid), udg_resourceBoard[pid])
            call LeaderboardDisplay(udg_resourceBoard[pid], GetLocalPlayer()==Player(pid))
            call LeaderboardAddItem(udg_resourceBoard[pid], "Storage                  Income/Sec", 0, Player(0))
            call LeaderboardSetItemLabelColor(udg_resourceBoard[pid], 0, 255, 255, 255, 255)
            call LeaderboardSetItemValueColor(udg_resourceBoard[pid], 0, 255, 255, 255, 255)
            call LeaderboardAddItem(udg_resourceBoard[pid], "Mass", 1, Player(1))
            call LeaderboardSetItemLabelColor(udg_resourceBoard[pid], 1, 255, 204, 0, 255)
            call LeaderboardSetItemValueColor(udg_resourceBoard[pid], 1, 255, 204, 0, 255)
            call LeaderboardAddItem(udg_resourceBoard[pid], "Energy", 10, Player(2))
            call LeaderboardSetItemLabelColor(udg_resourceBoard[pid], 2, 85, 85, 255, 255)
            call LeaderboardSetItemValueColor(udg_resourceBoard[pid], 2, 85, 85, 255, 255)
            call LeaderboardSetItemStyle(udg_resourceBoard[pid],0,true,false,false)
            call LeaderboardSetSizeByItemCount(udg_resourceBoard[pid],2)
        endif
        set pid = pid + 1
    endloop
    if udg_noRush then
        set X = udg_playerStartX[GetPlayerId(GetLocalPlayer())]
        set Y = udg_playerStartY[GetPlayerId(GetLocalPlayer())]
        set w = 2*bj_PI/R2I(2*bj_PI*udg_noRushBaseRadius/128.)
        set a = w*.5
        set s = ""
        loop
            exitwhen a>2*bj_PI
            set noRushSFXn = noRushSFXn+1
            set curX = X+udg_noRushBaseRadius*Cos(a)
            set curY = Y+udg_noRushBaseRadius*Sin(a)
            set s = "Abilities\\Spells\\Human\\ManaFlare\\ManaFlareTarget.mdl"
            if curX>udg_mapMaxX then
                set curX = udg_mapMaxX
                set s = ""
            elseif curX<udg_mapMinX then
                set curX = udg_mapMinX
                set s = ""
            endif
            if curY>udg_mapMaxY then
                set curY = udg_mapMaxY
                set s = ""
            elseif curY<udg_mapMinY then
                set curY = udg_mapMinY
                set s = ""
            endif
            set udg_noRushCircleEffects[noRushSFXn] = AddSpecialEffect("Abilities\\Spells\\Human\\ManaFlare\\ManaFlareTarget.mdl",curX,curY)
            set a = a + w
        endloop
    endif
    set U = null
    if udg_modeValPrebuilt>0 then
        call Trig_Start_Game_Prebuild()
    endif
    if udg_modeValMode==2 then
        call TriggerExecute(gg_trg_Initialize_Team_Defense)
    endif
    if udg_ai then
        call TriggerExecute(gg_trg_Start_AI)
    endif
    call TimerStart(CreateTimer(),1.00,false,function Trig_Start_Game_GiveControlBack)
    set udg_calculateRessourceCaps = true
    set udg_calculateAdjecency = true
    call TriggerRegisterTimerEventPeriodic( gg_trg_General_Hints, 20.00 )
    call CheckVictory()
endfunction

function Trig_Start_Game_GetRandomPlayerIngame takes nothing returns player
    local integer pid = 0
    local player array possible
    local integer possibleCount = 0
    loop
        exitwhen pid > udg_maxPlayer
        if udg_playerInGame[pid] then
            set possibleCount = possibleCount + 1
            set possible[possibleCount] = Player(pid)
        endif
        set pid = pid + 1
    endloop
    return possible[GetRandomInt(1,possibleCount)]
endfunction

function Trig_Start_Game_PlaceTeams takes nothing returns nothing
    local integer startlocid
    local integer pid2
    local integer pid
    local real array StartX
    local real array StartY
    local player array StartPlayer
    local integer StartCount = udg_maxPlayerCount
    local integer array PlayerStartingLoc
    local real FinalTeamSpreading
    local boolean FirstFinal = true
    local integer alliesCount
    local integer array alliesPid
    local integer nearLoc
    local <