/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Wietlol's Custom Missile System 1.4 15/12/2015
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Description:
// This system is made to create custom missiles.
// It is designed to have 3D movement, events on collision, de-locusted missiles, different collision detections,
// targetable missiles, units as missiles, full missile control, collisions with items and destructables,
// missiles that can hit targets multiple times and with GUI support.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// How to install:
// 1. Copy or create all variables that are used in this map into your map.
// 1a. If you use vJASS then you can enable the CMS_vJASS_variables trigger and use that one.
// 1b. If you use GUI then you can use the CMS_GUI_variables trigger to automatically import them.
// 2. Copy the CMS_System trigger, CMS_Configuration trigger and CMS_Collision trigger and paste it into your map.
// 4. Import the same models that are imported by this map into yours.
// (You can export the files in the import manager.)
// (It is not necessary to import the icon too.)
// 5. Create or copy the objects "MISSILE", "DUMMY", "CMS ABILITY GHOST" and "CMS ABILITY MORPH" into your map.
// Make sure that "CMS ABILITY MORPH" has the proper values.
// 6. Set the variables in the CMS_Configuration trigger to the right values.
// 7. Make sure that you have all required libraries in your map.
// If one of the libraries from this map is of a higher version, then use the one from this map.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Feature list:
// This system:
// - allows you to create missiles with
// - 3d movement visualizations.
// - 3d movement calculations.
// - 3d acceleration.
// - collision detection with all widgets with different algorithms.
// - homing behavior.
// - a unique index for arrays with your custom data.
// - allows the creation of missiles from existing units (for usages like a dash or knockback).
// - has on-collide events for all widgets.
// - can run a large amount of missiles.
// - allows missile to hit the same target multiple times with a configurable delay as "Collision_Cooldown".
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function List:
// function CMS_CreateMissile takes unit source, integer typeId, unit whichMissile, boolean importDefaultValues returns integer
// Creates a new missile using the starting variables and the given parameters.
//
// function CMS_CreateMissileEx takes nothing returns integer
// Creates a new missile only using the starting variables.
// This function is recommended for GUI users.
//
// function CMS_DestroyMissile takes integer index returns boolean
// Immediately destroys the missile of the given index.
//
// function CMS_GetIndex takes unit whichMissile returns integer
// Returns the index of a missile.
// This can be used in combination with "CMS_DestroyMissile()".
//
// function CMS_SetDefaultVariables takes integer index returns nothing
// Sets all the param variables to their default value.
//
// function CMS_GetSpeedPerSecond takes integer index returns real
// Returns the speed per second.
// function CMS_SetSpeedPerSecond takes integer index, real speed returns nothing
// Sets the speed per second.
//
// function CMS_GetAngleDeg takes integer index returns real
// Returns the angle in degrees.
// function CMS_SetAngleDeg takes integer index, real angle returns nothing
// Sets the angle in degrees.
//
// function CMS_GetPitchDeg takes integer index returns real
// Returns the pitch in degrees.
// function CMS_SetPitchDeg takes integer index, real pitch returns nothing
// Sets the pitch in degrees.
//
// function CMS_GetAccelerationPerSecond takes integer index returns real
// Returns the acceleration per second.
// function CMS_SetAccelerationPerSecond takes integer index, real acc returns nothing
// Sets the acceleration per second.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Credits:
// * To Vexorian and Tickles
// - For Vexorian's dummy model that is used as the missile model which is editted by Tickles.
// * To Xonok
// - For showing me his missile system on which this structure is designed.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Changelog:
// 1.4 - 15/12/2015 - Additional features (detection, optimized events, acceleration).
// - Replaced locations with coordinates.
// - Removed "_Param" prefixes from variables that are not array variables of the missiles.
// - Added Acceleration.
// - Added event calls with udg_CMS_Param_Type[] as value.
// - Trigger calls for each X missiles to prevent op limit.
// - Optmized collision cooldown.
// - Added Rectangular collision detection.
// - Added Polygon collision detection.
// - Added booleans to check for Unit, Destructable and Item separately.
//
// 1.3.3 - 6/12/2015 - Fixed bugs
// - Replaced widget handles in hashtable with their handle index to prevent timer/widget leak
// when the target or missile is removed during the timer.
// - Fixed a bug where the missiles didn't start at their StartingHeight when a new missile was created.
// - Replaced some GetWidgetX/Y() with GetUnitX/Y().
// - Updated BasicFunctions usage.
// - Removed "_Param" from starting variables because of GUI variable length limit.
// - Added StartingDefaultValues to import default values for GUI usage. (Default true.)
// - Added CMS_CreateMissileEx(source, missile, typeId, importDefaultValues).
//
// 1.3.2 - 14/11/2015 - Reviewed system.
// - Added final starting parameters.
// - Replaced GetWidgetX()/GetWidgetY() with GetUnitX()/GetUnitY().
// - Replaced KillUnit() with UnitApplyTimedLife().
//
// 1.3 - 20/05/2015 - Redesigned system structure.
// - Placed calculations inside functions with a cache.
// - Removed calculations from the interval function.
// - Finished system's concept.
// - Removed the missile acceleration option.
//
// 1.2 - 15/05/2015 - Rewritten System
// - Rewrote the data structure into arrays only.
// - Ripped stuff that is not necessary.
// - Uses locust bugged units so the missiles are targetable but unselectable.
// - Uses better getter and setter.
// - Uses library and got rid of triggers.
//
// 1.1 - 26/03/2015 - Collision Fixes
// - Fixed map bounds check.
// - Added Ghost ability.
// - Added CMS_Param_Remove_Collision.
//
// 1.0 - 01/03/2015 - First official release.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Known bugs:
// - None
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// CMS System
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
library CustomMissileSystem uses PositionFunctions, TimeFunctions
//These globals are not needed in GUI so they are implemented inside the system itself.
globals
integer udg_CMS_COLLISIONTYPE_POLYGON
Polygon array udg_CMS_Param_Polygon
hashtable udg_CMS_HASHTABLE = InitHashtable()
group udg_CMS_GROUP = CreateGroup()
timer udg_CMS_TIMER = CreateTimer()
real udg_CMS_INTERVAL = 0.03
trigger udg_CMS_TRIGGER = CreateTrigger()
integer udg_CMS_LOOP_MAX = 100
//Missile positions in interval function.
real udg_CMS_X = 0
real udg_CMS_Y = 0
real udg_CMS_X_OLD = 0
real udg_CMS_Y_OLD = 0
//Rectangular collision detection.
real udg_CMS_RX = 0
real udg_CMS_RY = 0
real udg_CMS_RW = 0
real udg_CMS_RH = 0
real udg_CMS_RA = 0
real udg_CMS_GameTime = 0
integer udg_CMS_NextIndex = 0
boolean array udg_CMS_Index_Occupied
integer array udg_CMS_MissileIndex
real array udg_CMS_Param_OriginalHeight
real array udg_CMS_Param_V_X
real array udg_CMS_Param_V_Y
real array udg_CMS_Param_V_Z
real array udg_CMS_Param_A_X
real array udg_CMS_Param_A_Y
real array udg_CMS_Param_A_Z
integer udg_CMS_IntervalCount
real array udg_CMS_Cache_V_H
integer array udg_CMS_Cache_V_H_Index
real array udg_CMS_Cache_A_H
integer array udg_CMS_Cache_A_H_Index
real array udg_CMS_Cache_Angle
integer array udg_CMS_Cache_Angle_Index
real array udg_CMS_Cache_Pitch
integer array udg_CMS_Cache_Pitch_Index
real array udg_CMS_Cache_Speed
integer array udg_CMS_Cache_Speed_Index
real array udg_CMS_Cache_Acceleration
integer array udg_CMS_Cache_Acceleration_Index
endglobals
//Set the default variables of the params with the given index.
function CMS_SetDefaultVariables takes integer index returns nothing
set udg_CMS_Param_Collision_Cooldown[index] = 1.
set udg_CMS_Param_Collision_Dest[index] = false
set udg_CMS_Param_Collision_Height[index] = 0.
set udg_CMS_Param_Collision_Height_Inc[index] = 0.
set udg_CMS_Param_Collision_Item[index] = false
set udg_CMS_Param_Collision_Type[index] = 0
set udg_CMS_Param_Collision_Unit[index] = true
set udg_CMS_Param_Collision_Width[index] = 50.
set udg_CMS_Param_Collision_Width_Inc[index] = 0.
set udg_CMS_Param_Distance[index] = 0.
set udg_CMS_Param_Duration[index] = 0.
set udg_CMS_Param_Effect[index] = null
set udg_CMS_Param_Gravity[index] = 0.
set udg_CMS_Param_IsAUnit[index] = false
set udg_CMS_Param_IsDestroyed[index] = false
set udg_CMS_Param_IsFlying[index] = false
set udg_CMS_Param_IsHoming[index] = false
set udg_CMS_Param_MaxDistance[index] = 0.
set udg_CMS_Param_MaxDuration[index] = 0.
set udg_CMS_Param_Missile[index] = null
set udg_CMS_Param_OriginalHeight[index] = 0.
set udg_CMS_Param_Source[index] = null
set udg_CMS_Param_Subtype[index] = 0
set udg_CMS_Param_Target_Location[index] = null
set udg_CMS_Param_Target_Type[index] = 0
set udg_CMS_Param_Target_Unit[index] = null
set udg_CMS_Param_TurnRate[index] = 0.
set udg_CMS_Param_Type[index] = -1
set udg_CMS_Param_WalkingHeight[index] = 0
set udg_CMS_Param_A_X[index] = 0.
set udg_CMS_Param_A_Y[index] = 0.
set udg_CMS_Param_A_Z[index] = 0.
set udg_CMS_Param_V_X[index] = 0.
set udg_CMS_Param_V_Y[index] = 0.
set udg_CMS_Param_V_Z[index] = 0.
set udg_CMS_Cache_A_H[index] = 0.
set udg_CMS_Cache_V_H[index] = 0.
set udg_CMS_Cache_Acceleration[index] = 0.
set udg_CMS_Cache_Angle[index] = 0.
set udg_CMS_Cache_Pitch[index] = 0.
set udg_CMS_Cache_Speed[index] = 0.
set udg_CMS_Cache_V_H_Index[index] = 0
set udg_CMS_Cache_Acceleration_Index[index] = 0
set udg_CMS_Cache_Angle_Index[index] = 0
set udg_CMS_Cache_Pitch_Index[index] = 0
set udg_CMS_Cache_Speed_Index[index] = 0
endfunction
//Create a new unique id for the missile.
function CMS_CreateUniqueId takes nothing returns integer
loop
set udg_CMS_NextIndex = udg_CMS_NextIndex + 1
if udg_CMS_NextIndex > 8190 then
set udg_CMS_NextIndex = 1
endif
exitwhen not udg_CMS_Index_Occupied[udg_CMS_NextIndex]
endloop
set udg_CMS_Index_Occupied[udg_CMS_NextIndex] = true
return udg_CMS_NextIndex
endfunction
//Set the Z angle animation.
function CMS_SetUnitZAngle takes unit whichUnit, real angle returns nothing
//Can only be used on Vexorian's Dummy model or other models which use the same animations.
local integer i = GetUnitTypeId(whichUnit)
if i != udg_CMS_MISSILE_UNITTYPE and i != udg_CMS_DUMMY_UNITTYPE then
return
endif
set i = R2I(angle*RADTODEG + 90.5)
if i >= 180 then
set i = 179
elseif i < 0 then
set i = 0
endif
call SetUnitAnimationByIndex(whichUnit, i)
endfunction
//Get the missile index of the given unit.
function CMS_GetIndex takes unit whichMissile returns integer
return udg_CMS_MissileIndex[GetUnitUserData(whichMissile)]
endfunction
//Set/get horizontal velocity.
//Only used internal.
function CMS_GetVH takes integer index returns real
local real V_H
if udg_CMS_Cache_V_H_Index[index] == udg_CMS_IntervalCount then
return udg_CMS_Cache_V_H[index]
endif
set V_H = SquareRoot(udg_CMS_Param_V_X[index]*udg_CMS_Param_V_X[index] + udg_CMS_Param_V_Y[index]*udg_CMS_Param_V_Y[index])
set udg_CMS_Cache_V_H[index] = V_H
set udg_CMS_Cache_V_H_Index[index] = udg_CMS_IntervalCount
return V_H
endfunction
function CMS_SetVH takes integer index, real V_H returns nothing
local real V_H_Factor
if CMS_GetVH(index) == 0. then
set udg_CMS_Param_V_X[index] = 0.
set udg_CMS_Param_V_Y[index] = 0.
else
set V_H_Factor = V_H / udg_CMS_Cache_V_H[index]
set udg_CMS_Param_V_X[index] = udg_CMS_Param_V_X[index] * V_H_Factor
set udg_CMS_Param_V_Y[index] = udg_CMS_Param_V_Y[index] * V_H_Factor
endif
set udg_CMS_Cache_V_H[index] = V_H
set udg_CMS_Cache_V_H_Index[index] = udg_CMS_IntervalCount
endfunction
//Set/get 3D speed.
//BJ functions for speed per second and normal functions for speed per interval.
function CMS_GetSpeed takes integer index returns real
local real speed
if udg_CMS_Cache_Speed_Index[index] == udg_CMS_IntervalCount then
return udg_CMS_Cache_Speed[index]
endif
set speed = SquareRoot(udg_CMS_Param_V_X[index]*udg_CMS_Param_V_X[index] + udg_CMS_Param_V_Y[index]*udg_CMS_Param_V_Y[index] + udg_CMS_Param_V_Z[index]*udg_CMS_Param_V_Z[index])
set udg_CMS_Cache_Speed[index] = speed
set udg_CMS_Cache_Speed_Index[index] = udg_CMS_IntervalCount
return speed
endfunction
function CMS_SetSpeed takes integer index, real speed returns nothing
local real factor
local real oldSpeed = CMS_GetSpeed(index)
if oldSpeed == 0. then
set udg_CMS_Param_V_X[index] = speed
else
set factor = speed/oldSpeed
set udg_CMS_Param_V_X[index] = udg_CMS_Param_V_X[index] * factor
set udg_CMS_Param_V_Y[index] = udg_CMS_Param_V_Y[index] * factor
set udg_CMS_Param_V_Z[index] = udg_CMS_Param_V_Z[index] * factor
endif
set udg_CMS_Cache_Speed[index] = speed
set udg_CMS_Cache_Speed_Index[index] = udg_CMS_IntervalCount
endfunction
function CMS_GetSpeedPerSecond takes integer index returns real
return CMS_GetSpeed(index) / udg_CMS_INTERVAL
endfunction
function CMS_SetSpeedPerSecond takes integer index, real speed returns nothing
call CMS_SetSpeed(index, speed * udg_CMS_INTERVAL)
endfunction
function CMS_GetAH takes integer index returns real
local real A_H
if udg_CMS_Cache_A_H_Index[index] == udg_CMS_IntervalCount then
return udg_CMS_Cache_A_H[index]
endif
set A_H = SquareRoot(udg_CMS_Param_A_X[index]*udg_CMS_Param_A_X[index] + udg_CMS_Param_A_Y[index]*udg_CMS_Param_A_Y[index])
set udg_CMS_Cache_A_H[index] = A_H
set udg_CMS_Cache_A_H_Index[index] = udg_CMS_IntervalCount
return A_H
endfunction
function CMS_SetAH takes integer index, real A_H returns nothing
local real A_H_Factor
local real speed
if CMS_GetAH(index) == 0. then
set speed = CMS_GetSpeed(index)
if speed == 0. then
set udg_CMS_Param_A_X[index] = A_H
else
set udg_CMS_Param_A_X[index] = A_H * (udg_CMS_Param_V_X[index] / speed)
set udg_CMS_Param_A_Y[index] = A_H * (udg_CMS_Param_V_Y[index] / speed)
set udg_CMS_Param_A_Z[index] = A_H * (udg_CMS_Param_V_Z[index] / speed)
endif
else
set A_H_Factor = A_H / udg_CMS_Cache_A_H[index]
set udg_CMS_Param_A_X[index] = udg_CMS_Param_A_X[index] * A_H_Factor
set udg_CMS_Param_A_Y[index] = udg_CMS_Param_A_Y[index] * A_H_Factor
endif
set udg_CMS_Cache_A_H[index] = A_H
set udg_CMS_Cache_A_H_Index[index] = udg_CMS_IntervalCount
endfunction
//Set/get angle (facing angle).
function CMS_GetAngle takes integer index returns real
local real angle
if udg_CMS_Cache_Angle_Index[index] == udg_CMS_IntervalCount then
return udg_CMS_Cache_Angle[index]
endif
if udg_CMS_Param_V_X[index] == 0. then
if udg_CMS_Param_V_Y[index] < 0. then
set angle = PI * 1.5
elseif udg_CMS_Param_V_Y[index] > 0. then
set angle = PI * 0.5
else
set angle = 0.
endif
else
set angle = Atan(udg_CMS_Param_V_Y[index] / udg_CMS_Param_V_X[index])
if udg_CMS_Param_V_X[index] < 0. then
set angle = angle -PI
endif
endif
set udg_CMS_Cache_Angle[index] = angle
set udg_CMS_Cache_Angle_Index[index] = udg_CMS_IntervalCount
return angle
endfunction
function CMS_SetAngle takes integer index, real angle returns nothing
local real V_H = CMS_GetVH(index)
local real A_H = CMS_GetAH(index)
local real cos = Cos(angle)
local real sin = Sin(angle)
set udg_CMS_Param_V_X[index] = cos * V_H
set udg_CMS_Param_V_Y[index] = sin * V_H
set udg_CMS_Param_A_X[index] = cos * A_H
set udg_CMS_Param_A_Y[index] = sin * A_H
call SetUnitFacing(udg_CMS_Param_Missile[udg_CMS_LoopIndex], angle*RADTODEG)
set udg_CMS_Cache_Angle[index] = angle
set udg_CMS_Cache_Angle_Index[index] = udg_CMS_IntervalCount
endfunction
function CMS_GetAngleDeg takes integer index returns real
return CMS_GetAngle(index) * RADTODEG
endfunction
function CMS_SetAngleDeg takes integer index, real angle returns nothing
call CMS_SetAngle(index, angle * DEGTORAD)
endfunction
//Set/get pitch (vertical angle).
//BJ functions for degree and normal functions for radians.
function CMS_GetPitch takes integer index returns real
local real pitch
local real V_H
if udg_CMS_Cache_Pitch_Index[index] == udg_CMS_IntervalCount then
return udg_CMS_Cache_Pitch[index]
endif
set V_H = CMS_GetVH(index)
if V_H == 0. then
if udg_CMS_Param_V_Z[index] < 0. then
set pitch = PI * 1.5
elseif udg_CMS_Param_V_Z[index] > 0. then
set pitch = PI * 0.5
else
set pitch = 0.
endif
else
set pitch = Atan(udg_CMS_Param_V_Z[index] / V_H)
endif
set udg_CMS_Cache_Pitch[index] = pitch
set udg_CMS_Cache_Pitch_Index[index] = udg_CMS_IntervalCount
return pitch
endfunction
function CMS_SetPitch takes integer index, real pitch returns nothing
local real V_H = CMS_GetVH(index)
local real V = SquareRoot(V_H*V_H + udg_CMS_Param_V_Z[index]*udg_CMS_Param_V_Z[index])
local real A_H = CMS_GetAH(index)
local real A = SquareRoot(A_H*A_H + udg_CMS_Param_A_Z[index]*udg_CMS_Param_A_Z[index])
local real sin = Sin(pitch)
local real cos = Cos(pitch)
call CMS_SetVH(index, cos * V)
set udg_CMS_Param_V_Z[index] = sin * V
call CMS_SetAH(index, cos * A)
set udg_CMS_Param_A_Z[index] = sin * A
call CMS_SetUnitZAngle(udg_CMS_Param_Missile[index], pitch)
set udg_CMS_Cache_Pitch[index] = pitch
set udg_CMS_Cache_Pitch_Index[index] = udg_CMS_IntervalCount
endfunction
function CMS_GetPitchDeg takes integer index returns real
return CMS_GetPitch(index) * RADTODEG
endfunction
function CMS_SetPitchDeg takes integer index, real pitch returns nothing
call CMS_SetPitch(index, pitch * DEGTORAD)
endfunction
function CMS_GetAcceleration takes integer index returns real
local real acc
if udg_CMS_Cache_Acceleration_Index[index] == udg_CMS_IntervalCount then
return udg_CMS_Cache_Acceleration[index]
endif
set acc = SquareRoot(udg_CMS_Param_A_X[index]*udg_CMS_Param_A_X[index] + udg_CMS_Param_A_Y[index]*udg_CMS_Param_A_Y[index] + udg_CMS_Param_A_Z[index]*udg_CMS_Param_A_Z[index])
set udg_CMS_Cache_Acceleration[index] = acc
set udg_CMS_Cache_Acceleration_Index[index] = udg_CMS_IntervalCount
return acc
endfunction
function CMS_SetAcceleration takes integer index, real acc returns nothing
local real factor
local real oldAcc = CMS_GetAcceleration(index)
local real speed
if oldAcc == 0. then
set speed = CMS_GetSpeed(index)
if speed == 0. then
set udg_CMS_Param_A_X[index] = acc
else
set udg_CMS_Param_A_X[index] = acc * (udg_CMS_Param_V_X[index] / speed)
set udg_CMS_Param_A_Y[index] = acc * (udg_CMS_Param_V_Y[index] / speed)
set udg_CMS_Param_A_Z[index] = acc * (udg_CMS_Param_V_Z[index] / speed)
endif
else
set factor = acc/oldAcc
set udg_CMS_Param_A_X[index] = udg_CMS_Param_A_X[index] * factor
set udg_CMS_Param_A_Y[index] = udg_CMS_Param_A_Y[index] * factor
set udg_CMS_Param_A_Z[index] = udg_CMS_Param_A_Z[index] * factor
endif
set udg_CMS_Cache_Acceleration[index] = acc
set udg_CMS_Cache_Acceleration_Index[index] = udg_CMS_IntervalCount
endfunction
function CMS_GetAccelerationPerSecond takes integer index returns real
return CMS_GetAcceleration(index) / (udg_CMS_INTERVAL*udg_CMS_INTERVAL)
endfunction
function CMS_SetAccelerationPerSecond takes integer index, real acc returns nothing
call CMS_SetAcceleration(index, acc * (udg_CMS_INTERVAL*udg_CMS_INTERVAL))
endfunction
//Destroy the missile of index "index".
function CMS_DestroyMissile takes integer index returns boolean
local unit missile
local real originalHeight
local boolean isAUnit
set udg_CMS_Index = index
set udg_CMS_Event_Missile_Destroyed = -1
set udg_CMS_Event_Missile_Destroyed = 0
set udg_CMS_Event_Missile_Destroyed = -1
set udg_CMS_Event_Missile_Destroyed = udg_CMS_Param_Type[udg_CMS_Index]
if not udg_CMS_Param_IsDestroyed[index] then
return false
endif
set missile = udg_CMS_Param_Missile[udg_CMS_Index]
set originalHeight = udg_CMS_Param_OriginalHeight[udg_CMS_Index]
set isAUnit = udg_CMS_Param_IsAUnit[udg_CMS_Index]
//Remove the special effect and target location.
call DestroyEffect(udg_CMS_Param_Effect[index])
call RemoveLocation(udg_CMS_Param_Target_Location[index])
set udg_CMS_MissileIndex[GetUnitUserData(udg_CMS_Param_Missile[udg_CMS_Amount])] = index
set udg_CMS_MissileIndex[GetUnitUserData(udg_CMS_Param_Missile[index])] = 0
call FlushChildHashtable(udg_CMS_HASHTABLE, GetHandleId(udg_CMS_Param_Missile[index]))
set udg_CMS_Param_Collision_Cooldown[index] = udg_CMS_Param_Collision_Cooldown[udg_CMS_Amount]
set udg_CMS_Param_Collision_Dest[index] = udg_CMS_Param_Collision_Dest[udg_CMS_Amount]
set udg_CMS_Param_Collision_Height[index] = udg_CMS_Param_Collision_Height[udg_CMS_Amount]
set udg_CMS_Param_Collision_Height_Inc[index] = udg_CMS_Param_Collision_Height_Inc[udg_CMS_Amount]
set udg_CMS_Param_Collision_Item[index] = udg_CMS_Param_Collision_Item[udg_CMS_Amount]
set udg_CMS_Param_Collision_Type[index] = udg_CMS_Param_Collision_Type[udg_CMS_Amount]
set udg_CMS_Param_Collision_Unit[index] = udg_CMS_Param_Collision_Unit[udg_CMS_Amount]
set udg_CMS_Param_Collision_Width[index] = udg_CMS_Param_Collision_Width[udg_CMS_Amount]
set udg_CMS_Param_Collision_Width_Inc[index] = udg_CMS_Param_Collision_Width_Inc[udg_CMS_Amount]
set udg_CMS_Param_Distance[index] = udg_CMS_Param_Distance[udg_CMS_Amount]
set udg_CMS_Param_Duration[index] = udg_CMS_Param_Duration[udg_CMS_Amount]
set udg_CMS_Param_Effect[index] = udg_CMS_Param_Effect[udg_CMS_Amount]
set udg_CMS_Param_Gravity[index] = udg_CMS_Param_Gravity[udg_CMS_Amount]
set udg_CMS_Param_Index[index] = udg_CMS_Param_Index[udg_CMS_Amount]
set udg_CMS_Param_IsAUnit[index] = udg_CMS_Param_IsAUnit[udg_CMS_Amount]
set udg_CMS_Param_IsDestroyed[index] = udg_CMS_Param_IsDestroyed[udg_CMS_Amount]
set udg_CMS_Param_IsFlying[index] = udg_CMS_Param_IsFlying[udg_CMS_Amount]
set udg_CMS_Param_IsHoming[index] = udg_CMS_Param_IsHoming[udg_CMS_Amount]
set udg_CMS_Param_MaxDistance[index] = udg_CMS_Param_MaxDistance[udg_CMS_Amount]
set udg_CMS_Param_MaxDuration[index] = udg_CMS_Param_MaxDuration[udg_CMS_Amount]
set udg_CMS_Param_Missile[index] = udg_CMS_Param_Missile[udg_CMS_Amount]
set udg_CMS_Param_OriginalHeight[index] = udg_CMS_Param_OriginalHeight[udg_CMS_Amount]
set udg_CMS_Param_Source[index] = udg_CMS_Param_Source[udg_CMS_Amount]
set udg_CMS_Param_Subtype[index] = udg_CMS_Param_Subtype[udg_CMS_Amount]
set udg_CMS_Param_Target_Location[index] = udg_CMS_Param_Target_Location[udg_CMS_Amount]
set udg_CMS_Param_Target_Type[index] = udg_CMS_Param_Target_Type[udg_CMS_Amount]
set udg_CMS_Param_Target_Unit[index] = udg_CMS_Param_Target_Unit[udg_CMS_Amount]
set udg_CMS_Param_TurnRate[index] = udg_CMS_Param_TurnRate[udg_CMS_Amount]
set udg_CMS_Param_Type[index] = udg_CMS_Param_Type[udg_CMS_Amount]
set udg_CMS_Param_WalkingHeight[index] = udg_CMS_Param_WalkingHeight[udg_CMS_Amount]
set udg_CMS_Param_A_X[index] = udg_CMS_Param_A_X[udg_CMS_Amount]
set udg_CMS_Param_A_Y[index] = udg_CMS_Param_A_Y[udg_CMS_Amount]
set udg_CMS_Param_A_Z[index] = udg_CMS_Param_A_Z[udg_CMS_Amount]
set udg_CMS_Param_V_X[index] = udg_CMS_Param_V_X[udg_CMS_Amount]
set udg_CMS_Param_V_Y[index] = udg_CMS_Param_V_Y[udg_CMS_Amount]
set udg_CMS_Param_V_Z[index] = udg_CMS_Param_V_Z[udg_CMS_Amount]
set udg_CMS_Cache_A_H[index] = udg_CMS_Cache_A_H[udg_CMS_Amount]
set udg_CMS_Cache_V_H[index] = udg_CMS_Cache_V_H[udg_CMS_Amount]
set udg_CMS_Cache_Acceleration[index] = udg_CMS_Cache_Acceleration[udg_CMS_Amount]
set udg_CMS_Cache_Angle[index] = udg_CMS_Cache_Angle[udg_CMS_Amount]
set udg_CMS_Cache_Pitch[index] = udg_CMS_Cache_Pitch[udg_CMS_Amount]
set udg_CMS_Cache_Speed[index] = udg_CMS_Cache_Speed[udg_CMS_Amount]
set udg_CMS_Cache_V_H_Index[index] = udg_CMS_Cache_V_H_Index[udg_CMS_Amount]
set udg_CMS_Cache_Acceleration_Index[index] = udg_CMS_Cache_Acceleration_Index[udg_CMS_Amount]
set udg_CMS_Cache_Angle_Index[index] = udg_CMS_Cache_Angle_Index[udg_CMS_Amount]
set udg_CMS_Cache_Pitch_Index[index] = udg_CMS_Cache_Pitch_Index[udg_CMS_Amount]
set udg_CMS_Cache_Speed_Index[index] = udg_CMS_Cache_Speed_Index[udg_CMS_Amount]
set udg_CMS_Param_Collision_Cooldown[udg_CMS_Amount] = 0.
set udg_CMS_Param_Collision_Dest[udg_CMS_Amount] = false
set udg_CMS_Param_Collision_Height[udg_CMS_Amount] = 0.
set udg_CMS_Param_Collision_Height_Inc[udg_CMS_Amount] = 0.
set udg_CMS_Param_Collision_Item[udg_CMS_Amount] = false
set udg_CMS_Param_Collision_Type[udg_CMS_Amount] = 0
set udg_CMS_Param_Collision_Unit[udg_CMS_Amount] = false
set udg_CMS_Param_Collision_Width[udg_CMS_Amount] = 0.
set udg_CMS_Param_Collision_Width_Inc[udg_CMS_Amount] = 0.
set udg_CMS_Param_Distance[udg_CMS_Amount] = 0.
set udg_CMS_Param_Duration[udg_CMS_Amount] = 0.
set udg_CMS_Param_Effect[udg_CMS_Amount] = null
set udg_CMS_Param_Gravity[udg_CMS_Amount] = 0.
set udg_CMS_Param_Index[udg_CMS_Amount] = 0
set udg_CMS_Param_IsAUnit[udg_CMS_Amount] = false
set udg_CMS_Param_IsDestroyed[udg_CMS_Amount] = false
set udg_CMS_Param_IsFlying[udg_CMS_Amount] = false
set udg_CMS_Param_IsHoming[udg_CMS_Amount] = false
set udg_CMS_Param_MaxDistance[udg_CMS_Amount] = 0.
set udg_CMS_Param_MaxDuration[udg_CMS_Amount] = 0.
set udg_CMS_Param_Missile[udg_CMS_Amount] = null
set udg_CMS_Param_OriginalHeight[udg_CMS_Amount] = 0.
set udg_CMS_Param_Source[udg_CMS_Amount] = null
set udg_CMS_Param_Subtype[udg_CMS_Amount] = 0
set udg_CMS_Param_Target_Location[udg_CMS_Amount] = null
set udg_CMS_Param_Target_Type[udg_CMS_Amount] = 0
set udg_CMS_Param_Target_Unit[udg_CMS_Amount] = null
set udg_CMS_Param_TurnRate[udg_CMS_Amount] = 0.
set udg_CMS_Param_Type[udg_CMS_Amount] = 0
set udg_CMS_Param_WalkingHeight[udg_CMS_Amount] = 0.
set udg_CMS_Param_A_X[udg_CMS_Amount] = 0.
set udg_CMS_Param_A_Y[udg_CMS_Amount] = 0.
set udg_CMS_Param_A_Z[udg_CMS_Amount] = 0.
set udg_CMS_Param_V_X[udg_CMS_Amount] = 0.
set udg_CMS_Param_V_Y[udg_CMS_Amount] = 0.
set udg_CMS_Param_V_Z[udg_CMS_Amount] = 0.
set udg_CMS_Cache_A_H[udg_CMS_Amount] = 0.
set udg_CMS_Cache_V_H[udg_CMS_Amount] = 0.
set udg_CMS_Cache_Acceleration[udg_CMS_Amount] = 0.
set udg_CMS_Cache_Angle[udg_CMS_Amount] = 0.
set udg_CMS_Cache_Pitch[udg_CMS_Amount] = 0.
set udg_CMS_Cache_Speed[udg_CMS_Amount] = 0.
set udg_CMS_Cache_V_H_Index[udg_CMS_Amount] = 0
set udg_CMS_Cache_Acceleration_Index[udg_CMS_Amount] = 0
set udg_CMS_Cache_Angle_Index[udg_CMS_Amount] = 0
set udg_CMS_Cache_Pitch_Index[udg_CMS_Amount] = 0
set udg_CMS_Cache_Speed_Index[udg_CMS_Amount] = 0
set udg_CMS_Amount = udg_CMS_Amount -1
if not isAUnit then
call UnitApplyTimedLife(missile, 0, 0.01)
else
call UnitRemoveAbility(missile, udg_CMS_ABILITY_GHOST)
call SetUnitPathing(missile, true)
call SetUnitPosition(missile, GetUnitX(missile), GetUnitY(missile))
call SetUnitFlyHeight(missile, originalHeight, 999)
endif
if udg_CMS_LoopIndex > -1 then
set udg_CMS_LoopIndex = udg_CMS_LoopIndex -1
endif
if udg_CMS_Amount == 0 then
call PauseTimer(udg_CMS_TIMER)
endif
set missile = null
return true
endfunction
//! runtextmacro CMS_COLLISION_FUNCTIONS()
function CMS_Interval_X takes nothing returns boolean
local rect r
local unit FoG
local real z
local real angle
local real x
local real y
local integer iteration = 0
loop
if udg_CMS_LoopIndex > udg_CMS_Amount then
return true
endif
exitwhen iteration > udg_CMS_LOOP_MAX
set iteration = iteration +1
//Move missile.
set udg_CMS_X_OLD = GetUnitX(udg_CMS_Param_Missile[udg_CMS_LoopIndex])
set udg_CMS_Y_OLD = GetUnitY(udg_CMS_Param_Missile[udg_CMS_LoopIndex])
set udg_CMS_X = udg_CMS_X_OLD + udg_CMS_Param_V_X[udg_CMS_LoopIndex]
set udg_CMS_Y = udg_CMS_Y_OLD + udg_CMS_Param_V_Y[udg_CMS_LoopIndex]
call SetUnitX(udg_CMS_Param_Missile[udg_CMS_LoopIndex], udg_CMS_X)
call SetUnitY(udg_CMS_Param_Missile[udg_CMS_LoopIndex], udg_CMS_Y)
set z = GetUnitFlyHeight(udg_CMS_Param_Missile[udg_CMS_LoopIndex]) + udg_CMS_Param_V_Z[udg_CMS_LoopIndex] - (GetCoordinateZ(udg_CMS_X, udg_CMS_Y) - GetCoordinateZ(udg_CMS_X_OLD, udg_CMS_Y_OLD))
if z <= udg_CMS_Param_WalkingHeight[udg_CMS_LoopIndex] then
if udg_CMS_Param_IsFlying[udg_CMS_LoopIndex] or z < -20. then
set udg_CMS_Param_IsDestroyed[udg_CMS_LoopIndex] = true
call SetUnitFlyHeight(udg_CMS_Param_Missile[udg_CMS_LoopIndex], z, 0)
else
set z = udg_CMS_Param_WalkingHeight[udg_CMS_LoopIndex]
set udg_CMS_Param_V_Z[udg_CMS_LoopIndex] = 0.
call SetUnitFlyHeight(udg_CMS_Param_Missile[udg_CMS_LoopIndex], z, 0)
endif
else
call SetUnitFlyHeight(udg_CMS_Param_Missile[udg_CMS_LoopIndex], z, 0)
//Add gravity effect.
if udg_CMS_Param_Gravity[udg_CMS_LoopIndex] != 0. then
set udg_CMS_Param_V_Z[udg_CMS_LoopIndex] = udg_CMS_Param_V_Z[udg_CMS_LoopIndex] + udg_CMS_Param_Gravity[udg_CMS_LoopIndex]
call CMS_SetPitch(udg_CMS_LoopIndex, CMS_GetPitch(udg_CMS_LoopIndex))
endif
endif
//Check for the missile's limits.
set udg_CMS_Param_Distance[udg_CMS_LoopIndex] = udg_CMS_Param_Distance[udg_CMS_LoopIndex] + CMS_GetSpeed(udg_CMS_LoopIndex)
if udg_CMS_Param_MaxDistance[udg_CMS_LoopIndex] > 0. and udg_CMS_Param_Distance[udg_CMS_LoopIndex] >= udg_CMS_Param_MaxDistance[udg_CMS_LoopIndex] then
set udg_CMS_Param_IsDestroyed[udg_CMS_LoopIndex] = true
endif
set udg_CMS_Param_Duration[udg_CMS_LoopIndex] = udg_CMS_Param_Duration[udg_CMS_LoopIndex] + udg_CMS_INTERVAL
if udg_CMS_Param_MaxDuration[udg_CMS_LoopIndex] > 0. and udg_CMS_Param_Duration[udg_CMS_LoopIndex] >= udg_CMS_Param_MaxDuration[udg_CMS_LoopIndex] then
set udg_CMS_Param_IsDestroyed[udg_CMS_LoopIndex] = true
endif
//Check collision.
if udg_CMS_Param_Collision_Type[udg_CMS_LoopIndex] == udg_CMS_COLLISIONTYPE_SIMPLE then
call SetRect(RECT, udg_CMS_X - udg_CMS_Param_Collision_Width[udg_CMS_LoopIndex], udg_CMS_Y - udg_CMS_Param_Collision_Width[udg_CMS_LoopIndex], udg_CMS_X + udg_CMS_Param_Collision_Width[udg_CMS_LoopIndex], udg_CMS_Y + udg_CMS_Param_Collision_Width[udg_CMS_LoopIndex])
//Collision with units.
if udg_CMS_Param_Collision_Unit[udg_CMS_LoopIndex] then
call GroupEnumUnitsInRect(udg_CMS_GROUP, RECT, null)
loop
set FoG = FirstOfGroup(udg_CMS_GROUP)
exitwhen FoG == null
call GroupRemoveUnit(udg_CMS_GROUP, FoG)
call CMS_Collide_Unit(FoG)
endloop
endif
//Collision with destructables.
if udg_CMS_Param_Collision_Dest[udg_CMS_LoopIndex] then
call EnumDestructablesInRect(RECT, null, function CMS_Collide_Dest_Simple)
endif
//Collision with items.
if udg_CMS_Param_Collision_Item[udg_CMS_LoopIndex] then
call EnumItemsInRect(RECT, null, function CMS_Collide_Item_Simple)
endif
//Increase width and height.
set udg_CMS_Param_Collision_Width[udg_CMS_LoopIndex] = udg_CMS_Param_Collision_Width[udg_CMS_LoopIndex] + udg_CMS_Param_Collision_Width_Inc[udg_CMS_LoopIndex]
set udg_CMS_Param_Collision_Height[udg_CMS_LoopIndex] = udg_CMS_Param_Collision_Height[udg_CMS_LoopIndex] + udg_CMS_Param_Collision_Height_Inc[udg_CMS_LoopIndex]
elseif udg_CMS_Param_Collision_Type[udg_CMS_LoopIndex] == udg_CMS_COLLISIONTYPE_CIRCLE then
call SetRect(RECT, udg_CMS_X - udg_CMS_Param_Collision_Width[udg_CMS_LoopIndex], udg_CMS_Y - udg_CMS_Param_Collision_Width[udg_CMS_LoopIndex], udg_CMS_X + udg_CMS_Param_Collision_Width[udg_CMS_LoopIndex], udg_CMS_Y + udg_CMS_Param_Collision_Width[udg_CMS_LoopIndex])
//Collision with units.
if udg_CMS_Param_Collision_Unit[udg_CMS_LoopIndex] then
call GroupEnumUnitsInRange(udg_CMS_GROUP, udg_CMS_X, udg_CMS_Y, udg_CMS_Param_Collision_Width[udg_CMS_LoopIndex], null)
loop
set FoG = FirstOfGroup(udg_CMS_GROUP)
exitwhen FoG == null
call GroupRemoveUnit(udg_CMS_GROUP, FoG)
call CMS_Collide_Unit(FoG)
endloop
endif
//Collision with destructables.
if udg_CMS_Param_Collision_Dest[udg_CMS_LoopIndex] then
call EnumDestructablesInRect(RECT, null, function CMS_Collide_Dest_Circle)
endif
//Collision with items.
if udg_CMS_Param_Collision_Item[udg_CMS_LoopIndex] then
call EnumItemsInRect(RECT, null, function CMS_Collide_Item_Circle)
endif
//Increase width and height.
set udg_CMS_Param_Collision_Width[udg_CMS_LoopIndex] = udg_CMS_Param_Collision_Width[udg_CMS_LoopIndex] + udg_CMS_Param_Collision_Width_Inc[udg_CMS_LoopIndex]
set udg_CMS_Param_Collision_Height[udg_CMS_LoopIndex] = udg_CMS_Param_Collision_Height[udg_CMS_LoopIndex] + udg_CMS_Param_Collision_Height_Inc[udg_CMS_LoopIndex]
elseif udg_CMS_Param_Collision_Type[udg_CMS_LoopIndex] == udg_CMS_COLLISIONTYPE_RECTANGLE then
//Collision with units.
set udg_CMS_RA = GetUnitFacing(udg_CMS_Param_Missile[udg_CMS_LoopIndex])*DEGTORAD
set udg_CMS_RX = (udg_CMS_X+udg_CMS_X_OLD) /2
set udg_CMS_RY = (udg_CMS_Y+udg_CMS_Y_OLD) /2
set udg_CMS_RW = udg_CMS_Param_Collision_Width[udg_CMS_LoopIndex]*2 + DistanceBetweenCoordinates(udg_CMS_X, udg_CMS_Y, udg_CMS_X_OLD, udg_CMS_Y_OLD)
set udg_CMS_RH = udg_CMS_Param_Collision_Width[udg_CMS_LoopIndex]*2
set z = udg_CMS_RW/2
call SetRect(RECT, udg_CMS_RX-z, udg_CMS_RY-z, udg_CMS_RX+z, udg_CMS_RY+z)
if udg_CMS_Param_Collision_Unit[udg_CMS_LoopIndex] then
call GroupEnumUnitsInRect(udg_CMS_GROUP, RECT, null)
loop
set FoG = FirstOfGroup(udg_CMS_GROUP)
exitwhen FoG == null
call GroupRemoveUnit(udg_CMS_GROUP, FoG)
if IsPointInAngledRectangleRad(udg_CMS_RX, udg_CMS_RY, udg_CMS_RW, udg_CMS_RH, udg_CMS_RA, GetUnitX(FoG), GetUnitY(FoG)) then
call CMS_Collide_Unit(FoG)
endif
endloop
endif
//Collision with destructables.
if udg_CMS_Param_Collision_Dest[udg_CMS_LoopIndex] then
call EnumDestructablesInRect(RECT, null, function CMS_Collide_Dest_Rectangle)
endif
//Collision with items.
if udg_CMS_Param_Collision_Item[udg_CMS_LoopIndex] then
call EnumItemsInRect(RECT, null, function CMS_Collide_Item_Rectangle)
endif
elseif udg_CMS_Param_Collision_Type[udg_CMS_LoopIndex] == udg_CMS_COLLISIONTYPE_POLYGON then
call udg_CMS_Param_Polygon[udg_CMS_LoopIndex].setPosition(udg_CMS_X, udg_CMS_Y)
call udg_CMS_Param_Polygon[udg_CMS_LoopIndex].setRotationDeg(GetUnitFacing(udg_CMS_Param_Missile[udg_CMS_LoopIndex]))
call udg_CMS_Param_Polygon[udg_CMS_LoopIndex].getBounds() //Stores the bounds in RECT (BasicFunctions)
//Collision with units.
if udg_CMS_Param_Collision_Unit[udg_CMS_LoopIndex] then
call GroupEnumUnitsInRect(udg_CMS_GROUP, RECT, null)
loop
set FoG = FirstOfGroup(udg_CMS_GROUP)
exitwhen FoG == null
call GroupRemoveUnit(udg_CMS_GROUP,FoG)
if udg_CMS_Param_Polygon[udg_CMS_LoopIndex].containsPoint(GetUnitX(FoG), GetUnitY(FoG)) then
call CMS_Collide_Unit(FoG)
endif
endloop
endif
//Collision with destructables.
if udg_CMS_Param_Collision_Dest[udg_CMS_LoopIndex] then
call EnumDestructablesInRect(RECT, null, function CMS_Collide_Dest_Polygon)
endif
//Collision with items.
if udg_CMS_Param_Collision_Item[udg_CMS_LoopIndex] then
call EnumItemsInRect(RECT, null, function CMS_Collide_Item_Polygon)
endif
endif
//Update direction if the missile is homing.
if udg_CMS_Param_IsHoming[udg_CMS_LoopIndex] then
if udg_CMS_Param_Target_Type[udg_CMS_LoopIndex] == udg_CMS_TARGETTYPE_UNIT then
//Update angle.
set x = GetUnitX(udg_CMS_Param_Target_Unit[udg_CMS_LoopIndex])
set y = GetUnitY(udg_CMS_Param_Target_Unit[udg_CMS_LoopIndex])
set angle = DenormalizeAngleDeg(AngleBetweenCoordinatesDeg(udg_CMS_X, udg_CMS_Y, x, y) - CMS_GetAngleDeg(udg_CMS_LoopIndex))
if angle > udg_CMS_Param_TurnRate[udg_CMS_LoopIndex] then
set angle = udg_CMS_Param_TurnRate[udg_CMS_LoopIndex]
elseif angle < -udg_CMS_Param_TurnRate[udg_CMS_LoopIndex] then
set angle = -udg_CMS_Param_TurnRate[udg_CMS_LoopIndex]
endif
call CMS_SetAngleDeg(udg_CMS_LoopIndex, CMS_GetAngleDeg(udg_CMS_LoopIndex) + angle)
//Update pitch.
if udg_CMS_Param_IsFlying[udg_CMS_LoopIndex] then
set angle = AngleBetweenCoordinatesDeg(0, GetUnitFlyHeight(udg_CMS_Param_Missile[udg_CMS_LoopIndex])+GetCoordinateZ(udg_CMS_X, udg_CMS_Y), DistanceBetweenCoordinates(x, y, udg_CMS_X, udg_CMS_Y), GetUnitFlyHeight(udg_CMS_Param_Target_Unit[udg_CMS_LoopIndex])+GetCoordinateZ(udg_CMS_X, udg_CMS_Y)) - CMS_GetPitchDeg(udg_CMS_LoopIndex)
if angle > udg_CMS_Param_TurnRate[udg_CMS_LoopIndex] then
set angle = udg_CMS_Param_TurnRate[udg_CMS_LoopIndex]
elseif angle < -udg_CMS_Param_TurnRate[udg_CMS_LoopIndex] then
set angle = -udg_CMS_Param_TurnRate[udg_CMS_LoopIndex]
endif
call CMS_SetPitchDeg(udg_CMS_LoopIndex, CMS_GetPitchDeg(udg_CMS_LoopIndex) + angle)
endif
elseif udg_CMS_Param_Target_Type[udg_CMS_LoopIndex] == udg_CMS_TARGETTYPE_LOCATION then
//Update angle.
set x = GetLocationX(udg_CMS_Param_Target_Location[udg_CMS_LoopIndex])
set y = GetLocationY(udg_CMS_Param_Target_Location[udg_CMS_LoopIndex])
set angle = DenormalizeAngleDeg(AngleBetweenCoordinatesDeg(udg_CMS_X, udg_CMS_Y, x, y) - CMS_GetAngleDeg(udg_CMS_LoopIndex))
if angle > udg_CMS_Param_TurnRate[udg_CMS_LoopIndex] then
set angle = udg_CMS_Param_TurnRate[udg_CMS_LoopIndex]
elseif angle < -udg_CMS_Param_TurnRate[udg_CMS_LoopIndex] then
set angle = -udg_CMS_Param_TurnRate[udg_CMS_LoopIndex]
endif
call CMS_SetAngleDeg(udg_CMS_LoopIndex, CMS_GetAngleDeg(udg_CMS_LoopIndex) + angle)
//Update pitch.
if udg_CMS_Param_IsFlying[udg_CMS_LoopIndex] then
set angle = AngleBetweenCoordinatesDeg(0, GetUnitFlyHeight(udg_CMS_Param_Missile[udg_CMS_LoopIndex])+GetCoordinateZ(udg_CMS_X, udg_CMS_Y), DistanceBetweenCoordinates(x, y, udg_CMS_X, udg_CMS_Y), GetCoordinateZ(x, y)) - CMS_GetPitchDeg(udg_CMS_LoopIndex)
if angle > udg_CMS_Param_TurnRate[udg_CMS_LoopIndex] then
set angle = udg_CMS_Param_TurnRate[udg_CMS_LoopIndex]
elseif angle < -udg_CMS_Param_TurnRate[udg_CMS_LoopIndex] then
set angle = -udg_CMS_Param_TurnRate[udg_CMS_LoopIndex]
endif
call CMS_SetPitchDeg(udg_CMS_LoopIndex, CMS_GetPitchDeg(udg_CMS_LoopIndex) + angle)
endif
endif
endif
set udg_CMS_Param_V_X[udg_CMS_LoopIndex] = udg_CMS_Param_V_X[udg_CMS_LoopIndex] + udg_CMS_Param_A_X[udg_CMS_LoopIndex]
set udg_CMS_Param_V_Y[udg_CMS_LoopIndex] = udg_CMS_Param_V_Y[udg_CMS_LoopIndex] + udg_CMS_Param_A_Y[udg_CMS_LoopIndex]
set udg_CMS_Param_V_Z[udg_CMS_LoopIndex] = udg_CMS_Param_V_Z[udg_CMS_LoopIndex] + udg_CMS_Param_A_Z[udg_CMS_LoopIndex]
if udg_CMS_Param_IsDestroyed[udg_CMS_LoopIndex] then
call CMS_DestroyMissile(udg_CMS_LoopIndex)
endif
set udg_CMS_LoopIndex = udg_CMS_LoopIndex +1
endloop
return false
endfunction
//This is the interval of the timer.
function CMS_Interval takes nothing returns nothing
set udg_CMS_LoopIndex = 1
set udg_CMS_IntervalCount = udg_CMS_IntervalCount +1
set udg_CMS_GameTime = GetElapsedGameTime()
loop
exitwhen TriggerEvaluate(udg_CMS_TRIGGER)
endloop
set udg_CMS_LoopIndex = -1
endfunction
function CMS_CreateMissile takes unit source, integer typeId, unit whichMissile, boolean importDefaultValues returns integer
local integer id
local timer t
local location startingLocation = udg_CMS_StartingLocation
local integer otherIndex = 0
local integer sourceId
local integer missileId
set udg_CMS_Amount = udg_CMS_Amount +1
if importDefaultValues then
call CMS_SetDefaultVariables(udg_CMS_Amount)
endif
set udg_CMS_Param_Missile[udg_CMS_Amount] = whichMissile
set udg_CMS_Param_Source[udg_CMS_Amount] = source
set udg_CMS_Param_Type[udg_CMS_Amount] = typeId
if udg_CMS_Param_Missile[udg_CMS_Amount] == null then
if udg_CMS_StartingLocust then
//Create a new missile dummy and give it locust.
set udg_CMS_Param_Missile[udg_CMS_Amount] = CreateUnit(GetOwningPlayer(udg_CMS_Param_Source[udg_CMS_Amount]), udg_CMS_MISSILE_UNITTYPE, GetLocationX(startingLocation), GetLocationY(startingLocation), udg_CMS_StartingAngle)
call UnitAddAbility(udg_CMS_Param_Missile[udg_CMS_Amount], 'Aloc')
call UnitMakeAbilityPermanent(udg_CMS_Param_Missile[udg_CMS_Amount], true, 'Aloc')
else
//Create a new dummy unit and transform it into the missile dummy to de-locust the unit.
set udg_CMS_Param_Missile[udg_CMS_Amount] = CreateUnit(GetOwningPlayer(udg_CMS_Param_Source[udg_CMS_Amount]), udg_CMS_DUMMY_UNITTYPE, GetLocationX(startingLocation), GetLocationY(startingLocation), udg_CMS_StartingAngle)
call UnitAddAbility(udg_CMS_Param_Missile[udg_CMS_Amount], udg_CMS_ABILITY_MORPH)
call UnitRemoveAbility(udg_CMS_Param_Missile[udg_CMS_Amount], udg_CMS_ABILITY_MORPH)
//Remove collision.
call UnitAddAbility(udg_CMS_Param_Missile[udg_CMS_Amount], udg_CMS_ABILITY_GHOST)
call UnitMakeAbilityPermanent(udg_CMS_Param_Missile[udg_CMS_Amount], true, udg_CMS_ABILITY_GHOST)
call SetUnitPathing(udg_CMS_Param_Missile[udg_CMS_Amount], false)
endif
else
set otherIndex = CMS_GetIndex(udg_CMS_Param_Missile[udg_CMS_Amount])
//Remove collision.
call UnitAddAbility(udg_CMS_Param_Missile[udg_CMS_Amount], udg_CMS_ABILITY_GHOST)
call UnitMakeAbilityPermanent(udg_CMS_Param_Missile[udg_CMS_Amount], true, udg_CMS_ABILITY_GHOST)
call SetUnitPathing(udg_CMS_Param_Missile[udg_CMS_Amount], false)
endif
//Add and remove crow form.
if UnitAddAbility(udg_CMS_Param_Missile[udg_CMS_Amount], 'Arav') then
call UnitRemoveAbility(udg_CMS_Param_Missile[udg_CMS_Amount], 'Arav')
endif
//Make sure that the source is not immediately hit.
if udg_CMS_StartingSourceFilter then
call SaveReal(udg_CMS_HASHTABLE, GetHandleId(udg_CMS_Param_Missile[udg_CMS_Amount]), GetHandleId(udg_CMS_Param_Source[udg_CMS_Amount]), GetElapsedGameTime())
endif
//Save the original height.
if otherIndex > 0 then
set udg_CMS_Param_OriginalHeight[udg_CMS_Amount] = GetUnitFlyHeight(udg_CMS_Param_Missile[udg_CMS_Amount])
call SetUnitFlyHeight(udg_CMS_Param_Missile[udg_CMS_Amount], udg_CMS_StartingHeight, 999)
else
set udg_CMS_Param_OriginalHeight[udg_CMS_Amount] = udg_CMS_Param_OriginalHeight[otherIndex]
call SetUnitFlyHeight(udg_CMS_Param_Missile[udg_CMS_Amount], udg_CMS_StartingHeight, 0)
endif
//Generate speed and direction.
call CMS_SetSpeedPerSecond(udg_CMS_Amount, udg_CMS_StartingSpeed)
call CMS_SetAngleDeg(udg_CMS_Amount, udg_CMS_StartingAngle)
call CMS_SetPitchDeg(udg_CMS_Amount, udg_CMS_StartingPitch)
call CMS_SetAccelerationPerSecond(udg_CMS_Amount, udg_CMS_StartingAcceleration)
//Start the timer if this is the first missile.
if udg_CMS_Amount == 1 then
call TimerStart(udg_CMS_TIMER, udg_CMS_INTERVAL, true, function CMS_Interval)
endif
//Create the unique index.
set udg_CMS_Param_Index[udg_CMS_Amount] = CMS_CreateUniqueId()
set udg_CMS_MissileIndex[GetUnitUserData(udg_CMS_Param_Missile[udg_CMS_Amount])] = udg_CMS_Amount
//Call the event.
set udg_CMS_Event_Missile_Created = -1
set udg_CMS_Event_Missile_Created = 0
set udg_CMS_Event_Missile_Created = -1
set udg_CMS_Event_Missile_Created = udg_CMS_Param_Type[udg_CMS_Amount]
//Clean leaks.
call RemoveLocation(startingLocation)
set startingLocation = null
//Reset variables to standard settings.
set udg_CMS_StartingAcceleration = 0.
set udg_CMS_StartingAngle = 0.
set udg_CMS_StartingHeight = 0.
set udg_CMS_StartingLocation = null
set udg_CMS_StartingLocust = true
set udg_CMS_StartingPitch = 0.
set udg_CMS_StartingSourceFilter = true
set udg_CMS_StartingSpeed = 0.
return udg_CMS_Amount
endfunction
//This function creates a new missile.
//It uses the missile source and all starting variables.
function CMS_CreateMissileEx takes nothing returns integer
local integer id = CMS_CreateMissile(udg_CMS_StartingSource, udg_CMS_StartingType, udg_CMS_StartingMissile, udg_CMS_StartingDefaultValues)
set udg_CMS_StartingSource = null
set udg_CMS_StartingType = -1
set udg_CMS_StartingMissile = null
set udg_CMS_StartingDefaultValues = true
return id
endfunction
endlibrary
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// This code initializes the standard settings.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//This is the initial function.
function InitTrig_CMS_System takes nothing returns nothing
call TriggerAddCondition(udg_CMS_TRIGGER, Filter(function CMS_Interval_X))
//Initialize the constants.
set udg_CMS_COLLISIONTYPE_NONE = 0
set udg_CMS_COLLISIONTYPE_SIMPLE = 1
set udg_CMS_COLLISIONTYPE_CIRCLE = 2
set udg_CMS_COLLISIONTYPE_RECTANGLE = 3
set udg_CMS_COLLISIONTYPE_POLYGON = 4
set udg_CMS_TARGETTYPE_NONE = 0
set udg_CMS_TARGETTYPE_UNIT = 1
set udg_CMS_TARGETTYPE_LOCATION = 2
//Initialize the indexes.
set udg_CMS_IntervalCount = 1
set udg_CMS_LoopIndex = -1
set udg_CMS_Amount = 0
//Initialize standard starting settings.
set udg_CMS_StartingAcceleration = 0.
set udg_CMS_StartingAngle = 0.
set udg_CMS_StartingDefaultValues = true
set udg_CMS_StartingHeight = 0.
set udg_CMS_StartingLocation = null
set udg_CMS_StartingLocust = true
set udg_CMS_StartingMissile = null
set udg_CMS_StartingPitch = 0.
set udg_CMS_StartingSource = null
set udg_CMS_StartingSourceFilter = true
set udg_CMS_StartingSpeed = 0.
set udg_CMS_StartingType = -1
//! runtextmacro CMS_INIT()
endfunction
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// CMS System end
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////