//TESH.scrollpos=0
//TESH.alwaysfold=0
function Sim_Error takes player ForPlayer, string msg returns nothing
local sound error = CreateSoundFromLabel("InterfaceError",false,false,false,10,10)
if (GetLocalPlayer() == ForPlayer) then
if (msg!="") and (msg!=null) then
call ClearTextMessages()
call DisplayTimedTextToPlayer(ForPlayer, 0.52, -1.00, 2.00, "|cffffcc00"+msg+"|r" )
endif
call StartSound( error )
endif
call KillSoundWhenDone( error)
set error=null
endfunction
Name | Type | is_array | initial_value |
AI_Move_Integer | integer | Yes | |
AI_Move_Region | rect | Yes | |
Arena | integer | No | |
ArenaVoteTimer | timer | No | |
AssistGroup | force | Yes | |
Assists | integer | Yes | |
Attacker | player | Yes | |
Boolean | boolean | No | |
BooleanTeams | boolean | No | |
BooleanTimeout | boolean | No | |
Boomerang_Angle | real | Yes | |
Boomerang_Distance | real | Yes | |
Boomerang_HitGroup | group | Yes | |
Boomerang_Integers | integer | Yes | |
Boomerang_Missile | unit | Yes | |
Boomerang_Unit | unit | Yes | |
Boomerang_X | real | Yes | |
Boomerang_Y | real | Yes | |
BT_Group | group | No | |
BT_Illusion | unit | Yes | |
BT_Integer | integer | Yes | |
BT_Unit | unit | Yes | |
CameraPoint | location | No | |
CB_Timer | timer | Yes | |
ChannelLockdown_Group | group | No | |
ChannelLockdown_Integers | integer | Yes | |
ChannelLockdown_Target | unit | Yes | |
ChannelLockdown_Unit | unit | Yes | |
CHM_Group | group | No | |
CHM_Integers | integer | Yes | |
CHM_Missile | unit | Yes | |
CHM_Target | unit | Yes | |
CHM_Unit | unit | Yes | |
Color | playercolor | Yes | |
ColorCodes | string | Yes | |
ColorString | string | No | |
CRC_Angle | real | Yes | |
CRC_Group | group | No | |
CRC_Integers | integer | Yes | |
CRC_Missile | unit | Yes | |
CRC_Unit | unit | Yes | |
CurrentArenaCinematic | integer | No | |
CurrentAttack | abilcode | Yes | |
DamageDealt | real | Yes | |
DamageTaken | real | Yes | |
Dart1_Angle | real | Yes | |
Dart1_Integer | integer | Yes | |
Dart1_Missile | unit | Yes | |
Dart1_Unit | unit | Yes | |
Dart2_Integer | integer | Yes | |
Dart2_SFX | integer | Yes | |
Dart2_Target | unit | Yes | |
Dart2_Time | real | Yes | |
Dart2_Unit | unit | Yes | |
Dart2_X | real | Yes | |
Dart2_Y | real | Yes | |
Daytime | boolean | No | |
Deaths | integer | Yes | |
EndGame | boolean | No | |
Fade_Group | group | No | |
Fade_Integers | integer | Yes | |
Fade_Real | real | Yes | |
Fade_Unit | unit | Yes | |
FFAFlag | item | No | |
FFAFlagDestination | unit | No | |
FFAFlagDropTimer | timer | No | |
FFAFlagSpawn | location | No | |
Flag | item | Yes | |
FlagDropTimer | timer | Yes | |
FlagHide | boolean | Yes | |
FlagPoints | location | Yes | |
FlagRoom | unit | Yes | |
GameMode | integer | No | |
GameSettings | unit | No | |
GameTimer | timer | No | |
GameTimerWindow | timerdialog | No | |
GameTimeSet | integer | No | |
GW_CastPoint | location | Yes | |
GW_Group | group | No | |
GW_HitGroup | group | Yes | |
GW_Integers | integer | Yes | |
GW_Period | integer | Yes | |
GW_TargetPoint | location | Yes | |
GW_Unit | unit | Yes | |
Hawk_Boolean | boolean | Yes | |
Hawk_BooleanTarget | boolean | Yes | |
Hawk_Group | group | No | |
Hawk_Integers | integer | Yes | |
Hawk_Missile | unit | Yes | |
Hawk_Size | real | Yes | |
Hawk_Target | unit | Yes | |
Hawk_TargetPoint | location | Yes | |
Hawk_Unit | unit | Yes | |
Hero | unit | Yes | |
Hero_Icons | imagefile | Yes | |
HeroPicker | unit | Yes | |
HeroRespawn | integer | Yes | |
HM_Group | group | No | |
HM_Integers | integer | Yes | |
HM_Missile | unit | Yes | |
HM_Target | unit | Yes | |
HM_Unit | unit | Yes | |
Host | player | No | |
Integer1 | integer | No | |
Integer2 | integer | No | |
Integer3 | integer | No | |
IssueOrder | unit | No | |
JD_Angle | real | Yes | |
JD_Distances | real | Yes | |
JD_Group | group | No | |
JD_Integers | integer | Yes | |
JD_JumpHigh | real | Yes | |
JD_PointPosition | location | Yes | |
JD_PointTarget | location | Yes | |
JD_RealTimer | real | Yes | |
JD_SFX | effect | Yes | |
JD_SpeedUnits | real | Yes | |
JD_TempPoint | location | Yes | |
JD_Unit | unit | Yes | |
JDA_TargetPoint | location | No | |
JDA_Unit | unit | No | |
KBA_Caster | unit | No | |
KBA_DestroyTrees | boolean | No | |
KBA_DistancePerLevel | real | No | |
KBA_Level | integer | No | |
KBA_Speed | real | No | |
KBA_StartingPosition | location | No | |
KBA_TargetUnit | unit | No | |
Kills | integer | Yes | |
KnockbackImmune | group | No | |
KunoichiRewindGroup | group | No | |
LeaverGroup | force | No | |
Lockdown_Castpoint | location | Yes | |
Lockdown_Group | group | No | |
Lockdown_Integers | integer | Yes | |
Lockdown_Lightning | lightning | Yes | |
Lockdown_SFXInteger | integer | Yes | |
Lockdown_Target | unit | Yes | |
Lockdown_Unit | unit | Yes | |
LoopInteger_MultiboardCreation | integervar | No | |
Mana | real | Yes | |
Multiboard | multiboard | No | |
MultiboardInfoRow | integer | Yes | |
MultiboardPlayerRow | integer | Yes | |
Net_Angle | real | Yes | |
Net_Integers | integer | Yes | |
Net_Unit | unit | Yes | |
Oni | unit | No | |
OniPlayer | player | No | |
PickingPhase | boolean | No | |
Player | player | No | |
PlayerDeaths | integer | Yes | |
PlayerKills | integer | Yes | |
PlayerRow | integer | Yes | |
PlayersPlaying | force | No | |
PlayerUnits | unit | Yes | |
RandomArenaBoolean | boolean | No | |
RandomHint | string | Yes | |
RandomSpawnIntegerFFA | integer | Yes | |
RandomSpawnIntegerTeam1 | integer | Yes | |
RandomSpawnIntegerTeam2 | integer | Yes | |
RandomSpawnPoint | location | Yes | |
RC_Angle | real | Yes | |
RC_Integers | integer | Yes | |
RC_Missile | unit | Yes | |
RC_Unit | unit | Yes | |
Real1 | real | No | |
Real2 | real | No | |
Real3 | real | No | |
Rematch_Boolean | boolean | No | |
Rematch_Timer | timer | No | |
Rematch_Vote | boolean | Yes | |
Rematch_Votes | integer | No | |
RematchTimer | timer | No | |
RematchTimerWindow | timerdialog | No | |
RespawnUnit | unit | Yes | |
ReviveTime | integer | No | |
Rewind_X | real | Yes | |
Rewind_Y | real | Yes | |
RFade_Integers | integer | Yes | |
RFade_Real | real | Yes | |
RFade_Unit | unit | Yes | |
SB_Angle1 | real | Yes | |
SB_Angle2 | real | Yes | |
SB_Fade | real | Yes | |
SB_HitGroup | group | Yes | |
SB_Integers | integer | Yes | |
SB_Missile1 | unit | Yes | |
SB_Missile2 | unit | Yes | |
SB_TempPoint | location | Yes | |
SB_Timer | real | Yes | |
SB_Unit | unit | Yes | |
Score | integer | Yes | |
ScoreToWin | integer | No | |
Shuriken_Angle | real | Yes | |
Shuriken_Group | group | No | |
Shuriken_Integers | integer | Yes | |
Shuriken_Owner | unit | Yes | |
Shuriken_Unit | unit | Yes | |
ShurikenSpawn_Angle | real | Yes | |
ShurikenSpawn_Group | group | No | |
ShurikenSpawn_Integers | integer | Yes | |
ShurikenSpawn_Unit | unit | Yes | |
SpawnPoint | group | Yes | |
Spell_Backstab_Atked | unit | Yes | |
Spell_Backstab_Atker | unit | Yes | |
Spell_Backstab_Trig | trigger | Yes | |
Spell_BlackCloud_Group | group | No | |
Spell_Bladespin_Group | group | No | |
Spell_EruptiveWake_Group | group | No | |
Spell_Evade_Group | group | No | |
Spell_Fleetfeet_Group | group | No | |
Spell_Harikiri_Group | group | No | |
Spell_Illusion_Force | force | No | |
Spell_LightningStrike_Group | group | No | |
Spell_Shadowstep_Unit | unit | Yes | |
Spell_SonicBoom_Group | group | No | |
Spell_Warp_Group | group | No | |
Spell_Windblow_Group | group | No | |
SpikeTrap_Integers | integer | Yes | |
SpikeTrap_Owner | unit | Yes | |
SpikeTrap_Unit | unit | Yes | |
SS_Integers | integer | Yes | |
SS_TempPoint | location | Yes | |
SS_Unit | unit | Yes | |
SS_Vision | unit | Yes | |
StaticShield_Group | group | No | |
StaticShield_Integers | integer | Yes | |
StaticShield_Target | unit | Yes | |
StaticShield_Unit | unit | Yes | |
String | string | Yes | |
Switch_Boolean | boolean | No | |
Switch_Timer | timer | No | |
Switch_Vote | boolean | Yes | |
Switch_Votes | integer | No | |
Switchers | player | Yes | |
Teams | force | Yes | |
TeamScore | integer | Yes | |
tempability | abilcode | No | |
TempGroup | group | No | |
TempGroup2 | group | No | |
tempInt | integer | No | |
tempItem | item | No | |
tempLoc | location | No | |
tempLoc2 | location | No | |
TempPlayerGroup | force | No | |
TempPlayerGroup2 | force | No | |
TempPoint1 | location | No | |
TempPoint2 | location | No | |
TempPoint3 | location | No | |
TempPoint4 | location | No | |
tempunitgroup | group | No | |
ToggleFade | boolean | Yes | |
ToggleHealthPotTarget | boolean | Yes | false |
ToggleLockCam | force | No | |
ToggleShadowstepSelect | boolean | Yes | false |
TP_Angle | real | Yes | |
TP_Group | group | No | |
TP_Integers | integer | Yes | |
TP_Missile | unit | Yes | |
TP_PointPosition | location | Yes | |
TP_PointTarget | location | Yes | |
TP_TempPoint | location | Yes | |
TP_Unit | unit | Yes | |
Unit | unit | No | |
UnitType | unitcode | Yes | |
Visibility | fogmodifier | Yes | |
Weapons | integer | No | |
Weather | weathereffect | No | |
WeatherInteger | integer | No | |
winner | integer | No | |
winnerflagger | unit | No |
//TESH.scrollpos=54
//TESH.alwaysfold=0
//******************************************************************************
//* *
//* K N O C K B A C K *
//* Actual Code *
//* v1.07 *
//* *
//* By: Rising_Dusk *
//* *
//******************************************************************************
library Knockback initializer Init needs TerrainPathability, GroupUtils, UnitIndexingUtils, LastOrder
globals
//*********************************************************
//* These are the configuration constants for the system
//*
//* EFFECT_ATTACH_POINT: Where on the unit the effect attaches
//* EFFECT_PATH_WATER: What special effect to attach over water
//* EFFECT_PATH_GROUND: What special effect to attach over ground
//* DEST_RADIUS: Radius around which destructs die
//* DEST_RADIUS_SQUARED: Radius squared around which destructs die
//* ADJACENT_RADIUS: Radius for knocking back adjacent units
//* ADJACENT_FACTOR: Factor for collision speed transfers
//* TIMER_INTERVAL: The interval for the timer that gets run
//* ISSUE_LAST_ORDER: A boolean to issue last orders or not
//*
private constant string EFFECT_ATTACH_POINT = "origin"
private constant string EFFECT_PATH_WATER = "MDX\\KnockbackWater.mdx"
private constant string EFFECT_PATH_GROUND = "MDX\\KnockbackDust.mdx"
private constant real DEST_RADIUS = 180.
private constant real DEST_RADIUS_SQUARED = DEST_RADIUS*DEST_RADIUS
private constant real ADJACENT_RADIUS = 180.
private constant real ADJACENT_FACTOR = 0.75
private constant real TIMER_INTERVAL = 0.05
private constant boolean ISSUE_LAST_ORDER = true
//*********************************************************
//* These are static constants used by the system and shouldn't be changed
//*
//* Timer: The timer that runs all of the effects for the spell
//* Counter: The counter for how many KB instances exist
//* HitIndex: Indexes for a given unit's knockback
//* Knockers: The array of all struct instances that exist
//* Entries: Counters for specific unit instances in system
//* ToClear: How many instances to remove on next run
//* DesBoolexpr: The check used for finding destructables
//* AdjBoolexpr: The check for picking adjacent units to knockback
//* DestRect: The rect used to check for destructables
//*
private timer Timer = CreateTimer()
private integer Counter = 0
private integer array HitIndex
private integer array Knockers
private integer array Entries
private integer array ToClear
private boolexpr DesBoolexpr = null
private boolexpr AdjBoolexpr = null
private rect DestRect = Rect(0,0,1,1)
//* Temporary variables used by the system
private real TempX = 0.
private real TempY = 0.
private unit TempUnit1 = null
private unit TempUnit2 = null
endglobals
//* Boolean for whether or not to display effects on a unit
private function ShowEffects takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_FLYING)
endfunction
//* Functions for the destructable destruction
private function KillDests_Check takes nothing returns boolean
local real x = GetDestructableX(GetFilterDestructable())
local real y = GetDestructableY(GetFilterDestructable())
return (TempX-x)*(TempX-x) + (TempY-y)*(TempY-y) <= DEST_RADIUS_SQUARED
endfunction
private function KillDests takes nothing returns nothing
if ( GetDestructableTypeId(GetEnumDestructable()) == 'ZTtc' or GetDestructableTypeId(GetEnumDestructable()) == 'ZTtw' ) then
call KillDestructable(GetEnumDestructable())
endif
endfunction
//* Functions for knocking back adjacent units
private function KnockAdj_Check takes nothing returns boolean
return TempUnit2 != GetFilterUnit() and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(TempUnit1)) and IsUnitType(GetFilterUnit(), UNIT_TYPE_GROUND) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) and GetWidgetLife(GetFilterUnit()) > 0.405 and GetUnitAbilityLevel(GetFilterUnit(), 'Avul') <= 0
endfunction
//******************************************************************************
//* Some additional functions that can be used
function KnockbackStop takes unit targ returns boolean
local integer id = GetUnitId(targ)
set ToClear[id] = Entries[id]
return ToClear[id] > 0
endfunction
function IsKnockedBack takes unit targ returns boolean
return Entries[GetUnitId(targ)] > 0
endfunction
//* Struct for the system, I recommend leaving it alone
private struct knocker
unit Source = null
unit Target = null
group HitGroup = null
effect KBEffect = null
integer FXMode = 0
boolean KillDest = false
boolean KnockAdj = false
boolean ChainAdj = false
boolean ShowEff = false
real Decrement = 0.
real Displace = 0.
real CosA = 0.
real SinA = 0.
public method checkterrain takes knocker n returns integer
local integer i = 0
local real x = GetUnitX(n.Target)
local real y = GetUnitY(n.Target)
if IsTerrainPathingType(x, y, TERRAIN_PATHING_LAND) then
set i = 1
elseif IsTerrainPathingType(x, y, TERRAIN_PATHING_SHALLOW) then
set i = 2
endif
return i
endmethod
static method create takes unit source, unit targ, real angle, real disp, real dec, boolean killDestructables, boolean knockAdjacent, boolean chainAdjacent returns knocker
local knocker n = knocker.allocate()
set n.Target = targ
set n.Source = source
set n.FXMode = n.checkterrain(n)
set n.HitGroup = NewGroup()
set n.KillDest = killDestructables
set n.KnockAdj = knockAdjacent
set n.ChainAdj = chainAdjacent
set n.ShowEff = ShowEffects(targ)
set n.Decrement = dec
set n.Displace = disp
set n.CosA = Cos(angle)
set n.SinA = Sin(angle)
if n.ShowEff then
if n.FXMode == 1 then
set n.KBEffect = AddSpecialEffectTarget(EFFECT_PATH_GROUND, n.Target, EFFECT_ATTACH_POINT)
elseif n.FXMode == 2 then
set n.KBEffect = AddSpecialEffectTarget(EFFECT_PATH_WATER, n.Target, EFFECT_ATTACH_POINT)
debug else
debug call BJDebugMsg(SCOPE_PREFIX+" Error (On Create): Unknown Terrain Type")
endif
endif
return n
endmethod
private method onDestroy takes nothing returns nothing
local integer id = GetUnitId(this.Target)
set Entries[id] = Entries[id] - 1
if GetWidgetLife(this.Target) > 0.405 and Entries[id] <= 0 and ISSUE_LAST_ORDER then
//* Issue last order if activated
call IssueLastOrder(this.Target)
endif
if this.ShowEff then
//* Destroy effect if it exists
call DestroyEffect(this.KBEffect)
endif
call ReleaseGroup(this.HitGroup)
endmethod
endstruct
private function Update takes nothing returns nothing
local unit u = null
local unit s = null
local rect r = null
local knocker n = 0
local knocker m = 0
local integer i = Counter - 1
local integer j = 0
local integer mode = 0
local integer id = 0
local real xi = 0.
local real yi = 0.
local real xf = 0.
local real yf = 0.
loop
exitwhen i < 0
set n = Knockers[i]
set u = n.Target
set mode = n.FXMode
set id = GetUnitId(u)
set xi = GetUnitX(u)
set yi = GetUnitY(u)
if n.Displace <= 0 or ToClear[id] > 0 then
//* Clean up the knockback when it is over
if ToClear[id] > 0 then
set ToClear[id] = ToClear[id] - 1
endif
call n.destroy()
set Counter = Counter - 1
if Counter < 0 then
call PauseTimer(Timer)
set Counter = 0
else
set Knockers[i] = Knockers[Counter]
endif
else
//* Propagate the knockback in space and time
set xf = xi + n.Displace*n.CosA
set yf = yi + n.Displace*n.SinA
call SetUnitPosition(u, xf, yf)
set n.FXMode = n.checkterrain(n)
//* Modify the special effect if necessary
if n.ShowEff then
if n.FXMode == 1 and mode == 2 then
call DestroyEffect(n.KBEffect)
set n.KBEffect = AddSpecialEffectTarget(EFFECT_PATH_GROUND, n.Target, EFFECT_ATTACH_POINT)
elseif n.FXMode == 2 and mode == 1 then
call DestroyEffect(n.KBEffect)
set n.KBEffect = AddSpecialEffectTarget(EFFECT_PATH_WATER, n.Target, EFFECT_ATTACH_POINT)
debug elseif n.FXMode == 0 then
debug call BJDebugMsg(SCOPE_PREFIX+" Error (In Update): Unknown Terrain Type")
endif
endif
//* Decrement displacement left to go
set n.Displace = n.Displace - n.Decrement
//* Destroy destructables if desired
if n.KillDest then
set TempX = GetUnitX(u)
set TempY = GetUnitY(u)
call MoveRectTo(DestRect, TempX, TempY)
call EnumDestructablesInRect(DestRect, DesBoolexpr, function KillDests)
endif
//* Knockback nearby units if desired
if n.KnockAdj then
set xi = GetUnitX(u)
set yi = GetUnitY(u)
set TempUnit1 = n.Source
set TempUnit2 = u
call GroupEnumUnitsInRange(ENUM_GROUP, xi, yi, ADJACENT_RADIUS, AdjBoolexpr)
loop
set s = FirstOfGroup(ENUM_GROUP)
exitwhen s == null
if not IsUnitInGroup(s, n.HitGroup) then
if ( IsUnitInGroup(s, udg_KnockbackImmune ) == false) then
if ( UnitHasBuffBJ(GetEnumUnit(), 'B000') == false ) then
set xf = GetUnitX(s)
set yf = GetUnitY(s)
call GroupAddUnit(n.HitGroup, s)
set m = knocker.create(n.Source, s, Atan2(yf-yi, xf-xi), n.Displace*ADJACENT_FACTOR, n.Decrement, n.KillDest, n.ChainAdj, n.ChainAdj)
call GroupAddUnit(m.HitGroup, u)
set Knockers[Counter] = m
set Counter = Counter + 1
endif
endif
endif
call GroupRemoveUnit(ENUM_GROUP, s)
endloop
endif
endif
set i = i - 1
endloop
set u = null
set s = null
endfunction
//******************************************************************************
//* How to knockback a unit
function KnockbackTarget takes unit source, unit targ, real angle, real startspeed, real decrement, boolean killDestructables, boolean knockAdjacent, boolean chainAdjacent returns boolean
local knocker n = 0
local integer id = GetUnitId(targ)
local boolean b = true
//* Protect users from themselves
if decrement <= 0. or startspeed <= 0. or targ == null then
debug call BJDebugMsg(SCOPE_PREFIX+" Error (On Call): Invalid Starting Conditions")
set b = false
else
//* Can't chain if you don't knockback adjacent units
if not knockAdjacent and chainAdjacent then
set chainAdjacent = false
endif
set n = knocker.create(source, targ, angle*bj_DEGTORAD, startspeed*TIMER_INTERVAL, decrement*TIMER_INTERVAL*TIMER_INTERVAL, killDestructables, knockAdjacent, chainAdjacent)
if Counter == 0 then
call TimerStart(Timer, TIMER_INTERVAL, true, function Update)
endif
set Entries[id] = Entries[id] + 1
set HitIndex[id] = Counter + 1
set Knockers[Counter] = n
set Counter = Counter + 1
endif
return b
endfunction
private function Init takes nothing returns nothing
call SetRect(DestRect, -DEST_RADIUS, -DEST_RADIUS, DEST_RADIUS, DEST_RADIUS)
set DesBoolexpr = Condition(function KillDests_Check)
set AdjBoolexpr = Condition(function KnockAdj_Check)
endfunction
endlibrary
//TESH.scrollpos=29
//TESH.alwaysfold=0
library TerrainPathability initializer Initialization
//******************************************************************************
//* BY: Rising_Dusk
//*
//* This can be used to detect the type of pathing a specific point of terrain
//* is, whether land, shallow water, or deep water. This type of detection
//* should have been easy to do using natives, but the IsTerrainPathable(...)
//* native is very counterintuitive and does not permit easy detection in one
//* call. For that reason, this library was developed.
//*
//* The system requires a dummy unit of some sort. There are no real
//* requirements upon the dummy unit, but it needs a non-zero movement speed.
//* More importantly than the dummy unit, though, it needs a custom windwalk
//* based unit ability with a 0.00 duration and no fade time. Both of those
//* raw id's (for the unit and windwalk dummy) need to be configured below.
//*
//* There is an objectmerger call available for those of you too lazy to build
//* your own windwalk based ability. Simply uncomment it below and save once,
//* then close and reopen your map and recomment the line.
//*
globals
constant integer TERRAIN_PATHING_DEEP = 1
constant integer TERRAIN_PATHING_SHALLOW = 2
constant integer TERRAIN_PATHING_LAND = 3
constant integer TERRAIN_PATHING_WALKABLE = 4
private unit Dummy = null
private constant integer DUMMY_UNIT_ID = 'hfoo'
private constant integer DUMMY_WINDWALK_ID = 'win&'
private constant player OWNING_PLAYER = Player(15)
//* These variables shouldn't be adjusted
private real WorldMinX = 0.
private real WorldMinY = 0.
endglobals
////! external ObjectMerger w3a ANwk win& anam "Collision Ability" ansf "" Owk3 1 0.0 Owk4 1 0 Owk2 1 0.0 Owk1 1 0.0 acdn 1 0.0 ahdu 1 0.0 adur 1 0. aher 0 amcs 1 0
function IsTerrainPathingType takes real x, real y, integer terrainPathingType returns boolean
local boolean b = false
if terrainPathingType == TERRAIN_PATHING_DEEP then
set b = not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
elseif terrainPathingType == TERRAIN_PATHING_SHALLOW then
set b = not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
elseif terrainPathingType == TERRAIN_PATHING_LAND then
set b = IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY)
elseif terrainPathingType == TERRAIN_PATHING_WALKABLE then
call SetUnitPosition(Dummy, x, y)
set b = GetUnitX(Dummy) == x and GetUnitY(Dummy) == y and not (not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY))
call SetUnitX(Dummy, WorldMinX)
call SetUnitY(Dummy, WorldMinY)
endif
return b
endfunction
private function Initialization takes nothing returns nothing
set WorldMinX = GetRectMinX(bj_mapInitialPlayableArea)
set WorldMinY = GetRectMinY(bj_mapInitialPlayableArea)
set Dummy = CreateUnit(OWNING_PLAYER, DUMMY_UNIT_ID, 0., 0., 0.)
call UnitAddAbility(Dummy, DUMMY_WINDWALK_ID)
call UnitAddAbility(Dummy, 'e000')
call IssueImmediateOrderById(Dummy, 852129)
call SetUnitX(Dummy, WorldMinX)
call SetUnitY(Dummy, WorldMinY)
endfunction
endlibrary
//TESH.scrollpos=88
//TESH.alwaysfold=0
library UnitIndexingUtils initializer Init
//******************************************************************************
//* BY: Rising_Dusk
//*
//* -: RED FLAVOR :-
//*
//* This can be used to index units with a unique integer for use with arrays
//* and things like that. This has a limit of 8191 indexes allocated at once in
//* terms of actually being usable in arrays. It won't give you an error if you
//* exceed 8191, but that is an unrealistic limit anyways.
//*
//* The red flavor uses a periodic timer to automatically recycle a unit's index
//* when UnitUserData goes to 0 for that unit (when it is removed from the game).
//* This can be slower than the blue flavor if you have many units on the map at
//* a time because it uses an O(n) search, but it automatically recycles indexes
//* for units that get removed from the game by decaying or RemoveUnit. It will
//* run the timer for COUNT_PER_ITERATION units before ending. The timer will
//* pick up where it left off on the next run-through.
//*
//* To use, call GetUnitId on a unit to retrieve its unique integer id. This
//* library allocates a unique index to a unit the instant it is created, which
//* means you can call GetUnitId immediately after creating the unit with no
//* worry.
//*
//* Function Listing --
//* function GetUnitId takes unit u returns integer
//*
globals
private constant real TIMER_PERIODICITY = 5.
private constant integer COUNT_PER_ITERATION = 64
private integer POSITION = 0
private integer array STACK
private unit array UNIT_STACK
private integer STACK_SIZE = 0
private integer ASSIGNED = 1
private integer MAX_INDEX = 0
endglobals
//Function to get the unit's unique integer id, inlines to getting its userdata
function GetUnitId takes unit u returns integer
return GetUnitUserData(u)
endfunction
//Filter for units to index
private function UnitFilter takes nothing returns boolean
return true
endfunction
private function Clear takes nothing returns nothing
local integer i = POSITION
loop
exitwhen (POSITION > MAX_INDEX or POSITION > i+COUNT_PER_ITERATION)
if UNIT_STACK[POSITION] != null and GetUnitUserData(UNIT_STACK[POSITION]) == 0 then
set STACK[STACK_SIZE] = POSITION
set STACK_SIZE = STACK_SIZE + 1
set UNIT_STACK[POSITION] = null
endif
set POSITION = POSITION + 1
endloop
if POSITION > MAX_INDEX then
set POSITION = 0
endif
endfunction
private function Add takes nothing returns boolean
local integer id = 0
if STACK_SIZE > 0 then
set STACK_SIZE = STACK_SIZE - 1
set id = STACK[STACK_SIZE]
else
set id = ASSIGNED
set ASSIGNED = ASSIGNED + 1
if ASSIGNED > MAX_INDEX then
set MAX_INDEX = ASSIGNED
endif
endif
call SetUnitUserData(GetFilterUnit(), id)
set UNIT_STACK[id] = GetFilterUnit()
return true
endfunction
private function GroupAdd takes nothing returns nothing
local integer id = 0
if STACK_SIZE > 0 then
set STACK_SIZE = STACK_SIZE - 1
set id = STACK[STACK_SIZE]
else
set id = ASSIGNED
set ASSIGNED = ASSIGNED + 1
if ASSIGNED > MAX_INDEX then
set MAX_INDEX = ASSIGNED
endif
endif
call SetUnitUserData(GetEnumUnit(), id)
set UNIT_STACK[id] = GetEnumUnit()
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
local region r = CreateRegion()
local group g = CreateGroup()
local integer i = 0
//Use a filterfunc so units are indexed immediately
call RegionAddRect(r, bj_mapInitialPlayableArea)
call TriggerRegisterEnterRegion(t, r, And(Condition(function UnitFilter), Condition(function Add)))
//Start the timer to recycle indexes
call TimerStart(CreateTimer(), TIMER_PERIODICITY, true, function Clear)
//Loop and group per player to grab all units, including those with locust
loop
exitwhen i > 15
call GroupEnumUnitsOfPlayer(g, Player(i), Condition(function UnitFilter))
call ForGroup(g, function GroupAdd)
set i = i + 1
endloop
call DestroyGroup(g)
set r = null
set t = null
set g = null
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library GroupUtils
//******************************************************************************
//* BY: Rising_Dusk
//*
//* This library is a simple implementation of a stack for groups that need to
//* be in the user's control for greater than an instant of time. Additionally,
//* this library provides a single, global group variable for use with user-end
//* enumerations. It is important to note that users should not be calling
//* DestroyGroup() on the global group, since then it may not exist for when it
//* it is next needed.
//*
//* The group stack removes the need for destroying groups and replaces it with
//* a recycling method.
//* function NewGroup takes nothing returns group
//* function ReleaseGroup takes group g returns boolean
//* function GroupRefresh takes group g returns nothing
//*
//* NewGroup grabs a currently unused group from the stack or creates one if the
//* stack is empty. You can use this group however you'd like, but always
//* remember to call ReleaseGroup on it when you are done with it. If you don't
//* release it, it will 'leak' and your stack may eventually overflow if you
//* keep doing that.
//*
//* GroupRefresh cleans a group of any shadow references which may be clogging
//* its hash table. If you remove a unit from the game who is a member of a unit
//* group, it will 'effectively' remove the unit from the group, but leave a
//* shadow in its place. Calling GroupRefresh on a group will clean up any
//* shadow references that may exist within it.
//*
globals
//* Group for use with all instant enumerations
group ENUM_GROUP = CreateGroup()
//* Temporary references for GroupRefresh
private boolean Flag = false
private group Refr = null
//* Assorted constants
private constant integer MAX_HANDLE_COUNT = 408000
private constant integer MIN_HANDLE_ID = 0x100000
//* Arrays and counter for the group stack
private group array Groups
private integer array Status[MAX_HANDLE_COUNT]
private integer Count = 0
endglobals
private function AddEx takes nothing returns nothing
if Flag then
call GroupClear(Refr)
set Flag = false
endif
call GroupAddUnit(Refr, GetEnumUnit())
endfunction
function GroupRefresh takes group g returns nothing
set Flag = true
set Refr = g
call ForGroup(Refr, function AddEx)
if Flag then
call GroupClear(g)
endif
endfunction
function NewGroup takes nothing returns group
if Count == 0 then
set Groups[0] = CreateGroup()
else
set Count = Count - 1
endif
set Status[GetHandleId(Groups[Count])-MIN_HANDLE_ID] = 1
return Groups[Count]
endfunction
function ReleaseGroup takes group g returns boolean
local integer stat = Status[GetHandleId(g)-MIN_HANDLE_ID]
local boolean b = true
if g == null then
debug call BJDebugMsg(SCOPE_PREFIX+" Error: Null groups cannot be released")
set b = false
elseif stat == 0 then
debug call BJDebugMsg(SCOPE_PREFIX+" Error: Group not part of stack")
set b = false
elseif stat == 2 then
debug call BJDebugMsg(SCOPE_PREFIX+" Error: Groups cannot be multiply released")
set b = false
elseif Count == 8191 then
debug call BJDebugMsg(SCOPE_PREFIX+" Error: Max groups achieved, destroying group")
call DestroyGroup(g)
set b = false
else
call GroupClear(g)
set Groups[Count] = g
set Count = Count + 1
set Status[GetHandleId(g)-MIN_HANDLE_ID] = 2
endif
return b
endfunction
endlibrary
//TESH.scrollpos=142
//TESH.alwaysfold=0
library LastOrder initializer Init needs UnitIndexingUtils
//******************************************************************************
//* BY: Rising_Dusk
//*
//* This library has a lot of usefulness for when you want to interface with the
//* last order a unit was given. This can be useful for simulating spell errors
//* and where you'd want to give them back the order they had prior to the spell
//* cast (whereas without this library, they'd just forget their orders).
//*
//* There are some handy interfacing options for your use here --
//* function GetLastOrderId takes unit u returns integer
//* function GetLastOrderString takes unit u returns string
//* function GetLastOrderType takes unit u returns integer
//* function GetLastOrderX takes unit u returns real
//* function GetLastOrderY takes unit u returns real
//* function GetLastOrderTarget takes unit u returns widget
//* function AbortOrder takes unit u returns boolean
//*
//* There are also some order commands that can be useful --
//* function IssueLastOrder takes unit u returns boolean
//* function IssueSecondLastOrder takes unit u returns boolean
//* function IsLastOrderFinished takes unit u returns boolean
//*
//* You can access any information you'd like about the orders for your own
//* order handling needs.
//*
globals
//* Storage for last order
private integer array Order
private integer array Type
private widget array Targ
private boolean array Flag
private real array X
private real array Y
//* Storage for second last order
private integer array P_Order
private integer array P_Type
private widget array P_Targ
private boolean array P_Flag
private real array P_X
private real array P_Y
//* Order type variables
constant integer ORDER_TYPE_TARGET = 1
constant integer ORDER_TYPE_POINT = 2
constant integer ORDER_TYPE_IMMEDIATE = 3
//* Trigger for the order catching
private trigger OrderTrg = CreateTrigger()
endglobals
//**********************************************************
function GetLastOrderId takes unit u returns integer
return Order[GetUnitId(u)]
endfunction
function GetLastOrderString takes unit u returns string
return OrderId2String(Order[GetUnitId(u)])
endfunction
function GetLastOrderType takes unit u returns integer
return Type[GetUnitId(u)]
endfunction
function GetLastOrderX takes unit u returns real
return X[GetUnitId(u)]
endfunction
function GetLastOrderY takes unit u returns real
return Y[GetUnitId(u)]
endfunction
function GetLastOrderTarget takes unit u returns widget
return Targ[GetUnitId(u)]
endfunction
//**********************************************************
private function OrderExclusions takes unit u, integer id returns boolean
//* Excludes specific orders or unit types from registering with the system
//*
//* 851972: stop
//* Stop is excluded from the system, but you can change it by
//* adding a check for it below. id == 851972
//*
//* 851971: smart
//* 851986: move
//* 851983: attack
//* 851984: attackground
//* 851990: patrol
//* 851993: holdposition
//* These are the UI orders that are passed to the system.
//*
//* >= 852055, <= 852762
//* These are all spell IDs from defend to incineratearrowoff with
//* a bit of leeway at the ends for orders with no strings.
//*
return id == 851971 or id == 851986 or id == 851983 or id == 851984 or id == 851990 or id == 851993 or (id >= 852055 and id <= 852762)
endfunction
private function LastOrderFilter takes unit u returns boolean
//* Some criteria for whether or not a unit's last order should be given
//*
//* INSTANT type orders are excluded because generally, reissuing an instant
//* order doesn't make sense. You can remove that check below if you'd like,
//* though.
//*
//* The Type check is really just to ensure that no spell recursion can
//* occur with IssueLastOrder. The problem with intercepting the spell cast
//* event is that it happens after the order is 'caught' and registered to
//* this system. Therefore, to just IssueLastOrder tells it to recast the
//* spell! That's a problem, so we need a method to eliminate it.
//*
local integer id = GetUnitId(u)
return u != null and GetWidgetLife(u) > 0.405 and Type[id] != ORDER_TYPE_IMMEDIATE
endfunction
private function SecondLastOrderFilter takes unit u returns boolean
//* Same as above but with regard to the second last order issued
local integer id = GetUnitId(u)
return u != null and GetWidgetLife(u) > 0.405 and P_Type[id] != ORDER_TYPE_IMMEDIATE and P_Order[id] != Order[id]
endfunction
//**********************************************************
function IsLastOrderFinished takes unit u returns boolean
return (GetUnitCurrentOrder(u) == 0 and Order[GetUnitId(u)] != 851972) or Flag[GetUnitId(u)]
endfunction
function IssueLastOrder takes unit u returns boolean
local integer id = GetUnitId(u)
local boolean b = false
if LastOrderFilter(u) and Order[id] != 0 and not Flag[id] then
if Type[id] == ORDER_TYPE_TARGET then
set b = IssueTargetOrderById(u, Order[id], Targ[id])
elseif Type[id] == ORDER_TYPE_POINT then
set b = IssuePointOrderById(u, Order[id], X[id], Y[id])
elseif Type[id] == ORDER_TYPE_IMMEDIATE then
set b = IssueImmediateOrderById(u, Order[id])
endif
endif
return b
endfunction
function IssueSecondLastOrder takes unit u returns boolean
//* This function has to exist because of spell recursion
local integer id = GetUnitId(u)
local boolean b = false
if SecondLastOrderFilter(u) and P_Order[id] != 0 and not P_Flag[id] then
if P_Type[id] == ORDER_TYPE_TARGET then
set b = IssueTargetOrderById(u, P_Order[id], P_Targ[id])
elseif P_Type[id] == ORDER_TYPE_POINT then
set b = IssuePointOrderById(u, P_Order[id], P_X[id], P_Y[id])
elseif P_Type[id] == ORDER_TYPE_IMMEDIATE then
set b = IssueImmediateOrderById(u, P_Order[id])
endif
endif
return b
endfunction
function AbortOrder takes unit u returns boolean
local boolean b = true
if IsUnitPaused(u) then
set b = false
else
call PauseUnit(u, true)
call IssueImmediateOrder(u, "stop")
call PauseUnit(u, false)
endif
return b
endfunction
//**********************************************************
private function Conditions takes nothing returns boolean
return OrderExclusions(GetTriggerUnit(), GetIssuedOrderId())
endfunction
private function Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local integer id = GetUnitId(u)
//* Store second to last order to eliminate spell recursion
set P_Order[id] = Order[id]
set P_Targ[id] = Targ[id]
set P_Type[id] = Type[id]
set P_Flag[id] = Flag[id]
set P_X[id] = X[id]
set P_Y[id] = Y[id]
set Flag[id] = false
set Order[id] = GetIssuedOrderId()
if GetTriggerEventId() == EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER then
set Targ[id] = GetOrderTarget()
set Type[id] = ORDER_TYPE_TARGET
set X[id] = GetWidgetX(GetOrderTarget())
set Y[id] = GetWidgetY(GetOrderTarget())
elseif GetTriggerEventId() == EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER then
set Targ[id] = null
set Type[id] = ORDER_TYPE_POINT
set X[id] = GetOrderPointX()
set Y[id] = GetOrderPointY()
elseif GetTriggerEventId() == EVENT_PLAYER_UNIT_ISSUED_ORDER then
set Targ[id] = null
set Type[id] = ORDER_TYPE_IMMEDIATE
set X[id] = GetUnitX(u)
set Y[id] = GetUnitY(u)
debug else
debug call BJDebugMsg(SCOPE_PREFIX+" Error: Order Doesn't Exist")
endif
set u = null
endfunction
//**********************************************************
private function SpellActions takes nothing returns nothing
set Flag[GetUnitId(GetTriggerUnit())] = true
endfunction
//**********************************************************
private function Init takes nothing returns nothing
local trigger trg = CreateTrigger()
call TriggerAddAction(OrderTrg, function Actions)
call TriggerAddCondition(OrderTrg, Condition(function Conditions))
call TriggerRegisterAnyUnitEventBJ(OrderTrg, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
call TriggerRegisterAnyUnitEventBJ(OrderTrg, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
call TriggerRegisterAnyUnitEventBJ(OrderTrg, EVENT_PLAYER_UNIT_ISSUED_ORDER)
call TriggerAddAction(trg, function SpellActions)
call TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_SPELL_EFFECT)
set trg = null
endfunction
endlibrary
//TESH.scrollpos=30
//TESH.alwaysfold=0
function Trig_Finish_Lockdown_Channel_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'A022' ) ) then
return false
endif
return true
endfunction
function Trig_Finish_Lockdown_Channel_Func002Func003C takes nothing returns boolean
if ( not ( udg_ChannelLockdown_Integers[1] == 0 ) ) then
return false
endif
return true
endfunction
function Trig_Finish_Lockdown_Channel_Func002Func005C takes nothing returns boolean
if ( not ( udg_Lockdown_Integers[1] == 0 ) ) then
return false
endif
return true
endfunction
function Trig_Finish_Lockdown_Channel_Actions takes nothing returns nothing
local boolean vis
set udg_ChannelLockdown_Integers[3] = 1
loop
exitwhen udg_ChannelLockdown_Integers[3] > udg_ChannelLockdown_Integers[2]
call GroupRemoveUnitSimple( udg_ChannelLockdown_Unit[udg_ChannelLockdown_Integers[3]], udg_ChannelLockdown_Group )
set udg_ChannelLockdown_Integers[1] = ( udg_ChannelLockdown_Integers[1] - 1 )
if ( Trig_Finish_Lockdown_Channel_Func002Func003C() ) then
set udg_ChannelLockdown_Integers[2] = 0
call DisableTrigger( gg_trg_Lockdown_Channel_Range )
else
endif
//
if ( Trig_Finish_Lockdown_Channel_Func002Func005C() ) then
call EnableTrigger( gg_trg_Lockdown_Loop )
else
endif
set udg_Lockdown_Integers[1] = ( udg_Lockdown_Integers[1] + 1 )
set udg_Lockdown_Integers[2] = ( udg_Lockdown_Integers[2] + 1 )
//
set udg_Lockdown_Target[udg_Lockdown_Integers[2]] = udg_ChannelLockdown_Target[udg_ChannelLockdown_Integers[3]]
set udg_Lockdown_Unit[udg_Lockdown_Integers[2]] = udg_ChannelLockdown_Unit[udg_ChannelLockdown_Integers[3]]
//
set udg_Lockdown_SFXInteger[udg_Lockdown_Integers[2]] = 0
//
set udg_Lockdown_Castpoint[udg_Lockdown_Integers[2]] = GetUnitLoc(udg_Lockdown_Target[udg_Lockdown_Integers[2]])
set udg_TempPoint1 = GetUnitLoc(udg_ChannelLockdown_Unit[udg_Lockdown_Integers[2]])
set udg_TempPoint2 = GetUnitLoc(udg_ChannelLockdown_Target[udg_Lockdown_Integers[2]])
call CreateNUnitsAtLoc( 1, 'e001', Player(PLAYER_NEUTRAL_AGGRESSIVE), udg_TempPoint2, 0.00 )
call UnitApplyTimedLife(GetLastCreatedUnit(),'BTLF', 5.00)
call UnitAddAbilityBJ( 'A023', GetLastCreatedUnit() )
call IssueTargetOrderBJ( GetLastCreatedUnit(), "faeriefire", udg_Lockdown_Target[udg_Lockdown_Integers[2]] )
set vis = IsLocationVisibleToPlayer(udg_Lockdown_Castpoint[udg_Lockdown_Integers[3]], GetLocalPlayer()) or IsUnitVisible(udg_Lockdown_Target[udg_Lockdown_Integers[3]],GetLocalPlayer())
set udg_Lockdown_Lightning[udg_Lockdown_Integers[2]] = AddLightningEx("FORK",vis,GetLocationX(udg_TempPoint2),GetLocationY(udg_TempPoint2),(GetLocationZ(udg_TempPoint2)+45+GetUnitFlyHeight(udg_ChannelLockdown_Target[udg_Lockdown_Integers[2]])),GetLocationX(udg_TempPoint1),GetLocationY(udg_TempPoint1),(GetLocationZ(udg_TempPoint1)+45))
call RemoveLocation(udg_TempPoint1)
call RemoveLocation(udg_TempPoint2)
//
call GroupAddUnitSimple( udg_Lockdown_Unit[udg_Lockdown_Integers[2]], udg_Lockdown_Group )
set udg_ChannelLockdown_Integers[3] = udg_ChannelLockdown_Integers[3] + 1
endloop
endfunction
//===========================================================================
function InitTrig_Finish_Lockdown_Channel takes nothing returns nothing
set gg_trg_Finish_Lockdown_Channel = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Finish_Lockdown_Channel, EVENT_PLAYER_UNIT_SPELL_FINISH )
call TriggerAddCondition( gg_trg_Finish_Lockdown_Channel, Condition( function Trig_Finish_Lockdown_Channel_Conditions ) )
call TriggerAddAction( gg_trg_Finish_Lockdown_Channel, function Trig_Finish_Lockdown_Channel_Actions )
endfunction
//TESH.scrollpos=16
//TESH.alwaysfold=0
function Trig_Lockdown_Loop_Func001Func001Func003C takes nothing returns boolean
if ( not ( udg_Lockdown_Integers[1] == 0 ) ) then
return false
endif
return true
endfunction
function Trig_Lockdown_Loop_Func001Func001Func004Func003Func003C takes nothing returns boolean
if ( not ( IsTerrainPathableBJ(udg_TempPoint3, PATHING_TYPE_WALKABILITY) == false ) ) then
return false
endif
return true
endfunction
function Trig_Lockdown_Loop_Func001Func001Func004Func003C takes nothing returns boolean
if ( not ( DistanceBetweenPoints(udg_TempPoint1, udg_Lockdown_Castpoint[udg_Lockdown_Integers[3]]) >= 300.00 ) ) then
return false
endif
return true
endfunction
function Trig_Lockdown_Loop_Func001Func001Func004C takes nothing returns boolean
if ( not ( UnitHasBuffBJ(udg_Lockdown_Target[udg_Lockdown_Integers[3]], 'B00O') == true ) ) then
return false
endif
return true
endfunction
function Trig_Lockdown_Loop_Func001Func001C takes nothing returns boolean
if ( not ( IsUnitInGroup(udg_Lockdown_Unit[udg_Lockdown_Integers[3]], udg_Lockdown_Group) == true ) ) then
return false
endif
return true
endfunction
function Trig_Lockdown_Loop_Actions takes nothing returns nothing
local boolean vis = ( IsLocationVisibleToPlayer(udg_Lockdown_Castpoint[udg_Lockdown_Integers[3]], GetLocalPlayer()) or IsUnitVisible(udg_Lockdown_Target[udg_Lockdown_Integers[3]],GetLocalPlayer()) )
set udg_Lockdown_Integers[3] = 1
loop
exitwhen udg_Lockdown_Integers[3] > udg_Lockdown_Integers[2]
if ( Trig_Lockdown_Loop_Func001Func001C() ) then
if ( Trig_Lockdown_Loop_Func001Func001Func004C() ) then
set udg_TempPoint1 = GetUnitLoc(udg_Lockdown_Target[udg_Lockdown_Integers[3]])
if ( Trig_Lockdown_Loop_Func001Func001Func004Func003C() ) then
set udg_TempPoint2 = PolarProjectionBJ(udg_Lockdown_Castpoint[udg_Lockdown_Integers[3]], 300.00, AngleBetweenPoints(udg_Lockdown_Castpoint[udg_Lockdown_Integers[3]], udg_TempPoint1))
set udg_TempPoint3 = PolarProjectionBJ(udg_TempPoint1, DistanceBetweenPoints(udg_TempPoint1, udg_TempPoint2), AngleBetweenPoints(udg_TempPoint1, udg_Lockdown_Castpoint[udg_Lockdown_Integers[3]]))
if ( Trig_Lockdown_Loop_Func001Func001Func004Func003Func003C() ) then
if ( IsUnitInGroup(udg_Lockdown_Target[udg_Lockdown_Integers[3]], udg_JD_Group) == false and IsUnitInGroup(udg_Lockdown_Target[udg_Lockdown_Integers[3]], udg_TP_Group) == false ) then
call SetUnitX(udg_Lockdown_Target[udg_Lockdown_Integers[3]] , GetLocationX(udg_TempPoint3))
call SetUnitY(udg_Lockdown_Target[udg_Lockdown_Integers[3]] , GetLocationY(udg_TempPoint3))
if udg_Lockdown_SFXInteger[udg_Lockdown_Integers[3]] >= 15 then
set udg_Lockdown_SFXInteger[udg_Lockdown_Integers[3]] = 0
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl",udg_Lockdown_Target[udg_Lockdown_Integers[3]],"chest"))
else
set udg_Lockdown_SFXInteger[udg_Lockdown_Integers[3]] = ( udg_Lockdown_SFXInteger[udg_Lockdown_Integers[3]] + 1 )
endif
endif
endif
call MoveLightningEx(udg_Lockdown_Lightning[udg_Lockdown_Integers[3]],vis,GetLocationX(udg_TempPoint3),GetLocationY(udg_TempPoint3),(GetLocationZ(udg_TempPoint3)+45+GetUnitFlyHeight(udg_Lockdown_Target[udg_Lockdown_Integers[3]])),GetLocationX(udg_Lockdown_Castpoint[udg_Lockdown_Integers[3]]),GetLocationY(udg_Lockdown_Castpoint[udg_Lockdown_Integers[3]]),(GetLocationZ(udg_Lockdown_Castpoint[udg_Lockdown_Integers[3]])+45))
call RemoveLocation(udg_TempPoint2)
call RemoveLocation(udg_TempPoint3)
else
call MoveLightningEx(udg_Lockdown_Lightning[udg_Lockdown_Integers[3]],vis,GetLocationX(udg_TempPoint1),GetLocationY(udg_TempPoint1),(GetLocationZ(udg_TempPoint1)+45+GetUnitFlyHeight(udg_Lockdown_Target[udg_Lockdown_Integers[3]])),GetLocationX(udg_Lockdown_Castpoint[udg_Lockdown_Integers[3]]),GetLocationY(udg_Lockdown_Castpoint[udg_Lockdown_Integers[3]]),(GetLocationZ(udg_Lockdown_Castpoint[udg_Lockdown_Integers[3]])+45))
endif
call RemoveLocation(udg_TempPoint1)
else
call GroupRemoveUnitSimple( udg_Lockdown_Unit[udg_Lockdown_Integers[3]], udg_Lockdown_Group )
endif
else
call DestroyLightning(udg_Lockdown_Lightning[udg_Lockdown_Integers[3]])
call RemoveLocation(udg_Lockdown_Castpoint[udg_Lockdown_Integers[3]])
set udg_Lockdown_Integers[1] = ( udg_Lockdown_Integers[1] - 1 )
if ( Trig_Lockdown_Loop_Func001Func001Func003C() ) then
set udg_Lockdown_Integers[2] = 0
call DisableTrigger( GetTriggeringTrigger() )
else
endif
endif
set udg_Lockdown_Integers[3] = udg_Lockdown_Integers[3] + 1
endloop
endfunction
//===========================================================================
function InitTrig_Lockdown_Loop takes nothing returns nothing
set gg_trg_Lockdown_Loop = CreateTrigger( )
call DisableTrigger( gg_trg_Lockdown_Loop )
call TriggerRegisterTimerEventPeriodic( gg_trg_Lockdown_Loop, 0.03 )
call TriggerAddAction( gg_trg_Lockdown_Loop, function Trig_Lockdown_Loop_Actions )
endfunction