Name | Type | is_array | initial_value |
ClsR_Ability | abilcode | No | |
ClsR_AbilityLevels | integer | No | |
ClsR_AbilityOrder | ordercode | No | |
ClsR_AreaOfEffect | real | Yes | |
ClsR_areaOfTarget | real | Yes | |
ClsR_Caster | unit | Yes | |
ClsR_casterOwner | player | Yes | |
ClsR_Counter | integer | Yes | |
ClsR_Counter2 | integer | Yes | |
ClsR_CountRockets | boolean | No | |
ClsR_DamagePerRocket | real | Yes | |
ClsR_DelayPerWave | real | No | |
ClsR_FirstWaveDelay | real | No | |
ClsR_Hashtable | hashtable | No | |
ClsR_HitTargetOnly | boolean | No | |
ClsR_Last | integer | No | |
ClsR_lastPitch | real | Yes | |
ClsR_lastX | real | Yes | |
ClsR_lastY | real | Yes | |
ClsR_lastZ | real | Yes | |
ClsR_Level | integer | Yes | |
ClsR_MakeUnitExplode | boolean | No | |
ClsR_mapBorder | real | Yes | |
ClsR_MaxIndex | integer | No | |
ClsR_Next | integer | Yes | |
ClsR_NoTarget | boolean | No | |
ClsR_OrientationPitch | real | No | |
ClsR_OrientationRoll | real | No | |
ClsR_OrientationYaw | real | No | |
ClsR_Pitch | real | Yes | |
ClsR_posX | real | Yes | |
ClsR_posY | real | Yes | |
ClsR_posZ | real | Yes | |
ClsR_PreferTargetUnit | boolean | No | |
ClsR_Prev | integer | Yes | |
ClsR_realTimer | real | Yes | |
ClsR_realTimer2 | real | Yes | |
ClsR_Recyclable | integer | No | |
ClsR_Recycle | integer | Yes | |
ClsR_RocketAttackType | attacktype | No | |
ClsR_RocketDamageType | damagetype | No | |
ClsR_rocketFx | effect | Yes | |
ClsR_RocketsCollisionSize | real | No | |
ClsR_RocketsCount | integer | Yes | |
ClsR_RocketsCrashHeight | real | No | |
ClsR_RocketsDamageRange | real | Yes | |
ClsR_RocketsExpirationTime | real | No | |
ClsR_RocketsFacingWidth | real | No | |
ClsR_RocketsInterval | real | No | |
ClsR_RocketsMaxFacingVariation | real | No | |
ClsR_RocketsMaxPitchVariation | real | No | |
ClsR_RocketsMinFacingVariation | real | No | |
ClsR_RocketsMinPitchVariation | real | No | |
ClsR_RocketsModel | string | No | |
ClsR_RocketsPerSecond | integer | No | |
ClsR_RocketsPerWave | integer | No | |
ClsR_RocketsSize | real | No | |
ClsR_RocketsSpawnHeightBonus | real | No | |
ClsR_RocketsSpawnOffset | real | No | |
ClsR_RocketsSpeedBase | real | Yes | |
ClsR_RocketsTurnAcceleration | real | Yes | |
ClsR_RocketsUnitsHeightBonus | real | No | |
ClsR_Roll | real | Yes | |
ClsR_Stage | integer | Yes | |
ClsR_Target | unit | Yes | |
ClsR_targetCollision | real | Yes | |
ClsR_TargetEffectAttachment | string | No | |
ClsR_TargetEffectModel | string | No | |
ClsR_targetType | integer | Yes | |
ClsR_tempGroup | group | No | |
ClsR_Timer | timer | No | |
ClsR_ZLocator | location | No | |
z_BlueSpawnPoint | location | No | |
z_BlueUnitType | unitcode | Yes | |
z_CreepsAttackPoint | location | No | |
z_CreepsSpawnPoint | location | Yes | |
z_CreepsSpawnPointTypes | integer | Yes | |
z_CreepsUnitType | unitcode | Yes | |
z_EnableBlackMask | boolean | No | |
z_EnableFogOfWar | boolean | No | |
z_RedSpawnPoint | location | No | |
z_RedUnitType | unitcode | Yes | |
z_SpawnUnits | boolean | No | |
z_StartingTimeOfDay | real | No |
//***************************************************************************
//* *
//* *
//* +----------------------------+ *
//* | Cluster Rockets [v1.1.1] | *
//* | by Ofel [ClsR_] | *
//* +----------------------------+ *
//* *
//* Requires: *
//* - JassHelper, enable JassHelper from Trigger Editor -> *
//* JassHelper -> Enable JassHelper. *
//* *
//***************************************************************************
//***************************************************************************
//*
//* Additional Configuration
//*
globals
boolean ClsR_PRELOAD_SPELL = true
boolean ClsR_BOUNDS_ENTIRE_MAP = true
real ClsR_FRAME_UPDATE = 1 / 32.
real ClsR_COLLISION_SCAN_RANGE = 200.00
real ClsR_PI = 3.1415926
real ClsR_DEGTORAD = 0.0174532
real ClsR_RADTODEG = 57.2957795
endglobals
//---------------------------------------------------------------------------
//*
//* Filteration
//*
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Units that can be acquired as target by the rockets.
function ClsR_AcquisitionFilter takes unit filterUnit, player casterOwner returns boolean
return IsUnitEnemy(filterUnit, casterOwner) and not IsUnitType(filterUnit, UNIT_TYPE_MAGIC_IMMUNE)
endfunction
//---------------------------------------------------------------------------
// Units that can trigger collision with the rockets.
function ClsR_CollisionFilter takes unit filterUnit, player casterOwner returns boolean
return IsUnitEnemy(filterUnit, casterOwner)
endfunction
//---------------------------------------------------------------------------
// Units that can receive damage.
function ClsR_DamageExplosionFilter takes unit filterUnit, player casterOwner returns boolean
return not IsUnitType(filterUnit, UNIT_TYPE_MAGIC_IMMUNE)
endfunction
//*
//* End of Configuration
//*
//***************************************************************************
//---------------------------------------------------------------------------
// Checks if unit is alive.
function ClsR_IsUnitAlive takes unit targetUnit returns boolean
return GetUnitTypeId(targetUnit) != 0 and not IsUnitType(targetUnit, UNIT_TYPE_DEAD)
endfunction
//---------------------------------------------------------------------------
// Checks if unit is channeling the spell.
function ClsR_IsUnitChanneling takes unit targetUnit returns boolean
return GetUnitCurrentOrder(targetUnit) == udg_ClsR_AbilityOrder
endfunction
//---------------------------------------------------------------------------
// Returns absolute value.
function ClsR_RAbs takes real a returns real
if (a >= 0) then
return a
else
return -a
endif
endfunction
//---------------------------------------------------------------------------
// Returns bounded x.
function ClsR_BoundX takes real x returns real
if x > udg_ClsR_mapBorder[1] then
set x = udg_ClsR_mapBorder[1]
elseif x < udg_ClsR_mapBorder[3] then
set x = udg_ClsR_mapBorder[3]
endif
return x
endfunction
//---------------------------------------------------------------------------
// Returns bounded y.
function ClsR_BoundY takes real y returns real
if y > udg_ClsR_mapBorder[2] then
set y = udg_ClsR_mapBorder[2]
elseif y < udg_ClsR_mapBorder[4] then
set y = udg_ClsR_mapBorder[4]
endif
return y
endfunction
//---------------------------------------------------------------------------
// Returns 2D distance between points - adapted from a vJASS library by
// Nestharus.
function ClsR_GetDistance2D takes real x, real y returns real
return SquareRoot(x*x+y*y)
endfunction
//---------------------------------------------------------------------------
// Returns 3D distance between points - adapted from a vJASS library by
// Nestharus.
function ClsR_GetDistance3D takes real x, real y, real z returns real
return SquareRoot(x*x+y*y+z*z)
endfunction
//---------------------------------------------------------------------------
// Returns z angle between points - adapted from a vJASS library by
// Nestharus.
function ClsR_AngleZ takes real x, real y returns real
return Atan2(y, x)
endfunction
//---------------------------------------------------------------------------
// Returns z angle between points using distance on the xy plane - adapted
// from a vJASS library by Nestharus.
function ClsR_AnglePointsZ takes real distance2D, real z returns real
return Atan2(z, distance2D)
endfunction
//---------------------------------------------------------------------------
// Returns the orientation angles in 3D space - adapted from a Wurst library
// by Wareditor.
function ClsR_GetOrientation3D takes real x, real y, real z returns nothing
local real ax
local real ay
local real px
local real py
if x == 0 and y == 0 then
if z > 0 then
set ax = -bj_PI*0.5
else
set ax = bj_PI*0.5
endif
elseif z != 0 then
set ax = ClsR_RAbs(x)
set ay = ClsR_RAbs(y)
set px = ax / (ax + ay)
set py = 1 - px
if y == 0 then
set ax = 0
else
set ax = Atan(z/y)*py
endif
if x == 0 then
set ay = 0
else
set ay = -Atan(z/x)*px
endif
endif
set udg_ClsR_OrientationYaw = ax
set udg_ClsR_OrientationPitch = ay
set udg_ClsR_OrientationRoll = Atan2(y, x)
endfunction
//---------------------------------------------------------------------------
// Returns the half of a unit collision size.
function ClsR_GetUnitCollisionRadius takes unit targetUnit returns real
return BlzGetUnitCollisionSize(targetUnit) / 2.
endfunction
//---------------------------------------------------------------------------
// Returns terrain z - adapted from a vJASS library by D.O.G.
function ClsR_GetTerrainZ takes real x, real y returns real
// Move Z location finder
call MoveLocation(udg_ClsR_ZLocator, x, y)
// Return location terrain z
return GetLocationZ(udg_ClsR_ZLocator)
endfunction
//---------------------------------------------------------------------------
// Returns (height + terrain z) of a unit alternatively.
function ClsR_GetUnitZAlt takes unit targetUnit, real x, real y returns real
local real height
if IsUnitType(targetUnit, UNIT_TYPE_FLYING) then
set height = GetUnitFlyHeight(targetUnit)
else
// Add bonus height when unit is not a flying type
set height = GetUnitFlyHeight(targetUnit) + udg_ClsR_RocketsUnitsHeightBonus
endif
// Return joined height and terrain z
return height + ClsR_GetTerrainZ(x, y)
endfunction
//---------------------------------------------------------------------------
// Returns 3D distance between a point and a unit.
function ClsR_GetDistanceToUnit3D takes real sourceX, real sourceY, real sz, unit targetUnit returns real
local real targetX = GetUnitX(targetUnit)
local real targetY = GetUnitY(targetUnit)
local real targetZ = ClsR_GetUnitZAlt(targetUnit, targetX, targetY)
return ClsR_GetDistance3D(targetX-sourceX, targetY-sourceY, targetZ-sz)
endfunction
//---------------------------------------------------------------------------
// Registers rocket target unit data.
function ClsR_RegisterTargetUnit takes integer rIndex returns nothing
local integer targetHandleID = GetHandleId(udg_ClsR_Target[rIndex])
local integer targetedCount = LoadInteger(udg_ClsR_Hashtable, targetHandleID, 0)
set udg_ClsR_lastX[rIndex] = GetUnitX(udg_ClsR_Target[rIndex])
set udg_ClsR_lastY[rIndex] = GetUnitY(udg_ClsR_Target[rIndex])
set udg_ClsR_lastZ[rIndex] = ClsR_GetUnitZAlt(udg_ClsR_Target[rIndex], udg_ClsR_lastX[rIndex], udg_ClsR_lastY[rIndex])
if targetedCount == 0 then
call SaveEffectHandle(udg_ClsR_Hashtable, targetHandleID, 0, AddSpecialEffectTarget(udg_ClsR_TargetEffectModel, udg_ClsR_Target[rIndex], udg_ClsR_TargetEffectAttachment))
endif
call SaveInteger(udg_ClsR_Hashtable, targetHandleID, 0, targetedCount + 1)
endfunction
//---------------------------------------------------------------------------
// Returns new target near a target point (Area of Effect).
function ClsR_AcquireNewTarget takes real x, real y, integer index returns unit
// Declare locals
local unit enumUnit
local integer i = 0
// Null reference
set udg_ClsR_Target[0] = null
// Enumerate all units in range
call GroupEnumUnitsInRange(udg_ClsR_tempGroup, x, y, udg_ClsR_AreaOfEffect[udg_ClsR_Level[index]], null)
loop
set enumUnit = FirstOfGroup(udg_ClsR_tempGroup)
exitwhen enumUnit == null
if enumUnit != udg_ClsR_Caster[index] and ClsR_IsUnitAlive(enumUnit) and ClsR_AcquisitionFilter(enumUnit, udg_ClsR_casterOwner[index]) then
// Random target
set i = i + 1
if GetRandomInt(1, i) == 1 then
set udg_ClsR_Target[0] = enumUnit
endif
endif
call GroupRemoveUnit(udg_ClsR_tempGroup, enumUnit)
endloop
// Return new target
return udg_ClsR_Target[0]
endfunction
//---------------------------------------------------------------------------
// Returns random terrain target inside Area of Effect.
function ClsR_AcquireTerrainTarget takes integer rIndex, integer cIndex returns nothing
local real facing = GetRandomReal(-ClsR_PI, ClsR_PI)
local real range = GetRandomReal(0, udg_ClsR_areaOfTarget[udg_ClsR_Level[cIndex]])
set udg_ClsR_lastX[rIndex] = udg_ClsR_posX[cIndex] + range * Cos(facing)
set udg_ClsR_lastY[rIndex] = udg_ClsR_posY[cIndex] + range * Sin(facing)
set udg_ClsR_lastZ[rIndex] = ClsR_GetTerrainZ(udg_ClsR_lastX[rIndex], udg_ClsR_lastY[rIndex])
endfunction
//---------------------------------------------------------------------------
// Returns new allocation index of a linked list.
function ClsR_Create takes nothing returns integer
// Declare locals
local integer newIndex = 0
// Allocate index
if udg_ClsR_Recyclable == 0 then
set udg_ClsR_MaxIndex = udg_ClsR_MaxIndex + 1
set newIndex = udg_ClsR_MaxIndex
else
set udg_ClsR_Recyclable = udg_ClsR_Recyclable - 1
set newIndex = udg_ClsR_Recycle[udg_ClsR_Recyclable]
endif
set udg_ClsR_Next[newIndex] = 0
set udg_ClsR_Next[udg_ClsR_Last] = newIndex
set udg_ClsR_Prev[newIndex] = udg_ClsR_Last
set udg_ClsR_Last = newIndex
// Return allocated index
return newIndex
endfunction
//---------------------------------------------------------------------------
// Cleans an instance by index.
function ClsR_Destroy takes integer index returns nothing
// Clean up
set udg_ClsR_Caster[index] = null
set udg_ClsR_Target[index] = null
set udg_ClsR_rocketFx[index] = null
set udg_ClsR_casterOwner[index] = null
set udg_ClsR_Stage[index] = 0
// Recycle index
if udg_ClsR_Last == index then
set udg_ClsR_Last = udg_ClsR_Prev[index]
endif
set udg_ClsR_Recycle[udg_ClsR_Recyclable] = index
set udg_ClsR_Recyclable = udg_ClsR_Recyclable + 1
set udg_ClsR_Next[udg_ClsR_Prev[index]] = udg_ClsR_Next[index]
set udg_ClsR_Prev[udg_ClsR_Next[index]] = udg_ClsR_Prev[index]
if udg_ClsR_Next[0] == 0 then
// --- When no active instances left
call PauseTimer(udg_ClsR_Timer)
endif
endfunction
//---------------------------------------------------------------------------
// Destroys rocket and damage nearby units.
function ClsR_TerminateRocket takes integer rocketIndex returns nothing
// Declare locals
local unit enumUnit
local integer targetHandleID
local integer targetedCount
// Enumerate all units near the rocket
call GroupEnumUnitsInRange(udg_ClsR_tempGroup, udg_ClsR_posX[rocketIndex], udg_ClsR_posY[rocketIndex], udg_ClsR_RocketsDamageRange[udg_ClsR_Level[rocketIndex]]+ClsR_COLLISION_SCAN_RANGE, null)
loop
set enumUnit = FirstOfGroup(udg_ClsR_tempGroup)
exitwhen enumUnit == null
if ClsR_GetDistanceToUnit3D(udg_ClsR_posX[rocketIndex], udg_ClsR_posY[rocketIndex], udg_ClsR_posZ[rocketIndex], enumUnit)-ClsR_GetUnitCollisionRadius(enumUnit) <= udg_ClsR_RocketsDamageRange[udg_ClsR_Level[rocketIndex]] then
if enumUnit != udg_ClsR_Caster[rocketIndex] and ClsR_IsUnitAlive(enumUnit) and ClsR_DamageExplosionFilter(enumUnit, udg_ClsR_casterOwner[rocketIndex]) then
// --- Exclude caster and dead units
// Make unit explode on death
call SetUnitExploded(enumUnit, udg_ClsR_MakeUnitExplode)
// Damage unit
call UnitDamageTarget(udg_ClsR_Caster[rocketIndex], enumUnit, udg_ClsR_DamagePerRocket[udg_ClsR_Level[rocketIndex]], true, false, udg_ClsR_RocketAttackType, udg_ClsR_RocketDamageType, WEAPON_TYPE_WHOKNOWS)
// Make unit normal
call SetUnitExploded(enumUnit, false)
endif
endif
call GroupRemoveUnit(udg_ClsR_tempGroup, enumUnit)
endloop
call GroupClear(udg_ClsR_tempGroup)
// Destroy rocket missile effect
call DestroyEffect(udg_ClsR_rocketFx[rocketIndex])
if ClsR_IsUnitAlive(udg_ClsR_Target[rocketIndex]) then
set targetHandleID = GetHandleId(udg_ClsR_Target[rocketIndex])
set targetedCount = LoadInteger(udg_ClsR_Hashtable, targetHandleID, 0)
if targetedCount == 1 then
call DestroyEffect(LoadEffectHandle(udg_ClsR_Hashtable, targetHandleID, 0))
call FlushChildHashtable(udg_ClsR_Hashtable, targetHandleID)
else
call SaveInteger(udg_ClsR_Hashtable, targetHandleID, 0, targetedCount - 1)
endif
endif
// End rocket instance
call ClsR_Destroy(rocketIndex)
endfunction
//---------------------------------------------------------------------------
// Creates new rocket instance.
function ClsR_LaunchRocket takes integer casterIndex returns nothing
// Declare locals
local integer rocketIndex
local real casterFacingRad = GetUnitFacing(udg_ClsR_Caster[casterIndex]) * ClsR_DEGTORAD
local real sourceX = GetUnitX(udg_ClsR_Caster[casterIndex]) + udg_ClsR_RocketsSpawnOffset * Cos(casterFacingRad) // Spawn x
local real sourceY = GetUnitY(udg_ClsR_Caster[casterIndex]) + udg_ClsR_RocketsSpawnOffset * Sin(casterFacingRad) // Spawn y
local real sourceZ = GetUnitFlyHeight(udg_ClsR_Caster[casterIndex]) + ClsR_GetTerrainZ(sourceX, sourceY) + udg_ClsR_RocketsSpawnHeightBonus // Spawn height + terrain z
local real targetX
local real targetY
local real targetZ
local real anglePointsZ
local real rocketFacing
local real rocketPitch
// Allocate new index
set rocketIndex = ClsR_Create()
// Note: Target type 0 - Instant (No target)
// Target type 1 - Unit target
// Target type 2 - Point target
if udg_ClsR_targetType[casterIndex] == 0 then
set udg_ClsR_Target[rocketIndex] = ClsR_AcquireNewTarget(udg_ClsR_posX[casterIndex], udg_ClsR_posY[casterIndex], casterIndex)
if udg_ClsR_Target[rocketIndex] != null then
set udg_ClsR_targetCollision[rocketIndex] = ClsR_GetUnitCollisionRadius(udg_ClsR_Target[rocketIndex])
call ClsR_RegisterTargetUnit(rocketIndex)
else
call ClsR_AcquireTerrainTarget(rocketIndex, casterIndex)
endif
elseif udg_ClsR_targetType[casterIndex] == 1 then
if ClsR_IsUnitAlive(udg_ClsR_Target[casterIndex]) then
set udg_ClsR_Target[rocketIndex] = udg_ClsR_Target[casterIndex]
set udg_ClsR_targetCollision[rocketIndex] = udg_ClsR_targetCollision[casterIndex]
call ClsR_RegisterTargetUnit(rocketIndex)
else
call ClsR_AcquireTerrainTarget(rocketIndex, casterIndex)
endif
elseif udg_ClsR_targetType[casterIndex] == 2 and udg_ClsR_AreaOfEffect[udg_ClsR_Level[casterIndex]] > 0 then
if udg_ClsR_PreferTargetUnit then
set udg_ClsR_Target[rocketIndex] = ClsR_AcquireNewTarget(udg_ClsR_posX[casterIndex], udg_ClsR_posY[casterIndex], casterIndex)
endif
if udg_ClsR_Target[rocketIndex] != null then
set udg_ClsR_targetCollision[rocketIndex] = ClsR_GetUnitCollisionRadius(udg_ClsR_Target[rocketIndex])
call ClsR_RegisterTargetUnit(rocketIndex)
else
call ClsR_AcquireTerrainTarget(rocketIndex, casterIndex)
endif
endif
// Copy properties to local reference variables
set targetX = udg_ClsR_lastX[rocketIndex]
set targetY = udg_ClsR_lastY[rocketIndex]
set targetZ = udg_ClsR_lastZ[rocketIndex]
// Get new 3D angles
set anglePointsZ = ClsR_AnglePointsZ(ClsR_GetDistance2D(targetX-sourceX, targetY-sourceY), targetZ-sourceZ)
set rocketFacing = GetRandomReal(casterFacingRad-udg_ClsR_RocketsMinFacingVariation, casterFacingRad+udg_ClsR_RocketsMaxFacingVariation)
set rocketPitch = GetRandomReal(anglePointsZ-udg_ClsR_RocketsMinPitchVariation, anglePointsZ+udg_ClsR_RocketsMaxPitchVariation)
set udg_ClsR_rocketFx[rocketIndex] = AddSpecialEffect(udg_ClsR_RocketsModel, sourceX, sourceY)
call BlzSetSpecialEffectOrientation(udg_ClsR_rocketFx[rocketIndex], rocketFacing, rocketPitch, 0)
call BlzSetSpecialEffectZ(udg_ClsR_rocketFx[rocketIndex], sourceZ)
call BlzSetSpecialEffectScale(udg_ClsR_rocketFx[rocketIndex], udg_ClsR_RocketsSize)
set udg_ClsR_Roll[rocketIndex] = rocketFacing
set udg_ClsR_Pitch[rocketIndex] = rocketPitch
set udg_ClsR_lastPitch[rocketIndex] = rocketPitch
set udg_ClsR_posX[rocketIndex] = sourceX
set udg_ClsR_posY[rocketIndex] = sourceY
set udg_ClsR_posZ[rocketIndex] = sourceZ
set udg_ClsR_Caster[rocketIndex] = udg_ClsR_Caster[casterIndex]
set udg_ClsR_casterOwner[rocketIndex] = udg_ClsR_casterOwner[casterIndex]
set udg_ClsR_Level[rocketIndex] = udg_ClsR_Level[casterIndex]
// Set up rocket expiration timer
set udg_ClsR_realTimer[rocketIndex] = udg_ClsR_RocketsExpirationTime
// Stage 2 - Handle rockets movement
set udg_ClsR_Stage[rocketIndex] = 2
// Update launched rockets counter
set udg_ClsR_Counter[casterIndex] = udg_ClsR_Counter[casterIndex] - 1
endfunction
//---------------------------------------------------------------------------
// Clears any death unit targeted by the rockets.
function ClsR_onUnitDeath takes nothing returns boolean
local integer targetHandleID = GetHandleId(GetTriggerUnit())
if LoadInteger(udg_ClsR_Hashtable, targetHandleID, 0) > 0 then
call DestroyEffect(LoadEffectHandle(udg_ClsR_Hashtable, targetHandleID, 0))
call FlushChildHashtable(udg_ClsR_Hashtable, targetHandleID)
endif
return false
endfunction
//---------------------------------------------------------------------------
// Loops all active instances.
function ClsR_Periodic takes nothing returns nothing
// Declare locals
local real sourceX
local real sourceY
local real sourceZ
local real targetX
local real targetY
local real targetZ
local real tempX
local real tempY
local real tempZ
local real dist
local real dist3D
local real angleZ
local real anglePointsZ
local unit enumUnit
local integer casterHandleID
local integer index = 0
// Loop all instances
loop
set index = udg_ClsR_Next[index]
exitwhen index == 0
// Stage 1: Handle spell channeling, launches x rockets each seconds
if udg_ClsR_Stage[index] == 1 then
if ClsR_IsUnitAlive(udg_ClsR_Caster[index]) then
if ClsR_IsUnitChanneling(udg_ClsR_Caster[index]) and udg_ClsR_Counter[index] != 0 then
// Update wave interval timer
set udg_ClsR_realTimer[index] = udg_ClsR_realTimer[index] - ClsR_FRAME_UPDATE
if udg_ClsR_realTimer[index] <= 0 then
// Update rocket launch interval timer
set udg_ClsR_realTimer2[index] = udg_ClsR_realTimer2[index] + ClsR_FRAME_UPDATE
if udg_ClsR_realTimer2[index] >= udg_ClsR_RocketsInterval then
// Launch rocket
call ClsR_LaunchRocket(index)
// Reset rocket launch timer
set udg_ClsR_realTimer2[index] = 0
set udg_ClsR_Counter2[index] = udg_ClsR_Counter2[index] + 1
if udg_ClsR_Counter2[index] >= udg_ClsR_RocketsPerWave then
// Reset wave timer
set udg_ClsR_realTimer[index] = udg_ClsR_DelayPerWave
// Reset rocket-per-wave counter
set udg_ClsR_Counter2[index] = 0
endif
endif
endif
else
// --- When caster finished channeling or all rockets has launched
set casterHandleID = GetHandleId(udg_ClsR_Caster[index])
// Unmark caster from 'channeling' state
call SaveBoolean(udg_ClsR_Hashtable, casterHandleID, 1, false)
if not LoadBoolean(udg_ClsR_Hashtable, casterHandleID, 0) and ClsR_IsUnitChanneling(udg_ClsR_Caster[index]) and udg_ClsR_Counter[index] == 0 then
call IssueImmediateOrderById(udg_ClsR_Caster[index], 851972)
else
call SaveBoolean(udg_ClsR_Hashtable, casterHandleID, 0, false)
endif
call ClsR_Destroy(index)
endif
else
// --- When caster died
// Unmark caster from 'channeling' state
call SaveBoolean(udg_ClsR_Hashtable, GetHandleId(udg_ClsR_Caster[index]), 1, false)
call ClsR_Destroy(index)
endif
// Stage 2: Handle rockets, determines movement
elseif udg_ClsR_Stage[index] == 2 then
if udg_ClsR_realTimer[index] > 0 then
// Update rocket expiration timer
set udg_ClsR_realTimer[index] = udg_ClsR_realTimer[index] - ClsR_FRAME_UPDATE
// Copy 3D position to local reference variables
set sourceX = udg_ClsR_posX[index]
set sourceY = udg_ClsR_posY[index]
set sourceZ = udg_ClsR_posZ[index]
// Check if there's a target unit to pursue
if udg_ClsR_Target[index] != null and ClsR_IsUnitAlive(udg_ClsR_Target[index]) then
set targetX = GetUnitX(udg_ClsR_Target[index])
set targetY = GetUnitY(udg_ClsR_Target[index])
set targetZ = ClsR_GetUnitZAlt(udg_ClsR_Target[index], targetX, targetY)
// Save target last known position
set udg_ClsR_lastX[index] = targetX
set udg_ClsR_lastY[index] = targetY
set udg_ClsR_lastZ[index] = targetZ
else
// If target has disappear, use the last known position
set targetX = udg_ClsR_lastX[index]
set targetY = udg_ClsR_lastY[index]
set targetZ = udg_ClsR_lastZ[index]
endif
// Calculate difference
set tempX = targetX - sourceX
set tempY = targetY - sourceY
set tempZ = targetZ - sourceZ
if udg_ClsR_Target[index] != null and ClsR_IsUnitAlive(udg_ClsR_Target[index]) and ClsR_GetDistance3D(tempX, tempY, tempZ)-udg_ClsR_RocketsCollisionSize <= udg_ClsR_targetCollision[index] then
// --- When target is alive and is in collision range
call ClsR_TerminateRocket(index)
else
set dist = ClsR_GetDistance2D(tempX, tempY)
set angleZ = ClsR_AngleZ(tempX, tempY)
set anglePointsZ = ClsR_AnglePointsZ(dist, tempZ)
// Get new 3D position
set targetX = sourceX + udg_ClsR_RocketsSpeedBase[udg_ClsR_Level[index]] * Cos(udg_ClsR_Roll[index]) * Cos(udg_ClsR_Pitch[index])
set targetY = sourceY + udg_ClsR_RocketsSpeedBase[udg_ClsR_Level[index]] * Sin(udg_ClsR_Roll[index]) * Cos(udg_ClsR_Pitch[index])
set targetZ = sourceZ + udg_ClsR_RocketsSpeedBase[udg_ClsR_Level[index]] * Sin(udg_ClsR_Pitch[index])
set udg_ClsR_posX[index] = targetX + udg_ClsR_RocketsTurnAcceleration[udg_ClsR_Level[index]] * Cos(angleZ) * Cos(anglePointsZ)
set udg_ClsR_posY[index] = targetY + udg_ClsR_RocketsTurnAcceleration[udg_ClsR_Level[index]] * Sin(angleZ) * Cos(anglePointsZ)
set udg_ClsR_posZ[index] = targetZ + udg_ClsR_RocketsTurnAcceleration[udg_ClsR_Level[index]] * Sin(anglePointsZ)
// Calculate difference
set tempX = udg_ClsR_posX[index] - sourceX
set tempY = udg_ClsR_posY[index] - sourceY
set tempZ = udg_ClsR_posZ[index] - sourceZ
// Get new 3D angle
call ClsR_GetOrientation3D(tempX, tempY, tempZ)
set udg_ClsR_Roll[index] = udg_ClsR_OrientationRoll
set udg_ClsR_Pitch[index] = ClsR_AnglePointsZ(ClsR_GetDistance2D(tempX, tempY), tempZ)
// Get bounded coordinates
set udg_ClsR_posX[0] = ClsR_BoundX(udg_ClsR_posX[index])
set udg_ClsR_posY[0] = ClsR_BoundX(udg_ClsR_posY[index])
// Apply new position
call BlzSetSpecialEffectPosition(udg_ClsR_rocketFx[index], udg_ClsR_posX[0], udg_ClsR_posY[0], udg_ClsR_posZ[index])
// Apply new orientation
call BlzSetSpecialEffectOrientation(udg_ClsR_rocketFx[index], udg_ClsR_Roll[index], udg_ClsR_lastPitch[index], udg_ClsR_OrientationYaw)
call BlzSetSpecialEffectPitch(udg_ClsR_rocketFx[index], udg_ClsR_OrientationPitch)
set udg_ClsR_lastPitch[index] = udg_ClsR_OrientationPitch
if BlzGetLocalSpecialEffectZ(udg_ClsR_rocketFx[index]) - ClsR_GetTerrainZ(udg_ClsR_posX[0], udg_ClsR_posY[0]) <= udg_ClsR_RocketsCrashHeight then
// --- When rocket touch the ground
call ClsR_TerminateRocket(index)
elseif not udg_ClsR_HitTargetOnly then
// Enumerate all units near the rocket
call GroupEnumUnitsInRange(udg_ClsR_tempGroup, udg_ClsR_posX[index], udg_ClsR_posY[index], udg_ClsR_RocketsCollisionSize+ClsR_COLLISION_SCAN_RANGE, null)
loop
set enumUnit = FirstOfGroup(udg_ClsR_tempGroup)
exitwhen enumUnit == null
// Check if the rocket has hit a unit
if ClsR_GetDistanceToUnit3D(udg_ClsR_posX[index], udg_ClsR_posY[index], udg_ClsR_posZ[index], enumUnit)-udg_ClsR_RocketsCollisionSize <= ClsR_GetUnitCollisionRadius(enumUnit) then
if enumUnit != udg_ClsR_Caster[index] and ClsR_IsUnitAlive(enumUnit) and ClsR_CollisionFilter(enumUnit, udg_ClsR_casterOwner[index]) then
// --- Exclude caster and dead units
// --- When the rocket collide with filtered units
call ClsR_TerminateRocket(index)
set enumUnit = null
exitwhen true
endif
endif
call GroupRemoveUnit(udg_ClsR_tempGroup, enumUnit)
endloop
call GroupClear(udg_ClsR_tempGroup)
endif
endif
else
// --- When rocket expiration timer finished
call ClsR_TerminateRocket(index)
endif
endif
endloop
endfunction
//---------------------------------------------------------------------------
// Handles any unit that is starting the effect of the spell.
function ClsR_onEffect takes nothing returns boolean
// Declare locals
local integer casterIndex
local integer casterHandleID
local unit targetUnit
local real targetX
local real targetY
if GetSpellAbilityId() == udg_ClsR_Ability then
set udg_ClsR_Caster[0] = GetTriggerUnit()
set casterIndex = ClsR_Create()
set casterHandleID = GetHandleId(udg_ClsR_Caster[0])
call SaveBoolean(udg_ClsR_Hashtable, casterHandleID, 0, false)
// Mark caster as 'channeling'
call SaveBoolean(udg_ClsR_Hashtable, casterHandleID, 1, true)
// Save index to end this instance when the caster starts another one
call SaveInteger(udg_ClsR_Hashtable, casterHandleID, 1, casterIndex)
set udg_ClsR_Caster[casterIndex] = udg_ClsR_Caster[0]
set udg_ClsR_casterOwner[casterIndex] = GetTriggerPlayer()
set udg_ClsR_Level[casterIndex] = GetUnitAbilityLevel(udg_ClsR_Caster[casterIndex], udg_ClsR_Ability)
set targetUnit = GetSpellTargetUnit()
// Note: When target type in Object Editor is set to "Instant
// (No Target)", GetSpellTargetUnit returns the caster.
if targetUnit == udg_ClsR_Caster[0] then
set udg_ClsR_targetType[casterIndex] = 0
set udg_ClsR_posX[casterIndex] = GetUnitX(udg_ClsR_Caster[0])
set udg_ClsR_posY[casterIndex] = GetUnitY(udg_ClsR_Caster[0])
elseif targetUnit != null then
set udg_ClsR_targetType[casterIndex] = 1
set udg_ClsR_Target[casterIndex] = targetUnit
set udg_ClsR_targetCollision[casterIndex] = ClsR_GetUnitCollisionRadius(targetUnit)
set udg_ClsR_posX[casterIndex] = GetUnitX(targetUnit)
set udg_ClsR_posY[casterIndex] = GetUnitY(targetUnit)
set udg_ClsR_posZ[casterIndex] = ClsR_GetUnitZAlt(targetUnit, udg_ClsR_posX[casterIndex], udg_ClsR_posY[casterIndex])
else
set udg_ClsR_targetType[casterIndex] = 2
set udg_ClsR_Target[casterIndex] = null
set udg_ClsR_posX[casterIndex] = GetSpellTargetX()
set udg_ClsR_posY[casterIndex] = GetSpellTargetY()
set udg_ClsR_posZ[casterIndex] = ClsR_GetTerrainZ(udg_ClsR_posX[casterIndex], udg_ClsR_posY[casterIndex])
endif
set targetUnit = null
// Set up wave interval timer
set udg_ClsR_realTimer[casterIndex] = udg_ClsR_FirstWaveDelay - ClsR_FRAME_UPDATE
// Set up rocket launch interval timer
set udg_ClsR_realTimer2[casterIndex] = ClsR_FRAME_UPDATE
if udg_ClsR_CountRockets then
// Set up launched rockets counter
set udg_ClsR_Counter[casterIndex] = udg_ClsR_RocketsCount[udg_ClsR_Level[casterIndex]]
else
// Give a signal not to count launched rockets
set udg_ClsR_Counter[casterIndex] = -1
endif
// Set up rocket-per-wave counter
set udg_ClsR_Counter2[casterIndex] = 0
// Stage 1 - Handle spell channeling, launches rockets
set udg_ClsR_Stage[casterIndex] = 1
if udg_ClsR_Prev[casterIndex] == 0 then
// --- When no instances ever activated
call TimerStart(udg_ClsR_Timer, ClsR_FRAME_UPDATE, true, function ClsR_Periodic)
endif
endif
return false
endfunction
//---------------------------------------------------------------------------
// Handles the spell before it is casted.
function ClsR_SpellPrecast takes integer casterHandleID returns nothing
// End previous spell channeling instance
set udg_ClsR_Counter[LoadInteger(udg_ClsR_Hashtable, casterHandleID, 1)] = 0
// Mark unit before it starts casting the spell
// Note: Since the caster will be ordered to 'stop' when launched rockets
// reaches a limit, this one will helps ignore that action when the
// caster start another instance.
call SaveBoolean(udg_ClsR_Hashtable, casterHandleID, 0, true)
endfunction
//---------------------------------------------------------------------------
// Handles any unit that is casting the spell (No target).
function ClsR_onCast takes nothing returns boolean
// Declare locals
local integer casterHandleID
if GetSpellAbilityId() == udg_ClsR_Ability then
set casterHandleID = GetHandleId(GetTriggerUnit())
// Check if the caster is already channeling the spell
if LoadBoolean(udg_ClsR_Hashtable, casterHandleID, 1) then
call ClsR_SpellPrecast(casterHandleID)
endif
endif
return false
endfunction
//---------------------------------------------------------------------------
// Handles any unit that is casting the spell (Unit or point target).
function ClsR_onOrder takes nothing returns boolean
// Declare locals
local integer casterHandleID
if GetUnitCurrentOrder(GetTriggerUnit()) == udg_ClsR_AbilityOrder then
// Note: This function is also executed when a caster learn the spell
// while channeling.
set casterHandleID = GetHandleId(GetTriggerUnit())
// Check if the caster is already channeling the spell
if LoadBoolean(udg_ClsR_Hashtable, casterHandleID, 1) then
call ClsR_SpellPrecast(casterHandleID)
endif
endif
return false
endfunction
//---------------------------------------------------------------------------
// Initializes spell properties.
function ClsR_Initialize takes nothing returns nothing
local integer i = 0
local trigger trig = CreateTrigger()
local trigger trig2 = CreateTrigger()
local rect map
if ClsR_BOUNDS_ENTIRE_MAP then
set map = GetWorldBounds()
else
set map = bj_mapInitialPlayableArea
endif
set udg_ClsR_mapBorder[1] = GetRectMaxX(map)
set udg_ClsR_mapBorder[2] = GetRectMaxY(map)
set udg_ClsR_mapBorder[3] = GetRectMinX(map)
set udg_ClsR_mapBorder[4] = GetRectMinY(map)
call RemoveRect(map)
// Convert facing and pitch angle from degree to radian
set udg_ClsR_RocketsFacingWidth = udg_ClsR_RocketsFacingWidth / 2.
set udg_ClsR_RocketsMaxFacingVariation = (udg_ClsR_RocketsMaxFacingVariation + udg_ClsR_RocketsFacingWidth) * ClsR_DEGTORAD
set udg_ClsR_RocketsMinFacingVariation = (udg_ClsR_RocketsMinFacingVariation + udg_ClsR_RocketsFacingWidth) * ClsR_DEGTORAD
set udg_ClsR_RocketsMaxPitchVariation = udg_ClsR_RocketsMaxPitchVariation * ClsR_DEGTORAD
set udg_ClsR_RocketsMinPitchVariation = udg_ClsR_RocketsMinPitchVariation * ClsR_DEGTORAD
set udg_ClsR_RocketsInterval = 1 / I2R(udg_ClsR_RocketsPerSecond)
// Initialize additional properties
loop
set i = i + 1
exitwhen i > udg_ClsR_AbilityLevels
set udg_ClsR_RocketsSpeedBase[i] = udg_ClsR_RocketsSpeedBase[i] * ClsR_FRAME_UPDATE
set udg_ClsR_RocketsTurnAcceleration[i] = udg_ClsR_RocketsTurnAcceleration[i] * ClsR_FRAME_UPDATE
set udg_ClsR_areaOfTarget[i] = (udg_ClsR_AreaOfEffect[i] - udg_ClsR_RocketsDamageRange[i]) / 2.
endloop
// Initialize terrain z finder
if udg_ClsR_ZLocator == null then
set udg_ClsR_ZLocator = Location(0, 0)
endif
// Initialize spell hashtable
if udg_ClsR_Hashtable == null then
set udg_ClsR_Hashtable = InitHashtable()
endif
// Initialize iteration timer
if udg_ClsR_Timer == null then
set udg_ClsR_Timer = CreateTimer()
endif
// Initialize dummy group
if udg_ClsR_tempGroup == null then
set udg_ClsR_tempGroup = CreateGroup()
endif
if ClsR_PRELOAD_SPELL then
// Preload files
call Preload(udg_ClsR_RocketsModel)
endif
if udg_ClsR_NoTarget then
// Register a trigger for when a unit cast the spell
call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_SPELL_CAST)
call TriggerAddCondition(trig, Condition(function ClsR_onCast))
else
// Register a trigger for when a unit is ordered to cast the spell
call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
call TriggerAddCondition(trig, Condition(function ClsR_onOrder))
endif
// Register a trigger for when a unit is dying
call TriggerRegisterAnyUnitEventBJ(trig2, EVENT_PLAYER_UNIT_DEATH)
call TriggerAddCondition(trig2, Condition(function ClsR_onUnitDeath))
// Null references
set trig = null
set trig2 = null
endfunction
//===========================================================================
// This function automatically runs on map initialization.
function InitTrig_Cluster_Rockets takes nothing returns nothing
set gg_trg_Cluster_Rockets = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(gg_trg_Cluster_Rockets, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(gg_trg_Cluster_Rockets, Condition(function ClsR_onEffect))
endfunction
//***************************************************************************
//*
//* TestHelper v1.0.1
//*
//***************************************************************************
//***************************************************************************
//*
//* Additional Configuration
//*
constant function z_SpawnStartCountdown takes nothing returns real
return 1.00
endfunction
constant function z_RedSpawnInterval takes nothing returns real
return 20.00
endfunction
constant function z_BlueSpawnInterval takes nothing returns real
return 20.00
endfunction
constant function z_CreepsSpawnInterval takes nothing returns real
return 30.00
endfunction
constant function z_DocumentationMode takes nothing returns boolean
return false
endfunction
//*
//* End of Configuration
//*
//===========================================================================
constant function z_PlayerRed takes nothing returns player
return Player(0)
endfunction
constant function z_PlayerBlue takes nothing returns player
return Player(1)
endfunction
constant function z_PlayerCreeps takes nothing returns player
return Player(PLAYER_NEUTRAL_AGGRESSIVE)
endfunction
function z_redSpawn takes nothing returns nothing
local integer i = 0
local unit u
loop
set i = i + 1
exitwhen udg_z_RedUnitType[i] == null
set u = CreateUnit(z_PlayerRed(), udg_z_RedUnitType[i], GetLocationX(udg_z_RedSpawnPoint), GetLocationY(udg_z_RedSpawnPoint), GetRandomReal(0, 360))
call IssuePointOrderById(u, 851983, GetLocationX(udg_z_BlueSpawnPoint), GetLocationY(udg_z_BlueSpawnPoint))
call SetPlayerState(z_PlayerRed(), PLAYER_STATE_RESOURCE_FOOD_USED, 0)
endloop
set u = null
endfunction
function z_blueSpawn takes nothing returns nothing
local integer i = 0
local unit u
loop
set i = i + 1
exitwhen udg_z_BlueUnitType[i] == null
set u = CreateUnit(z_PlayerBlue(), udg_z_BlueUnitType[i], GetLocationX(udg_z_BlueSpawnPoint), GetLocationY(udg_z_BlueSpawnPoint), GetRandomReal(0, 360))
call IssuePointOrderById(u, 851983, GetLocationX(udg_z_RedSpawnPoint), GetLocationY(udg_z_RedSpawnPoint))
call SetPlayerState(z_PlayerBlue(), PLAYER_STATE_RESOURCE_FOOD_USED, 0)
endloop
set u = null
endfunction
function z_creepsSpawn takes nothing returns nothing
local integer i = 0
local integer i2
local integer i3 = 0
local unit u
loop
set i = i + 1
exitwhen udg_z_CreepsSpawnPoint[i] == null
set i2 = 0
loop
set i2 = i2 + 1
exitwhen i2 > udg_z_CreepsSpawnPointTypes[i]
set i3 = i3 + 1
set u = CreateUnit(z_PlayerCreeps(), udg_z_CreepsUnitType[i3], GetLocationX(udg_z_CreepsSpawnPoint[i]), GetLocationY(udg_z_CreepsSpawnPoint[i]), GetRandomReal(0, 360))
call IssuePointOrderById(u, 851983, GetLocationX(udg_z_CreepsAttackPoint), GetLocationY(udg_z_CreepsAttackPoint))
endloop
endloop
set u = null
endfunction
function z_onGameStart takes nothing returns boolean
call FogEnable(udg_z_EnableFogOfWar)
call FogMaskEnable(udg_z_EnableBlackMask)
call SetFloatGameState(GAME_STATE_TIME_OF_DAY, udg_z_StartingTimeOfDay)
call DestroyTrigger(GetTriggeringTrigger())
return false
endfunction
function z_onSpawnStart takes nothing returns boolean
local timer redTimer
local timer blueTimer
local timer creepsTimer
if udg_z_SpawnUnits then
set redTimer = CreateTimer()
set blueTimer = CreateTimer()
set creepsTimer = CreateTimer()
call z_redSpawn()
call z_blueSpawn()
call z_creepsSpawn()
call TimerStart(redTimer, z_RedSpawnInterval(), true, function z_redSpawn)
call TimerStart(blueTimer, z_BlueSpawnInterval(), true, function z_blueSpawn)
call TimerStart(creepsTimer, z_CreepsSpawnInterval(), true, function z_creepsSpawn)
set redTimer = null
set blueTimer = null
set creepsTimer = null
endif
call DestroyTrigger(GetTriggeringTrigger())
return false
endfunction
function z_onHeroRevive takes nothing returns boolean
local unit hero = GetTriggerUnit()
local location l
if IsUnitType(hero, UNIT_TYPE_HERO) then
set l = GetStartLocationLoc(GetPlayerStartLocation(GetTriggerPlayer()))
call ReviveHeroLoc(hero, l, true)
call RemoveLocation(l)
endif
set hero = null
return false
endfunction
function z_onRedFinish takes nothing returns boolean
local unit u = GetTriggerUnit()
if not IsUnitType(u, UNIT_TYPE_HERO) and GetOwningPlayer(u) == z_PlayerRed() then
call RemoveUnit(u)
endif
set u = null
return false
endfunction
function z_onBlueFinish takes nothing returns boolean
local unit u = GetTriggerUnit()
if not IsUnitType(u, UNIT_TYPE_HERO) and GetOwningPlayer(u) == z_PlayerBlue() then
call RemoveUnit(u)
endif
set u = null
return false
endfunction
//===========================================================================
function InitTrig_TestHelper takes nothing returns nothing
local trigger gameStartTrig = CreateTrigger()
local trigger spawnStartTrig = CreateTrigger()
local trigger redFinishTrig = CreateTrigger()
local trigger blueFinishTrig = CreateTrigger()
local trigger heroReviveTrig = CreateTrigger()
call TriggerRegisterTimerEvent(gameStartTrig, 0, false)
call TriggerAddCondition(gameStartTrig, Condition(function z_onGameStart))
if not z_DocumentationMode() then
call TriggerRegisterTimerEvent(spawnStartTrig, z_SpawnStartCountdown(), false)
call TriggerAddCondition(spawnStartTrig, Condition(function z_onSpawnStart))
call TriggerRegisterEnterRectSimple(redFinishTrig, gg_rct_Blue_Spawn)
call TriggerAddCondition(redFinishTrig, Condition(function z_onRedFinish))
call TriggerRegisterEnterRectSimple(blueFinishTrig, gg_rct_Red_Spawn)
call TriggerAddCondition(blueFinishTrig, Condition(function z_onBlueFinish))
endif
call TriggerRegisterAnyUnitEventBJ(heroReviveTrig, EVENT_PLAYER_UNIT_DEATH)
call TriggerAddCondition(heroReviveTrig, Condition(function z_onHeroRevive))
set gameStartTrig = null
set spawnStartTrig = null
set redFinishTrig = null
set blueFinishTrig = null
set heroReviveTrig = null
endfunction