//TESH.scrollpos=0
//TESH.alwaysfold=0
Name | Type | is_array | initial_value |
AI | player | No | |
AIBodies | group | No | |
AIBodiesMax | integer | No | 6 |
AIBodyType | unitcode | Yes | |
AIChangeAbility | abilcode | Yes | |
AIInfested | boolean | No | |
AIMain | unit | No | |
AIMemoryChip | item | No | |
AIMemoryChipHolder | unit | No | |
AIName | string | Yes | |
AIUpgradeCheck | boolean | Yes | |
AIUpgradeItemType | itemcode | Yes | |
AIUpgradeLevel | integer | Yes | 1 |
AIUpgradeSlot | integer | Yes | |
AreaIn | integer | Yes | |
Armor | unit | Yes | |
ArmorGroup | group | No | |
ArmorUser | unit | Yes | |
AtmospericDead | boolean | No | |
AtmospericInt | integer | No | |
AttackedGroup | group | No | |
Backtracker | unit | No | |
BacktrackTimer | timer | No | |
Barricade | unit | Yes | |
BarricadeCount | integer | Yes | |
BlackHole | unit | No | |
BlackHoleLoc | location | No | |
BlankName | string | No | |
BloodTestCountdown | timer | No | |
BloodTesterInt | integer | No | |
BloodTesterText | texttag | No | |
BloodTestTimer | timer | No | |
BloodTestWindow | timerdialog | No | |
BombGroup | group | No | |
BombTimer | timer | No | |
Book | itemcode | Yes | |
BookDialog | dialog | Yes | |
BookNumber | integer | Yes | |
BookOption1 | button | Yes | |
BookOption2 | button | Yes | |
BookOption3 | button | Yes | |
BookQuit | button | Yes | |
BookString1 | string | Yes | |
BookString2 | string | Yes | |
BookString3 | string | Yes | |
Bool | boolean | No | |
BrokenContains | group | No | |
Brute | unit | No | |
BruteAngle | real | No | |
BruteDistance | real | No | |
BruteGroup | group | No | |
BruteHit | group | No | |
BruteLoc | location | No | |
CageLoc | location | Yes | |
Captain | player | No | |
Cerb | player | No | PlayerNP |
CerbDead | boolean | No | |
CerbTimer | timer | No | |
Chooser | integer | Yes | |
ColorString | string | Yes | |
Containment | unit | Yes | |
Containment_Count | integer | Yes | |
Containment_Dead | boolean | Yes | |
Containment_Dummy | unit | Yes | |
ContainmentPicked | unit | No | |
Cooldown | unit | Yes | |
DEBUGMODE | boolean | No | |
DontRepick | boolean | No | |
DynamicAnatLvl | integer | No | 3 |
EggSackUnits | unit | Yes | |
EggTimer | real | No | |
Elevatorunits | group | No | |
EnergyStormOn | boolean | No | false |
EnergyStormTimer | timer | No | |
Event | integer | No | |
EventTimer | timer | No | |
EventTimerDuration | timer | No | |
EventTimerWarning | timer | No | |
EventTimerWindow | timerdialog | No | |
Evo_Lvl | integer | No | 1 |
EvolutionRate | integer | No | 1 |
FabriItem | item | Yes | |
FabriLoc | location | No | |
FabriStat | real | Yes | |
FabriTarg | unit | No | |
FabriTimer | timer | No | |
FabriUser | unit | No | |
FemaleFirstName | string | Yes | |
FemaleJokeName | string | Yes | |
FinishCaster | unit | No | |
FluxAng | real | No | |
FluxDist | real | No | |
FluxDummy | unit | No | |
FluxUser | unit | No | |
FluxZ | real | No | |
ForceDock | boolean | No | |
FreezeOn | boolean | Yes | |
GainEvo | boolean | No | true |
GameOver | boolean | No | |
GameStarted | boolean | No | |
GameTimer | timer | No | |
GeneStatus | boolean | Yes | |
GeneTimer | real | Yes | |
GeneUser | unit | No | |
Group | group | No | |
h | handle | No | |
HATable | hashtable | No | |
HomingAng | real | Yes | |
HorizionCaster | unit | No | |
HorizionEffect | effect | No | |
HorizionGroup | group | No | |
HorizionPoint | location | No | |
Humans | force | No | |
HungerGroup | group | No | |
HungerUser | unit | No | |
Images | group | No | |
Incubator | unit | No | |
Incubator_Dead | boolean | No | |
IncubatorShield | destructable | No | |
Infector | unit | No | |
IntoxLvl | integer | Yes | |
IsMental | boolean | No | |
IsParasite | boolean | No | |
Item | item | No | |
Kills | integer | Yes | |
LastName | string | Yes | |
LevitateCaster | unit | No | |
LevitateFalling | boolean | No | |
LevitateForce | unit | No | |
LevitateHeight | real | No | 200.00 |
LevitateTarget | unit | No | |
LevitateTossing | boolean | No | |
LevitateTossLoc | location | No | |
LevitateTossSpeed | real | No | |
LevitateZ | real | No | |
Listening | force | Yes | |
LocalPlayer | player | No | |
Male_Names_Chosen | integer | No | |
MaleFirstName | string | Yes | |
MaleJokeName | string | Yes | |
MaxHandleIndex | integer | No | |
MCPlayer | player | Yes | |
MCPressesLeft | integer | No | |
MCReal | real | Yes | |
MCTimer | timer | No | |
MCUnit | unit | Yes | |
MentalWallGroup | group | Yes | |
Missle | group | No | |
MUI | integer | No | |
MutationTimer | timer | No | |
Neturals | group | No | |
NewCerbNeeded | boolean | No | |
Nopathunits | group | No | |
Note | destructable | No | |
Obs | force | No | |
Open | boolean | Yes | |
Orb | item | No | |
OverlapCaster | unit | No | |
OverlapClones | unit | Yes | |
OverlapLevel | integer | No | |
OverlapTarget | unit | No | |
OverpowerUser | unit | No | |
Oxy_On | boolean | No | true |
Parasites | force | No | |
Pathcheckunit | unit | No | |
Planet | unit | No | |
PlanetVesselFaceAng | real | Yes | |
PlanetVesselLandRegion | rect | Yes | |
Player | player | No | |
PlayerAt | integer | Yes | |
PlayerColors | string | Yes | |
PlayerName | string | Yes | |
PlayerNo | integer | Yes | |
Players | force | No | |
Point | location | No | |
PowerOn | boolean | No | true |
PrivateLine | force | Yes | |
RadioblastLevel | integer | No | |
RandomItem | itemcode | Yes | |
RealPlayerName | string | Yes | |
RepickPoints | integer | No | |
RepickTimer | timer | No | |
RSM | unit | No | |
Saved | boolean | Yes | |
ScreenShakeLevel | real | No | |
ScreenShakeTimer | timer | No | |
ShipDocked | integer | Yes | |
ShipGoingFrom | integer | Yes | -1 |
ShipTimer | integer | Yes | |
SolarStorm | boolean | No | |
SolarStormEffect | weathereffect | No | |
SpawnMarker | unit | Yes | |
Spawns | integer | No | 0 |
Station | unit | No | |
StationLanded | boolean | No | |
StationLaunchTimer | timer | No | |
StationSelfDestructOn | boolean | No | |
StationSelfDestructTimer | timer | No | |
StationSelfDestructTimerWindow | timerdialog | No | |
Suit | item | Yes | |
SuitOff | boolean | No | |
TempBool | boolean | No | |
TempGroup | group | No | |
TempInt | integer | No | |
TempInt01 | integer | No | 1 |
TempInt02 | integer | No | |
TempLoc01 | location | No | |
TempLoc02 | location | No | |
TempPlayers01 | force | No | |
TempPlayers02 | force | No | |
TempReal | real | No | |
TempReal01 | real | No | |
TempReal02 | real | No | |
TempUnit | unit | No | |
Tk_Group | force | No | |
Tk_Player | player | No | |
Tk_Prisioners | force | No | |
Tk_Timer | real | Yes | |
Tk_Voters | force | Yes | |
Tk_Votes | integer | Yes | |
Tkingon | boolean | No | true |
TotalPlayers | integer | No | |
True | boolean | No | |
TurretLeft | unit | Yes | |
TurretLeftUsing | player | Yes | |
TurretRight | unit | Yes | |
TurretRightUsing | player | Yes | |
UsingAI | boolean | No | true |
UsingControl | boolean | Yes | |
UsingFemaleName | boolean | Yes | |
UsingName | boolean | Yes | |
VentDummies | group | No | |
Vessel | unit | Yes | |
VesselAng | real | Yes | |
VesselControler | player | Yes | |
VesselControls | rect | Yes | |
VesselDeathRegion | rect | Yes | |
VesselDummy | unit | Yes | |
VesselPlanetLoc | location | Yes | |
VesselStationLoc | location | Yes | |
Weapon_Type | integer | Yes | |
WhirlCaster | unit | No | |
WhirlTimer | timer | No |
//TESH.scrollpos=24
//TESH.alwaysfold=0
//All my epic peices of code that I've stolen/made, use them at your own peril!
native UnitAlive takes unit id returns boolean
library MainFunctsLibary
globals
private group g = CreateGroup()
endglobals
function AddLocust takes unit whichUnit returns nothing
call UnitAddAbility(whichUnit, 'Aloc')
endfunction
function RemoveLocust takes unit whichUnit returns nothing
call ShowUnit(whichUnit, false)
call UnitRemoveAbility(whichUnit, 'Aloc')
call ShowUnit(whichUnit, true)
endfunction
function LocustCheck takes unit whichUnit returns integer
return GetUnitAbilityLevelSwapped('Aloc',whichUnit)
endfunction
//Checking if unit is a giant
function IsGiant takes unit u returns boolean
return IsUnitType(u, UNIT_TYPE_GIANT)
endfunction
// New gate modifier
function ModifyGate takes integer gateOperation, destructable d returns nothing
if (gateOperation == bj_GATEOPERATION_CLOSE) then
if (GetDestructableLife(d) <= 0) then
call DestructableRestoreLife(d, GetDestructableMaxLife(d), true)
endif
call SetDestructableAnimation(d, "morph alternate")
elseif (gateOperation == bj_GATEOPERATION_OPEN) then
if (GetDestructableLife(d) > 0) then
call KillDestructable(d)
endif
call SetDestructableAnimation(d, "morph")
elseif (gateOperation == bj_GATEOPERATION_DESTROY) then
if (GetDestructableLife(d) > 0) then
call KillDestructable(d)
endif
call SetDestructableAnimation(d, "death")
else
// Unrecognized gate state - ignore the request.
endif
endfunction
// XY functions
function A2PXY takes real x,real y,real xt,real yt returns real
return ModuloReal(bj_RADTODEG*Atan2(yt-y,xt-x),360.)
endfunction
function D2PXY takes real x,real y,real xt,real yt returns real
local real dx=xt-x
local real dy=yt-y
return SquareRoot(dx*dx+dy*dy)
endfunction
function GetXYZ takes real x, real y returns real
local location l = Location(x, y)
local real z = GetLocationZ(l)
call RemoveLocation(l)
set l = null
return z
endfunction
function IsPointWalkable takes real x,real y returns boolean
call ShowUnit(udg_Pathcheckunit,true)
call SetUnitPosition(udg_Pathcheckunit,x,y)
call ShowUnit(udg_Pathcheckunit,false)
return GetUnitX(udg_Pathcheckunit)==x and GetUnitY(udg_Pathcheckunit)==y
endfunction
function IsPointWalkableLoc takes location loc returns boolean
return IsPointWalkable(GetLocationX(loc),GetLocationY(loc))
endfunction
//This was made by emjlr3, and changed by me
function GetDeflectionAngle takes unit missile,real x, real y,real face returns real
local real angle = bj_RADTODEG*Atan2(y-GetUnitY(missile),x-GetUnitX(missile))
set missile = null
return face+180.+(2.*(angle-face))
endfunction
function CustomError 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 DisplayTimedTextToPlayer( ForPlayer, 0.52, -1.00, 2.00, "|cffffcc00"+msg+"|r" )
endif
call StartSound( error )
endif
call KillSoundWhenDone( error)
set error=null
endfunction
//My Parabola function, modded to use Z
function JumpParabola takes real dist, real maxdist,real curve, real startZ, real userZ returns real
local real t = (dist*2)/maxdist-1
return (-t*t+1)*(maxdist/curve)+(startZ-userZ)
endfunction
function SetUnitPathingEx takes unit u, boolean pathtype returns nothing
if pathtype == false then
call SetUnitPathing(u,pathtype)
call GroupAddUnit(udg_Nopathunits,u)
else
call SetUnitPathing(u,pathtype)
call GroupRemoveUnit(udg_Nopathunits,u)
endif
endfunction
//Unit Group Helpers
function Enum_AntiLeak takes nothing returns boolean
return true
endfunction
function GetUnitsInRange takes real radius,real x,real y returns group
call GroupClear(g)
call GroupEnumUnitsInRange(g,x,y,radius,Filter(function Enum_AntiLeak))
return g
endfunction
function CopyGroup takes group g returns group
set bj_groupAddGroupDest = CreateGroup()
call ForGroup(g, function GroupAddGroupEnum)
return bj_groupAddGroupDest
endfunction
//Filter for 1 player, very helpful
function CinematicFilterGenericForPlayer takes player whichPlayer, real duration, blendmode bmode, string tex, real red0, real green0, real blue0, real trans0, real red1, real green1, real blue1, real trans1 returns nothing
if ( GetLocalPlayer() == whichPlayer ) then
call SetCineFilterTexture(tex)
call SetCineFilterBlendMode(bmode)
call SetCineFilterTexMapFlags(TEXMAP_FLAG_NONE)
call SetCineFilterStartUV(0, 0, 1, 1)
call SetCineFilterEndUV(0, 0, 1, 1)
call SetCineFilterStartColor(PercentTo255(red0), PercentTo255(green0), PercentTo255(blue0), PercentTo255(100-trans0))
call SetCineFilterEndColor(PercentTo255(red1), PercentTo255(green1), PercentTo255(blue1), PercentTo255(100-trans1))
call SetCineFilterDuration(duration)
call DisplayCineFilter(true)
endif
endfunction
function CooldownChild takes nothing returns nothing
local timer t = GetExpiredTimer()
local player p = GetHandlePlayer(t,"p")
set udg_Cooldown[GetConvertedPlayerId(p)] = CreateUnit(p,'cool',GetUnitX(udg_Infector),GetUnitY(udg_Infector),0)
call FlushHandleLocals(t)
set t = null
set p = null
endfunction
function Cooldown takes player p returns nothing
local timer t = CreateTimer()
call KillUnit(udg_Cooldown[GetConvertedPlayerId(p)])
call SetHandleHandle(t,"p",p)
call TimerStart(t,240,false,function CooldownChild)
set t = null
endfunction
endlibrary
//TESH.scrollpos=25
//TESH.alwaysfold=0
//
// _ ___ ___ __ _ _____ ___ _____ _ _____ ___
// /_\ / __| __| \| |_ _| / __|_ _/_\_ _/ __|
// / _ \ (_ | _|| \ \ | | | \__ \ | |/ _ \| | \__ \
// /_/ \_\___|___|_|\__| |_| |___/ |_/_/ \_\_| |___/
// By Jesus4Lyf. v1.1.0.
//
// What is AgentStats?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// AgentStats is a handle count debugging tool for monitoring the number of
// handles in game, in debug mode.
//
// How to implement?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Create a new trigger object called AgentStats, go to 'Edit -> Convert
// to Custom Text', and replace everything that's there with this script.
//
// Then, import the "trackagents.j" file to "war3mapImported\trackagents.j".
//
// Commands Provided:
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Type the following commands in game:
//
// -count Displays the number of agents in the game.
// -count <handle> Displays the number of <handle>s in the game.
// -stats Displays agent stats.
// -stats <handle> Displays <handle> stats.
//
// Examples:
// -stats timer
// -count triggerevent
// -stats
// -count widget
// -count
//
library AgentStats initializer OnInit
globals
private constant integer SEARCH_DEGREE=20
private constant string COMMAND_CHAR="-"
private constant integer COMMAND_CHAR_LENGTH=StringLength(COMMAND_CHAR)
private constant string TRACKER_PATH="war3mapImported\\trackagents.j"
endglobals
globals
private string array TypeName
private hashtable NameToType=InitHashtable()
private constant integer TYPE_UNKNOWN =0
private constant integer TYPE_WIDGET =1
private constant integer TYPE_TRIGGER =2
private constant integer TYPE_DESTRUCTABLE =3
private constant integer TYPE_ITEM =4
private constant integer TYPE_UNIT =5
private constant integer TYPE_TIMER =6
private constant integer TYPE_HASHTABLE =7
private constant integer TYPE_TRIGGEREVENT =8
private constant integer TYPE_TRIGGERCONDITION =9
private constant integer TYPE_TRIGGERACTION =10
private constant integer TYPE_PLAYER =11
private constant integer TYPE_GROUP =12
private constant integer TYPE_EFFECT =13
private constant integer TYPE_LOCATION =14
private constant integer TYPE_RECT =15
private constant integer TYPE_BOOLEXPR =16
private constant integer TYPE_SOUND =17
private constant integer TYPE_FORCE =18
private constant integer TYPE_UNITPOOL =19
private constant integer TYPE_ITEMPOOL =20
private constant integer TYPE_QUEST =21
private constant integer TYPE_QUESTITEM =22
private constant integer TYPE_DEFEATCONDITION =23
private constant integer TYPE_TIMERDIALOG =24
private constant integer TYPE_LEADERBOARD =25
private constant integer TYPE_MULTIBOARDITEM =26
private constant integer TYPE_MULTIBOARD =27
private constant integer TYPE_TRACKABLE =28
private constant integer TYPE_DIALOG =29
private constant integer TYPE_BUTTON =30
private constant integer TYPE_TEXTTAG =31
private constant integer TYPE_LIGHTNING =32
private constant integer TYPE_IMAGE =33
private constant integer TYPE_UBERSPLAT =34
private constant integer TYPE_REGION =35
private constant integer TYPE_FOGSTATE =36
private constant integer TYPE_FOGMODIFIER =37
private constant integer TYPE_ABILITY =38
private constant integer MAX_TYPE =38
endglobals
private function InitTypeNames takes nothing returns nothing
local integer i=MAX_TYPE
set TypeName[TYPE_UNKNOWN] ="UNKNOWN"
set TypeName[TYPE_WIDGET] ="Widget"
set TypeName[TYPE_TRIGGER] ="Trigger"
set TypeName[TYPE_DESTRUCTABLE] ="Destructable"
set TypeName[TYPE_ITEM] ="Item"
set TypeName[TYPE_UNIT] ="Unit"
set TypeName[TYPE_TIMER] ="Timer"
set TypeName[TYPE_HASHTABLE] ="Hashtable"
set TypeName[TYPE_TRIGGEREVENT] ="TriggerEvent"
set TypeName[TYPE_TRIGGERCONDITION] ="TriggerCondition"
set TypeName[TYPE_TRIGGERACTION] ="TriggerAction"
set TypeName[TYPE_PLAYER] ="Player"
set TypeName[TYPE_GROUP] ="Group"
set TypeName[TYPE_EFFECT] ="Effect"
set TypeName[TYPE_LOCATION] ="Location"
set TypeName[TYPE_RECT] ="Rect"
set TypeName[TYPE_BOOLEXPR] ="BoolExpr"
set TypeName[TYPE_SOUND] ="Sound"
set TypeName[TYPE_FORCE] ="Force"
set TypeName[TYPE_UNITPOOL] ="UnitPool"
set TypeName[TYPE_ITEMPOOL] ="ItemPool"
set TypeName[TYPE_QUEST] ="Quest"
set TypeName[TYPE_QUESTITEM] ="QuestItem"
set TypeName[TYPE_DEFEATCONDITION] ="DefeatCondition"
set TypeName[TYPE_TIMERDIALOG] ="TimerDialog"
set TypeName[TYPE_LEADERBOARD] ="Leaderboard"
set TypeName[TYPE_MULTIBOARDITEM] ="MultiboardItem"
set TypeName[TYPE_MULTIBOARD] ="Multiboard"
set TypeName[TYPE_TRACKABLE] ="Trackable"
set TypeName[TYPE_DIALOG] ="Dialog"
set TypeName[TYPE_BUTTON] ="Button"
set TypeName[TYPE_TEXTTAG] ="TextTag"
set TypeName[TYPE_LIGHTNING] ="Lightning"
set TypeName[TYPE_IMAGE] ="Image"
set TypeName[TYPE_UBERSPLAT] ="Ubersplat"
set TypeName[TYPE_REGION] ="Region"
set TypeName[TYPE_FOGSTATE] ="FogState"
set TypeName[TYPE_FOGMODIFIER] ="FogModifier"
set TypeName[TYPE_ABILITY] ="Ability"
loop
call SaveInteger(NameToType,0,StringHash(StringCase(TypeName[i],false)),i)
exitwhen i==0
set i=i-1
endloop
endfunction
globals
private hashtable Read=InitHashtable()
private hashtable Count=InitHashtable()
private integer CountInstance=-1
private integer Sum=0
endglobals
//! textmacro AgentStats__Count takes TYPECAPS
call SaveInteger(Count,CountInstance,TYPE_$TYPECAPS$,LoadInteger(Count,CountInstance,TYPE_$TYPECAPS$)+1)
set Sum=Sum+1
//! endtextmacro
private function CreateInstance takes nothing returns nothing
local integer i=SEARCH_DEGREE
local group g
loop
exitwhen i==0
set i=i-1
call DestroyGroup(CreateGroup())
endloop
set g=CreateGroup()
set i=GetHandleId(g)
call DestroyGroup(g)
set g=null
// Populate "Read"
call SaveInteger(Read,0,0,i)
call Preloader(TRACKER_PATH)
set CountInstance=CountInstance+1
loop
exitwhen i==0x100000
set i=i-1
if LoadWidgetHandle(Read,0,i)!=null then
call SaveInteger(Count,CountInstance,TYPE_WIDGET,LoadInteger(Count,CountInstance,TYPE_WIDGET)+1)
if LoadUnitHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("UNIT")
elseif LoadDestructableHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("DESTRUCTABLE")
elseif LoadItemHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("ITEM")
endif
elseif LoadTriggerHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("TRIGGER")
elseif LoadTimerHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("TIMER")
elseif LoadHashtableHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("HASHTABLE")
elseif LoadTriggerEventHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("TRIGGEREVENT")
elseif LoadTriggerConditionHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("TRIGGERCONDITION")
elseif LoadTriggerActionHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("TRIGGERACTION")
elseif LoadPlayerHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("PLAYER")
elseif LoadGroupHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("GROUP")
elseif LoadEffectHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("EFFECT")
elseif LoadLocationHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("LOCATION")
elseif LoadRectHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("RECT")
elseif LoadBooleanExprHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("BOOLEXPR")
elseif LoadSoundHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("SOUND")
elseif LoadForceHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("FORCE")
elseif LoadUnitPoolHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("UNITPOOL")
elseif LoadItemPoolHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("ITEMPOOL")
elseif LoadQuestHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("QUEST")
elseif LoadQuestItemHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("QUESTITEM")
elseif LoadDefeatConditionHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("DEFEATCONDITION")
elseif LoadTimerDialogHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("DIALOG")
elseif LoadLeaderboardHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("LEADERBOARD")
elseif LoadMultiboardItemHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("MULTIBOARDITEM")
elseif LoadMultiboardHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("MULTIBOARD")
elseif LoadTrackableHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("TRACKABLE")
elseif LoadDialogHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("DIALOG")
elseif LoadButtonHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("BUTTON")
elseif LoadTextTagHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("TEXTTAG")
elseif LoadLightningHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("LIGHTNING")
elseif LoadImageHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("IMAGE")
elseif LoadUbersplatHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("UBERSPLAT")
elseif LoadRegionHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("REGION")
elseif LoadFogStateHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("FOGSTATE")
elseif LoadFogModifierHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("FOGMODIFIER")
elseif LoadAbilityHandle(Read,0,i)!=null then
//! runtextmacro AgentStats__Count("ABILITY")
elseif HaveSavedHandle(Read,0,i) then
//! runtextmacro AgentStats__Count("UNKNOWN")
endif
endloop
call SaveInteger(Count,CountInstance,-1,Sum)
set Sum=0
endfunction
// Abstraction
private function GetLastInstance takes nothing returns integer
return CountInstance
endfunction
private function GetTypeCount takes integer whichInstance, integer whichType returns integer
return LoadInteger(Count,whichInstance,whichType)
endfunction
private function GetType takes string typeNameLowerCase returns integer
return LoadInteger(NameToType,0,StringHash(typeNameLowerCase))
endfunction
private function GetTypeName takes integer whichType returns string
return TypeName[whichType]
endfunction
private function GetTotalCount takes integer whichInstance returns integer
return LoadInteger(Count,whichInstance,-1)
endfunction
globals
private integer array Sorted
endglobals
private function InitSort takes nothing returns nothing
local integer i=MAX_TYPE
loop
set Sorted[i]=i
exitwhen i==0
set i=i-1
endloop
endfunction
private function Sort takes integer whichInstance returns nothing
local integer i=1
local integer j
local integer val
loop
set val=Sorted[i]
set j=i-1
loop
exitwhen j<0 or GetTypeCount(whichInstance,Sorted[j])>GetTypeCount(whichInstance,val)
set Sorted[j+1]=Sorted[j]
set j=j-1
endloop
set Sorted[j+1]=val
exitwhen i==MAX_TYPE
set i=i+1
endloop
endfunction
private function CommandCount takes string subject returns nothing
local integer t=GetType(subject)
if t!=0 or subject=="unknown" then
call BJDebugMsg("Number of "+GetTypeName(t)+"s: "+I2S(GetTypeCount(GetLastInstance(),t)))
else
call BJDebugMsg("Number of agents: "+I2S(GetTotalCount(GetLastInstance())))
endif
endfunction
private function CommandStats takes string subject returns nothing
local integer t=GetType(subject)
if t!=0 or subject=="unknown" then
call BJDebugMsg(" ")
call BJDebugMsg(" == "+GetTypeName(t)+" Stats ==")
call BJDebugMsg("Currently: "+I2S(GetTypeCount(GetLastInstance(),t))+" exist.")
call BJDebugMsg("Last Scan: "+I2S(GetTypeCount(GetLastInstance()-1,t))+" existed.")
call BJDebugMsg("Post Init: "+I2S(GetTypeCount(0,t))+" existed.")
call BJDebugMsg("Currently, "+GetTypeName(t)+"s make up "+/*
*/R2S(GetTypeCount(GetLastInstance(),t)*100./GetTotalCount(GetLastInstance()))/*
*/+"% of all agents.")
call BJDebugMsg("Since last scan, "+GetTypeName(t)+"s have increased by "+/*
*/I2S(GetTypeCount(GetLastInstance(),t)-GetTypeCount(GetLastInstance()-1,t))/*
*/+".")
else
call Sort(GetLastInstance())
call BJDebugMsg(" ")
call BJDebugMsg(" == Agent Stats ==")
call BJDebugMsg("Currently: "+I2S(GetTotalCount(GetLastInstance()))+" exist.")
call BJDebugMsg("Last Scan: "+I2S(GetTotalCount(GetLastInstance()-1))+" existed.")
call BJDebugMsg("Post Init: "+I2S(GetTotalCount(0))+" existed.")
call BJDebugMsg("Since last scan, Agents have increased by "+/*
*/I2S(GetTotalCount(GetLastInstance())-GetTotalCount(GetLastInstance()-1))/*
*/+".")
call Sort(GetLastInstance())
call BJDebugMsg("Most common agents:")
call BJDebugMsg("1. "+GetTypeName(Sorted[0])+"s - "+I2S(GetTypeCount(GetLastInstance(),Sorted[0]))+" in existance.")
call BJDebugMsg("2. "+GetTypeName(Sorted[1])+"s - "+I2S(GetTypeCount(GetLastInstance(),Sorted[1]))+" in existance.")
call BJDebugMsg("3. "+GetTypeName(Sorted[2])+"s - "+I2S(GetTypeCount(GetLastInstance(),Sorted[2]))+" in existance.")
endif
endfunction
private function OnChat takes nothing returns boolean
local string s=GetEventPlayerChatString()
set s=StringCase(SubString(s,COMMAND_CHAR_LENGTH,StringLength(s)),false)
if SubString(s,0,5)=="count" then
call CreateInstance.evaluate()
call CommandCount(SubString(s,6,StringLength(s)))
elseif SubString(s,0,5)=="stats" then
call CreateInstance.evaluate()
call CommandStats(SubString(s,6,StringLength(s)))
endif
return false
endfunction
private function PostInit takes nothing returns nothing
call CreateInstance() // Creates instance #0
if GetTotalCount(GetLastInstance())==0 then
call BJDebugMsg("AgentStats Error: Blizzard may have fixed the return bug, or else you are missing "+TRACKER_PATH+".")
endif
call DestroyTimer(GetExpiredTimer())
endfunction
private function OnInit takes nothing returns nothing
debug local integer i=11
debug local trigger t=CreateTrigger()
debug call StoreInteger(InitGameCache("Preloader.w3v"),"globals","hashtable",GetHandleId(Read))
debug call InitTypeNames()
debug call InitSort()
debug call TimerStart(CreateTimer(),0,false,function PostInit)
debug loop
debug call TriggerRegisterPlayerChatEvent(t,Player(i),COMMAND_CHAR,false)
debug exitwhen i==0
debug set i=i-1
debug endloop
debug call TriggerAddCondition(t,Filter(function OnChat))
debug set t=null
endfunction
endlibrary
//TESH.scrollpos=24
//TESH.alwaysfold=0
//good ol LHV, :)
library LHV
function HATable takes nothing returns hashtable
if udg_HATable == null then
set udg_HATable = InitHashtable()
endif
return udg_HATable
endfunction
function SetHandleHandle takes handle subject, string name, agent value returns nothing
if value==null then
call RemoveSavedHandle( HATable(), GetHandleId(subject), StringHash(name))
else
call SaveAgentHandle( HATable(), GetHandleId(subject), StringHash(name), value)
endif
endfunction
function SetHandleText takes handle subject, string name, texttag value returns nothing
call SaveTextTagHandle(HATable(), GetHandleId(subject), StringHash(name), value)
endfunction
function SetHandleInt takes handle subject, string name, integer value returns nothing
call SaveInteger(HATable(), GetHandleId(subject), StringHash(name), value)
endfunction
function SetHandleBoolean takes handle subject, string name, boolean value returns nothing
call SaveBoolean(HATable(), GetHandleId(subject), StringHash(name), value)
endfunction
function SetHandleReal takes handle subject, string name, real value returns nothing
call SaveReal(HATable(), GetHandleId(subject), StringHash(name), value)
endfunction
function SetHandleString takes handle subject, string name, string value returns nothing
call SaveStr(HATable(), GetHandleId(subject), StringHash(name), value)
endfunction
function GetHandleInt takes handle subject, string name returns integer
return LoadInteger(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleBoolean takes handle subject, string name returns boolean
return LoadBoolean(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleReal takes handle subject, string name returns real
return LoadReal(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleString takes handle subject, string name returns string
return LoadStr(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleUnit takes handle subject, string name returns unit
return LoadUnitHandle(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleItem takes handle subject, string name returns item
return LoadItemHandle(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleTimer takes handle subject, string name returns timer
return LoadTimerHandle(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleText takes handle subject, string name returns texttag
return LoadTextTagHandle(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleTrigger takes handle subject, string name returns trigger
return LoadTriggerHandle(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleEffect takes handle subject, string name returns effect
return LoadEffectHandle(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleGroup takes handle subject, string name returns group
return LoadGroupHandle(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleLightning takes handle subject, string name returns lightning
return LoadLightningHandle(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleWidget takes handle subject, string name returns widget
return LoadWidgetHandle(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleLocation takes handle subject, string name returns location
return LoadLocationHandle(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandlePlayer takes handle subject, string name returns player
return LoadPlayerHandle(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleRegion takes handle subject, string name returns region
return LoadRegionHandle(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleRect takes handle subject, string name returns rect
return LoadRectHandle(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleForce takes handle subject, string name returns force
return LoadForceHandle(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleFogmodifier takes handle subject, string name returns fogmodifier
return LoadFogModifierHandle(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function GetHandleTimerDialog takes handle subject, string name returns timerdialog
return LoadTimerDialogHandle(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function HaveHandleHandle takes handle subject, string name returns boolean
return HaveSavedHandle(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function HaveHandleInt takes handle subject, string name returns boolean
return HaveSavedInteger(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function HaveHandleReal takes handle subject, string name returns boolean
return HaveSavedReal(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function HaveHandleString takes handle subject, string name returns boolean
return HaveSavedString(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function HaveHandleBoolean takes handle subject, string name returns boolean
return HaveSavedBoolean(HATable(), GetHandleId(subject), StringHash(name))
endfunction
function RemoveHandle takes handle subject, string name returns nothing
call SaveAgentHandle(HATable(),GetHandleId(subject),StringHash(name), null)
call RemoveSavedHandle(HATable(),GetHandleId(subject),StringHash(name))
endfunction
function RemoveInt takes handle subject, string name returns nothing
call SaveInteger(HATable(),GetHandleId(subject),StringHash(name), 0)
call RemoveSavedInteger(HATable(),GetHandleId(subject),StringHash(name))
endfunction
function RemoveReal takes handle subject, string name returns nothing
call SaveReal(HATable(),GetHandleId(subject),StringHash(name), 0.0)
call RemoveSavedReal(HATable(),GetHandleId(subject),StringHash(name))
endfunction
function RemoveBoolean takes handle subject, string name returns nothing
call SaveBoolean(HATable(),GetHandleId(subject),StringHash(name), false)
call RemoveSavedBoolean(HATable(),GetHandleId(subject),StringHash(name))
endfunction
function RemoveStr takes handle subject, string name returns nothing
call SaveStr(HATable(),GetHandleId(subject),StringHash(name), null)
call RemoveSavedString(HATable(),GetHandleId(subject),StringHash(name))
endfunction
function FlushHandleLocals takes handle subject returns nothing
call FlushChildHashtable(HATable(), GetHandleId(subject) )
endfunction
endlibrary
//TESH.scrollpos=100
//TESH.alwaysfold=0
library Knockback
globals
//*********************
//* Configuration
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯
//*
//* Defines the rate (in seconds) that the knockback will iterate through the stack.
private constant real LOOP_REF = 0.03
//*
//* Determines whether to use SetUnitPosition or SetUnitX/Y to adjust the subject's
//* position. SetUnitPosition pauses the subject but factors pathability into its movement.
private constant boolean PAUSE_SUBJECT = false
//*
//* If PAUSE_SUBJECT is off, then INCLUDE_PATHING will check the pathability of a set of
//* coordinates before moving the unit.
private constant boolean INCLUDE_PATHING = true
//*
//*
//*****************************************************************************
endglobals
struct knockback
readonly unit subject = null
readonly real velocity
readonly real rotation
private real rotationCos
private real rotationSin
readonly real friction
// --------------------------------------------------------------------------------------------------
private static timer priv_stackLoop = CreateTimer()
private static constant real priv_stackLoopRef = LOOP_REF
private real priv_time
private boolean priv_stopped = false
// --------------------------------------------------------------------------------------------------
private integer priv_index
private static thistype array priv_stack
private static integer priv_stackN = 0
// --------------------------------------------------------------------------------------------------
method stop takes nothing returns nothing
// Instead of directly destroying an instance from knockback, the user can tell the system
// that he/she wants the knockback to be stopped. If the knockback is to be stopped, it will
// be on the next iteration.
set .priv_stopped = true
endmethod
private method onDestroy takes nothing returns nothing
set thistype.priv_stackN = thistype.priv_stackN-1
set thistype.priv_stack[.priv_index] = thistype.priv_stack[thistype.priv_stackN]
set thistype.priv_stack[.priv_index].priv_index = .priv_index
if (.priv_stackN == 0) then
call PauseTimer(thistype.priv_stackLoop)
endif
endmethod
private static method onRef takes nothing returns nothing
local integer i = .priv_stackN-1
local thistype kb
local real x
local real y
local real iX
local real iY
local item it
loop
exitwhen(i < 0)
set kb = .priv_stack[i]
if (kb!=0) then
set x = GetUnitX(kb.subject) + kb.velocity * kb.rotationCos
set y = GetUnitY(kb.subject) + kb.velocity * kb.rotationSin
static if PAUSE_SUBJECT then
call SetUnitPosition(kb.subject, x, y)
else
static if not PAUSE_SUBJECT and INCLUDE_PATHING then
set it = CreateItem('afac', x, y)
set iX = GetItemX(it)
set iY = GetItemY(it)
if ((iX-x)*(iX-x) + (iY-y)*(iY-y)) <= (32*32) then
call SetUnitX(kb.subject, x)
call SetUnitY(kb.subject, y)
endif
call RemoveItem(it)
else
call SetUnitX(kb.subject, x)
call SetUnitY(kb.subject, y)
endif
endif
set kb.velocity = kb.velocity + kb.friction
set kb.priv_time = kb.priv_time - .priv_stackLoopRef
if (kb.priv_time <= 0.00) or kb.priv_stopped then
call kb.destroy()
endif
endif
set i=i-1
endloop
set it=null
endmethod
static method create takes unit u, real angle, real distance, real time returns thistype
local thistype kb = .allocate()
set kb.subject = u
set kb.velocity = 2*distance/time
set kb.rotation = angle
set kb.rotationCos = Cos(angle)
set kb.rotationSin = Sin(angle)
set kb.friction = -kb.velocity/time
set kb.priv_index = .priv_stackN
set kb.priv_time = time
set kb.velocity = kb.velocity * .priv_stackLoopRef
set kb.friction = kb.friction * .priv_stackLoopRef * .priv_stackLoopRef
if (.priv_stackN == 0) then
call TimerStart(.priv_stackLoop, .priv_stackLoopRef, true, function thistype.onRef)
endif
set .priv_stack[.priv_stackN] = kb
set .priv_stackN = .priv_stackN + 1
return kb
endmethod
endstruct
endlibrary
//TESH.scrollpos=47
//TESH.alwaysfold=0
//====================================
// PreventSave
//====================================
//
// This library is simple enough. It allows you to enable or
// disabled game saving. It works by showing a dialog instantly
// before a game is saved. This closes the save screen therefor
// the game is never actually saved.
//
// Nothing visually happens to the game except for maybe a quick open
// and close of the save dialog, though it's hardly noticeable.
// This even works in single player surprisngly without pausing the game
// which usually happens when a dialog is opened offline.
//
// You can toggle allowing or disallowing saving by setting
// GAME_ALLOW_SAVE to true, or false.
//
//====================================
// Import Instructions
//====================================
//
// 1. Copy this entire script.
// 2. Create a new trigger in your trigger
// editor and convert it to Jass.
// 3. Paste this in there and save the map.
//
// This requires JassHelper which is included
// in JassNewGenPack.
//
library PreventSave initializer onInit
globals
boolean GAME_ALLOW_SAVE = false
endglobals
globals
private dialog D = DialogCreate()
private timer T = CreateTimer()
endglobals
private function Exit takes nothing returns nothing
call DialogDisplay(GetLocalPlayer(), D, false)
endfunction
private function StopSave takes nothing returns nothing
local integer i = 0
if not GAME_ALLOW_SAVE then
call DialogDisplay(GetLocalPlayer(), D, true)
call TimerStart(T, 0.00, false, function Exit)
endif
endfunction
private function onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterGameEvent(t, EVENT_GAME_SAVE)
call TriggerAddAction(t, function StopSave)
endfunction
endlibrary
//TESH.scrollpos=35
//TESH.alwaysfold=0
library AutocastOrderEvent initializer Init requires Event
globals
private constant integer OFFSET = 0xD0000
private integer array Data
private Event On
private Event Off
private integer i
endglobals
function TriggerRegisterAutocastOnEvent takes trigger whichTrigger returns nothing
call On.register(whichTrigger)
endfunction
function TriggerRegisterAutocastOffEvent takes trigger whichTrigger returns nothing
call Off.register(whichTrigger)
endfunction
private function Fire takes nothing returns boolean
set i = Data[GetIssuedOrderId() - OFFSET]
if i == 1 then
call On.fire()
elseif i == 2 then
call Off.fire()
endif
return false
endfunction
private function RegisterOrder takes integer i returns nothing
set i = i - OFFSET
set Data[i] = 1
set Data[i + 1] = 2
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 15
loop
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_ISSUED_ORDER, null)
exitwhen i == 0
set i = i - 1
endloop
call TriggerAddCondition(t, Condition(function Fire))
set On = Event.create()
set Off = Event.create()
call TriggerSleepAction(1)
//Register all autocast orders. Oh God.
call RegisterOrder(0xD0060) //Heal
call RegisterOrder(0xD0063) //Inner Fire
call RegisterOrder(0xD006C) //Slow
call RegisterOrder(0xD0204) //Spell Steal
call RegisterOrder(0xD0086) //Bloodlust
call RegisterOrder(0xD00F4) //Web
call RegisterOrder(0xD00DF) //Curse
call RegisterOrder(0xD00E6) //Raise Dead
call RegisterOrder(0xD0242) //Essence of Blight
call RegisterOrder(0xD0245) //Spirit Touch
call RegisterOrder(0xD01EA) //Frost Armor
call RegisterOrder(0xD00B6) //Faerie Fire
call RegisterOrder(0xD00A5) //Abolish Magic
call RegisterOrder(0xD00CE) //Searing Arrows
call RegisterOrder(0xD0114) //Cold Arrows
call RegisterOrder(0xD027A) //Parasite
call RegisterOrder(0xD0039) //Repair
call RegisterOrder(0xD00EB) //Restore
call RegisterOrder(0xD00C2) //Renew
call RegisterOrder(0xD00BE) //Recharge
call RegisterOrder(0xD0248) //Carrion Beetles
call RegisterOrder(0xD0262) //Black Arrow
call RegisterOrder(0xD023C) //Orb of Annihilation
call RegisterOrder(0xD0053) //Get Corpse
call RegisterOrder(0xD0049) //Kaboom!
call RegisterOrder(0xD011F) //Poison Arrows
endfunction
endlibrary
//TESH.scrollpos=389
//TESH.alwaysfold=0
library KBS initializer Init
//***************************************************************************************
//** **
//** Knockback System (KBS) **By kenny!** **
//** v 2.04 **
//** **
//** A system I made that can be used for knockback spells in a variety of **
//** applications in a map. User defined variables make it easy to give the desired **
//** effect for any spell. **
//** **
//** Requires: **
//** - A vJASS preprocessor (NewGen Pack). **
//** - No other systems. **
//** - A dummy unit. One can be found in this map ('u000') **
//** - The special effects found in the import/export section of this map. **
//** They are the "Dust.mdx" and the "SlideWater.mdx". Or you can use your **
//** own if you have some. **
//** **
//***************************************************************************************
//***************************************************************************************
//** **
//** Other Information: **
//** - Angle is taken in degrees. But can easily be changed if you know how. **
//** - Units will be stopped if they hit the map borders. **
//** - Remember to import the special effect into your map if you need them. **
//** - There are two functions that can be used in this system. **
//** - NEW FUNCTION: KBS_BeginCommon() is for all the common knockback uses in **
//** your map. It only takes 4 parameters, and use global parameters for Area **
//** AllowMove and CheckPathing. Making it an icredibly easy function to use. **
//** **
//** Sliding Distances: **
//** - This is some general knowledge on the different distances and how to **
//** get them. **
//** - Sliding distances have change d in this version of the system. **
//** - The function call (KBS_Begin/Ex) now takes distance and duration **
//** parameters instead of startspeed and deceleration. **
//** - Therefore the parameter 'Distance' will set the length of the knockback **
//** while the parameter 'Duration" will set the time it will take. **
//** **
//***************************************************************************************
//***************************************************************************************
//** **
//** Implementation: **
//** - First off you need the NewGen world editor. This is a must. **
//** - Copy this trigger into your map. Or make a trigger in your map and **
//** convert it to custom text. Then copy this text into that trigger. **
//** - Now you will either need to export the special effects from this map to **
//** your map, or you will need your own. I do not take credit for the **
//** special effects found in this map. **
//** - Once you have the effects in your map. Find the configuration block **
//** that is underneath all this green text. Change the WATER_SFX and the **
//** DIRT_SFX strings to the ones in your map. These should be the same if **
//** you exported the ones from this map. **
//** - Make sure you have the dummy unit needed. It can be any unit, but i **
//** suggest you use the one found in this map, it is labelled 'Dummy Unit' **
//** or 'u000'. **
//** - Your done! Save your map, make a spell using this system and try it out. **
//** **
//** NOTE: Please report any bugs to me at thehelper.net via PM. (User name: kenny!)**
//** **
//***************************************************************************************
//***************************************************************************************
//** **
//** Usage: **
//** **
//** call KBS_Begin(Target,Distance,Duration,Angle,Area) **
//** or **
//**call KBS_BeginEx(Target,Distance,Duration,Angle,Effect,Area,AllowMove,CheckPathing)**
//** or **
//** call KBS_BeginCommon(Target,Distance,Duration,Angle) **
//** **
//** - Target - The unit that will be used in the knockback. **
//** - Distance - The distance of the knockback (how far the unit will slide). **
//** - Duration - The duration of the knockback refers to how long the unit **
//** will slide for. **
//** - Angle - The angle that the unit will be knocked back at. **
//** THIS MUST BE IN DEGREES. <- Easier for GUI users. **
//** - Effect - This is only used in the extended function. If you do not **
//** want one of the predefined effects, you can choose your own. **
//** However, this effect is attached to the unit and removed at **
//** the end, so non-looping or repeating effect wont work. **
//** - Area - This determines whether or not trees will be knocked down. **
//** For trees to be knocked down, a positive number (real) must **
//** be used, such as 150.00, which would give a radius of 150.00 **
//** in which trees will be knocked down. **
//** For trees to not be knocked down, a negative number (real) **
//** must be used, such as -150.00, which would create a radius **
//** that if a tree comes within it, the unit will stop moving. **
//** For none of those effects, the number 0 (0.00) can be used. **
//** This will just cause the units to "bounce" off trees. **
//** -Allowmove - This boolean will decided whether or not you want the unit **
//** to have the ability to move while being knocked back. **
//** "true" will allow them to move, while "false" will not. **
//** -CheckPathing - A boolean that, if true, will check for unpathable terrain **
//** such as a wall or cliff, or where doodads may be. If false **
//** it will ignore these changes and the unit will be pushed **
//** along the wall, cliff or doodad. **
//** **
//** REMEMBER: Positive = trees destroyed, Negative = trees not destroyed. **
//** **
//** Example of Usage: **
//** **
//** -call KBS_Begin(target,500.00,2.00,270.00,150.00) **
//** or **
//** -call KBS_BeginEx(target,500.00,2.00,270.00,"Effect.mdl",-150.00,true,true) **
//** **
//** The first one will cause the target unit of a spell to be knocked back 500.00 **
//** range over a 2.00 second duration. It will be knocked back at an angle of **
//** 270.00, which I'm pretty sure is south, and it will knock down trees within **
//** a 150.00 radius around the unit. **
//** **
//** The bottom one of the two will do the exact same as the top, however you are **
//** able to choose your own special effect that will be attached to the unit. As **
//** you can see, the number for Area (destroying trees) is negative, therefore **
//** no trees will be knocked down, and the unit will stop moving if it comes in **
//** contact with a tree. There is also an extra boolean nearing end, this is for **
//** allowing units to move while sliding. It is true, meaning units are allowed. **
//** There is also an added feature that will check for pathable terrain and stop a **
//** unit if it comes in contact with things such as walls, cliffs or doodads. **
//** If true, the unit will stop moving if it comes in direct contact will a wall **
//** or cliff. **
//** **
//***************************************************************************************
//***************************************************************************************
//** **
//** Other functions: **
//** **
//** - call KBS_IsUnitSliding(Target) **
//** **
//** - This function checks if a picked unit is currently sliding using this **
//** system. It will return true if it is. **
//** **
//** - call KBS_StopUnitSliding(Target) **
//** **
//** - This function will stop a picked unit from sliding (using this system). **
//** It also returns true if the unit is stopped. **
//** **
//** - These functions can be used in conjunction with each other, by checking if a **
//** unit is sliding then stopping it if it is. The regular Storm Bolt spell in **
//** the Test Spells section uses these two function in conjunction with each **
//** other as an example. **
//** **
//***************************************************************************************
//***************************************************************************************
//** **
//** Some points on checking for pathable terrain: **
//** **
//**` - The area specified for destroying trees must be at least 75.00-100.00 range **
//** larger than the distance for checking for pathing, which is below in the **
//** globals block. **
//** - When using KBS_BeginEx() and using either 0.00 or a negative value for the **
//** parameter 'Area' (destroying trees) it is better to have CheckPathing as **
//** FALSE. This is due to the fact that setting CheckPathing to TRUE will **
//** override the 'Area' Parameter and stop a unit if it gets near trees. **
//** - Basically what this means is that you cannot get a unit to just 'bounce' off **
//** trees anymore, it is either destroy trees or get stopped by them. **
//** **
//***************************************************************************************
globals
// CONFIGURABLES:
private constant integer DUMMY_ID = 'hpea' // This is the dummy unit.
private constant real INTERVAL = 0.04 // Recommended Interval.
private constant string ATTACH_POINT = "origin" // Attachment point for effects.
private constant string WATER_SFX = "" // Water slide effect.
private constant string DIRT_SFX = "" // Ground slide effect.
private constant string COLLISION_SFX = "Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissile.mdl" // Collision effect when unit hits a wall/cliff etc.
private constant boolean SHOW_COLLISION = true // Whether or not effect will show if a unit collides with a wall/cliff etc.
// The follow are used when using KBS_BeginCommon() for the common parameters that will be used.
private constant real COMMON_AREA = 150.00 // The area in which trees will be destroyed.
private constant boolean COMMON_ALLOW_MOVE = true // Whether or not to allow units to move.
private constant boolean COMMON_CHECK_PATHING = true // Whether or not to check pathing.
// The following raw codes will probably not need to be changed for most maps.
private constant integer HARVEST = 'Ahrl' // Raw code for: Harvest(Ghouls Lumber).
private constant integer LOCUST = 'Aloc' // Raw code for Locust ability.
// The following value is used for terrain pathability checking.
private constant real DISTANCE = 50.00
// The above is the distance in front of the unit that terrain pathability
// will be checked. A value of 40.00-50.00 is recommended. Also make sure
// that this distance is AT LEAST 75.00-100.00 units less than the ranges set
// for destroying trees, otherwise it wont work properly.
// Example: Keep above distance at 50.00, and use 150.00 for knocking down trees.
// This seems to work very well.
private constant real MAX_RANGE = 10.00
// Max range for checking for pathability. I suggest you leave this alone.
endglobals
//***************************************************************************************
//** **
//** DO NOT TOUCH BELOW HERE UNLESS YOU KNOW WHAT YOUR ARE DOING! **
//** **
//***************************************************************************************
private keyword Data
globals
private Data array D
private boolean array BA
private item array Hidden
private integer Hidden_max = 0
private integer Total = 0
private real Game_maxX = 0.00
private real Game_minX = 0.00
private real Game_maxY = 0.00
private real Game_minY = 0.00
private rect Rect1 = null
private unit Tree_dummy = null
private item Item = null
private timer Timer = null
private boolexpr Tree_filt = null
endglobals
//=======================================================================
private function Filter_items takes nothing returns nothing
if IsItemVisible(GetEnumItem()) then
set Hidden[Hidden_max] = GetEnumItem()
call SetItemVisible(Hidden[Hidden_max],false)
set Hidden_max = Hidden_max + 1
endif
endfunction
// Thanks to Vexorian for original concept, and Anitarf for the up-to-date version. (Slightly midified).
function Check_pathability takes real x1, real y1 returns boolean
local real x2 = 0.00
local real y2 = 0.00
call SetRect(Rect1,0.00,0.00,128.00,128.00)
call MoveRectTo(Rect1,x1,y1)
call EnumItemsInRect(Rect1,null,function Filter_items)
call SetItemPosition(Item,x1,y1)
set x2 = GetItemX(Item)
set y2 = GetItemY(Item)
call SetItemVisible(Item,false)
loop
exitwhen Hidden_max <= 0
set Hidden_max = Hidden_max - 1
call SetItemVisible(Hidden[Hidden_max],true)
set Hidden[Hidden_max] = null
endloop
return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) < MAX_RANGE * MAX_RANGE
endfunction
//=======================================================================
private function Destroy_trees takes nothing returns nothing
if BA[0] then
call KillDestructable(GetEnumDestructable()) // Used to destroy destructables.
else
set BA[1] = true
endif
endfunction
// Thanks to PitzerMike for this function. (Modified Slightly).
private function Check_trees takes nothing returns boolean
local destructable dest = GetFilterDestructable()
local boolean result = false
if GetDestructableLife(dest) > 0.405 then
call ShowUnit(Tree_dummy,true)
call SetUnitX(Tree_dummy,GetWidgetX(dest))
call SetUnitY(Tree_dummy,GetWidgetY(dest))
set result = IssueTargetOrder(Tree_dummy,"harvest",dest)
call IssueImmediateOrder(Tree_dummy,"stop")
call ShowUnit(Tree_dummy,false)
set dest = null
return result
endif
set dest = null
return result
endfunction
// Checks if a point is on the map boundaries.
private function Outside_bounds takes real x, real y returns boolean
return (x > Game_maxX or y > Game_maxY or x < Game_minX or y < Game_minY)
endfunction
//=======================================================================
private struct Data
unit targ = null
real speed = 0.00
real decrease = 0.00
real sin = 0.00
real cos = 0.00
real radius = 0.00
integer sfxmode = 0
effect sfx = null
boolean custom = false
boolean allowmove = false
boolean pathing = false
boolean forcestop = false
// Checking for terrain type.
method terrain takes nothing returns integer
local real x = GetUnitX(.targ)
local real y = GetUnitY(.targ)
if IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY) then
return 1
elseif not IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
return 2
endif
return 0
endmethod
static method create takes unit Target, real Distance, real Duration, real Angle, string Effect, real Area, boolean AllowMove, boolean CheckPathing returns Data
local Data d = Data.allocate()
// Allocates struct members to user defined variables.
set d.targ = Target
set d.speed = (2.00 * Distance) / (Duration + 1.00)
set d.decrease = d.speed / Duration
set d.sin = Sin(Angle)
set d.cos = Cos(Angle)
set d.radius = Area
set d.allowmove = AllowMove
set d.pathing = CheckPathing
set d.sfxmode = d.terrain()
if Effect != "" and Effect != null then
set d.custom = true
endif
// Adding effects to the unit.
if d.custom then
set d.sfx = AddSpecialEffectTarget(Effect,d.targ,ATTACH_POINT)
else
if d.sfxmode == 1 then
set d.sfx = AddSpecialEffectTarget(DIRT_SFX,d.targ,ATTACH_POINT)
elseif d.sfxmode == 2 then
set d.sfx = AddSpecialEffectTarget(WATER_SFX,d.targ,ATTACH_POINT)
endif
endif
return d
endmethod
private method onDestroy takes nothing returns nothing
set .targ = null
if .sfx != null then
call DestroyEffect(.sfx) // Destroys effects if needed.
set .sfx = null
endif
set BA[0] = false
set BA[1] = false
endmethod
endstruct
//=======================================================================
private function Update takes nothing returns nothing
local integer i = 1
local integer newmode = 0
local integer height = 0
local Data d = 0
local real x = 0.00
local real y = 0.00
local real newx = 0.00
local real newy = 0.00
loop
exitwhen i > Total
set d = D[i]
set newmode = d.sfxmode
set x = GetUnitX(d.targ)
set y = GetUnitY(d.targ)
// Destroys trees if wanted, or stops the unit
if d.radius != 0.00 then
set BA[0] = d.radius > 0.00
call SetRect(Rect1,x - d.radius,y - d.radius,x + d.radius,y + d.radius)
call EnumDestructablesInRect(Rect1,Tree_filt,function Destroy_trees)
endif
// Checks for terrain pathability, such as walls and cliffs.
if d.pathing then
if Check_pathability(x + DISTANCE * d.cos,y + DISTANCE * d.sin) == false then
set height = 1
if SHOW_COLLISION then
call DestroyEffect(AddSpecialEffect(COLLISION_SFX,x,y))
endif
endif
endif
if not d.custom then
set d.sfxmode = d.terrain() // Checks for pathing again.
// Adds special effect if terrain changes.
if d.sfxmode == 1 and newmode == 2 then
call DestroyEffect(d.sfx)
set d.sfx = AddSpecialEffectTarget(DIRT_SFX,d.targ,ATTACH_POINT)
elseif d.sfxmode == 2 and newmode == 1 then
call DestroyEffect(d.sfx)
set d.sfx = AddSpecialEffectTarget(WATER_SFX,d.targ,ATTACH_POINT)
endif
endif
if d.speed <= 0 or Outside_bounds(x,y) or BA[1] or height == 1 or d.forcestop == true then
call d.destroy() // Finish knockback
set D[i] = D[Total]
set Total = Total - 1
set i = i - 1
set height = 0
else
set newx = x + d.speed * d.cos
set newy = y + d.speed * d.sin
// Allows unit to move while sliding, if specified.
if d.allowmove then
call SetUnitX(d.targ,newx)
call SetUnitY(d.targ,newy)
else
call SetUnitPosition(d.targ,newx,newy)
endif
set d.speed = d.speed - d.decrease // Sets new speed.
endif
set i = i + 1
endloop
if Total <= 0 then
call PauseTimer(Timer)
set Total = 0
endif
endfunction
//=======================================================================
// Checks if a unit is sliding - returns true if it is.
public function IsUnitSliding takes unit Target returns boolean
local integer i = 1
loop
exitwhen i > Total
if D[i].targ == Target then
return true
endif
set i = i + 1
endloop
return false
endfunction
//=======================================================================
// Stops a unit from sliding - returns true if a unit is stopped.
public function StopUnitSliding takes unit Target returns boolean
local integer i = 1
loop
exitwhen i > Total
if D[i].targ == Target then
set D[i].forcestop = true
return true
endif
set i = i + 1
endloop
return false
endfunction
//=======================================================================
// Extended function - gives the most customisation for a single unit knockback.
public function BeginEx takes unit Target, real Distance, real Duration, real Angle, string Effect, real Area, boolean AllowMove, boolean CheckPathing returns boolean
local Data d = 0
if Target == null or UnitAlive(Target) == false or Distance <= 0.00 or Duration <= 0.00 or IsUnitType(Target,UNIT_TYPE_FLYING) == true or IsUnitType(Target,UNIT_TYPE_STRUCTURE) == true or GetUnitAbilityLevel(Target,'A03V') == 1 then
debug call BJDebugMsg("Error: Invalid input in KBS_Begin(Ex)") // Error message.
return false
endif
set d = Data.create(Target,Distance,(Duration/INTERVAL),(Angle * 0.01745328),Effect,Area,AllowMove,CheckPathing)
set Total = Total + 1
if Total == 1 then
call TimerStart(Timer,INTERVAL,true,function Update)
endif
set D[Total] = d
return true
endfunction
//=======================================================================
// Basic function - Can be used in a wide variety of ways and gives a basic knockback.
public function Begin takes unit Target, real Distance, real Duration, real Angle, real Area returns nothing
call BeginEx(Target,Distance,Duration,Angle,"",Area,false,false)
endfunction
// Common function - For all basic knockback needs, easy to use and simple to remember.
public function BeginCommon takes unit Target, real Distance, real Duration, real Angle returns nothing
call BeginEx(Target,Distance,Duration,Angle,null,COMMON_AREA,COMMON_ALLOW_MOVE,COMMON_CHECK_PATHING)
endfunction
//=======================================================================
// Sets map boundries and sets timer, rect and filter.
private function Init takes nothing returns nothing
set Timer = CreateTimer()
set Rect1 = Rect(0.00,0.00,1.00,1.00)
set Tree_filt = Filter(function Check_trees)
// Map bounds
set Game_maxX = GetRectMaxX(bj_mapInitialPlayableArea) - 64.00
set Game_maxY = GetRectMaxY(bj_mapInitialPlayableArea) - 64.00
set Game_minX = GetRectMinX(bj_mapInitialPlayableArea) + 64.00
set Game_minY = GetRectMinY(bj_mapInitialPlayableArea) + 64.00
// Boolean values for destroying trees
set BA[0] = false
set BA[1] = false
// Creating unit for destroying trees
set Tree_dummy = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),DUMMY_ID,0.00,0.00,0.00)
call SetUnitPathing(Tree_dummy,false)
call ShowUnit(Tree_dummy,false)
call UnitAddAbility(Tree_dummy,HARVEST)
call UnitAddAbility(Tree_dummy,LOCUST)
// Creating item for pathability checking
set Item = CreateItem('ciri',0.00,0.00)
call SetItemVisible(Item,false)
endfunction
endlibrary
//TESH.scrollpos=8
//TESH.alwaysfold=0
library WAAS initializer Init
globals //Do not touch
private unit EQUIPER = null
private unit UNEQUIPER = null
private timer TIMER = CreateTimer()
private integer array WEAPONID[100]
private integer array WEAPONABILITY[100]
private integer array ARMORID[100]
private integer array 1STARMORABILITY[100]
private integer array 2NDARMORABILITY[100]
private integer array ARMOREFFECT[100]
private integer array ARMORTYPE[100]
//These are modable
private constant integer CHAOSID='S000' //Chaos ability used by the system.
private constant integer UNEQUIPWEP=0
private constant integer UNEQUIPARM=0
private constant integer WEAPONMAX=100 //The ammount of weapons you have in use.
private constant integer ARMORMAX=30
endglobals
//You must set the ability/item ID's in the function below.
private function SetVars takes nothing returns nothing
set WEAPONID[1] = 0
set ARMORID[2] = 'I00D'
set ARMORID[3] = 'I02P'
endfunction
private function AddAbil takes nothing returns nothing
if IsPlayerInForce(GetOwningPlayer(EQUIPER),udg_Parasites) == true then
call UnitAddAbility(EQUIPER,'A005')
if GetUnitTypeId(EQUIPER) == 'h000' then
call UnitAddAbility(EQUIPER,'A011')
endif
endif
set EQUIPER = null
endfunction
private function Equip takes nothing returns nothing
local unit u = GetTriggerUnit()
local integer i = 1
local integer count
local boolean b = false
loop
exitwhen i ==ARMORMAX
if ARMORID[i] == GetItemTypeId(GetManipulatedItem()) then
set b = true
set count = i
endif
set i = i + 1
endloop
if b == true then
call UnitAddAbility(u,CHAOSID)
call SetUnitAbilityLevel(u,CHAOSID,count)
if EQUIPER == null then
set EQUIPER = GetTriggerUnit()
call TimerStart(TIMER,0.00,false,function AddAbil)
endif
endif
set u =null
endfunction
private function Init takes nothing returns nothing
local trigger equip = CreateTrigger()
local trigger unequip = CreateTrigger()
call TriggerAddAction(equip,function Equip)
call TriggerRegisterAnyUnitEventBJ(equip, EVENT_PLAYER_UNIT_USE_ITEM )
call SetVars()
endfunction
endlibrary
//TESH.scrollpos=6
//TESH.alwaysfold=0
library CreateDummy initializer int
globals
private unit array DUMMY
private integer count = 0
//Config
private constant integer DUMMYMAX = 100 //Max ammount of dummy units
private constant integer DUMMYID = 'hpea' //Unit ID of the dummy units
private constant player OWNER = Player(15) //Owner of dummy units when not in use
private constant real WAIT = 2 //Wait after map int before dummy units are created
endglobals
function CreateDummy takes player id, real x, real y, real face returns unit
set count = count + 1
if count == DUMMYMAX then
set count = 0
endif
call ShowUnit(DUMMY[count],true)
call SetUnitOwner(DUMMY[count],id,true)
call SetUnitX(DUMMY[count],x)
call SetUnitY(DUMMY[count],y)
call SetUnitFacingTimed(DUMMY[count],face,0)
return DUMMY[count]
endfunction
function KillDummy takes unit dummy returns boolean
if GetUnitTypeId(dummy) == DUMMYID then
call ShowUnit(dummy,false)
call SetUnitFlyHeight(dummy,0,0)
call SetUnitOwner(dummy,OWNER,true)
endif
return false
endfunction
private function int takes nothing returns nothing
local integer i = 0
call TriggerSleepAction(WAIT)
loop
exitwhen i == DUMMYMAX
set i = i + 1
set DUMMY[i] = CreateUnit(OWNER,DUMMYID,0,0,0)
call SetUnitUserData(DUMMY[i],i)
endloop
endfunction
endlibrary
//TESH.scrollpos=17
//TESH.alwaysfold=0
library Recycle
//settings
globals
public constant boolean AUTO_CLEAR = false
endglobals
/*Utility Information
//===================================================================
Name: Recycle
Version: 6.0
Author: Nestharus
-Help from Jesus4Lyf for initial designs
Description:
What does it do-
Recycles handles so that when getting new handles of the same type,
a recycled handle can be returned instead of creating a new handle. This
increases map performance.
Requirements: NA
Installation: NA
Variables:
------------------------------------------------------------------
AUTO_CLEAN-
If true, will automatically clear out recycled handles (GroupClear,
PauseTimer) at a slight performance hit.
Functions:
------------------------------------------------------------------
-get returns type
will return the type
Timer.get()
Group.get()
ex-
timer t = Timer.get()
-release(type h)
Will release the type and stop it.
Timer.release(h)
Group.release(h)
ex-
timer t = Timer.get()
Timer.release(t)
------------------------------------------------------------------*/
//! textmacro CREATE_STACK takes name, type, clean, create
struct $name$ extends array
public $type$ handles
public static integer index = 0
public static method release takes $type$ h returns nothing
static if DEBUG_MODE then
if h == null then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "ERROR - Recycle: Freed null handle.")
endif
if $name$.index > 8190 then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "ERROR - Recycle: Overfilled recycle stack (8191 released objects)!")
endif
endif
static if AUTO_CLEAR then
$clean$
endif
set $name$[$name$.index].handles = h
set $name$.index = $name$.index + 1
endmethod
public static method get takes nothing returns $type$
if $name$.index == 0 then
return $create$
endif
set $name$.index = $name$.index - 1
return $name$[$name$.index].handles
endmethod
endstruct
//! endtextmacro
//! runtextmacro CREATE_STACK("Timer", "timer", "call PauseTimer(h)", "CreateTimer()")
//! runtextmacro CREATE_STACK("Group", "group", "call GroupClear(h)", "CreateGroup()")
endlibrary
//TESH.scrollpos=21
//TESH.alwaysfold=0
library EffectZ
// _________________________________________
// +-----------------------------------------+
// | E F F E C T Z |
// +-----------------------------------------+
// | - Feel free to take these out of this |
// | library and put them directly into |
// | your code. |
// | - I don't care about credit. I haven't |
// | even included my name here. :] |
// +-----------------------------------------+
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
globals
private destructable D
private effect E
endglobals
function AddSpecialEffectZ takes string modelName, real x, real y, real z returns effect
set D = CreateDestructableZ( 'OTip', x, y, z, 0., 1., 0)
set E = AddSpecialEffect(modelName, x, y)
call RemoveDestructable(D)
return E
endfunction
function AddSpecialEffectLocZ takes string modelName, location where, real z returns effect
set D = CreateDestructableZ( 'OTip', GetLocationX(where), GetLocationY(where), z, 0., 1., 0)
set E = AddSpecialEffectLoc(modelName, where)
call RemoveDestructable(D)
return E
endfunction
endlibrary
//TESH.scrollpos=397
//TESH.alwaysfold=0
//
// _ ___ ___ ___ _______________________________________________
// /_\ |_ _| \/ __| || A D V A N C E D I N D E X I N G ||
// / _ \ | || |) \__ \ || A N D ||
// /_/ \_\___|___/|___/ || D A T A S T O R A G E ||
// By Jesus4Lyf ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// v 1.0.3
// What is AIDS?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// AIDS assigns unique integers between 1 and 8191 to units which enter
// the map. These can be used for arrays and data attaching.
//
// AIDS also allows you to define structs which are created automatically
// when units enter the map, and filtering which units should be indexed
// as well as for which units these structs should be created.
//
// How to implement?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Simply create a new trigger object called AIDS, go to 'Edit -> Convert
// to Custom Text', and replace everything that's there with this script.
//
// At the top of the script, there is a 'UnitIndexingFilter' constant
// function. If the function returns true for the unit, then that unit
// will be automatically indexed. Setting this to true will automatically
// index all units. Setting it to false will disable automatic indexing.
//
// Functions:
// ¯¯¯¯¯¯¯¯¯¯¯¯
// function GetUnitId takes unit u returns integer
// - This returns the index of an indexed unit. This will return 0
// if the unit has not been indexed.
// - This function inlines. It does not check if the unit needs an
// index. This function is for the speed freaks.
// - Always use this if 'UnitIndexingFilter' simply returns true.
//
// function GetUnitIndex takes unit u returns integer
// - This will return the index of a unit if it has one, or assign
// an index if the unit doesn't have one (and return the new index).
// - Use this if 'UnitIndexingFilter' doesn't return true.
//
// function GetIndexUnit takes integer index returns unit
// - This returns the unit which has been assigned the 'index'.
//
// AIDS Structs:
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// - Insert: //! runtextmacro AIDS() at the top of a struct to make it
// an AIDS struct.
// - AIDS structs cannot be created or destroyed manually. Instead, they
// are automatically created when an appropriate unit enters the map.
// - You cannot give members default values in their declaration.
// (eg: private integer i=5 is not allowed)
// - You cannot use array members.
// - AIDS structs must "extend array". This will remove some unused
// functions and enforce the above so there will be no mistakes.
// - There are four optional methods you can use in AIDS structs:
// - AIDS_onCreate takes nothing returns nothing
// - This is called when the struct is 'created' for the unit.
// - In here you can assign members their default values, which
// you would usually assign in their declarations.
// (eg: set this.i=5)
// - AIDS_onDestroy takes nothing returns nothing
// - This is called when the struct is 'destroyed' for the unit.
// - This is your substitute to the normal onDestroy method.
// - AIDS_filter takes unit u returns boolean
// - This is similar to the constant filter in the main system.
// - Each unit that enters the map will be tested by each AIDS
// struct filter. If it returns true for that unit, that unit
// will be indexed if it was not already, the AIDS struct will
// have its AIDS_onCreate method called, and later have its
// AIDS_onDestroy method called when the index is recycled.
// - Not declaring this will use the default AIDS filter instead.
// - AIDS_onInit takes nothing returns nothing
// - This is because I stole your onInit function with my textmacro.
// - You can use '.unit' from any AIDS struct to get the unit for which
// the struct is for.
// - The structs id will be the units index, so getting the struct for
// a unit inlines to a single native call, and you can typecast between
// different AIDS structs. This is the premise of AIDS.
// - Never create or destroy AIDS structs directly.
// - You can call .AIDS_addLock() and AIDS_removeLock() to increase or
// decrease the lock level on the struct. If a struct's lock level is
// not 0, it will not be destroyed until it is reduced to 0. Locks just
// put off AIDS struct destruction in case you wish to attach to a timer
// or something which must expire before the struct data disappears.
// Hence, not freeing all locks will leak the struct (and index).
//
// PUI and AutoIndex:
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// - AIDS includes the PUI textmacros and the AutoIndex module, because
// these systems are not compatible with AIDS but have valid and distinct
// uses.
// - The PUI textmacros are better to use for spells than AIDS structs,
// because they are not created for all units, just those targetted by
// the spell (or whatever else is necessary).
// - The AutoData module is good for very simple array syntax for data
// attachment (although I don't recommend that people actually use it,
// it's here mostly for compatability). Note that unlike the PUI textmacros,
// units must pass the AIDS filter in order for this module to work with
// them. This is exactly as the same as in AutoIndex itself (AutoIndex
// has a filter too).
//
// Thanks:
// ¯¯¯¯¯¯¯¯¯
// - Romek, for writing 90% of this user documentation, challenging my
// interface, doing some testing, suggesting improvements and inspiring
// me to re-do my code to include GetUnitIndex as non-inlining.
// - grim001, for writing the AutoData module, and AutoIndex. I used the
// on-enter-map method that he used. Full credits for the AutoData module.
// - Cohadar, for writing his PUI textmacros. Full credits to him for these,
// except for my slight optimisations for this system.
// Also, I have used an optimised version of his PeriodicRecycler from
// PUI in this system to avoid needing a RemoveUnitEx function.
// - Vexorian, for helping Cohadar on the PUI textmacro.
// - Larcenist, for suggesting the AIDS acronym. Originally he suggested
// 'Alternative Index Detection System', but obviously I came up with
// something better. In fact, I'd say it looks like the acronym was
// an accident. Kinda neat, don't you think? :P
//
// Final Notes:
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// - With most systems, I wouldn't usually add substitutes for alternative
// systems. However, UnitData systems are an exception, because they
// are incompatible with eachother. Since using this system forbids
// people from using the real PUI or AutoIndex, and a lot of resources
// use either of these, it made sense not to break them all.
//
// - If this documentation confused you as to how to use the system, just
// leave everything as default and use GetUnitId everywhere.
//
// - To use this like PUI (if you don't like spamming indices) simply
// make the AIDS filter return false, and use GetUnitIndex.
//
library AIDS initializer InitAIDS
//==============================================================================
// Configurables
//
globals
private constant real PERIOD = 0.03125 // Recycles 32 units/second max.
endglobals // Lower to be able to recycle faster.
private constant function UnitIndexingFilter takes unit u returns boolean
return true
endfunction
//==============================================================================
// System code
//
globals
// The unit stored at an index.
private unit array IndexUnit
private integer array LockLevel
endglobals
//==============================================================================
globals
// Recycle stack
private integer array RecycledIndex
private integer MaxRecycledIndex = 0
// Previous highest index
private integer MaxIndex = 0
endglobals
//==============================================================================
globals
private integer array DecayingIndex
private integer MaxDecayingIndex=0
private integer DecayChecker=0
endglobals
//==============================================================================
globals
// The Add/Remove stack (or assign/recycle stack).
//
// Indexing can become recusive since units can be created on index
// assignment or deallocation.
// To support this, a stack is used to store the event response results.
private integer ARStackLevel=0
private integer array ARStackIndex
private unit array ARStackUnit
// A later discovery revealed that the Add/Remove stack did not need to be
// used for deallocation. The alternative used works fine...
endglobals
public constant function GetEnteringIndexUnit takes nothing returns unit
return ARStackUnit[ARStackLevel]
endfunction
public function GetIndexOfEnteringUnit takes nothing returns integer
// Called in AIDS structs when units do not pass the initial AIDS filter.
if ARStackIndex[ARStackLevel]==0 then
// Get new index, from recycler first, else new.
// Store the current index on the (new) top level of the AR stack.
if MaxRecycledIndex==0 then // Get new.
set MaxIndex=MaxIndex+1
set ARStackIndex[ARStackLevel]=MaxIndex
else // Get from recycle stack.
set ARStackIndex[ARStackLevel]=RecycledIndex[MaxRecycledIndex]
set MaxRecycledIndex=MaxRecycledIndex-1
endif
// Store index on unit.
call SetUnitUserData(ARStackUnit[ARStackLevel],ARStackIndex[ARStackLevel])
set IndexUnit[ARStackIndex[ARStackLevel]]=ARStackUnit[ARStackLevel]
// Add index to recycle list.
set MaxDecayingIndex=MaxDecayingIndex+1
set DecayingIndex[MaxDecayingIndex]=ARStackIndex[ARStackLevel]
endif
return ARStackIndex[ARStackLevel]
endfunction
public constant function GetIndexOfEnteringUnitAllocated takes nothing returns integer
// Called in AIDS structs when units have passed the initial AIDS filter.
return ARStackIndex[ARStackLevel]
endfunction
public constant function GetDecayingIndex takes nothing returns integer
return DecayingIndex[DecayChecker]
endfunction
//==============================================================================
globals
// For structs and such which need to do things on unit index assignment.
private trigger OnEnter=CreateTrigger()
// The same, but for when units pass the initial filter anyway.
private trigger OnEnterAllocated=CreateTrigger()
// For structs and such which need to do things on unit index deallocation.
private trigger OnDeallocate=CreateTrigger()
endglobals
public function RegisterOnEnter takes boolexpr b returns triggercondition
return TriggerAddCondition(OnEnter,b)
endfunction
public function RegisterOnEnterAllocated takes boolexpr b returns triggercondition
return TriggerAddCondition(OnEnterAllocated,b)
endfunction
public function RegisterOnDeallocate takes boolexpr b returns triggercondition
return TriggerAddCondition(OnDeallocate,b)
endfunction
//==============================================================================
function GetIndexUnit takes integer index returns unit
debug if index==0 then
debug call BJDebugMsg("|cFFFF0000Error using AIDS:|r Trying to get the unit of index 0.")
debug elseif IndexUnit[index]==null then
debug call BJDebugMsg("|cFFFF0000Error using AIDS:|r Trying to get the unit of unassigned index.")
debug endif
return IndexUnit[index]
endfunction
function GetUnitId takes unit u returns integer
debug if u==null then
debug call BJDebugMsg("|cFFFF0000Error using AIDS:|r Trying to get the id (inlines) of null unit.")
debug elseif GetUnitUserData(u)==0 then
debug call BJDebugMsg("|cFFFF0000Error using AIDS:|r Trying to use GetUnitId (inlines) when you should be using GetUnitIndex (unit didn't pass filter).")
debug endif
return GetUnitUserData(u)
endfunction
globals//locals
private integer getindex
endglobals
function GetUnitIndex takes unit u returns integer // Cannot be recursive.
set getindex=GetUnitId(u)
if getindex==0 then
// Get new index, from recycler first, else new.
// Store the current index in getindex.
if MaxRecycledIndex==0 then // Get new.
set MaxIndex=MaxIndex+1
set getindex=MaxIndex
else // Get from recycle stack.
set getindex=RecycledIndex[MaxRecycledIndex]
set MaxRecycledIndex=MaxRecycledIndex-1
endif
// Store index on unit.
call SetUnitUserData(u,getindex)
set IndexUnit[getindex]=u
// Add index to recycle list.
set MaxDecayingIndex=MaxDecayingIndex+1
set DecayingIndex[MaxDecayingIndex]=getindex
// Do not fire things here. No AIDS structs will be made at this point.
endif
return getindex
endfunction
//==============================================================================
public function AddLock takes integer index returns nothing
set LockLevel[index]=LockLevel[index]+1
endfunction
public function RemoveLock takes integer index returns nothing
set LockLevel[index]=LockLevel[index]-1
endfunction
//==============================================================================
private function PeriodicRecycler takes nothing returns nothing
if MaxDecayingIndex>0 then
set DecayChecker=DecayChecker+1
if DecayChecker>MaxDecayingIndex then
set DecayChecker=1
endif
if GetUnitUserData(IndexUnit[DecayingIndex[DecayChecker]])==0 then
if LockLevel[DecayingIndex[DecayChecker]]==0 then
// Fire things.
call TriggerEvaluate(OnDeallocate)
// Add the index to the recycler stack.
set MaxRecycledIndex=MaxRecycledIndex+1
set RecycledIndex[MaxRecycledIndex]=DecayingIndex[DecayChecker]
// Null the unit.
set IndexUnit[DecayingIndex[DecayChecker]]=null
// Remove index from decay list.
set DecayingIndex[DecayChecker]=DecayingIndex[MaxDecayingIndex]
set MaxDecayingIndex=MaxDecayingIndex-1
endif
endif
endif
endfunction
//==============================================================================
public function IndexEnum takes nothing returns boolean // Can be recursive...
// Start by adding another level on the AR stack (for recursion's sake).
set ARStackLevel=ARStackLevel+1
// Store the current unit on the (new) top level of the AR stack.
set ARStackUnit[ARStackLevel]=GetFilterUnit()
if UnitIndexingFilter(ARStackUnit[ARStackLevel]) then
// Get new index, from recycler first, else new.
// Store the current index on the (new) top level of the AR stack.
if MaxRecycledIndex==0 then // Get new.
set MaxIndex=MaxIndex+1
set ARStackIndex[ARStackLevel]=MaxIndex
else // Get from recycle stack.
set ARStackIndex[ARStackLevel]=RecycledIndex[MaxRecycledIndex]
set MaxRecycledIndex=MaxRecycledIndex-1
endif
// Store index on unit.
call SetUnitUserData(ARStackUnit[ARStackLevel],ARStackIndex[ARStackLevel])
set IndexUnit[ARStackIndex[ARStackLevel]]=ARStackUnit[ARStackLevel]
// Add index to recycle list.
set MaxDecayingIndex=MaxDecayingIndex+1
set DecayingIndex[MaxDecayingIndex]=ARStackIndex[ARStackLevel]
// Fire things.
call TriggerEvaluate(OnEnter)
else
// The unit did not pass the filters, so does not need to be auto indexed.
// However, for certain AIDS structs, it may still require indexing.
// These structs may index the unit on their creation.
// We flag that an index must be assigned by setting the current index to 0.
set ARStackIndex[ARStackLevel]=0
// Fire things.
call TriggerEvaluate(OnEnter)
endif
// Decrement the stack.
set ARStackLevel=ARStackLevel-1
return false
endfunction
//==============================================================================
private function InitAIDS takes nothing returns nothing
local region r=CreateRegion()
local group g=CreateGroup()
local integer n=15
// This must be done first, due to recursion. :)
call RegionAddRect(r,bj_mapInitialPlayableArea)
call TriggerRegisterEnterRegion(CreateTrigger(),r,Condition(function IndexEnum))
set r=null
loop
call GroupEnumUnitsOfPlayer(g,Player(n),Condition(function IndexEnum))
//Enum every non-filtered unit on the map during initialization and assign it a unique
//index. By using GroupEnumUnitsOfPlayer, even units with Locust can be detected.
exitwhen n==0
set n=n-1
endloop
call DestroyGroup(g)
set g=null
call TimerStart(CreateTimer(),PERIOD,true,function PeriodicRecycler)
endfunction
//==============================================================================
public struct DEFAULT extends array
method AIDS_onCreate takes nothing returns nothing
endmethod
method AIDS_onDestroy takes nothing returns nothing
endmethod
static method AIDS_filter takes unit u returns boolean
if GetUnitTypeId(u) == 'sDoc' or GetUnitTypeId(u) == 'sTDc' or GetUnitId(u) > 0 or GetUnitTypeId(u) == 'hpea' then
return false
endif
return true
endmethod
static method AIDS_onInit takes nothing returns nothing
endmethod
endstruct
//===========================================================================
// Never create or destroy AIDS structs directly.
// Also, do not initialise members except by using the AIDS_onCreate method.
//===========================================================================
//! textmacro AIDS
// This magic line makes default methods get called which do nothing
// if the method are otherwise undefined.
private static delegate AIDS_DEFAULT AIDS_DELEGATE=0
//-----------------------------------------------------------------------
// Gotta know whether or not to destroy on deallocation...
private boolean AIDS_instanciated
//-----------------------------------------------------------------------
static method operator[] takes unit whichUnit returns thistype
return GetUnitId(whichUnit)
endmethod
method operator unit takes nothing returns unit
// Allows structVar.unit to return the unit.
return GetIndexUnit(this)
endmethod
//-----------------------------------------------------------------------
method AIDS_addLock takes nothing returns nothing
call AIDS_AddLock(this)
endmethod
method AIDS_removeLock takes nothing returns nothing
call AIDS_RemoveLock(this)
endmethod
//-----------------------------------------------------------------------
private static method AIDS_onEnter takes nothing returns boolean
// At this point, the unit might not have been assigned an index.
if thistype.AIDS_filter(AIDS_GetEnteringIndexUnit()) then
// Flag it for destruction on deallocation.
set thistype(AIDS_GetIndexOfEnteringUnit()).AIDS_instanciated=true
// Can use inlining "Assigned" function now, as it must be assigned.
call thistype(AIDS_GetIndexOfEnteringUnitAllocated()).AIDS_onCreate()
endif
return false
endmethod
private static method AIDS_onEnterAllocated takes nothing returns boolean
// At this point, the unit must have been assigned an index.
if thistype.AIDS_filter(AIDS_GetEnteringIndexUnit()) then
// Flag it for destruction on deallocation. Slightly faster!
set thistype(AIDS_GetIndexOfEnteringUnitAllocated()).AIDS_instanciated=true
// Can use inlining "Assigned" function now, as it must be assigned.
call thistype(AIDS_GetIndexOfEnteringUnitAllocated()).AIDS_onCreate()
endif
return false
endmethod
private static method AIDS_onDeallocate takes nothing returns boolean
if thistype(AIDS_GetDecayingIndex()).AIDS_instanciated then
call thistype(AIDS_GetDecayingIndex()).AIDS_onDestroy()
// Unflag destruction on deallocation.
set thistype(AIDS_GetDecayingIndex()).AIDS_instanciated=false
endif
return false
endmethod
//-----------------------------------------------------------------------
private static method onInit takes nothing returns nothing
call AIDS_RegisterOnEnter(Condition(function thistype.AIDS_onEnter))
call AIDS_RegisterOnEnterAllocated(Condition(function thistype.AIDS_onEnterAllocated))
call AIDS_RegisterOnDeallocate(Condition(function thistype.AIDS_onDeallocate))
// Because I robbed you of your struct's onInit method.
call thistype.AIDS_onInit()
endmethod
//! endtextmacro
endlibrary
library PUI uses AIDS
//===========================================================================
// Allowed PUI_PROPERTY TYPES are: unit, integer, real, boolean, string
// Do NOT put handles that need to be destroyed here (timer, trigger, ...)
// Instead put them in a struct and use PUI textmacro
//===========================================================================
//! textmacro PUI_PROPERTY takes VISIBILITY, TYPE, NAME, DEFAULT
$VISIBILITY$ struct $NAME$
private static unit array pui_unit
private static $TYPE$ array pui_data
//-----------------------------------------------------------------------
// Returns default value when first time used
//-----------------------------------------------------------------------
static method operator[] takes unit whichUnit returns $TYPE$
local integer pui = GetUnitId(whichUnit) // Changed from GetUnitIndex.
if .pui_unit[pui] != whichUnit then
set .pui_unit[pui] = whichUnit
set .pui_data[pui] = $DEFAULT$
endif
return .pui_data[pui]
endmethod
//-----------------------------------------------------------------------
static method operator[]= takes unit whichUnit, $TYPE$ whichData returns nothing
local integer pui = GetUnitIndex(whichUnit)
set .pui_unit[pui] = whichUnit
set .pui_data[pui] = whichData
endmethod
endstruct
//! endtextmacro
//===========================================================================
// Never destroy PUI structs directly.
// Use .release() instead, will call .destroy()
//===========================================================================
//! textmacro PUI
private static unit array pui_unit
private static integer array pui_data
private static integer array pui_id
//-----------------------------------------------------------------------
// Returns zero if no struct is attached to unit
//-----------------------------------------------------------------------
static method operator[] takes unit whichUnit returns integer
local integer pui = GetUnitId(whichUnit) // Changed from GetUnitIndex.
// Switched the next two lines for optimisation.
if .pui_unit[pui] != whichUnit then
if .pui_data[pui] != 0 then
// recycled index detected
call .destroy(.pui_data[pui])
set .pui_unit[pui] = null
set .pui_data[pui] = 0
endif
endif
return .pui_data[pui]
endmethod
//-----------------------------------------------------------------------
// This will overwrite already attached struct if any
//-----------------------------------------------------------------------
static method operator[]= takes unit whichUnit, integer whichData returns nothing
local integer pui = GetUnitIndex(whichUnit)
if .pui_data[pui] != 0 then
call .destroy(.pui_data[pui])
endif
set .pui_unit[pui] = whichUnit
set .pui_data[pui] = whichData
set .pui_id[whichData] = pui
endmethod
//-----------------------------------------------------------------------
// If you do not call release struct will be destroyed when unit handle gets recycled
//-----------------------------------------------------------------------
method release takes nothing returns nothing
local integer pui= .pui_id[integer(this)]
call .destroy()
set .pui_unit[pui] = null
set .pui_data[pui] = 0
endmethod
//! endtextmacro
endlibrary
library AutoIndex uses AIDS
module AutoData
private static thistype array data
// Fixed up the below to use thsitype instead of integer.
static method operator []= takes unit u, thistype i returns nothing
set .data[GetUnitId(u)] = i //Just attaching a struct to the unit
endmethod //using the module's thistype array.
static method operator [] takes unit u returns thistype
return .data[GetUnitId(u)] //Just returning the attached struct.
endmethod
endmodule
endlibrary
//TESH.scrollpos=545
//TESH.alwaysfold=0
//
// _ ___ ___ ___ _______________________________________________
// /_\ |_ _| \/ __| || A D V A N C E D I N D E X I N G ||
// / _ \ | || |) \__ \ || A N D ||
// /_/ \_\___|___/|___/ || D A T A S T O R A G E ||
// By Jesus4Lyf ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// v 1.1.0
// What is AIDS?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// AIDS assigns unique integers between 1 and 8191 to units which enter
// the map. These can be used for arrays and data attaching.
//
// AIDS also allows you to define structs which are created automatically
// when units enter the map, and filtering which units should be indexed
// as well as for which units these structs should be created.
//
// How to implement?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Simply create a new trigger object called AIDS, go to 'Edit -> Convert
// to Custom Text', and replace everything that's there with this script.
//
// Save the map, close it, reopen it, and then delete the "!" from the
// FAR left side of the next lines (so "external" will line up with this line):
//! external ObjectMerger w3a Adef AIDS anam "State Detection" ansf "(AIDS)" aart "" arac 0
//
// At the top of the script, there is a 'UnitIndexingFilter' constant
// function. If the function returns true for the unit, then that unit
// will be automatically indexed. Setting this to true will automatically
// index all units. Setting it to false will disable automatic indexing.
//
// Functions:
// ¯¯¯¯¯¯¯¯¯¯¯¯
// function GetUnitId takes unit u returns integer
// - This returns the index of an indexed unit. This will return 0
// if the unit has not been indexed.
// - This function inlines. It does not check if the unit needs an
// index. This function is for the speed freaks.
// - Always use this if 'UnitIndexingFilter' simply returns true.
//
// function GetUnitIndex takes unit u returns integer
// - This will return the index of a unit if it has one, or assign
// an index if the unit doesn't have one (and return the new index).
// - Use this if 'UnitIndexingFilter' doesn't return true.
//
// function GetIndexUnit takes integer index returns unit
// - This returns the unit which has been assigned the 'index'.
//
// AIDS Structs:
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// - Insert: //! runtextmacro AIDS() at the top of a struct to make it
// an AIDS struct.
// - AIDS structs cannot be created or destroyed manually. Instead, they
// are automatically created when an appropriate unit enters the map.
// - You cannot give members default values in their declaration.
// (eg: private integer i=5 is not allowed)
// - You cannot use array members.
// - AIDS structs must "extend array". This will remove some unused
// functions and enforce the above so there will be no mistakes.
// - There are four optional methods you can use in AIDS structs:
// - AIDS_onCreate takes nothing returns nothing
// - This is called when the struct is 'created' for the unit.
// - In here you can assign members their default values, which
// you would usually assign in their declarations.
// (eg: set this.i=5)
// - AIDS_onDestroy takes nothing returns nothing
// - This is called when the struct is 'destroyed' for the unit.
// - This is your substitute to the normal onDestroy method.
// - AIDS_filter takes unit u returns boolean
// - This is similar to the constant filter in the main system.
// - Each unit that enters the map will be tested by each AIDS
// struct filter. If it returns true for that unit, that unit
// will be indexed if it was not already, the AIDS struct will
// have its AIDS_onCreate method called, and later have its
// AIDS_onDestroy method called when the index is recycled.
// - Not declaring this will use the default AIDS filter instead.
// - AIDS_onInit takes nothing returns nothing
// - This is because I stole your onInit function with my textmacro.
// - You can use '.unit' from any AIDS struct to get the unit for which
// the struct is for.
// - The structs id will be the units index, so getting the struct for
// a unit inlines to a single native call, and you can typecast between
// different AIDS structs. This is the premise of AIDS.
// - Never create or destroy AIDS structs directly.
// - You can call .AIDS_addLock() and AIDS_removeLock() to increase or
// decrease the lock level on the struct. If a struct's lock level is
// not 0, it will not be destroyed until it is reduced to 0. Locks just
// put off AIDS struct destruction in case you wish to attach to a timer
// or something which must expire before the struct data disappears.
// Hence, not freeing all locks will leak the struct (and index).
//
// PUI and AutoIndex:
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// - AIDS includes the PUI textmacros and the AutoIndex module, because
// these systems are not compatible with AIDS but have valid and distinct
// uses.
// - The PUI textmacros are better to use for spells than AIDS structs,
// because they are not created for all units, just those targetted by
// the spell (or whatever else is necessary).
// - The AutoData module is good for very simple array syntax for data
// attachment (although I don't recommend that people actually use it,
// it's here mostly for compatability). Note that unlike the PUI textmacros,
// units must pass the AIDS filter in order for this module to work with
// them. This is exactly as the same as in AutoIndex itself (AutoIndex
// has a filter too).
//
// Thanks:
// ¯¯¯¯¯¯¯¯¯
// - Romek, for writing 90% of this user documentation, challenging my
// interface, doing some testing, suggesting improvements and inspiring
// me to re-do my code to include GetUnitIndex as non-inlining.
// - grim001, for writing the AutoData module, and AutoIndex. I used the
// on-enter-map method that he used. Full credits for the AutoData module.
// - Cohadar, for writing his PUI textmacros. Full credits to him for these,
// except for my slight optimisations for this system.
// Also, I have used an optimised version of his PeriodicRecycler from
// PUI in this system to avoid needing a RemoveUnitEx function.
// - Vexorian, for helping Cohadar on the PUI textmacro.
// - Larcenist, for suggesting the AIDS acronym. Originally he suggested
// 'Alternative Index Detection System', but obviously I came up with
// something better. In fact, I'd say it looks like the acronym was
// an accident. Kinda neat, don't you think? :P
//
// Final Notes:
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// - With most systems, I wouldn't usually add substitutes for alternative
// systems. However, UnitData systems are an exception, because they
// are incompatible with eachother. Since using this system forbids
// people from using the real PUI or AutoIndex, and a lot of resources
// use either of these, it made sense not to break them all.
//
// - If this documentation confused you as to how to use the system, just
// leave everything as default and use GetUnitId everywhere.
//
// - To use this like PUI (if you don't like spamming indices) simply
// make the AIDS filter return false, and use GetUnitIndex.
//
library AIDS initializer InitAIDS
//==============================================================================
// Configurables
//
globals
private constant boolean USE_PERIODIC_RECYCLER = false
private constant real PERIOD = 0.03125 // Recycles 32 units/second max.
// Lower to be able to recycle faster.
// Only used if USE_PERIODIC_RECYCLER
// is set to true.
private constant integer LEAVE_DETECTION_ABILITY = 'AIDS'
endglobals
private function UnitIndexingFilter takes unit u returns boolean
return true
endfunction
//==============================================================================
// System code
//
globals
// The unit stored at an index.
private unit array IndexUnit
private integer array LockLevel
endglobals
//==============================================================================
globals
// Recycle stack
private integer array RecycledIndex
private integer MaxRecycledIndex = 0
// Previous highest index
private integer MaxIndex = 0
endglobals
//==============================================================================
globals
private integer array DecayingIndex
private integer MaxDecayingIndex=0
private integer DecayChecker=0
endglobals
globals
private timer UndefendTimer=CreateTimer()
private integer array UndefendIndex
private integer UndefendStackIndex=0
endglobals
globals
private integer array UndefendExpiringIndex
private integer UndefendExpiringIndexLevel=0
endglobals
//==============================================================================
globals
// The Add/Remove stack (or assign/recycle stack).
//
// Indexing can become recusive since units can be created on index
// assignment or deallocation.
// To support this, a stack is used to store the event response results.
private integer ARStackLevel=0
private integer array ARStackIndex
private unit array ARStackUnit
// A later discovery revealed that the Add/Remove stack did not need to be
// used for deallocation. The alternative used works fine...
endglobals
public constant function GetEnteringIndexUnit takes nothing returns unit
return ARStackUnit[ARStackLevel]
endfunction
public function GetIndexOfEnteringUnit takes nothing returns integer
// Called in AIDS structs when units do not pass the initial AIDS filter.
if ARStackIndex[ARStackLevel]==0 then
// Get new index, from recycler first, else new.
// Store the current index on the (new) top level of the AR stack.
if MaxRecycledIndex==0 then // Get new.
set MaxIndex=MaxIndex+1
set ARStackIndex[ARStackLevel]=MaxIndex
else // Get from recycle stack.
set ARStackIndex[ARStackLevel]=RecycledIndex[MaxRecycledIndex]
set MaxRecycledIndex=MaxRecycledIndex-1
endif
// Store index on unit.
call SetUnitUserData(ARStackUnit[ARStackLevel],ARStackIndex[ARStackLevel])
set IndexUnit[ARStackIndex[ARStackLevel]]=ARStackUnit[ARStackLevel]
// Add index to recycle list.
set MaxDecayingIndex=MaxDecayingIndex+1
set DecayingIndex[MaxDecayingIndex]=ARStackIndex[ARStackLevel]
endif
return ARStackIndex[ARStackLevel]
endfunction
public constant function GetIndexOfEnteringUnitAllocated takes nothing returns integer
// Called in AIDS structs when units have passed the initial AIDS filter.
return ARStackIndex[ARStackLevel]
endfunction
public constant function GetDecayingIndex takes nothing returns integer
static if USE_PERIODIC_RECYCLER then
return DecayingIndex[DecayChecker]
else
return UndefendExpiringIndex[UndefendExpiringIndexLevel]
endif
endfunction
//==============================================================================
globals
// For structs and such which need to do things on unit index assignment.
private trigger OnEnter=CreateTrigger()
// The same, but for when units pass the initial filter anyway.
private trigger OnEnterAllocated=CreateTrigger()
// For structs and such which need to do things on unit index deallocation.
private trigger OnDeallocate=CreateTrigger()
endglobals
public function RegisterOnEnter takes boolexpr b returns triggercondition
return TriggerAddCondition(OnEnter,b)
endfunction
public function RegisterOnEnterAllocated takes boolexpr b returns triggercondition
return TriggerAddCondition(OnEnterAllocated,b)
endfunction
public function RegisterOnDeallocate takes boolexpr b returns triggercondition
return TriggerAddCondition(OnDeallocate,b)
endfunction
//==============================================================================
function GetIndexUnit takes integer index returns unit
debug if index==0 then
debug call BJDebugMsg("|cFFFF0000Error using AIDS:|r Trying to get the unit of index 0.")
debug elseif IndexUnit[index]==null then
debug call BJDebugMsg("|cFFFF0000Error using AIDS:|r Trying to get the unit of unassigned index.")
debug endif
return IndexUnit[index]
endfunction
function GetUnitId takes unit u returns integer
debug if u==null then
debug call BJDebugMsg("|cFFFF0000Error using AIDS:|r Trying to get the id (inlines) of null unit.")
debug elseif GetUnitUserData(u)==0 then
debug call BJDebugMsg("|cFFFF0000Error using AIDS:|r Trying to use GetUnitId (inlines) when you should be using GetUnitIndex (unit didn't pass filter).")
debug endif
return GetUnitUserData(u)
endfunction
globals//locals
private integer getindex
endglobals
function GetUnitIndex takes unit u returns integer // Cannot be recursive.
debug if u==null then
debug call BJDebugMsg("|cFFFF0000Error using AIDS:|r Trying to get the index of null unit.")
debug endif
set getindex=GetUnitUserData(u)
if getindex==0 then
// Get new index, from recycler first, else new.
// Store the current index in getindex.
if MaxRecycledIndex==0 then // Get new.
set MaxIndex=MaxIndex+1
set getindex=MaxIndex
else // Get from recycle stack.
set getindex=RecycledIndex[MaxRecycledIndex]
set MaxRecycledIndex=MaxRecycledIndex-1
endif
// Store index on unit.
call SetUnitUserData(u,getindex)
set IndexUnit[getindex]=u
static if USE_PERIODIC_RECYCLER then
// Add index to recycle list.
set MaxDecayingIndex=MaxDecayingIndex+1
set DecayingIndex[MaxDecayingIndex]=getindex
else
// Add leave detection ability.
call UnitAddAbility(ARStackUnit[ARStackLevel],LEAVE_DETECTION_ABILITY)
call UnitMakeAbilityPermanent(ARStackUnit[ARStackLevel],true,LEAVE_DETECTION_ABILITY)
endif
// Do not fire things here. No AIDS structs will be made at this point.
endif
return getindex
endfunction
//==============================================================================
public function AddLock takes integer index returns nothing
set LockLevel[index]=LockLevel[index]+1
endfunction
public function RemoveLock takes integer index returns nothing
set LockLevel[index]=LockLevel[index]-1
static if not USE_PERIODIC_RECYCLER then
if GetUnitUserData(IndexUnit[index])==0 and LockLevel[index]==0 then
// Increment stack for recursion.
set UndefendExpiringIndexLevel=UndefendExpiringIndexLevel+1
set UndefendExpiringIndex[UndefendExpiringIndexLevel]=index
// Fire things.
call TriggerEvaluate(OnDeallocate)
// Decrement stack for recursion.
set UndefendExpiringIndexLevel=UndefendExpiringIndexLevel-1
// Add the index to the recycler stack.
set MaxRecycledIndex=MaxRecycledIndex+1
set RecycledIndex[MaxRecycledIndex]=index
// Null the unit.
set IndexUnit[index]=null
endif
endif
endfunction
//==============================================================================
static if USE_PERIODIC_RECYCLER then
private function PeriodicRecycler takes nothing returns nothing
if MaxDecayingIndex>0 then
set DecayChecker=DecayChecker+1
if DecayChecker>MaxDecayingIndex then
set DecayChecker=1
endif
if GetUnitUserData(IndexUnit[DecayingIndex[DecayChecker]])==0 then
if LockLevel[DecayingIndex[DecayChecker]]==0 then
// Fire things.
call TriggerEvaluate(OnDeallocate)
// Add the index to the recycler stack.
set MaxRecycledIndex=MaxRecycledIndex+1
set RecycledIndex[MaxRecycledIndex]=DecayingIndex[DecayChecker]
// Null the unit.
set IndexUnit[DecayingIndex[DecayChecker]]=null
// Remove index from decay list.
set DecayingIndex[DecayChecker]=DecayingIndex[MaxDecayingIndex]
set MaxDecayingIndex=MaxDecayingIndex-1
endif
endif
endif
endfunction
else
private function UndefendFilter takes nothing returns boolean
return IsUnitType(GetFilterUnit(),UNIT_TYPE_DEAD)
endfunction
private function OnUndefendTimer takes nothing returns nothing
loop
exitwhen UndefendStackIndex==0
set UndefendStackIndex=UndefendStackIndex-1
set UndefendExpiringIndex[0]=UndefendIndex[UndefendStackIndex]
if IndexUnit[UndefendExpiringIndex[0]]!=null then
if GetUnitUserData(IndexUnit[UndefendExpiringIndex[0]])==0 then
if LockLevel[UndefendExpiringIndex[0]]==0 then
// Fire things.
call TriggerEvaluate(OnDeallocate)
// Add the index to the recycler stack.
set MaxRecycledIndex=MaxRecycledIndex+1
set RecycledIndex[MaxRecycledIndex]=UndefendExpiringIndex[0]
// Null the unit.
set IndexUnit[UndefendExpiringIndex[0]]=null
endif
endif
endif
endloop
endfunction
globals//locals
private integer UndefendFilterIndex
endglobals
private function OnUndefend takes nothing returns boolean
if GetIssuedOrderId()==852056 then // If undefend then...
set UndefendFilterIndex=GetUnitUserData(GetOrderedUnit())
if UndefendIndex[UndefendStackIndex-1]!=UndefendFilterIndex then // Efficiency perk.
set UndefendIndex[UndefendStackIndex]=UndefendFilterIndex
set UndefendStackIndex=UndefendStackIndex+1
call TimerStart(UndefendTimer,0,false,function OnUndefendTimer)
endif
endif
return false
endfunction
endif
//==============================================================================
public function IndexEnum takes nothing returns boolean // Can be recursive...
// Start by adding another level on the AR stack (for recursion's sake).
set ARStackLevel=ARStackLevel+1
// Store the current unit on the (new) top level of the AR stack.
set ARStackUnit[ARStackLevel]=GetFilterUnit()
if GetUnitUserData(ARStackUnit[ARStackLevel])==0 then // Has not been indexed.
if UnitIndexingFilter(ARStackUnit[ARStackLevel]) then
// Get new index, from recycler first, else new.
// Store the current index on the (new) top level of the AR stack.
if MaxRecycledIndex==0 then // Get new.
set MaxIndex=MaxIndex+1
set ARStackIndex[ARStackLevel]=MaxIndex
else // Get from recycle stack.
set ARStackIndex[ARStackLevel]=RecycledIndex[MaxRecycledIndex]
set MaxRecycledIndex=MaxRecycledIndex-1
endif
// Store index on unit.
call SetUnitUserData(ARStackUnit[ARStackLevel],ARStackIndex[ARStackLevel])
set IndexUnit[ARStackIndex[ARStackLevel]]=ARStackUnit[ARStackLevel]
static if USE_PERIODIC_RECYCLER then
// Add index to recycle list.
set MaxDecayingIndex=MaxDecayingIndex+1
set DecayingIndex[MaxDecayingIndex]=ARStackIndex[ARStackLevel]
else
// Add leave detection ability.
call UnitAddAbility(ARStackUnit[ARStackLevel],LEAVE_DETECTION_ABILITY)
call UnitMakeAbilityPermanent(ARStackUnit[ARStackLevel],true,LEAVE_DETECTION_ABILITY)
endif
// Fire things.
call TriggerEvaluate(OnEnter)
else
// The unit did not pass the filters, so does not need to be auto indexed.
// However, for certain AIDS structs, it may still require indexing.
// These structs may index the unit on their creation.
// We flag that an index must be assigned by setting the current index to 0.
set ARStackIndex[ARStackLevel]=0
// Fire things.
call TriggerEvaluate(OnEnter)
endif
endif
// Decrement the stack.
set ARStackLevel=ARStackLevel-1
return false
endfunction
//==============================================================================
private function InitAIDS takes nothing returns nothing
local region r=CreateRegion()
local group g=CreateGroup()
local integer n=15
static if USE_PERIODIC_RECYCLER then
call TimerStart(UndefendTimer,PERIOD,true,function PeriodicRecycler)
else
local trigger t=CreateTrigger()
loop
call TriggerRegisterPlayerUnitEvent(t,Player(n),EVENT_PLAYER_UNIT_ISSUED_ORDER,Filter(function UndefendFilter))
call SetPlayerAbilityAvailable(Player(n),LEAVE_DETECTION_ABILITY,false)
// Capture "undefend" orders.
exitwhen n==0
set n=n-1
endloop
set n=15
call TriggerAddCondition(t,Filter(function OnUndefend))
set t=null
endif
// This must be done first, due to recursion. :)
call RegionAddRect(r,GetWorldBounds())
call TriggerRegisterEnterRegion(CreateTrigger(),r,Filter(function IndexEnum))
set r=null
loop
call GroupEnumUnitsOfPlayer(g,Player(n),Filter(function IndexEnum))
//Enum every non-filtered unit on the map during initialization and assign it a unique
//index. By using GroupEnumUnitsOfPlayer, even units with Locust can be detected.
exitwhen n==0
set n=n-1
endloop
call DestroyGroup(g)
set g=null
endfunction
//==============================================================================
public struct DEFAULT extends array
method AIDS_onCreate takes nothing returns nothing
endmethod
method AIDS_onDestroy takes nothing returns nothing
endmethod
static method AIDS_filter takes unit u returns boolean
if GetUnitTypeId(u) == 'sDoc' or GetUnitTypeId(u) == 'sTDc' then
return false
endif
return UnitIndexingFilter(u)
endmethod
static method AIDS_onInit takes nothing returns nothing
endmethod
endstruct
//===========================================================================
// Never create or destroy AIDS structs directly.
// Also, do not initialise members except by using the AIDS_onCreate method.
//===========================================================================
//! textmacro AIDS
// This magic line makes default methods get called which do nothing
// if the methods are otherwise undefined.
private static delegate AIDS_DEFAULT AIDS_DELEGATE=0
//-----------------------------------------------------------------------
// Gotta know whether or not to destroy on deallocation...
private boolean AIDS_instanciated
//-----------------------------------------------------------------------
static method operator[] takes unit whichUnit returns thistype
return GetUnitId(whichUnit)
endmethod
method operator unit takes nothing returns unit
// Allows structVar.unit to return the unit.
return GetIndexUnit(this)
endmethod
//-----------------------------------------------------------------------
method AIDS_addLock takes nothing returns nothing
call AIDS_AddLock(this)
endmethod
method AIDS_removeLock takes nothing returns nothing
call AIDS_RemoveLock(this)
endmethod
//-----------------------------------------------------------------------
private static method AIDS_onEnter takes nothing returns boolean
// At this point, the unit might not have been assigned an index.
if thistype.AIDS_filter(AIDS_GetEnteringIndexUnit()) then
// Flag it for destruction on deallocation.
set thistype(AIDS_GetIndexOfEnteringUnit()).AIDS_instanciated=true
// Can use inlining "Assigned" function now, as it must be assigned.
call thistype(AIDS_GetIndexOfEnteringUnitAllocated()).AIDS_onCreate()
endif
return false
endmethod
private static method AIDS_onEnterAllocated takes nothing returns boolean
// At this point, the unit must have been assigned an index.
if thistype.AIDS_filter(AIDS_GetEnteringIndexUnit()) then
// Flag it for destruction on deallocation. Slightly faster!
set thistype(AIDS_GetIndexOfEnteringUnitAllocated()).AIDS_instanciated=true
// Can use inlining "Assigned" function now, as it must be assigned.
call thistype(AIDS_GetIndexOfEnteringUnitAllocated()).AIDS_onCreate()
endif
return false
endmethod
private static method AIDS_onDeallocate takes nothing returns boolean
if thistype(AIDS_GetDecayingIndex()).AIDS_instanciated then
call thistype(AIDS_GetDecayingIndex()).AIDS_onDestroy()
// Unflag destruction on deallocation.
set thistype(AIDS_GetDecayingIndex()).AIDS_instanciated=false
endif
return false
endmethod
//-----------------------------------------------------------------------
private static method onInit takes nothing returns nothing
call AIDS_RegisterOnEnter(Filter(function thistype.AIDS_onEnter))
call AIDS_RegisterOnEnterAllocated(Filter(function thistype.AIDS_onEnterAllocated))
call AIDS_RegisterOnDeallocate(Filter(function thistype.AIDS_onDeallocate))
// Because I robbed you of your struct's onInit method.
call thistype.AIDS_onInit()
endmethod
//! endtextmacro
endlibrary
library PUI uses AIDS
//===========================================================================
// Allowed PUI_PROPERTY TYPES are: unit, integer, real, boolean, string
// Do NOT put handles that need to be destroyed here (timer, trigger, ...)
// Instead put them in a struct and use PUI textmacro
//===========================================================================
//! textmacro PUI_PROPERTY takes VISIBILITY, TYPE, NAME, DEFAULT
$VISIBILITY$ struct $NAME$
private static unit array pui_unit
private static $TYPE$ array pui_data
//-----------------------------------------------------------------------
// Returns default value when first time used
//-----------------------------------------------------------------------
static method operator[] takes unit whichUnit returns $TYPE$
local integer pui = GetUnitId(whichUnit) // Changed from GetUnitIndex.
if .pui_unit[pui] != whichUnit then
set .pui_unit[pui] = whichUnit
set .pui_data[pui] = $DEFAULT$
endif
return .pui_data[pui]
endmethod
//-----------------------------------------------------------------------
static method operator[]= takes unit whichUnit, $TYPE$ whichData returns nothing
local integer pui = GetUnitIndex(whichUnit)
set .pui_unit[pui] = whichUnit
set .pui_data[pui] = whichData
endmethod
endstruct
//! endtextmacro
//===========================================================================
// Never destroy PUI structs directly.
// Use .release() instead, will call .destroy()
//===========================================================================
//! textmacro PUI
private static unit array pui_unit
private static integer array pui_data
private static integer array pui_id
//-----------------------------------------------------------------------
// Returns zero if no struct is attached to unit
//-----------------------------------------------------------------------
static method operator[] takes unit whichUnit returns integer
local integer pui = GetUnitId(whichUnit) // Changed from GetUnitIndex.
// Switched the next two lines for optimisation.
if .pui_unit[pui] != whichUnit then
if .pui_data[pui] != 0 then
// recycled index detected
call .destroy(.pui_data[pui])
set .pui_unit[pui] = null
set .pui_data[pui] = 0
endif
endif
return .pui_data[pui]
endmethod
//-----------------------------------------------------------------------
// This will overwrite already attached struct if any
//-----------------------------------------------------------------------
static method operator[]= takes unit whichUnit, integer whichData returns nothing
local integer pui = GetUnitIndex(whichUnit)
if .pui_data[pui] != 0 then
call .destroy(.pui_data[pui])
endif
set .pui_unit[pui] = whichUnit
set .pui_data[pui] = whichData
set .pui_id[whichData] = pui
endmethod
//-----------------------------------------------------------------------
// If you do not call release struct will be destroyed when unit handle gets recycled
//-----------------------------------------------------------------------
method release takes nothing returns nothing
local integer pui= .pui_id[integer(this)]
call .destroy()
set .pui_unit[pui] = null
set .pui_data[pui] = 0
endmethod
//! endtextmacro
endlibrary
library AutoIndex uses AIDS
module AutoData
private static thistype array data
// Fixed up the below to use thsitype instead of integer.
static method operator []= takes unit u, thistype i returns nothing
set .data[GetUnitId(u)] = i //Just attaching a struct to the unit
endmethod //using the module's thistype array.
static method operator [] takes unit u returns thistype
return .data[GetUnitId(u)] //Just returning the attached struct.
endmethod
endmodule
endlibrary
//TESH.scrollpos=5
//TESH.alwaysfold=0
library PauseSafety uses AIDS
private struct UnitData extends array
//! runtextmacro AIDS()
integer pauseLevel
private method AIDS_onDestroy takes nothing returns nothing
set this.pauseLevel=0
endmethod
endstruct
function SafePause takes unit whichUnit, boolean flag returns nothing
local UnitData dat=UnitData[whichUnit]
if flag then
set dat.pauseLevel=dat.pauseLevel+1
call PauseUnit(whichUnit,true)
call SetUnitTimeScalePercent(whichUnit,0)
else
set dat.pauseLevel=dat.pauseLevel-1
if dat.pauseLevel<=0 then
call PauseUnit(whichUnit,false)
call SetUnitTimeScalePercent(whichUnit,100)
set dat.pauseLevel=0
endif
endif
endfunction
endlibrary
//TESH.scrollpos=133
//TESH.alwaysfold=0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~ GT ~~ GTrigger ~~ By Jesus4Lyf ~~ Version 1.05 ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// What is GTrigger?
// - GTrigger is an event system that replaces the cumbersome WC3
// event system.
// - GTrigger only launches the necessary threads instead of x threads,
// where x is the number of times the event type occurs in the map.
//
// =Pros=
// - Instead of having 16 events (for "16" players) per use of an,
// event type, you have 0 per use and 16 total for that event type.
// - If you have 100 events of one type in your map, instead of firing
// 100 triggers each time any spell is cast, you fire only what's needed.
// - GTrigger is faster to code with, more efficient to execute, and just
// better programming practises and nicer code all round.
//
// =Cons=
// - If a trigger with a GTrigger event is destroyed, it must have its
// event unregistered first or it will leak an event (slows firing down).
// - Shouldn't use "wait" actions anywhere in the triggers.
//
// Functions:
// // General
// - GT_UnregisterTriggeringEvent()
//
// // Ability events
// - GT_RegisterStartsEffectEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_RegisterBeginsChanellingEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_RegisterBeginsCastingEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_RegisterStopsCastingEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_RegisterFinishesCastingEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_RegisterLearnsAbilityEvent(trigger, abilityid) (returns the trigger passed in)
// // Order events // (can use String2OrderIdBJ("OrderString") for orderid
// - GT_RegisterTargetOrderEvent(trigger, orderid) (returns the trigger passed in)
// - GT_RegisterPointOrderEvent(trigger, orderid) (returns the trigger passed in)
// - GT_RegisterNoTargetOrderEvent(trigger, orderid) (returns the trigger passed in)
// // Item events
// - GT_RegisterItemUsedEvent(trigger, itemtypeid) (returns the trigger passed in)
// - GT_RegisterItemAcquiredEvent(trigger, itemtypeid) (returns the trigger passed in)
// - GT_RegisterItemDroppedEvent(trigger, itemtypeid) (returns the trigger passed in)
// // Unit events
// - GT_RegisterUnitDiesEvent(trigger, unittypeid) (returns the trigger passed in)
//
// // Ability Events
// - GT_UnregisterSpellEffectEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_UnregisterBeginsChanellingEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_UnregisterBeginsCastingEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_UnregisterStopsCastingEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_UnregisterFinishesCastingEvent(trigger, abilityid) (returns the trigger passed in)
// - GT_UnregisterLearnsAbilityEvent(trigger, abilityid) (returns the trigger passed in)
// // Order events // (can use String2OrderIdBJ("OrderString") for orderid
// - GT_UnregisterTargetOrderEvent(trigger, orderid) (returns the trigger passed in)
// - GT_UnregisterPointOrderEvent(trigger, orderid) (returns the trigger passed in)
// - GT_UnregisterNoTargetOrderEvent(trigger, orderid) (returns the trigger passed in)
// // Item events
// - GT_UnregisterItemUsedEvent(trigger, itemtypeid) (returns the trigger passed in)
// - GT_UnregisterItemAcquiredEvent(trigger, itemtypeid) (returns the trigger passed in)
// - GT_UnregisterItemDroppedEvent(trigger, itemtypeid) (returns the trigger passed in)
// // Unit events
// - GT_UnregisterUnitDiesEvent(trigger, unittypeid) (returns the trigger passed in)
//
// Alternative interface (not recommended):
// If you aren't familiar with how this works, you shouldn't use it.
// All funcs must return false. (That is the only reason it isn't recommended.)
// // General
// - GT_RemoveTriggeringAction() // Use this to remove actions.
// // Ability Events
// - GT_AddStartsEffectAction(func, abilityid)
// - GT_AddBeginsChanellingActon(func, abilityid)
// - GT_AddBeginsCastingAction(func, abilityid)
// - GT_AddStopsCastingAction(func, abilityid)
// - GT_AddFinishesCastingAction(func, abilityid)
// - GT_AddLearnsAbilityAction(func, abilityid)
// // Order events // (can use String2OrderIdBJ("OrderString") for orderid
// - GT_AddTargetOrderAction(func, orderid)
// - GT_AddPointOrderAction(func, orderid)
// - GT_AddNoTargetOrderAction(func, orderid)
// // Item events
// - GT_AddItemUsedAction(func, itemtypeid)
// - GT_AddItemAcquiredAction(func, itemtypeid)
// - GT_AddItemDroppedAction(func, itemtypeid)
// // Unit events
// - GT_AddUnitDiesAction(func, unittypeid)
//
// Details:
// - Due to the storage method, only 8191 GTrigger events are possible at any one time.
//
// Thanks:
// - Daxtreme: For voluntarily testing this system and the UnitDies event idea.
// - kenny!: For the Order and Learns Ability event ideas.
//
// How to import:
// - Create a trigger named GT.
// - Convert it to custom text and replace the whole trigger text with this.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library GT initializer Init
//////////////
// Pointers //
////////////////////////////////////////////////////////////////////////////
// Assigned to abilities, and point to trigger grouping linked lists.
//
// Use:
// GetPointer --> int (pointer)
// FreePoifnter(int (pointer))
// set PointerTarget[int (pointer)]=int (list link)
// PointerTarget[int (pointer)] --> int (list link)
globals
// Pointer
private integer array PointerTarget
private integer PointerMax=0
// Spare Pointer Stack
private integer array NextPointer
private integer NextPointerMaxPlusOne=1
endglobals
private function GetPointer takes nothing returns integer
if NextPointerMaxPlusOne==1 then
set PointerMax=PointerMax+1
return PointerMax
endif
set NextPointerMaxPlusOne=NextPointerMaxPlusOne-1
return NextPointer[NextPointerMaxPlusOne]
endfunction
private function FreePointer takes integer pointer returns nothing
set PointerTarget[pointer]=0
set NextPointer[NextPointerMaxPlusOne]=pointer
set NextPointerMaxPlusOne=NextPointerMaxPlusOne+1
endfunction
///////////////////////////////////
// Trigger Grouping Linked Lists //
////////////////////////////////////////////////////////////////////////////
// Contains a chain of triggers to be executed together.
//
// Use:
// GetMem() --> int (mem)
// FreeMem(int (mem))
// Link(int (pointer), int (mem))
// Unlink(int (pointer), int (mem))
globals
// Spare Link Stack
private integer array NextMem
private integer NextMemMaxPlusOne=1
// Linked list
private trigger array Trig
private integer array Next
private integer array Prev
private integer TrigMax=0
endglobals
private function GetMem takes nothing returns integer
if NextMemMaxPlusOne==1 then
set TrigMax=TrigMax+1
return TrigMax
endif
set NextMemMaxPlusOne=NextMemMaxPlusOne-1
return NextMem[NextMemMaxPlusOne]
endfunction
private function FreeMem takes integer i returns nothing
set Trig[i]=null
set NextMem[NextMemMaxPlusOne]=i
set NextMemMaxPlusOne=NextMemMaxPlusOne+1
endfunction
// Linked list functionality
// NOTE: This means "Next" must be loaded BEFORE executing the trigger, which could delete the current link.
private function Link takes integer pointer, integer new returns nothing
set Prev[new]=0
set Next[new]=PointerTarget[pointer]
set Prev[PointerTarget[pointer]]=new
set PointerTarget[pointer]=new
endfunction
private function Unlink takes integer pointer, integer rem returns nothing
if Prev[rem]==0 then
set PointerTarget[pointer]=Next[rem]
set Prev[Next[rem]]=0
endif
set Next[Prev[rem]]=Next[rem]
set Prev[Next[rem]]=Prev[rem]
endfunction
//////////////////////
// GTrigger General //
////////////////////////////////////////////////////////////////////////////
// Only contains the UnregisterTriggeringEvent action for public use.
globals
boolean UnregisterLastEvent=false
endglobals
public function UnregisterTriggeringEvent takes nothing returns nothing
set UnregisterLastEvent=true
endfunction
/////////////////////////////////////
// GTrigger Ability Implementation //
////////////////////////////////////////////////////////////////////////////
// The nasty textmacro implementation of special "All Players" events.
//! textmacro SetupSpecialAllPlayersEvent takes NAME, EVENT, GETSPECIAL
globals
private trigger $NAME$Trigger=CreateTrigger()
// Extendable arrays
private integer array $NAME$AbilityIdA
private integer array $NAME$ListPointerA
private integer array $NAME$AbilityIdB
private integer array $NAME$ListPointerB
private integer array $NAME$AbilityIdC
private integer array $NAME$ListPointerC
private integer array $NAME$AbilityIdD
private integer array $NAME$ListPointerD
private integer array $NAME$AbilityIdE
private integer array $NAME$ListPointerE
endglobals
globals//locals
private integer GetOrCreateListPointer$NAME$AbilHashed
endglobals
private function GetOrCreate$NAME$ListPointer takes integer abil returns integer
set GetOrCreateListPointer$NAME$AbilHashed=abil-(abil/8191)*8191
if $NAME$AbilityIdA[GetOrCreateListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerA[GetOrCreateListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdA[GetOrCreateListPointer$NAME$AbilHashed]<1 then // Empty
set $NAME$AbilityIdA[GetOrCreateListPointer$NAME$AbilHashed]=abil
set $NAME$ListPointerA[GetOrCreateListPointer$NAME$AbilHashed]=GetPointer()
return $NAME$ListPointerA[GetOrCreateListPointer$NAME$AbilHashed]
endif
if $NAME$AbilityIdB[GetOrCreateListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerB[GetOrCreateListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdB[GetOrCreateListPointer$NAME$AbilHashed]<1 then // Empty
set $NAME$AbilityIdB[GetOrCreateListPointer$NAME$AbilHashed]=abil
set $NAME$ListPointerB[GetOrCreateListPointer$NAME$AbilHashed]=GetPointer()
return $NAME$ListPointerB[GetOrCreateListPointer$NAME$AbilHashed]
endif
if $NAME$AbilityIdC[GetOrCreateListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerC[GetOrCreateListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdC[GetOrCreateListPointer$NAME$AbilHashed]<1 then // Empty
set $NAME$AbilityIdC[GetOrCreateListPointer$NAME$AbilHashed]=abil
set $NAME$ListPointerC[GetOrCreateListPointer$NAME$AbilHashed]=GetPointer()
return $NAME$ListPointerC[GetOrCreateListPointer$NAME$AbilHashed]
endif
if $NAME$AbilityIdD[GetOrCreateListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerD[GetOrCreateListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdD[GetOrCreateListPointer$NAME$AbilHashed]<1 then // Empty
set $NAME$AbilityIdD[GetOrCreateListPointer$NAME$AbilHashed]=abil
set $NAME$ListPointerD[GetOrCreateListPointer$NAME$AbilHashed]=GetPointer()
return $NAME$ListPointerD[GetOrCreateListPointer$NAME$AbilHashed]
endif
if $NAME$AbilityIdE[GetOrCreateListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerE[GetOrCreateListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdE[GetOrCreateListPointer$NAME$AbilHashed]<1 then // Empty
set $NAME$AbilityIdE[GetOrCreateListPointer$NAME$AbilHashed]=abil
set $NAME$ListPointerE[GetOrCreateListPointer$NAME$AbilHashed]=GetPointer()
return $NAME$ListPointerE[GetOrCreateListPointer$NAME$AbilHashed]
endif
call BJDebugMsg("GTrigger Error: Ran out of storage locations for pointers on object "+GetObjectName(abil)+"!")
set PointerTarget[0]=0
return 0
endfunction
globals//locals
private integer GetListPointer$NAME$AbilHashed
endglobals
private function Get$NAME$ListPointer takes integer abil returns integer
set GetListPointer$NAME$AbilHashed=abil-(abil/8191)*8191
if $NAME$AbilityIdA[GetListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerA[GetListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdA[GetListPointer$NAME$AbilHashed]<1 then // Empty
set PointerTarget[0]=0 // Make sure.
return 0
endif
if $NAME$AbilityIdB[GetListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerB[GetListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdB[GetListPointer$NAME$AbilHashed]<1 then // Empty
set PointerTarget[0]=0 // Make sure.
return 0
endif
if $NAME$AbilityIdC[GetListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerC[GetListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdC[GetListPointer$NAME$AbilHashed]<1 then // Empty
set PointerTarget[0]=0 // Make sure.
return 0
endif
if $NAME$AbilityIdD[GetListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerD[GetListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdD[GetListPointer$NAME$AbilHashed]<1 then // Empty
set PointerTarget[0]=0 // Make sure.
return 0
endif
if $NAME$AbilityIdE[GetListPointer$NAME$AbilHashed]==abil then // Correct
return $NAME$ListPointerE[GetListPointer$NAME$AbilHashed]
elseif $NAME$AbilityIdE[GetListPointer$NAME$AbilHashed]<1 then // Empty
set PointerTarget[0]=0 // Make sure.
return 0
endif
call BJDebugMsg("GTrigger Error: Ran out of storage locations for pointers at ability "+GetObjectName(abil)+"!")
set PointerTarget[0]=0
return 0
endfunction
globals//locals
private integer Register$NAME$Mem
endglobals
public function Register$NAME$Event takes trigger t, integer abil returns trigger
set Register$NAME$Mem=GetMem()
set Trig[Register$NAME$Mem]=t
call Link(GetOrCreate$NAME$ListPointer(abil),Register$NAME$Mem)
return t
endfunction
globals//locals
private integer Unregister$NAME$Pointer
private integer Unregister$NAME$Mem
endglobals
public function Unregister$NAME$Event takes trigger t, integer abil returns trigger
set Unregister$NAME$Pointer=Get$NAME$ListPointer(abil)
set Unregister$NAME$Mem=PointerTarget[Unregister$NAME$Pointer]
loop
exitwhen Trig[Unregister$NAME$Mem]==t
if Unregister$NAME$Mem==0 then
return t // Not found.
endif
set Unregister$NAME$Mem=Next[Unregister$NAME$Mem]
endloop
call Unlink(Unregister$NAME$Pointer,Unregister$NAME$Mem)
call FreeMem(Unregister$NAME$Mem)
return t
endfunction
private function Trigger$NAME$Event takes nothing returns boolean
local integer Trigger$NAME$Pointer=Get$NAME$ListPointer($GETSPECIAL$)
local integer Trigger$NAME$Mem=PointerTarget[Trigger$NAME$Pointer]
local integer Trigger$NAME$NextMem
set UnregisterLastEvent=false
loop
exitwhen Trigger$NAME$Mem<1
set Trigger$NAME$NextMem=Next[Trigger$NAME$Mem]
if TriggerEvaluate(Trig[Trigger$NAME$Mem]) then
call TriggerExecute(Trig[Trigger$NAME$Mem])
endif
if UnregisterLastEvent then
set UnregisterLastEvent=false
call Unlink(Trigger$NAME$Pointer,Trigger$NAME$Mem)
call FreeMem(Trigger$NAME$Mem)
endif
set Trigger$NAME$Mem=Trigger$NAME$NextMem
endloop
return false
endfunction
private function Init$NAME$ takes nothing returns nothing
local integer i=bj_MAX_PLAYER_SLOTS
call TriggerAddCondition($NAME$Trigger,Condition(function Trigger$NAME$Event))
loop
set i=i-1
call TriggerRegisterPlayerUnitEvent($NAME$Trigger,Player(i),EVENT_PLAYER_$EVENT$,null)
exitwhen i==0
endloop
endfunction
//! endtextmacro
//! runtextmacro SetupSpecialAllPlayersEvent("StartsEffect", "UNIT_SPELL_EFFECT", "GetSpellAbilityId()")
//! runtextmacro SetupSpecialAllPlayersEvent("BeginsChanelling", "UNIT_SPELL_CHANNEL", "GetSpellAbilityId()")
//! runtextmacro SetupSpecialAllPlayersEvent("BeginsCasting", "UNIT_SPELL_CAST", "GetSpellAbilityId()")
//! runtextmacro SetupSpecialAllPlayersEvent("StopsCasting", "UNIT_SPELL_ENDCAST", "GetSpellAbilityId()")
//! runtextmacro SetupSpecialAllPlayersEvent("FinishesCasting", "UNIT_SPELL_FINISH", "GetSpellAbilityId()")
//! runtextmacro SetupSpecialAllPlayersEvent("TargetOrder", "UNIT_ISSUED_TARGET_ORDER", "GetIssuedOrderId()")
//! runtextmacro SetupSpecialAllPlayersEvent("PointOrder", "UNIT_ISSUED_POINT_ORDER", "GetIssuedOrderId()")
//! runtextmacro SetupSpecialAllPlayersEvent("NoTargetOrder", "UNIT_ISSUED_ORDER", "GetIssuedOrderId()")
//! runtextmacro SetupSpecialAllPlayersEvent("ItemUsed", "UNIT_USE_ITEM", "GetItemTypeId(GetManipulatedItem())")
//! runtextmacro SetupSpecialAllPlayersEvent("ItemAcquired", "UNIT_PICKUP_ITEM", "GetItemTypeId(GetManipulatedItem())")
//! runtextmacro SetupSpecialAllPlayersEvent("ItemDropped", "UNIT_DROP_ITEM", "GetItemTypeId(GetManipulatedItem())")
//! runtextmacro SetupSpecialAllPlayersEvent("UnitDies", "UNIT_DEATH", "GetUnitTypeId(GetTriggerUnit())")
//! runtextmacro SetupSpecialAllPlayersEvent("LearnsAbility", "HERO_SKILL", "GetLearnedSkill()")
// Note to self: Remember to update the Init function.
/////////////////////////////////////////
// GTrigger All Players Implementation //
////////////////////////////////////////////////////////////////////////////
// The textmacro implementation of other "All Players" events.
//! textmacro SetupAllPlayersEvent takes NAME, EVENT
globals
private trigger $NAME$Trigger=CreateTrigger()
private integer $NAME$ListPointer=0
endglobals
globals//locals
private integer Register$NAME$Mem
endglobals
public function Register$NAME$Event takes trigger t returns trigger
set Register$NAME$Mem=GetMem()
set Trig[Register$NAME$Mem]=t
call Link($NAME$ListPointer,Register$NAME$Mem)
return t
endfunction
globals//locals
private integer Unregister$NAME$Pointer
private integer Unregister$NAME$Mem
endglobals
public function Unregister$NAME$Event takes trigger t returns trigger
set Unregister$NAME$Mem=PointerTarget[$NAME$ListPointer]
loop
exitwhen Trig[Unregister$NAME$Mem]==t
if Unregister$NAME$Mem==0 then
return t // Not found.
endif
set Unregister$NAME$Mem=Next[Unregister$NAME$Mem]
endloop
call Unlink($NAME$ListPointer,Unregister$NAME$Mem)
call FreeMem(Unregister$NAME$Mem)
return t
endfunction
private function Trigger$NAME$Event takes nothing returns boolean
local integer Trigger$NAME$Mem=PointerTarget[$NAME$ListPointer]
local integer Trigger$NAME$NextMem
set UnregisterLastEvent=false
loop
exitwhen Trigger$NAME$Mem<1
set Trigger$NAME$NextMem=Next[Trigger$NAME$Mem]
if TriggerEvaluate(Trig[Trigger$NAME$Mem]) then
call TriggerExecute(Trig[Trigger$NAME$Mem])
endif
if UnregisterLastEvent then
set UnregisterLastEvent=false
call Unlink($NAME$ListPointer,Trigger$NAME$Mem)
call FreeMem(Trigger$NAME$Mem)
endif
set Trigger$NAME$Mem=Trigger$NAME$NextMem
endloop
return false
endfunction
private function Init$NAME$ takes nothing returns nothing
local integer i=bj_MAX_PLAYER_SLOTS
call TriggerAddCondition($NAME$Trigger,Condition(function Trigger$NAME$Event))
loop
set i=i-1
call TriggerRegisterPlayerUnitEvent($NAME$Trigger,Player(i),EVENT_PLAYER_UNIT_$EVENT$,null)
exitwhen i==0
endloop
// Initialise the pointer.
set $NAME$ListPointer=GetPointer()
endfunction
//! endtextmacro
// Old: //! runtextmacro SetupAllPlayersEvent("AnyUnitDies", "DEATH")
private function Init takes nothing returns nothing
// Ability events
call InitStartsEffect()
call InitBeginsChanelling()
call InitBeginsCasting()
call InitStopsCasting()
call InitFinishesCasting()
call InitLearnsAbility()
// Order events
call InitTargetOrder()
call InitPointOrder()
call InitNoTargetOrder()
// Item events
call InitItemUsed()
call InitItemAcquired()
call InitItemDropped()
// Unit events
call InitUnitDies()
endfunction
//////////////
// Wrappers //
////////////////////////////////////////////////////////////////////////////
// Wraps it up, for those who really want this interface.
// General
public function RemoveTriggeringAction takes nothing returns nothing
call UnregisterTriggeringEvent()
call DestroyTrigger(GetTriggeringTrigger())
endfunction
// Special All Player Events
//! textmacro AddSpecialAllPlayersWrapper takes EVENT
public function Add$EVENT$Action takes code func, integer special returns nothing
call TriggerAddCondition(Register$EVENT$Event(CreateTrigger(),special),Condition(func))
endfunction
//! endtextmacro
//! runtextmacro AddSpecialAllPlayersWrapper("StartsEffect")
//! runtextmacro AddSpecialAllPlayersWrapper("BeginsChanelling")
//! runtextmacro AddSpecialAllPlayersWrapper("BeginsCasting")
//! runtextmacro AddSpecialAllPlayersWrapper("StopsCasting")
//! runtextmacro AddSpecialAllPlayersWrapper("FinishesCasting")
//! runtextmacro AddSpecialAllPlayersWrapper("TargetOrder")
//! runtextmacro AddSpecialAllPlayersWrapper("PointOrder")
//! runtextmacro AddSpecialAllPlayersWrapper("NoTargetOrder")
//! runtextmacro AddSpecialAllPlayersWrapper("ItemUsed")
//! runtextmacro AddSpecialAllPlayersWrapper("ItemAcquired")
//! runtextmacro AddSpecialAllPlayersWrapper("ItemDropped")
//! runtextmacro AddSpecialAllPlayersWrapper("UnitDies")
//! runtextmacro AddSpecialAllPlayersWrapper("LearnsAbility")
// Note to self: Remember to update the Init function.
// All Player Events
//! textmacro AddAllPlayersWrapper takes EVENT
public function Add$EVENT$Action takes code func returns nothing
call TriggerAddCondition(Register$EVENT$Event(CreateTrigger()),Condition(func))
endfunction
//! endtextmacro
// Old: //! runtextmacro AddAllPlayersWrapper("AnyUnitDies")
endlibrary
//TESH.scrollpos=60
//TESH.alwaysfold=0
// ____ _ ____ _
// / ___| ___| |_| _ \ ___| | __ _ _ _
//| | _ / _ \ __| | | |/ _ \ |/ _` | | | |
//| |_| | __/ |_| |_| | __/ | (_| | |_| |
// \____|\___|\__|____/ \___|_|\__,_|\__, |
// |___/
// GetDelay v1.0c
//
// By cleeezzz, saw792, Jesus4Lyf, and Azlier
//
// What does it do?
// -Gets the delay/response time between the host and the players
//
// Pros
// -Don't know, you get the delay (Delay from player to host and then host to player
//
// Cons
// -A non-locust unit has to be created somewhere in the map
//
// How to use:
// -Set DUMMYID to the raw id of the dummy unit that will detect clicks, DO NOT USE THIS UNIT FOR ANYTHING ELSE.
// -Whenever you want to refresh everyone's delay, call the function DelayCalc like this --> call DelayCalc(), in GUI, Custom Script: call DelayCalc()
// -To retrieve a player's delay, use GetDelay(whichplayer) like this --> call GetDelay(Player(0)), which gives the delay of player 1, in GUI, i recommend creating a real variable, Custom Script: set udg_real = GetDelay(Player(0))
//
// How to import:
// - Either create a unit specifically for this system, or copy the Dummy unit the map
// - Create a trigger named GetDelay.
// - Convert it to custom text and replace the whole trigger text with this.
//
library GetDelay initializer Init
globals
//VALUES BELOW CAN BE MODIFIED
private constant integer DUMMYID = 'h000'//Can not have locust..., preferably set to Vex's model, dummy.mdx
private boolean TO_AND_FROM_HOST = false //Gets the time to ping from the player to the host and back. Set to false for just player to host. (Basically half of to and from)
private real MULTIPLIER = 1000. //If 1000., returns delay in Milliseconds, if 1., returns in Seconds.
//DO NO MODIFY BEYOND THIS LINE
private real array D
private group g = CreateGroup()
private timer T = CreateTimer()
private real Game_maxX
private real Game_maxY
private unit dummy
endglobals
function DelayCalc takes nothing returns nothing
local integer i = 0
local unit fog
if TimerGetRemaining(T) == 0 then
call ShowUnit(dummy,true)
loop
exitwhen i == 12
call SetUnitOwner(dummy,Player(i),true)
call GroupClear(g)
call GroupEnumUnitsSelected(g, Player(i),null)
if GetLocalPlayer() == Player(i) then
call ClearSelection()
call SelectUnit(dummy, true)
call ClearSelection()
loop
set fog = FirstOfGroup(g)
exitwhen fog == null
call SelectUnit(fog, true)
call GroupRemoveUnit(g,fog)
endloop
endif
set i = i + 1
endloop
call TimerStart(T, 5, false, null)
endif
endfunction
function GetDelay takes player p returns real
return D[GetPlayerId(p)]
endfunction
//====================================================
private function Conditions takes nothing returns boolean
if GetUnitTypeId(GetTriggerUnit()) == DUMMYID then
if TimerGetElapsed(T) != 0 then
if TO_AND_FROM_HOST == true then
set D[GetPlayerId(GetTriggerPlayer())] = TimerGetElapsed(T)*MULTIPLIER
else
set D[GetPlayerId(GetTriggerPlayer())] = (TimerGetElapsed(T)/2)*MULTIPLIER
endif
if GetLocalPlayer() == GetTriggerPlayer() then
call ShowUnit(dummy,false)
endif
endif
endif
return false
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
set Game_maxX = GetRectMaxX(bj_mapInitialPlayableArea)+50.00
set Game_maxY = GetRectMaxY(bj_mapInitialPlayableArea)+50.00
set dummy = CreateUnit(Player(13), DUMMYID, Game_maxX, Game_maxY, 0)
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SELECTED)
call TriggerAddCondition(t, Condition(function Conditions))
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~ Event ~~ By Jesus4Lyf ~~ Version 1.04 ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// What is Event?
// - Event simulates Warcraft III events. They can be created,
// registered for, fired and also destroyed.
// - Event, therefore, can also be used like a trigger "group".
// - This was created when there was an influx of event style systems
// emerging that could really benefit from a standardised custom
// events snippet. Many users were trying to achieve the same thing
// and making the same kind of errors. This snippet aims to solve that.
//
// Functions:
// - Event.create() --> Creates a new Event.
// - .destroy() --> Destroys an Event.
// - .fire() --> Fires all triggers which have been
// registered on this Event.
// - .register(trigger) --> Registers another trigger on this Event.
// - .unregister(trigger) --> Unregisters a trigger from this Event.
//
// Details:
// - Event is extremely efficient and lightweight.
// - It is safe to use with dynamic triggers.
// - Internally, it is just a linked list. Very simple.
//
// How to import:
// - Create a trigger named Event.
// - Convert it to custom text and replace the whole trigger text with this.
//
// Thanks:
// - Builder Bob for the trigger destroy detection method.
// - Azlier for inspiring this by ripping off my dodgier code.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library Event
///////////////
// EventRegs //
////////////////////////////////////////////////////////////////////////////
// For reading this far, you can learn one thing more.
// Unlike normal Warcraft III events, you can attach to Event registries.
//
// Event Registries are registrations of one trigger on one event.
// These cannot be created or destroyed, just attached to.
//
// It is VERY efficient for loading and saving data.
//
// Functions:
// - set eventReg.data = someStruct --> Store data.
// - eventReg.data --> Retreive data.
// - Event.getTriggeringEventReg() --> Get the triggering EventReg.
// - eventReg.destroy() --> Undo this registration.
//
private keyword destroyNode
struct EventReg extends array
integer data
method clear takes nothing returns nothing
set this.data=0
endmethod
method destroy takes nothing returns nothing
call Event(this).destroyNode()
endmethod
endstruct
private module Stack
static thistype top=0
static method increment takes nothing returns nothing
set thistype.top=thistype(thistype.top+1)
endmethod
static method decrement takes nothing returns nothing
set thistype.top=thistype(thistype.top-1)
endmethod
endmodule
private struct EventStack extends array
implement Stack
Event current
endstruct
struct Event
private trigger trig
private thistype next
private thistype prev
static method getTriggeringEventReg takes nothing returns EventReg
return EventStack.top.current
endmethod
static method create takes nothing returns Event
local Event this=Event.allocate()
set this.next=this
set this.prev=this
return this
endmethod
private static trigger currentTrigger
method fire takes nothing returns nothing
local thistype curr=this.next
call EventStack.increment()
loop
exitwhen curr==this
set thistype.currentTrigger=curr.trig
if IsTriggerEnabled(thistype.currentTrigger) then
set EventStack.top.current=curr
if TriggerEvaluate(thistype.currentTrigger) then
call TriggerExecute(thistype.currentTrigger)
endif
else
call EnableTrigger(thistype.currentTrigger) // Was trigger destroyed?
if IsTriggerEnabled(thistype.currentTrigger) then
call DisableTrigger(thistype.currentTrigger)
else // If trigger destroyed...
set curr.next.prev=curr.prev
set curr.prev.next=curr.next
call curr.deallocate()
endif
endif
set curr=curr.next
endloop
call EventStack.decrement()
endmethod
method register takes trigger t returns EventReg
local Event new=Event.allocate()
set new.prev=this.prev
set this.prev.next=new
set this.prev=new
set new.next=this
set new.trig=t
call EventReg(new).clear()
return new
endmethod
method destroyNode takes nothing returns nothing // called on EventReg
set this.prev.next=this.next
set this.next.prev=this.prev
call this.deallocate()
endmethod
method unregister takes trigger t returns nothing
local thistype curr=this.next
loop
exitwhen curr==this
if curr.trig==t then
set curr.next.prev=curr.prev
set curr.prev.next=curr.next
call curr.deallocate()
return
endif
set curr=curr.next
endloop
endmethod
method destroy takes nothing returns nothing
local thistype curr=this.next
loop
call curr.deallocate()
exitwhen curr==this
set curr=curr.next
endloop
endmethod
method chainDestroy takes nothing returns nothing
call this.destroy() // backwards compatability.
endmethod
endstruct
/////////////////////////////////////////////////////
// Demonstration Functions & Alternative Interface //
////////////////////////////////////////////////////////////////////////////
// What this would look like in normal WC3 style JASS (should all inline).
//
function CreateEvent takes nothing returns Event
return Event.create()
endfunction
function DestroyEvent takes Event whichEvent returns nothing
call whichEvent.chainDestroy()
endfunction
function FireEvent takes Event whichEvent returns nothing
call whichEvent.fire()
endfunction
function TriggerRegisterEvent takes trigger whichTrigger, Event whichEvent returns EventReg
return whichEvent.register(whichTrigger)
endfunction
// And for EventRegs...
function SetEventRegData takes EventReg whichEventReg, integer data returns nothing
set whichEventReg.data=data
endfunction
function GetEventRegData takes EventReg whichEventReg returns integer
return whichEventReg.data
endfunction
function GetTriggeringEventReg takes nothing returns integer
return Event.getTriggeringEventReg()
endfunction
endlibrary
//TESH.scrollpos=146
//TESH.alwaysfold=0
//
// ___ _ __ __ _ ___ ____ _______________________________
// | \ /_\ / |/ | /_\ / _\| __| || D E A L I T , ||
// | |) / _ \ / / | / |/ _ \| |/|| __| || D E T E C T I T , ||
// |___/_/ \_/_/|__/|_|_/ \_\___/|____| || B L O C K I T . ||
// By Jesus4Lyf ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// v 1.0.2
// What is Damage?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Damage is a damage dealing, detection and blocking system. It implements
// all such functionality. It also provides a means to detect what type
// of damage was dealt, so long as all damage in your map is dealt using
// this system's deal damage functions (except for basic attacks).
//
// It is completely recursively defined, meaning if you deal damage on
// taking damage, the type detection and other features like blocking
// will not malfunction.
//
// How to implement?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Create a new trigger object called Damage, go to 'Edit -> Convert to
// Custom Text', and replace everything that's there with this script.
//
// At the top of the script, there is a '//! external ObjectMerger' line.
// Save your map, close your map, reopen your map, and then comment out this
// line. Damage is now implemented. This line creates a dummy ability used
// in the system in some circumstances with damage blocking.
//
// Functions:
// ¯¯¯¯¯¯¯¯¯¯¯¯
// function Damage_RegisterEvent takes trigger whichTrigger returns nothing
// - This registers a special "any unit takes damage" event.
// - This event supports dynamic trigger use.
// - Only triggers registered on this event may block damage.
//
// function Damage_GetType takes nothing returns damagetype
// - This will get the type of damage dealt, like an event response,
// for when using a unit takes damage event (or the special event above).
//
// function Damage_IsPhysical takes nothing returns boolean
// function Damage_IsSpell takes nothing returns boolean
// function Damage_IsPure takes nothing returns boolean
// - Wrappers to simply check if Damage_GetType is certain types.
//
// function Damage_IsAttack takes nothing returns boolean
// - Checks if the damage is from a physical attack (so you can deal
// physical damage without it being registered as an actual attack).
//
// function Damage_Block takes real amount returns nothing
// function Damage_BlockAll takes nothing returns nothing
// - For use only with Damage_RegisterEvent.
// - Blocks 'amount' of the damage dealt.
// - Multiple blocks at once work correctly.
// - Blocking more than 100% of the damage will block 100% instead.
// - Damage_BlockAll blocks 100% of the damage being dealt.
//
// function Damage_EnableEvent takes boolean enable returns nothing
// - For disabling and re-enabling the special event.
// - Use it to deal damage which you do not want to be detected by
// the special event.
//
// function UnitDamageTargetEx takes lots of things returns boolean
// - Replaces UnitDamageTarget in your map, with the same arguments.
//
// function Damage_Physical takes unit source, unit target, real amount,
// attacktype whichType, boolean attack, boolean ranged returns boolean
// - A clean wrapper for physical damage.
// - 'attack' determines if this is to be treated as a real physical
// attack or just physical type damage.
// - 'ranged' determines if this is to be treated as a ranged or melee
// attack.
//
// function Damage_Spell takes unit source, unit target, real amount returns boolean
// - A clean wrapper for spell damage.
//
// function Damage_Pure takes unit source, unit target, real amount returns boolean
// - A clean wrapper for pure type damage (universal type, 100% damage).
//
// Thanks:
// ¯¯¯¯¯¯¯¯¯
// - Romek, for helping me find a better way to think about damage blocking.
//
library Damage initializer OnInit uses AIDS, Event
//============================================================
// external ObjectMerger w3a AIlz dprv anam "Life Bonus" ansf "(Damage System)" Ilif 1 500000 aite 0
globals
private constant integer LIFE_BONUS_ABIL='dprv'
endglobals
//============================================================
globals
private Event OnDamageEvent
private boolean EventEnabled=true
endglobals
public function RegisterEvent takes trigger whichTrigger returns nothing
call OnDamageEvent.register(whichTrigger)
endfunction
public function EnableEvent takes boolean enable returns nothing
set EventEnabled=enable
endfunction
//============================================================
globals
private integer TypeStackLevel=0
private damagetype array TypeStackValue
private boolean array TypeStackAttack
private real array ToBlock
endglobals
public function GetType takes nothing returns damagetype
return TypeStackValue[TypeStackLevel]
endfunction
public function IsAttack takes nothing returns boolean
return TypeStackAttack[TypeStackLevel]
endfunction
public function Block takes real amount returns nothing
set ToBlock[TypeStackLevel]=ToBlock[TypeStackLevel]+amount
endfunction
public function BlockAll takes nothing returns nothing
set ToBlock[TypeStackLevel]=ToBlock[TypeStackLevel]+GetEventDamage()
endfunction
//============================================================
globals
private integer BlockNum=0
private unit array BlockUnit
private real array BlockUnitLife
private real array BlockRedamage
private unit array BlockDamageSource
private timer BlockTimer=CreateTimer()
endglobals
//============================================================
globals
private unit array RemoveBoosted
private integer RemoveBoostedMax=0
private timer RemoveBoostedTimer=CreateTimer()
endglobals
globals//locals
private real BoostedLifeTemp
private unit BoostedLifeUnit
endglobals
private function RemoveBoostedTimerFunc takes nothing returns nothing
loop
exitwhen RemoveBoostedMax==0
set BoostedLifeUnit=RemoveBoosted[RemoveBoostedMax]
set BoostedLifeTemp=GetWidgetLife(BoostedLifeUnit)
call UnitRemoveAbility(BoostedLifeUnit,LIFE_BONUS_ABIL)
if BoostedLifeTemp>0.405 then
call SetWidgetLife(BoostedLifeUnit,BoostedLifeTemp)
endif
set RemoveBoostedMax=RemoveBoostedMax-1
endloop
endfunction
//============================================================
private keyword Detector // Darn, I actually had to do this. XD
globals//locals
private unit ForUnit
private real NextHealth
endglobals
private function OnDamageActions takes nothing returns boolean
if EventEnabled then
call OnDamageEvent.fire()
endif
if ToBlock[TypeStackLevel]!=0. then
//====================================================
// Blocking
set ForUnit=GetTriggerUnit()
set NextHealth=GetEventDamage()
if ToBlock[TypeStackLevel]>=NextHealth then
set NextHealth=GetWidgetLife(ForUnit)+NextHealth
else
set NextHealth=GetWidgetLife(ForUnit)+ToBlock[TypeStackLevel]
endif
call SetWidgetLife(ForUnit,NextHealth)
if GetWidgetLife(ForUnit)<NextHealth then
// NextHealth is over max health.
call UnitAddAbility(ForUnit,LIFE_BONUS_ABIL)
call SetWidgetLife(ForUnit,NextHealth)
set RemoveBoostedMax=RemoveBoostedMax+1
set RemoveBoosted[RemoveBoostedMax]=ForUnit
call ResumeTimer(RemoveBoostedTimer)
endif
//====================================================
set ToBlock[TypeStackLevel]=0.
endif
return false
endfunction
//============================================================
function UnitDamageTargetEx takes unit whichUnit, widget target, real amount, boolean attack, boolean ranged, attacktype attackType, damagetype damageType, weapontype weaponType returns boolean
local boolean result
set TypeStackLevel=TypeStackLevel+1
set TypeStackValue[TypeStackLevel]=damageType
set TypeStackAttack[TypeStackLevel]=attack
set result=UnitDamageTarget(whichUnit,target,amount,attack,ranged,attackType,damageType,weaponType)
set TypeStackLevel=TypeStackLevel-1
return result
endfunction
//! textmacro Damage__DealTypeFunc takes NAME, TYPE
public function $NAME$ takes unit source, unit target, real amount returns boolean
return UnitDamageTargetEx(source,target,amount,false,false,ATTACK_TYPE_NORMAL,$TYPE$,WEAPON_TYPE_WHOKNOWS)
endfunction
public function Is$NAME$ takes nothing returns boolean
return GetType()==$TYPE$
endfunction
//! endtextmacro
//! runtextmacro Damage__DealTypeFunc("Pure","DAMAGE_TYPE_UNIVERSAL")
//! runtextmacro Damage__DealTypeFunc("Spell","DAMAGE_TYPE_MAGIC")
// Uses different stuff, but works much the same way.
public function Physical takes unit source, unit target, real amount, attacktype whichType, boolean attack, boolean ranged returns boolean
return UnitDamageTargetEx(source,target,amount,attack,ranged,whichType,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
endfunction
public function IsPhysical takes nothing returns boolean
return GetType()==DAMAGE_TYPE_NORMAL
endfunction
//============================================================
private struct Detector extends array // Uses AIDS.
//! runtextmacro AIDS()
private static conditionfunc ACTIONS_COND
private trigger t
private method AIDS_onCreate takes nothing returns nothing
set this.t=CreateTrigger()
call TriggerAddCondition(this.t,thistype.ACTIONS_COND)
call TriggerRegisterUnitEvent(this.t,this.unit,EVENT_UNIT_DAMAGED)
endmethod
private method AIDS_onDestroy takes nothing returns nothing
call DestroyTrigger(this.t)
endmethod
private static method AIDS_onInit takes nothing returns nothing
set thistype.ACTIONS_COND=Condition(function OnDamageActions)
endmethod
endstruct
//============================================================
private function OnInit takes nothing returns nothing
local unit abilpreload=CreateUnit(Player(15),'uloc',0,0,0)
call UnitAddAbility(abilpreload,LIFE_BONUS_ABIL)
call RemoveUnit(abilpreload)
set abilpreload=null
set OnDamageEvent=Event.create()
set TypeStackValue[TypeStackLevel]=DAMAGE_TYPE_NORMAL
set TypeStackAttack[TypeStackLevel]=true
call TimerStart(RemoveBoostedTimer,0.0,false,function RemoveBoostedTimerFunc)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
// Autofly - by Azlier
// Requires a vJass preprocessor
// How to import:
// 1. Create a new trigger called AutoFly.
// 2. Convert the trigger to custom script, and replace all the code inside with this.
library_once AutoFly
private function Actions takes nothing returns boolean
if UnitAddAbility(GetFilterUnit(), 'Amrf') then
call UnitRemoveAbility(GetFilterUnit(), 'Amrf')
endif
return false
endfunction
private struct Hack extends array
static method onInit takes nothing returns nothing
local region r = CreateRegion()
local rect re = GetWorldBounds()
local group g = CreateGroup()
local integer i = 15
call RegionAddRect(r, re)
call TriggerRegisterEnterRegion(CreateTrigger(), r, Filter(function Actions))
call RemoveRect(re)
set re = null
loop
call GroupEnumUnitsOfPlayer(g, Player(i), Filter(function Actions))
exitwhen i == 0
set i = i - 1
endloop
call DestroyGroup(g)
set g = null
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Projectile initializer OnInit requires AIDS, T32, Event, Vector, AutoFly, GroupUtils, ListModule
//------------------------------------------------------------------------\\
// ____ _ _ _ _ \\
// | _ \ _ __ ___ (_) ___ ___| |_(_) | ___ \\
// | |_) | '__/ _ \| |/ _ \/ __| __| | |/ _ \ \\
// | __/| | | (_) | | __/ (__| |_| | | __/ \\
// |_| |_| \___// |\___|\___|\__|_|_|\___| \\
// |__/ By Kenny v1.0.0 (Beta) \\
// \\
//------------------------------------------------------------------------\\
// \\
// What is Projectile? \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// Projectile is a basic projectile system for simple and advanced \\
// custom spells. This system provides users with a simple interface \\
// that gives great control over projectiles in a map. Users can: \\
// \\
// - Create normal Projectiles using the simplest of methods \\
// available. \\
// - Create more advanced projectiles by extending structs and \\
// using bonus features. \\
// - Group Projectiles in range of XYZ coordinates (not available \\
// in most similar systems). \\
// - Register triggers to execute when two projectiles collide and \\
// do stuff with them. \\
// \\
// Projectile also has an internal BoundSentinel so that projectiles \\
// that are about to leave the map are destroyed before they can \\
// cause a crash. This internal BoundSentinel will also prevent \\
// other units from leaving the map (including user made projectiles \\
// not from this system). Therefore users can delete BoundSentinel \\
// if they use this. \\
// \\
// Thanks and credits: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// To Jesus4Lyf for AIDS, T32 and Event. \\
// To Azlier for AutoFly. \\
// To Anitarf for Vector. \\
// To Rising_Dusk for GroupUtils. \\
// To Vexorian for BoundSentinel and JassHelper. \\
// To Weep for discussing an efficient way to do collision detection. \\
// \\
// How to implement: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// Simply create a new trigger object called Projectile, go to: \\
// 'Edit -> Convert to Custom Text', and replace everything that's \\
// there with this script. \\
// \\
// Make sure you implement all the required systems for this system. \\
// That includes: AIDS, T32, Event, Vector, AutoFly, GroupUtils and \\
// Linked List Module. \\
// \\
// Next you have to make sure that you have the dummy.mdx model in \\
// your map before you continue importing this system. The dummy model \\
// can be found in the import section of this test map. \\
// \\
// Save the map, close it, reopen it, then delete the "!" from the \\
// start of the next line (so "external" lines up with this line): \\
// external ObjectMerger w3u ushd proj unam "Projectile Dummy" uabi Aloc uble 0 ucbs 0 ucpt 0 ushr 0000 umxp 0 umxr 0 umdl "dummy.mdl" uimz 0 ulpz 0 uprw 1 ushu "" uspa "" umvs 1 umas 1 umis 1 umvr 0.10 ucol 0 ufle 0000 usnd "" ufoo 0 ubba 0 ubdi 0 ubsi 0 uhom 0001 usid 1 usin 1 utyp "" upgr "" utip "" utub ""
// \\
// After you have done that, you are ready to use this system. Enjoy. \\
// \\
// Projectile API: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// Methods available: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// These methods are available to users who wish to use the most \\
// basic of interfaces. \\
// \\
// - Projectile.create(xPos,yPos,zPos,facing) --> Projectile \\
// \\
// The above will create a projectile at a desired location. The \\
// first three agruments in the create method refer to the x, y and \\
// z coordinates where you want the projectile to be created. The \\
// last of the arguments refers to which direction (in radians) you \\
// want the projectile to face initially. \\
// \\
// - .projectNormal(xPos,yPos,zPos,speed) --> Nothing \\
// \\
// The above will start the projectile moving towards a desired \\
// location. The first three arguments refer to the x, y and z \\
// coordinates of where you would like the projectile to travel to. \\
// The last argument refers to the speed at which you want the \\
// projectile to move. The speed is in units per second. \\
// \\
// - .projectArcing(xPos,yPos,zPos,speed,maxHeight) --> Nothing \\
// \\
// The above will start the projectile moving towards a desired \\
// location. The first three arguments refer to the x, y and z \\
// coordinates of where you would like the projectile to travel to. \\
// The second last argument refers to the speed at which you want \\
// the projectile to move. The speed is in units per second. The \\
// last argument refers to the maximum height of the arc of the \\
// projectile. \\
// \\
// - .modifyTargeting(xPos,yPos,zPos) --> Nothing \\
// \\
// The above will determine the new target coordinates of the \\
// projectile, thus changing its trajectory accordingly. The three \\
// arguments refer to the new x, y and z coordinates of the wanted \\
// target location. \\
// \\
// - .modifyPositioning(xPos,yPos,zPos) --> Nothing \\
// \\
// The above will set a given projectiles new position coordinates. \\
// The arguments for this method are the new x, y and z coordnates \\
// that the user must provide. This method was really just added for \\
// system completion, but there definately are uses for it. \\
// \\
// - .modifySpeed(speed) --> Nothing \\
// \\
// The above method will modify the speed of the projectile to what \\
// the user has specified. The argument is the new speed that has \\
// to be in units per second. Users can use other struct members to \\
// retrieve original, previous and current speeds. \\
// \\
// - .isUnitInHeightRange(whichUnit) --> Boolean \\
// \\
// The above is somewhat of a bonus feature that users can make use \\
// of when the projectile hits a unit. The boolean returned by this \\
// method tells us if the unit is within collision distance of the \\
// projectile in regards to unit and projectile height. This method \\
// makes simple vertical collision easier for users. The one unit \\
// argument refers to the unit you want to check. \\
// \\
// - .terminate() --> Nothing \\
// \\
// The above method will destroy a projectile and all data that is \\
// associated with it. This can be called at any time while a \\
// projectile is alive, and multiple calls accidently will not \\
// damage anything. \\
// \\
// Bonus functions available: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// These functions are available to users to give greater control over \\
// projectiles in a map. They use function interfaces, so you may need \\
// to read up on them if you want to use these. \\
// \\
// The onStart, onLoop, onFinish and onLand functions that users \\
// declare MUST take a Projectile argument and return nothing. For \\
// example: \\
// \\
// function OnStart takes Projectile p returns nothing \\
// // Do stuff with p here. \\
// endfunction \\
// \\
// The onProj function that users declare MUST take two Projectile \\
// arguments and return nothing. For example: \\
// \\
// function OnProj takes Projectile p1, Projectile p2 returns nothing \\
// // Do stuff with p1 and p2 here. \\
// endfunction \\
// \\
// The onUnit function that users declare MUST take one Projectile \\
// argument and one unit argument and return nothing. For example: \\
// \\
// function OnProj takes Projectile p, unit u returns nothing \\
// // Do stuff with p and u here. \\
// endfunction \\
// \\
// - .onStart --> Users can declare their own function to be \\
// executed when the projectile is launched. \\
// \\
// - .onLoop --> Users can declare their own function to be \\
// executed each iteration of the timer. \\
// \\
// - .onFinish --> Users can declare their own function to be \\
// executed when the projectile has ended. \\
// \\
// - .onLand --> Users can declare their own function to be \\
// executed when the projectile hits ground. \\
// \\
// - .onProj --> Users can declare their own function to be \\
// executed when the proj hits another proj. \\
// \\
// - .onUnit --> Users can declare their own function to be \\
// executed when the projectile hits a unit. \\
// \\
// Public members available: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// These members are available for users to freely change and modify \\
// at any time throughout the projectiles life span. However, unless \\
// you fully understand how they work, it is recommended that you \\
// set them only after you create the projectile and no where else. \\
// \\
// - .caster --> The casting unit of a projectile spell. Can \\
// be null if the projectile is just for effect. \\
// The caster is not automatically the owner. \\
// - .target --> The target unit of a projectile spell. A \\
// spell must have a target for homing to be \\
// enabled. Projectiles don't need targets. \\
// - .owner --> The owning player of the projectile, and \\
// commonly of the casting unit as well. This \\
// must be set separately to the caster. \\
// - .timedLife --> Gives the projectile a life span. By \\
// default projectiles an unlimited life span. \\
// Timed life should be in seconds. \\
// - .scaleSize --> Sets the scale size of the projectile. Due to \\
// warcraft limitations this can only be set and \\
// not retrieved. \\
// - .unitDamage --> Many users will definately need to save damage \\
// dealt somewhere and retrieve it. This allows \\
// users to save damage dealt into a projectile. \\
// - .unitCollision --> The radius in which a unit has to be to be \\
// considered a target. This does not have to be \\
// defined, as it will be set to default. \\
// - .projCollision --> The radius in which a projectile has to be \\
// to be considered a target. This does not have \\
// to be defined, as it will be set to default. \\
// - .pauseProj --> Users can pause all movement of a proj. \\
// This still allows .onLoop() and projectile \\
// collision. This is false by default. \\
// - .collideable --> Users can specify if a projectile is able \\
// to collide with other projectiles. This is \\
// false by default. \\
// - .enableHoming --> Users can specify if they want a projectile \\
// to be homing or not. A projectile must have a \\
// target for it to work. \\
// - .showDeathFx --> Whether or not to show the projectiles death \\
// effect. If true the projectile will be removed \\
// after RECYCLE_DELAY time has passed. \\
// - .effectPath --> Users can specify what the projectile looks \\
// like using this member. The effect path can \\
// even be retrieved for special effect usage. \\
// \\
// Readonly members available: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// Unlike the above members, these are not meant to be changed at any \\
// time throughout the duration of the projectile. Therefore, they \\
// are readonly, meaning that you can access them but not change \\
// them. \\
// \\
// - .proj --> Refers to the projectile unit itself. Can be \\
// useful for attaching effects amongst other \\
// things. \\
// - .angle --> Refers to the current XY facing angle of the \\
// projectile. Does not include Z coordinates. \\
// Can be useful for some projectile spells. \\
// - .pitch --> Refers to the current XYZ facing angle of the \\
// projectile. Includes Z coordinates as well. \\
// Can be useful for some projectile spells. \\
// - .pos --> Refers to the current position of the \\
// projectile. Users can access: .pos.x / .pos.y \\
// / .pos.z. This is a vector struct \\
// - .vel --> Refers to the current velocity of the \\
// projectile. Users can access: .vel.x / .vel.y \\
// / .vel.z. This is a vector struct. \\
// - .start --> Refers to the starting coordinates of the \\
// projectile. Users can access: .start.x / \\
// .start.y / .start.z. This is a vector struct. \\
// - .targ --> Refers to the target coordinates of the \\
// projectile. Users can access: .targ.x / \\
// .targ.y / .targ.z. This is a vector struct. \\
// - .currentSpeed --> Returns the current speed of a given \\
// projectile. Returned speed is in units per \\
// second. \\
// - .previousSpeed --> Returns the previous speed of a projectile, \\
// before its speed was modified. Returned speed \\
// is in units per second. \\
// - .originalSpeed --> Returns the original speed of a projectile, \\
// even if its speed has been modified multiple \\
// times. Returned speed is in units per second. \\
// - .isTerminated --> Returns true if the projectile instance has \\
// been terminated. Can be of use in quite rare \\
// circumstances. \\
// \\
// The static method operator: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// - Projectile[whichUnit] --> Projectile \\
// \\
// The static method operator is for unit to Projectile typcasting. \\
// Mainly for use when GroupEnumProjectiles... is used (see below). \\
// Users specify a unit and it will return the associated \\
// projectile struct, if there is any. \\
// \\
// Functions available: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// - GroupEnumProjectilesInRange(whichGroup,xPos,yPos,zPos,radius) \\
// \\
// Adds all projectiles within a certain radius of a location \\
// specified by the users to a group also specified by the user. \\
// Units added to the group can then be typecasted into a \\
// Projectile struct using the static method operator. \\
// \\
// The first argument is the group which users want to add the \\
// projectiles too. The next three arguments are the x, y and z \\
// coordinates that users want to check. The last argument is the \\
// radius in which units need to be to be added to the group. \\
// \\
// - ForProjectileGroup(whichGroup,callback,data) \\
// \\
// Executes the callback function for all projectiles in the group. \\
// The first argument refers to the group of projectiles you wish \\
// to work with. The second argument is a callback function that you \\
// want to use with each projectile instance. This callback is a \\
// function interface (like the onStart and onFinish functions), so \\
// users must know how to use them properly. For example: \\
// \\
// function Callback takes Projectile p, integer i returns nothing \\
// // Do stuff with p here. The I argument can be typecasted. \\
// endfunction \\
// \\
// As shown in the above example, the callback function must have \\
// one Projectile argument and one integer argument. The integer \\
// argument refers to the last argument in the ForProjectileGroup() \\
// function. Users may use this to transfer separate data to the \\
// callback function. If this data isn't needed, simply put 0 and \\
// don't use the integer argument in the callback function. \\
// \\
// - RegisterProjectileCollisionEvent(whichTrigger) \\
// \\
// Registers a specified trigger for projectile collision events. \\
// The trigger will then fire whenever a collision between \\
// projectiles occurs. Users are then given other functions to \\
// retrieve both of the projectiles that collided, so that they \\
// can do something special. The argument refers to the trigger \\
// that users want registered. \\
// \\
// - GetFirstCollisionProj() --> Projectile \\
// \\
// Retrieves the first projectile from the most recent collision \\
// event. Users can then use all the methods, operators and members \\
// from the struct to do something with the projectile. \\
// \\
// - GetSecondCollisionProj() --> Projectile \\
// \\
// Same as the above function. This will retrieve the other \\
// projectile that collided in the most recent collision event. \\
// Users can then do stuff with the retrieved struct. \\
// \\
// - IsUnitProjectile(whichUnit)-- > Boolean \\
// \\
// Basically a WC3 style wrapper for the static method operator. \\
// This function takes a unit argument and returns true if the unit \\
// is a projectile and false if it isn't. \\
// \\
// - GetUnitProjectileData(whichunit) --> Projectile \\
// \\
// Another WC3 style wrapper for the static method operator. This \\
// function will return the projectile instance attached to the \\
// passed through the function. Be sure to check the unit first. \\
// \\
// Basic usage: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// function Actions takes nothing returns nothing \\
// local unit caster = GetTriggerUnit() \\
// local real castx = GetUnitX(caster) \\
// local real casty = GetUnitY(caster) \\
// local real targx = GetSpellTargetX() \\
// local real targy = GetSpellTargetY() \\
// local real angle = Atan2((targy-casty),(targx-castx)) \\
// local Projectile p = 0 \\
// \\
// set p = Projectile.create(castx,casty,50.00,angle) \\
// \\
// set p.caster = caster \\
// set p.owner = GetOwningPlayer(p.caster) \\
// set p.effectPath = "Something.mdl" \\
// set p.scaleSize = 1.00 \\
// \\
// call p.projectNormal(targx,targy,0.00,1000.00) \\
// \\
// set caster = null \\
// endfunction \\
// \\
// More advanced usage: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// function OnUnit takes Projectile p, unit u returns nothing \\
// if IsUnitEnemy(u,p.owner) then \\
// if p.isUnitInHeightRange(u) then \\
// call UnitDamageTarget(...) \\
// endif \\
// endif \\
// endfunction \\
// \\
// function OnProj takes Projectile p1, Projectile p2 returns nothing \\
// call p1.terminate() \\
// call p2.terminate() \\
// endfunction \\
// \\
// function OnStart takes Projectile p returns nothing \\
// call DestroyEffect(AddSpecialEffect(...)) \\
// endfunction \\
// \\
// function OnFinish takes Projectile p returns nothing \\
// call DestroyEffect(AddSpecialEffect(...)) \\
// endfunction \\
// \\
// function Actions takes nothing returns nothing \\
// local unit caster = GetTriggerUnit() \\
// local unit target = GetSpellTargetUnit() \\
// local real castx = GetUnitX(caster) \\
// local real casty = GetUnitY(caster) \\
// local real targx = GetUnitX(target) \\
// local real targy = GetUnitY(target) \\
// local real angle = Atan2((targy-casty),(targx-castx)) \\
// local real height = GetUnitFlyHeight(target) \\
// local Proj p = 0 \\
// \\
// set p = Proj.create(castx,casty,50.00,angle) \\
// \\
// set p.caster = caster \\
// set p.target = target \\
// set p.owner = GetOwningPlayer(p.caster) \\
// set p.effectPath = "Something.mdl" \\
// set p.scaleSize = 1.00 \\
// set p.projCollision = 32.00 \\
// set p.unitCollision = 64.00 \\
// set p.collideable = true \\
// set p.enableHoming = true \\
// \\
// set p.onStart = OnStart <-- Name of the above function. \\
// set p.onFinish = OnFinish <-- Same here. \\
// set p.onProj = OnProj <-- And here. \\
// set p.onUnit = OnUnit <-- And here too. \\
// \\
// call p.projectArcing(targx,targy,height,1000.00,500.00) \\
// \\
// set caster = null \\
// set target = null \\
// endfunction \\
// \\
//------------------------------------------------------------------------\\
//------------------------------------------------------------------------\\
// Configurables: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// - DUMMY_ID --> The raw code of the dummy unit used for \\
// the projectiles in this system. \\
// - OWNER_ID --> The owning player of the projectiles \\
// used in this system. \\
// - MIN_START_HEIGHT --> The minimum starting hieght of any \\
// projectile. Shouldn't be changed. \\
// - MAX_ARC_START_HEIGHT --> The maximum starting height of an \\
// arcing projectile. Keep less than 100. \\
// - DEFAULT_UNIT_COLL --> The default unit collision radius for \\
// projectiles. \\
// - DEFAULT_PROJ_COLL --> The default projectile collision radius \\
// for projectiles. \\
// - RECYCLE_DELAY --> How long it takes for a projectile to be \\
// removed. Allows death effects. \\
// \\
//------------------------------------------------------------------------\\
globals
public constant integer DUMMY_ID = 'proj'
public constant player OWNER_ID = Player(PLAYER_NEUTRAL_PASSIVE)
private constant real MIN_START_HEIGHT = 5.00
private constant real MAX_ARC_START_HEIGHT = 75.00
private constant real DEFAULT_UNIT_COLL = 96.00
private constant real DEFAULT_PROJ_COLL = 64.00
private constant real RECYCLE_DELAY = 3.00
endglobals
//------------------------------------------------------------------------\\
// \\
// DO NOT TOUCH PAST THIS POINT UNLESS YOU KNOW WHAT YOUR ARE DOING!! \\
// \\
//------------------------------------------------------------------------\\
globals
private Event CollisionEvent = 0
private Projectile FirstProjData = 0
private Projectile SecondProjData = 0
private Projectile ProjectileList = 0
private real WorldMaxX = 0.00
private real WorldMaxY = 0.00
private real WorldMinX = 0.00
private real WorldMinY = 0.00
private hashtable TriggerHash = null
endglobals
//------------------------------------------------------------------------\\
// Function interfaces: Bonus functions available for greater control.
function interface OnStart takes Projectile instance returns nothing
function interface OnLoop takes Projectile instance returns nothing
function interface OnFinish takes Projectile instance returns nothing
function interface OnLand takes Projectile instance returns nothing
function interface OnUnit takes Projectile instance, unit whichUnit returns nothing
function interface OnProj takes Projectile instance, Projectile whichProj returns nothing
function interface ForGroupCallback takes Projectile whichProj, integer whichInst returns nothing
//------------------------------------------------------------------------\\
// ProjData: Stores Projectile structs allocated to dummy units.
private struct ProjData extends array
//! runtextmacro AIDS()
Projectile data
private static method AIDS_filter takes unit whichUnit returns boolean
return GetUnitTypeId(whichUnit) == DUMMY_ID
endmethod
private method AIDS_onCreate takes nothing returns nothing
set this.data = 0
endmethod
private method AIDS_onDestroy takes nothing returns nothing
set this.data = 0
endmethod
endstruct
//------------------------------------------------------------------------\\
// ForGroupStack: For recursion safety for ForProjectileGroup().
private struct ForGroupStack extends array
group forGroup
integer instance
integer callback
static thistype top = 0
static method increment takes nothing returns nothing
set thistype.top = thistype(thistype.top + 1)
endmethod
static method decrement takes nothing returns nothing
set thistype.top = thistype(thistype.top - 1)
endmethod
endstruct
//------------------------------------------------------------------------\\
// Unit recycler: To show the death effect of projectiles.
private struct UnitRecycler
unit recycled = null
real tick = 0.00
private method destroy takes nothing returns nothing
call RemoveUnit(this.recycled)
set this.recycled = null
call this.deallocate()
endmethod
private method periodic takes nothing returns nothing
if this.tick == T32_Tick then
call this.stopPeriodic()
call this.destroy()
endif
endmethod
implement T32x
static method add takes unit whichUnit returns nothing
local thistype this = thistype.allocate()
set this.recycled = whichUnit
set this.tick = T32_Tick + R2I(RECYCLE_DELAY / T32_PERIOD)
call this.startPeriodic()
endmethod
endstruct
//------------------------------------------------------------------------\\
// Projectile: The main struct interface for the system.
struct Projectile
implement LinkedList // Need linked list for GroupEnum function.
unit caster = null // Casting unit of the projectile.
unit target = null // Target unit of the projectile (if there is one).
player owner = null // Normally the owning unit of the caster.
real timedLife = -1.00 // Timed life of the projectile (if user wants one).
real unitDamage = 0.00 // Easier to pass damage through projectile.
real unitCollision = DEFAULT_UNIT_COLL // Collision radius for unit/proj collisions.
real projCollision = DEFAULT_PROJ_COLL // Collision radius for proj/proj collisions.
boolean pauseProj = false // If the projectile has been paused or not.
boolean collideable = false // If the projectile can collide with other projectiles.
boolean enableHoming = false // If the projectile is homing (must have a target unit to work).
boolean showDeathFx = true // Whether or not to show the projectiles death effect.
OnStart onStart = 0 // Function that is executed when the projectile is launched.
OnLoop onLoop = 0 // Function that is executed each iteration or the periodic timer.
OnFinish onFinish = 0 // Function that is executed when the projectile ends.
OnLand onLand = 0 // Function that is executed when the projectile hits the ground.
OnUnit onUnit = 0 // Function that is executed when the projectile hits a unit.
OnProj onProj = 0 // Function that is executed when the projectile hits another projectile.
readonly unit proj = null // The actual projectile unit.
readonly real angle = 0.00 // The angle at which the projectile is facing.
readonly real pitch = 0.00 // The pitch at which the projectile is facing.
readonly vector pos = 0 // A vector struct holding the XYZ coordinates of the projectiles position.
readonly vector vel = 0 // A vector struct holding the XYZ coordinates of the projectiles velocity.
readonly vector start = 0 // A vector struct holidng the XYZ coordinates of the projectiles starting location.
readonly vector targ = 0 // A vector struct holding the XYZ coordinates of the projectiles target location.
private trigger unitTrig = null // Trigger needed for the unit comes in range event.
private group dmgGroup = null // Group needed so units aren't hit more than once.
private region projReg = null // Region for the unit enters region event.
private rect projRect = null // Rect that is added and removed from the region periodically.
private trigger projTrig = null // Trigger needed for the unit enters region event.
private real height = 0.00 // Maximum height of an arcing projectile.
private real maxDist = 0.00 // Maximum distance of an arcing projectile.
private real distDone = 0.00 // Distance travelled by an arcing projectile.
private boolean arcing = false // If the projectile should be arcing or not.
private effect sfx = null // The effect attached to the projectile.
private string path = "" // The path of the above effect.
private boolean stop = false // If the projectile instance has been stopped (destroyed).
private real speed = 0.00 // The current speed of the projectile.
private real oriSpeed = 0.00 // The previous speed of the projectile.
private real oldSpeed = 0.00 // The original speed of the projectile.
private static boolexpr unitFilt = null // The condition used for unit collision.
private static boolexpr projFilt = null // The condition used for projectile collision.
private static vector tempVect = 0 // The helper vector needed for z height.
static method operator[] takes unit whichUnit returns thistype
return ProjData[whichUnit].data
endmethod
method operator scaleSize= takes real value returns nothing
call SetUnitScale(this.proj,value,0.00,0.00)
endmethod
method operator effectPath= takes string whichPath returns nothing
if this.sfx != null then
call DestroyEffect(this.sfx)
set this.path = ""
endif
if whichPath == "" then
set this.sfx = null
set this.path = ""
else
set this.sfx = AddSpecialEffectTarget(whichPath,this.proj,"origin")
set this.path = whichPath
endif
endmethod
method operator effectPath takes nothing returns string
return this.path
endmethod
method operator currentSpeed takes nothing returns real
return this.speed / T32_PERIOD
endmethod
method operator previousSpeed takes nothing returns real
return this.oldSpeed / T32_PERIOD
endmethod
method operator originalSpeed takes nothing returns real
return this.oriSpeed / T32_PERIOD
endmethod
method operator isTerminated takes nothing returns boolean
return this.stop
endmethod
method terminate takes nothing returns nothing
set this.effectPath = ""
set this.stop = true
endmethod
method isUnitInHeightRange takes unit whichUnit returns boolean
local real height = GetUnitFlyHeight(whichUnit)
call thistype.tempVect.getTerrainPoint(GetUnitX(whichUnit),GetUnitY(whichUnit))
set height = height - thistype.tempVect.z
return height <= this.pos.z + this.unitCollision and height >= (this.pos.z - this.unitCollision) - 128.00
endmethod
method modifyTargeting takes real xPos, real yPos, real zPos returns nothing
set this.angle = Atan2((yPos - this.pos.y),(xPos - this.pos.x))
set this.pitch = Atan2(SquareRoot((xPos - this.pos.x) * (xPos - this.pos.x) + (yPos - this.pos.y) * (yPos - this.pos.y)),(zPos - this.pos.z))
set this.vel.x = Sin(this.pitch) * Cos(this.angle) * speed
set this.vel.y = Sin(this.pitch) * Sin(this.angle) * speed
set this.vel.z = Cos(this.pitch) * speed
set this.targ.x = xPos
set this.targ.y = yPos
set this.targ.z = zPos
if not this.arcing then
call SetUnitAnimationByIndex(this.proj,R2I(bj_RADTODEG * Atan2(this.vel.z,SquareRoot(this.vel.x * this.vel.x + this.vel.y * this.vel.y)) + 0.50) + 90)
endif
call SetUnitFacing(this.proj,this.angle * bj_RADTODEG)
endmethod
method modifyPositioning takes real xPos, real yPos, real zPos returns nothing
set this.pos.x = xPos
set this.pos.y = yPos
set this.pos.z = zPos
endmethod
method modifySpeed takes real value returns nothing
set this.oldSpeed = this.speed
set this.speed = value * T32_PERIOD
set this.vel.x = Sin(this.pitch) * Cos(this.angle) * this.speed
set this.vel.y = Sin(this.pitch) * Sin(this.angle) * this.speed
set this.vel.z = Cos(this.pitch) * this.speed
endmethod
private method destroy takes nothing returns nothing
call this.onFinish.execute(this)
call this.pos.destroy()
call this.vel.destroy()
if this.sfx != null then
call DestroyEffect(this.sfx)
endif
if this.showDeathFx then
call UnitRecycler.add(this.proj)
else
call RemoveUnit(this.proj)
endif
call TriggerClearConditions(this.unitTrig)
call DisableTrigger(this.unitTrig)
call DestroyTrigger(this.unitTrig)
call TriggerClearConditions(this.projTrig)
call DisableTrigger(this.projTrig)
call DestroyTrigger(this.projTrig)
call RemoveRegion(this.projReg)
call RemoveRect(this.projRect)
call ReleaseGroup(this.dmgGroup)
set ProjData[this.proj].data = 0
set this.projTrig = null
set this.projRect = null
set this.projReg = null
set this.unitTrig = null
set this.dmgGroup = null
set this.caster = null
set this.proj = null
set this.sfx = null
set this.path = ""
call this.deallocate()
endmethod
private static method projectileFilter takes nothing returns boolean
local thistype this = LoadInteger(TriggerHash,GetHandleId(GetTriggeringTrigger()),0)
local unit filt = GetEnteringUnit()
local thistype that = Projectile[filt]
if that != 0 and this != 0 and this != that then
if that.collideable and this.collideable then
if (this.pos.z - that.pos.z) * (this.pos.z - that.pos.z) < this.projCollision * this.projCollision or /*
*/ (that.pos.z - this.pos.z) * (that.pos.z - this.pos.z) < that.projCollision * that.projCollision then
call this.onProj.execute(this,that)
call that.onProj.execute(that,this)
set FirstProjData = this
set SecondProjData = that
call CollisionEvent.fire()
endif
endif
endif
set filt = null
return false
endmethod
private static method collisionFilter takes nothing returns boolean
local thistype this = LoadInteger(TriggerHash,GetHandleId(GetTriggeringTrigger()),0)
local unit filt = GetFilterUnit()
if not IsUnitInGroup(filt,this.dmgGroup) then
call GroupAddUnit(this.dmgGroup,filt)
call this.onUnit.execute(this,filt)
endif
set filt = null
return false
endmethod
private method periodic takes nothing returns nothing
local real tempX = 0.00
local real tempY = 0.00
local real tempZ = 0.00
if this.stop then
call this.stopPeriodic()
call this.destroyThis()
else
if this.onLoop != 0 then
call this.onLoop.execute(this)
endif
if not this.pauseProj then
call RegionClearRect(this.projReg,this.projRect)
call SetRect(this.projRect,this.pos.x - this.projCollision,this.pos.y - this.projCollision,this.pos.x + this.projCollision,this.pos.y + this.projCollision)
call RegionAddRect(this.projReg,this.projRect)
if this.timedLife > -1.0 then
set this.timedLife = this.timedLife - T32_PERIOD
if this.timedLife <= 0.00 then
set this.stop = true
endif
endif
if this.target != null and this.enableHoming then
set tempX = GetUnitX(this.target)
set tempY = GetUnitY(this.target)
if this.targ.x != tempX and this.targ.y != tempY then
if this.arcing then
set this.arcing = false
endif
call this.modifyTargeting(tempX,tempY,this.targ.z)
endif
endif
call this.pos.add(this.vel)
call thistype.tempVect.getTerrainPoint(this.pos.x,this.pos.y)
if this.arcing then
set tempZ = this.pos.z
set this.pos.z = this.start.z + (4.00 * this.height / this.maxDist) * (this.maxDist - this.distDone) * (this.distDone / this.maxDist)
set this.distDone = this.distDone + this.speed
call SetUnitAnimationByIndex(this.proj,R2I(bj_RADTODEG * Atan2((this.pos.z - tempZ) + this.vel.z,SquareRoot(this.vel.x * this.vel.x + this.vel.y * this.vel.y)) + 0.50) + 90)
endif
call SetUnitX(this.proj,this.pos.x)
call SetUnitY(this.proj,this.pos.y)
call SetUnitFlyHeight(this.proj,this.pos.z - thistype.tempVect.z,0.00)
if IsTerrainPathable(this.pos.x,this.pos.y, PATHING_TYPE_FLYABILITY) == true then
set this.stop = true
endif
if thistype.tempVect.z >= this.pos.z then
call this.onLand.execute(this)
set this.stop = true
endif
endif
endif
endmethod
implement T32x
private method setCommon takes real xPos, real yPos, real zPos, real speed returns nothing
local real tempX = xPos - this.pos.x
local real tempY = yPos - this.pos.y
local real tempZ = zPos - this.pos.z
set this.angle = Atan2(tempY,tempX)
set this.pitch = Atan2(SquareRoot(tempX * tempX + tempY * tempY),tempZ)
set this.speed = speed * T32_PERIOD
set this.vel = vector.create(Sin(this.pitch) * Cos(this.angle) * this.speed,Sin(this.pitch) * Sin(this.angle) * this.speed,Cos(this.pitch) * this.speed)
set this.targ = vector.create(xPos,yPos,zPos)
set this.oriSpeed = this.speed
set this.oldSpeed = this.speed
call SetUnitAnimationByIndex(this.proj,R2I(bj_RADTODEG * Atan2(this.vel.z,SquareRoot(this.vel.x * this.vel.x + this.vel.y * this.vel.y)) + 0.50) + 90)
set this.unitTrig = CreateTrigger()
call SaveInteger(TriggerHash,GetHandleId(this.unitTrig),0,this)
call TriggerRegisterUnitInRange(this.unitTrig,this.proj,this.unitCollision,null)
call TriggerAddCondition(this.unitTrig,thistype.unitFilt)
set this.projTrig = CreateTrigger()
set this.projReg = CreateRegion()
set this.projRect = Rect(xPos - this.projCollision,yPos - this.projCollision,xPos + this.projCollision,yPos + this.projCollision)
call SaveInteger(TriggerHash,GetHandleId(this.projTrig),0,this)
call RegionAddRect(this.projReg,this.projRect)
call TriggerRegisterEnterRegion(this.projTrig,this.projReg,null)
call TriggerAddCondition(this.projTrig,thistype.projFilt)
endmethod
method projectArcing takes real xPos, real yPos, real zPos, real speed, real maxHeight returns nothing
call this.setCommon(xPos,yPos,zPos,speed)
if this.start.z > MAX_ARC_START_HEIGHT then
call thistype.tempVect.getTerrainPoint(this.start.x,this.start.y)
set this.start.z = MAX_ARC_START_HEIGHT - thistype.tempVect.z
call SetUnitFlyHeight(this.proj,this.start.z,0.00)
endif
set this.maxDist = SquareRoot((xPos - this.pos.x) * (xPos - this.pos.x) + (yPos - this.pos.y) * (yPos - this.pos.y) + (zPos - this.start.z) * (zPos - this.start.z)) - this.start.z
set this.height = maxHeight - this.start.z
set this.distDone = 0.00
set this.arcing = true
call this.onStart.execute(this)
call this.startPeriodic()
endmethod
method projectNormal takes real xPos, real yPos, real zPos, real speed returns nothing
call this.setCommon(xPos,yPos,zPos,speed)
call this.onStart.execute(this)
call this.startPeriodic()
endmethod
static method create takes real xPos, real yPos, real zPos, real facing returns thistype
local thistype this = thistype.allocate()
set this.proj = CreateUnit(OWNER_ID,DUMMY_ID,xPos,yPos,facing * bj_RADTODEG)
set this.pos = vector.create(xPos,yPos,zPos)
set this.start = vector.create(xPos,yPos,zPos)
set this.dmgGroup = NewGroup()
if zPos < MIN_START_HEIGHT then
set zPos = MIN_START_HEIGHT
endif
call SetUnitX(this.proj,xPos)
call SetUnitY(this.proj,yPos)
call thistype.tempVect.getTerrainPoint(xPos,yPos)
call SetUnitFlyHeight(this.proj,zPos - thistype.tempVect.z,0.00)
set this.start.z = zPos - thistype.tempVect.z
set ProjData[this.proj].data = ProjectileList.addToStart(this)
return this
endmethod
private static method onInit takes nothing returns nothing
set thistype.tempVect = vector.create(0.00,0.00,0.00)
set thistype.unitFilt = Condition(function thistype.collisionFilter)
set thistype.projFilt = Condition(function thistype.projectileFilter)
endmethod
endstruct
//------------------------------------------------------------------------\\
// GroupEnum function: Groups all projectiles in range, very useful.
function GroupProjectilesInRange takes group whichGroup, real x, real y, real z, real radius returns nothing
local Projectile p = ProjectileList.head
local vector v = vector.create(x,y,z)
call GroupClear(whichGroup)
loop
exitwhen p == 0
if p.pos.isInSphere(v,radius) then
call GroupAddUnit(whichGroup,p.proj)
endif
set p = p.next
endloop
call v.destroy()
endfunction
//------------------------------------------------------------------------\\
// ForProjectileGroup: For those who want a cleaner interface. Not recommended.
private function ForProjectileGroupCallback takes nothing returns nothing
call ForGroupCallback(ForGroupStack.top.callback).execute(ProjData[GetEnumUnit()].data,ForGroupStack.top.instance) // Don't kill me for this.
endfunction
function ForProjectileGroup takes group whichGroup, ForGroupCallback whichCallback, integer whichInst returns nothing
call ForGroupStack.increment()
set ForGroupStack.top.forGroup = whichGroup
set ForGroupStack.top.instance = whichInst
set ForGroupStack.top.callback = whichCallback
call ForGroup(whichGroup,function ForProjectileGroupCallback)
call ForGroupStack.decrement()
endfunction
//------------------------------------------------------------------------\\
// Global collision event: Useful for a variety of spells. Has event responses.
function RegisterProjectileCollisionEvent takes trigger whichTrigger returns EventReg
return CollisionEvent.register(whichTrigger)
endfunction
function GetFirstCollisionProj takes nothing returns Projectile
return FirstProjData
endfunction
function GetSecondCollisionProj takes nothing returns Projectile
return SecondProjData
endfunction
//------------------------------------------------------------------------\\
// WC3 style wrappers: For people who like normal WC3 style functions.
function IsUnitProjectile takes unit whichUnit returns boolean
return Projectile[whichUnit] != 0
endfunction
function GetUnitProjectileData takes unit whichUnit returns Projectile
return Projectile[whichUnit]
endfunction
//------------------------------------------------------------------------\\
// Bounds detection: Projectiles are destroyed when they try to leave the map.
private function OutsideMapRemoval takes nothing returns boolean
local unit u = GetLeavingUnit()
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local Projectile p = Projectile[u]
if p != 0 then
call p.terminate()
else
if(x > WorldMaxX) then
set x = WorldMaxX
elseif(x < WorldMinX) then
set x = WorldMinX
endif
if(y > WorldMaxY) then
set y = WorldMaxY
elseif(y < WorldMinY) then
set y = WorldMinY
endif
call SetUnitX(u,x)
call SetUnitY(u,y)
endif
set u=null
return false
endfunction
//------------------------------------------------------------------------\\
// Initialisation: Collision event, linked list, hashtable.
private function OnInit takes nothing returns nothing
local trigger trig = CreateTrigger()
local region reg = CreateRegion()
local rect rec = null
set CollisionEvent = Event.create()
set ProjectileList = Projectile.createList()
set TriggerHash = InitHashtable()
set WorldMaxX = GetRectMaxX(bj_mapInitialPlayableArea) - 64.00
set WorldMaxY = GetRectMaxY(bj_mapInitialPlayableArea) - 64.00
set WorldMinX = GetRectMinX(bj_mapInitialPlayableArea) + 64.00
set WorldMinY = GetRectMinY(bj_mapInitialPlayableArea) + 64.00
set rec = Rect(WorldMinX,WorldMinY,WorldMaxX,WorldMaxY)
call RegionAddRect(reg,rec)
call TriggerRegisterLeaveRegion(trig,reg,null)
call TriggerAddCondition(trig,Condition(function OutsideMapRemoval))
call RemoveRect(rec)
set trig = null
set rec = null
set reg = null
endfunction
endlibrary
//TESH.scrollpos=3
//TESH.alwaysfold=0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~ Timer32 ~~ By Jesus4Lyf ~~ Version 1.06 ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// What is Timer32?
// - Timer32 implements a fully optimised timer loop for a struct.
// - Instances can be added to the loop, which will call .periodic every
// PERIOD until .stopPeriodic() is called.
//
// =Pros=
// - Efficient.
// - Simple.
//
// =Cons=
// - Only allows one period.
// - The called method must be named ".periodic".
//
// Methods:
// - struct.startPeriodic()
// - struct.stopPeriodic()
//
// - private method periodic takes nothing returns nothing
//
// This must be defined in structs that implement Periodic Module.
// It will be executed by the module every PERIOD until .stopPeriodic() is called.
// Put "implement T32x" BELOW this method.
//
// Modules:
// - T32x
// Has no safety on .stopPeriodic or .startPeriodic (except debug messages
// to warn).
//
// - T32xs
// Has safety on .stopPeriodic and .startPeriodic so if they are called
// multiple times, or while otherwise are already stopped/started respectively,
// no error will occur, the call will be ignored.
//
// - T32
// The original, old version of the T32 module. This remains for backwards
// compatability, and is deprecated. The periodic method must return a boolean,
// false to continue running or true to stop.
//
// Details:
// - Uses one timer.
//
// - Do not, within a .periodic method, follow a .stopPeriodic call with a
// .startPeriodic call.
//
// How to import:
// - Create a trigger named T32.
// - Convert it to custom text and replace the whole trigger text with this.
//
// Thanks:
// - Infinitegde for finding a bug in the debug message that actually altered
// system operation (when in debug mode).
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library T32 initializer OnInit
globals
public constant real PERIOD=0.03125
public constant integer FPS=R2I(1.00/PERIOD)
public integer Tick=0 // very useful.
//==============================================================================
private trigger Trig=CreateTrigger()
endglobals
//==============================================================================
// The standard T32 module, T32x.
//
module T32x
private thistype next
private thistype prev
private static method PeriodicLoop takes nothing returns boolean
local thistype this=thistype(0).next
loop
exitwhen this==0
call this.periodic()
set this=this.next
endloop
return false
endmethod
method startPeriodic takes nothing returns nothing
debug if this.prev!=0 or thistype(0).next==this then
debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had startPeriodic called while already running!")
debug endif
set thistype(0).next.prev=this
set this.next=thistype(0).next
set thistype(0).next=this
set this.prev=thistype(0)
endmethod
method stopPeriodic takes nothing returns nothing
debug if this.prev==0 and thistype(0).next!=this then
debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had stopPeriodic called while not running!")
debug endif
// This is some real magic.
set this.prev.next=this.next
set this.next.prev=this.prev
// This will even work for the starting element.
debug set this.prev=0
endmethod
private static method onInit takes nothing returns nothing
call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop))
endmethod
endmodule
//==============================================================================
// The standard T32 module with added safety checks on .startPeriodic() and
// .stopPeriodic(), T32xs.
//
module T32xs
private thistype next
private thistype prev
private boolean runningPeriodic
private static method PeriodicLoop takes nothing returns boolean
local thistype this=thistype(0).next
loop
exitwhen this==0
call this.periodic()
set this=this.next
endloop
return false
endmethod
method startPeriodic takes nothing returns nothing
if not this.runningPeriodic then
set thistype(0).next.prev=this
set this.next=thistype(0).next
set thistype(0).next=this
set this.prev=thistype(0)
set this.runningPeriodic=true
endif
endmethod
method stopPeriodic takes nothing returns nothing
if this.runningPeriodic then
// This is some real magic.
set this.prev.next=this.next
set this.next.prev=this.prev
// This will even work for the starting element.
set this.runningPeriodic=false
endif
endmethod
private static method onInit takes nothing returns nothing
call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop))
endmethod
endmodule
//==============================================================================
// The original T32 module, for backwards compatability only.
//
module T32 // deprecated.
private thistype next
private thistype prev
private static method PeriodicLoop takes nothing returns boolean
local thistype this=thistype(0).next
loop
exitwhen this==0
if this.periodic() then
// This is some real magic.
set this.prev.next=this.next
set this.next.prev=this.prev
// This will even work for the starting element.
debug set this.prev=0
endif
set this=this.next
endloop
return false
endmethod
method startPeriodic takes nothing returns nothing
debug if this.prev!=0 or thistype(0).next==this then
debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had startPeriodic called while already running!")
debug endif
set thistype(0).next.prev=this
set this.next=thistype(0).next
set thistype(0).next=this
set this.prev=thistype(0)
endmethod
private static method onInit takes nothing returns nothing
call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop))
endmethod
endmodule
//==============================================================================
// System Core.
//
private function OnExpire takes nothing returns nothing
set Tick=Tick+1
call TriggerEvaluate(Trig)
endfunction
private function OnInit takes nothing returns nothing
call TimerStart(CreateTimer(),PERIOD,true,function OnExpire)
endfunction
endlibrary
//TESH.scrollpos=210
//TESH.alwaysfold=0
library GroupUtils initializer Init requires optional xebasic
//******************************************************************************
//* BY: Rising_Dusk
//*
//* This library is a combination of several features relevant to groups. First
//* and foremost, it contains a group stack that you can access dynamic groups
//* from. It also provides means to refresh groups and clear any shadow
//* references within them. The included boolexprs are there for backwards
//* compatibility with maps that happen to use them. Since the 1.24c patch,
//* null boolexprs used in GroupEnumUnits* calls no longer leak, so there is no
//* performance gain to using the BOOLEXPR_TRUE constant.
//*
//* Instead of creating/destroying groups, we have moved on to recycling them.
//* NewGroup pulls a group from the stack and ReleaseGroup adds it back. Always
//* remember to call ReleaseGroup on a group when you are done using it. If you
//* fail to do so enough times, the stack will overflow and no longer work.
//*
//* GroupRefresh cleans a group of any shadow references which may be clogging
//* its hashtable. 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. It is only worth doing this on
//* groups that you plan to have around for awhile.
//*
//* Constants that can be used from the library:
//* [group] ENUM_GROUP As you might expect, this group is good for
//* when you need a group just for enumeration.
//* [boolexpr] BOOLEXPR_TRUE This is a true boolexpr, which is important
//* because a 'null' boolexpr in enumeration
//* calls results in a leak. Use this instead.
//* [boolexpr] BOOLEXPR_FALSE This exists mostly for completeness.
//*
//* This library also includes a simple implementation of a group enumeration
//* call that factors collision of units in a given area of effect. This is
//* particularly useful because GroupEnumUnitsInRange doesn't factor collision.
//*
//* In your map, you can just replace all instances of GroupEnumUnitsInRange
//* with GroupEnumUnitsInArea with identical arguments and your spells will
//* consider all units colliding with the area of effect. After calling this
//* function as you would normally call GroupEnumUnitsInRange, you are free to
//* do anything with the group that you would normally do.
//*
//* If you don't use xebasic in your map, you may edit the MAX_COLLISION_SIZE
//* variable below and the library will use that as the added radius to check.
//* If you use xebasic, however, the script will automatically use xe's
//* collision size variable.
//*
//* You are also able to use GroupUnitsInArea. This function returns all units
//* within the area, no matter what they are, which can be convenient for those
//* instances where you actually want that.
//*
//* Example usage:
//* local group MyGroup = NewGroup()
//* call GroupRefresh(MyGroup)
//* call ReleaseGroup(MyGroup)
//* call GroupEnumUnitsInArea(ENUM_GROUP, x, y, 350., BOOLEXPR_TRUE)
//* call GroupUnitsInArea(ENUM_GROUP, x, y, 350.)
//*
globals
//If you don't have xebasic in your map, this value will be used instead.
//This value corresponds to the max collision size of a unit in your map.
private constant real MAX_COLLISION_SIZE = 256.00
//If you are insane and don't care about any of the protection involved in
//this library, but want this script to be really fast, set this to true.
private constant boolean LESS_SAFETY = false
endglobals
globals
//* Constants that are available to the user
group ENUM_GROUP = CreateGroup()
boolexpr BOOLEXPR_TRUE = null
boolexpr BOOLEXPR_FALSE = null
endglobals
globals
//* Hashtable for debug purposes
private hashtable ht = InitHashtable()
//* Temporary references for GroupRefresh
private boolean Flag = false
private group Refr = null
//* Arrays and counter for the group stack
private group array Groups
private integer Count = 0
//* Variables for use with the GroupUnitsInArea function
private real X = 0.
private real Y = 0.
private real R = 0.
private hashtable H = InitHashtable()
endglobals
private function HookDestroyGroup takes group g returns nothing
if g == ENUM_GROUP then
call BJDebugMsg(SCOPE_PREFIX+"Warning: ENUM_GROUP destroyed")
endif
endfunction
debug hook DestroyGroup HookDestroyGroup
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
static if not LESS_SAFETY then
call SaveInteger(ht, 0, GetHandleId(Groups[Count]), 1)
endif
return Groups[Count]
endfunction
function ReleaseGroup takes group g returns boolean
local integer id = GetHandleId(g)
static if LESS_SAFETY then
if g == null then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Null groups cannot be released")
return false
elseif Count == 8191 then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Max groups achieved, destroying group")
call DestroyGroup(g)
return false
endif
else
if g == null then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Null groups cannot be released")
return false
elseif not HaveSavedInteger(ht, 0, id) then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Group not part of stack")
return false
elseif LoadInteger(ht, 0, id) == 2 then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Groups cannot be multiply released")
return false
elseif Count == 8191 then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Max groups achieved, destroying group")
call DestroyGroup(g)
return false
endif
call SaveInteger(ht, 0, id, 2)
endif
call GroupClear(g)
set Groups[Count] = g
set Count = Count + 1
return true
endfunction
private function Filter takes nothing returns boolean
return IsUnitInRangeXY(GetFilterUnit(), X, Y, R)
endfunction
private function HookDestroyBoolExpr takes boolexpr b returns nothing
local integer bid = GetHandleId(b)
if HaveSavedHandle(H, 0, bid) then
//Clear the saved boolexpr
call DestroyBoolExpr(LoadBooleanExprHandle(H, 0, bid))
call RemoveSavedHandle(H, 0, bid)
endif
endfunction
hook DestroyBoolExpr HookDestroyBoolExpr
private constant function GetRadius takes real radius returns real
static if LIBRARY_xebasic then
return radius+XE_MAX_COLLISION_SIZE
else
return radius+MAX_COLLISION_SIZE
endif
endfunction
function GroupEnumUnitsInArea takes group whichGroup, real x, real y, real radius, boolexpr filter returns nothing
local real prevX = X
local real prevY = Y
local real prevR = R
local integer bid = 0
//Set variables to new values
set X = x
set Y = y
set R = radius
if filter == null then
//Adjusts for null boolexprs passed to the function
set filter = Condition(function Filter)
else
//Check for a saved boolexpr
set bid = GetHandleId(filter)
if HaveSavedHandle(H, 0, bid) then
//Set the filter to use to the saved one
set filter = LoadBooleanExprHandle(H, 0, bid)
else
//Create a new And() boolexpr for this filter
set filter = And(Condition(function Filter), filter)
call SaveBooleanExprHandle(H, 0, bid, filter)
endif
endif
//Enumerate, if they want to use the boolexpr, this lets them
call GroupEnumUnitsInRange(whichGroup, x, y, GetRadius(radius), filter)
//Give back original settings so nested enumerations work
set X = prevX
set Y = prevY
set R = prevR
endfunction
function GroupUnitsInArea takes group whichGroup, real x, real y, real radius returns nothing
local real prevX = X
local real prevY = Y
local real prevR = R
//Set variables to new values
set X = x
set Y = y
set R = radius
//Enumerate
call GroupEnumUnitsInRange(whichGroup, x, y, GetRadius(radius), Condition(function Filter))
//Give back original settings so nested enumerations work
set X = prevX
set Y = prevY
set R = prevR
endfunction
private function True takes nothing returns boolean
return true
endfunction
private function False takes nothing returns boolean
return false
endfunction
private function Init takes nothing returns nothing
set BOOLEXPR_TRUE = Condition(function True)
set BOOLEXPR_FALSE = Condition(function False)
endfunction
endlibrary
//TESH.scrollpos=80
//TESH.alwaysfold=0
library DoorSys initializer int
globals
private integer array HorizontalDoorID[10]
private integer array VerticalDoorID[10]
private group g = CreateGroup()
private hashtable hash
private constant integer DoorMax = 1
private constant integer HorizontalDoorBlocker ='B00A'
private constant integer VerticalDoorBlocker ='B009'
private constant boolean SetupDoorsOnInt=true
private constant real SetupDoorsWait=3
private constant real SetupDoorsRectSize=230
private constant string LockMessage="|cFF804000Door is now locked|r"
private constant string UnlockMessage="|cFF804000Door is now unlocked|r"
private constant string HitMessage="|cFF804000Door is locked|r"
private constant string LockSound="Doodads\\Cinematic\\DungeonLever\\Lever.wav"
private constant string HitSound="Sound\\Ambient\\DoodadEffects\\Switch.wav"
endglobals
private function setvars takes nothing returns nothing
//Set teh door id's
set HorizontalDoorID[0] = 'DTg5'
set VerticalDoorID[0] = 'DTg7'
set HorizontalDoorID[1] = 'LTe1'
set VerticalDoorID[1] = 'LTe3'
endfunction
private function UnitFilter takes nothing returns boolean
if UnitAlive(GetFilterUnit()) == true and IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) == false and IsUnitType(GetFilterUnit(),UNIT_TYPE_SUMMONED) == false and IsUnitType(GetFilterUnit(),UNIT_TYPE_TAUREN) == false and GetUnitAbilityLevel(GetFilterUnit(),'Aloc') == 0 and GetUnitTypeId(GetFilterUnit()) != 'e000' and GetUnitTypeId(GetFilterUnit()) != 'e008' then
return true
endif
return false
endfunction
private function TriggerUnitFilter takes nothing returns boolean
if UnitAlive(GetTriggerUnit()) == true and IsUnitType(GetTriggerUnit(),UNIT_TYPE_STRUCTURE) == false and IsUnitType(GetTriggerUnit(),UNIT_TYPE_SUMMONED) == false and IsUnitType(GetTriggerUnit(),UNIT_TYPE_TAUREN) == false and GetUnitAbilityLevel(GetTriggerUnit(),'Aloc') == 0 then
return true
endif
return false
endfunction
private function CloseFilter takes unit u returns boolean
if IsUnitType(u,UNIT_TYPE_SUMMONED) == false then
return false
endif
return true
endfunction
private function DoorOpen takes nothing returns nothing
local trigger t=GetTriggeringTrigger()
local destructable door = LoadDestructableHandle(hash, GetHandleId(t), StringHash("door"))
local destructable doorpath
local trigger destroytrigger
local sound hit
local boolean locked = LoadBoolean(hash, GetHandleId(door), StringHash("locked"))
debug call BJDebugMsg("opening door")
if GetDestructableLife(door) <= 0 then
debug call BJDebugMsg("Door r dead lol")
return
endif
if locked == true then
call DisplayTextToPlayer(GetOwningPlayer(GetTriggerUnit()),0,0,HitMessage)
set hit = CreateSoundFromLabel(HitSound,false,false,false,10,10)
if GetLocalPlayer() == GetOwningPlayer(GetTriggerUnit()) then
call StartSound(hit)
endif
call KillSoundWhenDone(hit)
else
debug call BJDebugMsg("Door opened")
set doorpath=LoadDestructableHandle(hash, GetHandleId(t), StringHash("doorpath"))
set destroytrigger = LoadTriggerHandle(hash, GetHandleId(t), StringHash("destroytrigger"))
call SaveReal(hash, GetHandleId(door), StringHash("life"), GetDestructableLife(door))
call SaveBoolean(hash, GetHandleId(door), StringHash("isopen"), true)
call DisableTrigger(destroytrigger)
call KillDestructable(door)
call KillDestructable(doorpath)
call SetDestructableAnimation(door, "death alternate")
call EnableTrigger(destroytrigger)
endif
set hit = null
set t = null
set door = null
set doorpath = null
set destroytrigger = null
endfunction
private function DoorClose takes nothing returns nothing
local trigger t=GetTriggeringTrigger()
local rect r=LoadRectHandle(hash, GetHandleId(t), StringHash("rect"))
local destructable door = LoadDestructableHandle(hash, GetHandleId(t), StringHash("door"))
local destructable doorpath = LoadDestructableHandle(hash, GetHandleId(t), StringHash("doorpath"))
local trigger destroytrigger=LoadTriggerHandle(hash, GetHandleId(t), StringHash("destroytrigger"))
local boolean isopen=LoadBoolean(hash, GetHandleId(door), StringHash("isopen"))
local boolean locked=LoadBoolean(hash,GetHandleId(door),StringHash("locked"))
debug call BJDebugMsg("door closed")
call GroupEnumUnitsInRect(g,r,Condition(function UnitFilter))
if CountUnitsInGroup(g) == 0 and isopen then
call SaveBoolean(hash, GetHandleId(door), StringHash("isopen"), false)
call DestructableRestoreLife(door, GetDestructableMaxLife(door), true)
call DestructableRestoreLife(doorpath, GetDestructableMaxLife(doorpath), true)
call SetDestructableLife(door,LoadReal(hash, GetHandleId(door),StringHash("life")))
call SetDestructableAnimation(door, "stand")
endif
call GroupClear(g)
set t = null
set door = null
set doorpath = null
set destroytrigger = null
set r = null
endfunction
private function DoorBustDown takes nothing returns nothing
local trigger t=GetTriggeringTrigger()
local destructable door = LoadDestructableHandle(hash, GetHandleId(t), StringHash("door"))
local destructable doorpath = LoadDestructableHandle(hash, GetHandleId(t), StringHash("doorpath"))
local trigger dooropen=LoadTriggerHandle(hash, GetHandleId(t), StringHash("t1"))
local trigger doorclose=LoadTriggerHandle(hash, GetHandleId(t), StringHash("t2"))
call DestroyTrigger(GetTriggeringTrigger())
call KillDestructable(doorpath)
call DestroyTrigger(dooropen)
call DestroyTrigger(doorclose)
debug call BJDebugMsg("Door killed")
set t = null
set door = null
set doorpath = null
set dooropen = null
set doorclose = null
endfunction
function LockDoor takes destructable door, boolean lock, player locker returns nothing
local destructable doorpath
local trigger destroytrigger
local rect r
local sound s
local integer i =0
local boolean b = false
loop
exitwhen i == DoorMax
if GetDestructableTypeId(GetFilterDestructable()) == HorizontalDoorID[i] or GetDestructableTypeId(GetFilterDestructable()) == VerticalDoorID[i] then
set b = true
endif
set i = i + 1
endloop
if b == true then
set doorpath = LoadDestructableHandle(hash,GetHandleId(door), StringHash("doorpath"))
debug call BJDebugMsg("door locked")
if lock == true then
if locker != null then
call DisplayTextToPlayer(locker,0,0,LockMessage)
set s = CreateSoundFromLabel(LockSound,false,false,false,10,10)
if GetLocalPlayer() == locker then
call StartSound(s)
endif
call KillSoundWhenDone(s)
endif
call SaveBoolean(hash, GetHandleId(door), StringHash("isopen"), false)
call DestructableRestoreLife(door, GetDestructableMaxLife(door), true)
call DestructableRestoreLife(doorpath, GetDestructableMaxLife(doorpath), true)
call SetDestructableLife(door,LoadReal(hash, GetHandleId(door),StringHash("life")))
call SetDestructableAnimation(door, "stand")
call SaveBoolean(hash, GetHandleId(door), StringHash("locked"), true)
else
if locker != null then
call DisplayTextToPlayer(locker,0,0,UnlockMessage)
// set s = CreateSoundFromLabel(LockSound,false,false,false,10,10)
// if GetLocalPlayer() == locker then
// call StartSound(s)
// endif
//call KillSoundWhenDone(s)
endif
set r=LoadRectHandle(hash, GetHandleId(door), StringHash("rect"))
call GroupEnumUnitsInRect(g,r,Condition(function UnitFilter))
call SaveBoolean(hash, GetHandleId(door), StringHash("locked"), false)
if CountUnitsInGroup(g) > 0 then
set destroytrigger = LoadTriggerHandle(hash, GetHandleId(door), StringHash("destroytrigger"))
call SaveReal(hash, GetHandleId(door), StringHash("life"), GetDestructableLife(door))
call SaveBoolean(hash, GetHandleId(door), StringHash("isopen"), true)
call DisableTrigger(destroytrigger)
call KillDestructable(door)
call EnableTrigger(destroytrigger)
call KillDestructable(doorpath)
call SetDestructableAnimation(door, "death alternate")
endif
call GroupClear(g)
endif
endif
set s = null
set destroytrigger = null
set doorpath = null
set r = null
endfunction
function ToggleLockDoor takes destructable door, player locker returns nothing
if LoadBoolean(hash,GetHandleId(door),StringHash("locked")) == true then
call LockDoor(door,false,locker)
else
call LockDoor(door,true,locker)
endif
endfunction
function RegisterDoor takes destructable door, rect where returns nothing
local integer i = 0
local trigger t=CreateTrigger()
local trigger k=CreateTrigger()
local trigger m=CreateTrigger()
local destructable doorpath
loop
if GetDestructableTypeId(door) == HorizontalDoorID[i] then
set doorpath = CreateDestructable(HorizontalDoorBlocker, GetDestructableX(door), GetDestructableY(door), 0, 1.0, 1)
endif
if GetDestructableTypeId(door) == VerticalDoorID[i] then
set doorpath = CreateDestructable(VerticalDoorBlocker, GetDestructableX(door), GetDestructableY(door), 0, 1.0, 1)
endif
exitwhen i == DoorMax
set i = i + 1
endloop
call TriggerRegisterEnterRectSimple( t, where)
call TriggerAddAction( t, function DoorOpen )
call TriggerRegisterLeaveRectSimple(k, where)
call TriggerAddAction(k, function DoorClose)
call TriggerAddCondition(t,Condition(function TriggerUnitFilter))
call TriggerAddCondition(k,Condition(function TriggerUnitFilter))
call TriggerRegisterDeathEvent(m,door)
call TriggerAddAction(m,function DoorBustDown)
call SaveDestructableHandle(hash, GetHandleId(t), StringHash("door"), door)
call SaveDestructableHandle(hash, GetHandleId(t), StringHash("doorpath"), doorpath)
call SaveRectHandle(hash, GetHandleId(t), StringHash("rect"), where)
call SaveDestructableHandle(hash, GetHandleId(k), StringHash("door"), door)
call SaveDestructableHandle(hash, GetHandleId(k), StringHash("doorpath"), doorpath)
call SaveRectHandle(hash, GetHandleId(k), StringHash("rect"), where)
call SaveDestructableHandle(hash, GetHandleId(m), StringHash("door"), door)
call SaveDestructableHandle(hash, GetHandleId(m), StringHash("doorpath"), doorpath)
call SaveRectHandle(hash, GetHandleId(m), StringHash("rect"), where)
call SaveTriggerHandle(hash, GetHandleId(m), StringHash("t1"), t)
call SaveTriggerHandle(hash, GetHandleId(m), StringHash("t2"), k)
call SaveTriggerHandle(hash, GetHandleId(door), StringHash("t1"), t)
call SaveTriggerHandle(hash, GetHandleId(door), StringHash("t2"), k)
call SaveBoolean(hash, GetHandleId(door), StringHash("locked"), false)
call SaveDestructableHandle(hash, GetHandleId(door), StringHash("doorpath"), doorpath)
call SaveRectHandle(hash, GetHandleId(door), StringHash("rect"), where)
call SaveTriggerHandle(hash, GetHandleId(door), StringHash("destroytrigger"), m)
call SaveTriggerHandle(hash, GetHandleId(t), StringHash("destroytrigger"), m)
call SaveTriggerHandle(hash, GetHandleId(k), StringHash("destroytrigger"), m)
debug call BJDebugMsg("door added")
set doorpath = null
endfunction
private function DoorFilter takes nothing returns boolean
local integer i = 0
loop
if GetDestructableTypeId(GetFilterDestructable()) == HorizontalDoorID[i] or GetDestructableTypeId(GetFilterDestructable()) == VerticalDoorID[i] then
return true
endif
exitwhen i == DoorMax
set i = i + 1
endloop
return false
endfunction
function DoorRegisterSimple takes destructable Door returns nothing
local location loc = GetDestructableLoc(Door)
local rect r = Rect(GetLocationX(loc) - SetupDoorsRectSize, GetLocationY(loc) - SetupDoorsRectSize, GetLocationX(loc) + SetupDoorsRectSize, GetLocationY(loc) + SetupDoorsRectSize)
call RegisterDoor(Door,r)
endfunction
private function intregister takes nothing returns nothing
call DoorRegisterSimple(GetEnumDestructable())
endfunction
private function reg takes nothing returns nothing
call EnumDestructablesInRect(GetPlayableMapRect(),Condition( function DoorFilter),function intregister)
endfunction
private function int takes nothing returns nothing
local timer t
call TriggerSleepAction(0)
call setvars()
set hash=InitHashtable()
if SetupDoorsOnInt == true then
set t = CreateTimer()
call TimerStart(t,SetupDoorsWait,false,function reg)
debug call BJDebugMsg("Setting up doors")
endif
set t = null
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Vector
//*****************************************************************
//* VECTOR LIBRARY
//*
//* written by: Anitarf
//*
//* The library contains a struct named vector, which represents a
//* point in 3D space. As such, it has three real members, one for
//* each coordinate: x, y, z. It also has the following methods:
//*
//* static method create takes real x, real y, real z returns vector
//* Creates a new vector with the given coordinates.
//*
//* method getLength takes nothing returns real
//* Returns the length of the vector it is called on.
//*
//* static method sum takes vector augend, vector addend returns vector
//* Returns the sum of two vectors as a new vector.
//*
//* method add takes vector addend returns nothing
//* Similar to sum, except that it doesn't create a new vector for the result,
//* but changes the vector it is called on by adding the "added" to it.
//*
//* static method difference takes vector minuend, vector subtrahend returns vector
//* Returns the difference between two vectors as a new vector.
//*
//* method subtract takes vector subtrahend returns nothing
//* Similar to difference, except that it doesn't create a new vector for the result,
//* but changes the vector it is called on by subtracting the "subtrahend" from it.
//*
//* method scale takes real factor returns nothing
//* Scales the vector it is called on by the given factor.
//*
//* method setLength takes real length returns nothing
//* Sets the length of the vector it is called on to the given value, maintaining it's orientation.
//*
//* static method dotProduct takes vector a, vector b returns real
//* Calculates the dot product (also called scalar product) of two vectors.
//*
//* static method crossProduct takes vector a, vector b returns vector
//* Calculates the cross product (also called vector product) of two vectors
//* and returns it as a new vector.
//*
//* static method tripleProductScalar takes vector a, vector b, vector c returns real
//* Calculates the triple scalar product of three vectors.
//*
//* static method tripleProductVector takes vector a, vector b, vector c returns vector
//* Calculates the triple vector product of three vectors and returns it as a new vector.
//*
//*
//* static method projectionVector takes vector projected, vector direction returns vector
//* Calculates the projection of the vector "projected" onto the vector "direction"
//* and returns it as a new vector.
//* Returns null if the vector direction has a length of 0.
//*
//* method projectVector takes vector direction returns nothing
//* Projects the vector it is called on onto the vector "direction".
//* Does nothing if the vector "direction" has a length of 0.
//*
//* static method projectionPlane takes vector projected, vector normal returns vector
//* Calculates the projection of the vector projected onto a plane defined by
//* it's normal vector and returns it as a new vector.
//* Returns null if the vector "normal" has a length of 0.
//*
//* method projectPlane takes vector normal returns nothing
//* Projects the vector it is called on onto a plane defined by it's normal vector.
//* Does nothing if the vector "normal" has a length of 0.
//*
//* static method getAngle takes vector a, vector b returns real
//* Returns the angle between two vectors, in radians, returns a value between 0 and pi.
//* Returns 0.0 if any of the vectors are 0 units long.
//*
//* method rotate takes vector axis, real angle returns nothing
//* Rotates the vector it is called on around the axis defined by the vector "axis"
//* by the given angle, which should be input in radians.
//* Does nothing if axis is 0 units long.
//*
//*
//* static method createTerrainPoint takes real x, real y returns vector
//* Creates a vector to the given terrain coordinate, taking it's z height into account.
//*
//* method getTerrainPoint takes real x, real y returns nothing
//* Sets the vector it is called on to the given terrain coordinate, taking it's z height into account.
//*
//* static method createTerrainNormal takes real x, real y, real sampleRadius returns vector
//* Creates the normal vector of the terrain at given coordinates. "sampleRadius" defines
//* how far apart the reference points will be, if they are further apart, the result will
//* be an impression of smoother terrain; normaly the value should be between 0 and 128.
//*
//* method getTerrainNormal takes real x, real y, real sampleRadius returns nothing
//* Sets the vector it is called on to the normal of the terrain at given coordinates.
//*
//*
//* method isInCylinder takes vector cylinderOrigin, vector cylinderHeight, real cylinderRadius returns boolean
//* Determines if a point is within a given cylinder. The cylinder's origin vector points
//* to the center of one of the two paralel circular sides, and the height vector points
//* from the origin point to the center of the other of the two paralel circular sides.
//* Returns false if the point is not in the cylinder or if the vector cylinderHeight is 0 units long.
//*
//* method isInCone takes vector coneOrigin, vector coneHeight, real coneRadius returns boolean
//* Determines if a point is within a given cone. The cone's origin vector points to the
//* center of the circular side, and the height vector points from the origin point to
//* the tip of the cone.
//* Returns false if the point is not in the cylinder or if the vector coneHeight is 0 units long.
//*
//* method isInSphere takes vector sphereOrigin, real sphereRadius returns boolean
//* Determines if a point is within a give sphere. The sphere's origin vector points to the
//* center of the sphere.
//* Returns false if the point is not in the sphere.
//*****************************************************************
struct vector
real x
real y
real z
static method create takes real x, real y, real z returns vector
local vector v = vector.allocate()
set v.x=x
set v.y=y
set v.z=z
return v
endmethod
method getLength takes nothing returns real
return SquareRoot(.x*.x + .y*.y + .z*.z)
endmethod
static method sum takes vector augend, vector addend returns vector
local vector v = vector.allocate()
set v.x = augend.x+addend.x
set v.y = augend.y+addend.y
set v.z = augend.z+addend.z
return v
endmethod
method add takes vector addend returns nothing
set this.x=this.x+addend.x
set this.y=this.y+addend.y
set this.z=this.z+addend.z
endmethod
static method difference takes vector minuend, vector subtrahend returns vector
local vector v = vector.allocate()
set v.x = minuend.x-subtrahend.x
set v.y = minuend.y-subtrahend.y
set v.z = minuend.z-subtrahend.z
return v
endmethod
method subtract takes vector subtrahend returns nothing
set this.x=this.x-subtrahend.x
set this.y=this.y-subtrahend.y
set this.z=this.z-subtrahend.z
endmethod
method scale takes real factor returns nothing
set this.x=this.x*factor
set this.y=this.y*factor
set this.z=this.z*factor
endmethod
method setLength takes real length returns nothing
local real l = SquareRoot(.x*.x + .y*.y + .z*.z)
if l == 0.0 then
debug call BJDebugMsg("Attempted to set the length of a vector with no length!")
return
endif
set l = length/l
set this.x = this.x*l
set this.y = this.y*l
set this.z = this.z*l
endmethod
static method dotProduct takes vector a, vector b returns real
return (a.x*b.x+a.y*b.y+a.z*b.z)
endmethod
static method crossProduct takes vector a, vector b returns vector
local vector v = vector.allocate()
set v.x = a.y*b.z - a.z*b.y
set v.y = a.z*b.x - a.x*b.z
set v.z = a.x*b.y - a.y*b.x
return v
endmethod
static method tripleProductScalar takes vector a, vector b, vector c returns real
return ((a.y*b.z - a.z*b.y)*c.x+(a.z*b.x - a.x*b.z)*c.y+(a.x*b.y - a.y*b.x)*c.z)
endmethod
static method tripleProductVector takes vector a, vector b, vector c returns vector
local vector v = vector.allocate()
local real n = a.x*c.x+a.y*c.y+a.z*c.z
local real m = a.x*b.x+a.y*b.y+a.z*b.z
set v.x = b.x*n-c.x*m
set v.y = b.y*n-c.y*m
set v.z = b.z*n-c.z*m
return v
endmethod
// ================================================================
static method projectionVector takes vector projected, vector direction returns vector
local vector v = vector.allocate()
local real l = direction.x*direction.x+direction.y*direction.y+direction.z*direction.z
if l == 0.0 then
call v.destroy()
debug call BJDebugMsg("Attempted to project onto a vector with no length!")
return null
endif
set l = (projected.x*direction.x+projected.y*direction.y+projected.z*direction.z) / l
set v.x = direction.x*l
set v.y = direction.y*l
set v.z = direction.z*l
return v
endmethod
method projectVector takes vector direction returns nothing
local real l = direction.x*direction.x+direction.y*direction.y+direction.z*direction.z
if l == 0.0 then
debug call BJDebugMsg("Attempted to project onto a vector with no length!")
return
endif
set l = (this.x*direction.x+this.y*direction.y+this.z*direction.z) / l
set this.x = direction.x*l
set this.y = direction.y*l
set this.z = direction.z*l
endmethod
static method projectionPlane takes vector projected, vector normal returns vector
local vector v = vector.allocate()
local real l = normal.x*normal.x+normal.y*normal.y+normal.z*normal.z
if l == 0.0 then
call v.destroy()
debug call BJDebugMsg("Attempted to project onto an undefined plane!")
return null
endif
set l = (projected.x*normal.x+projected.y*normal.y+projected.z*normal.z) / l
set v.x = projected.x - normal.x*l
set v.y = projected.y - normal.y*l
set v.z = projected.z - normal.z*l
return v
endmethod
method projectPlane takes vector normal returns nothing
local real l = normal.x*normal.x+normal.y*normal.y+normal.z*normal.z
if l == 0.0 then
debug call BJDebugMsg("Attempted to project onto an undefined plane!")
return
endif
set l = (this.x*normal.x+this.y*normal.y+this.z*normal.z) / l
set this.x = this.x - normal.x*l
set this.y = this.y - normal.y*l
set this.z = this.z - normal.z*l
endmethod
static method getAngle takes vector a, vector b returns real
local real l = SquareRoot(a.x*a.x + a.y*a.y + a.z*a.z)*SquareRoot(b.x*b.x + b.y*b.y + b.z*b.z)
if l == 0 then
debug call BJDebugMsg("Attempted to get angle between vectors with no length!")
return 0.0
endif
return Acos((a.x*b.x+a.y*b.y+a.z*b.z)/l) //angle is returned in radians
endmethod
method rotate takes vector axis, real angle returns nothing //angle is taken in radians
local real xx
local real xy
local real xz
local real yx
local real yy
local real yz
local real zx
local real zy
local real zz
local real al = axis.x*axis.x+axis.y*axis.y+axis.z*axis.z //axis length^2
local real f
local real c = Cos(angle)
local real s = Sin(angle)
if al == 0.0 then
debug call BJDebugMsg("Attempted to project onto a vector with no length!")
return
endif
set f = (this.x*axis.x+this.y*axis.y+this.z*axis.z) / al
set zx = axis.x*f
set zy = axis.y*f
set zz = axis.z*f //axis component of rotated vector
set xx = this.x-zx
set xy = this.y-zy
set xz = this.z-zz //component of vector perpendicular to axis
set al = SquareRoot(al)
set yx = (axis.y*xz - axis.z*xy)/al
set yy = (axis.z*xx - axis.x*xz)/al //y same length as x by using cross product and dividing with axis length
set yz = (axis.x*xy - axis.y*xx)/al //x,y - coordinate system in which we rotate
set this.x=xx*c+yx*s+zx
set this.y=xy*c+yy*s+zy
set this.z=xz*c+yz*s+zz
endmethod
// ================================================================
private static location loc = Location(0.0,0.0)
static method createTerrainPoint takes real x, real y returns vector
local vector v = vector.allocate()
call MoveLocation(vector.loc,x,y)
set v.x=x
set v.y=y
set v.z=GetLocationZ(loc)
return v
endmethod
method getTerrainPoint takes real x, real y returns nothing
call MoveLocation(vector.loc,x,y)
set this.x=x
set this.y=y
set this.z=GetLocationZ(loc)
endmethod
static method createTerrainNormal takes real x, real y, real sampleRadius returns vector
local vector v = vector.allocate()
local real zx
local real zy
call MoveLocation(vector.loc, x-sampleRadius, y)
set zx=GetLocationZ(vector.loc)
call MoveLocation(vector.loc, x+sampleRadius, y)
set zx=zx-GetLocationZ(vector.loc)
call MoveLocation(vector.loc, x, y-sampleRadius)
set zy=GetLocationZ(vector.loc)
call MoveLocation(vector.loc, x, y+sampleRadius)
set zy=zy-GetLocationZ(vector.loc)
set sampleRadius=2*sampleRadius
set v.x = zx*sampleRadius
set v.y = zy*sampleRadius
set v.z = sampleRadius*sampleRadius
return v
endmethod
method getTerrainNormal takes real x, real y, real sampleRadius returns nothing
local real zx
local real zy
call MoveLocation(vector.loc, x-sampleRadius, y)
set zx=GetLocationZ(vector.loc)
call MoveLocation(vector.loc, x+sampleRadius, y)
set zx=zx-GetLocationZ(vector.loc)
call MoveLocation(vector.loc, x, y-sampleRadius)
set zy=GetLocationZ(vector.loc)
call MoveLocation(vector.loc, x, y+sampleRadius)
set zy=zy-GetLocationZ(vector.loc)
set sampleRadius=2*sampleRadius
set this.x = zx*sampleRadius
set this.y = zy*sampleRadius
set this.z = sampleRadius*sampleRadius
endmethod
// ================================================================
method isInCylinder takes vector cylinderOrigin, vector cylinderHeight, real cylinderRadius returns boolean
local real l
local real x = this.x-cylinderOrigin.x
local real y = this.y-cylinderOrigin.y
local real z = this.z-cylinderOrigin.z
if x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z < 0.0 then //point below cylinder
return false
endif
set x = x-cylinderHeight.x
set y = y-cylinderHeight.y
set z = z-cylinderHeight.z
if x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z > 0.0 then //point above cylinder
return false
endif
set l = cylinderHeight.x*cylinderHeight.x+cylinderHeight.y*cylinderHeight.y+cylinderHeight.z*cylinderHeight.z
if l == 0.0 then
debug call BJDebugMsg("Cylinder with no height!")
return false
endif
set l = (x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z) / l
set x = x - cylinderHeight.x*l
set y = y - cylinderHeight.y*l
set z = z - cylinderHeight.z*l
if x*x+y*y+z*z > cylinderRadius*cylinderRadius then //point outside cylinder
return false
endif
return true
endmethod
method isInCone takes vector coneOrigin, vector coneHeight, real coneRadius returns boolean
local real l
local real x = this.x-coneOrigin.x
local real y = this.y-coneOrigin.y
local real z = this.z-coneOrigin.z
if x*coneHeight.x+y*coneHeight.y+z*coneHeight.z < 0.0 then //point below cone
return false
endif
set l = coneHeight.x*coneHeight.x+coneHeight.y*coneHeight.y+coneHeight.z*coneHeight.z
if l == 0.0 then
debug call BJDebugMsg("cone with no height!")
return false
endif
set l = (x*coneHeight.x+y*coneHeight.y+z*coneHeight.z) / l
set x = x - coneHeight.x*l
set y = y - coneHeight.y*l
set z = z - coneHeight.z*l
if SquareRoot(x*x+y*y+z*z) > coneRadius*(1.0-l) then //point outside cone
return false
endif
return true
endmethod
method isInSphere takes vector sphereOrigin, real sphereRadius returns boolean
if sphereRadius*sphereRadius < ((this.x-sphereOrigin.x)*(this.x-sphereOrigin.x)+(this.y-sphereOrigin.y)*(this.y-sphereOrigin.y)+(this.z-sphereOrigin.z)*(this.z-sphereOrigin.z)) then
return false
endif
return true
endmethod
endstruct
endlibrary
library VectorLib requires Vector // For backwards compatibility.
endlibrary
//TESH.scrollpos=7
//TESH.alwaysfold=0
//------------------------------------------------------------------------------------\\
// Linked List Module [v3.0.0] \\
// By Kenny & Jesus4Lyf. \\
// Constructed using vJASS. \\
// Requires: NewGen WE. \\
//------------------------------------------------------------------------------------\\
// \\
//------------------------------------------------------------------------------------\\
// DESCRIPTION: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// This module is a very powerful tool for structs. It enables users to create a \\
// linked list using a struct instance as the list itself, allowing for multiple \\
// lists in the one struct. It is simple to use and generates a very intuitive and \\
// basic interface that is easy to follow and understand. A linked list can be \\
// used to store struct instances instead of using the 'struct stack' method, and \\
// can also be used to attached a list to units and so on. When used appropriately \\
// it can give great functionality to users. \\
// \\
// METHODS: \\
// ¯¯¯¯¯¯¯¯¯ \\
// There are several methods available to you when you use this module, they \\
// include: \\
// \\
// Static methods: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// - .createList() - Creates a list using a struct instance as its 'base'. \\
// - Returns thistype. Retuns the list itself. \\
// \\
// Non-static methods: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// - .searchList() - Searches a list for a given instance of a struct type. \\
// - Returns thistype. \\
// \\
// - .destroyList() - Destroys each link in the list, as well as the list. \\
// - Returns nothing. \\
// \\
// - .addToStart() - Adds a struct instance to the start of the list. \\
// - Returns thistype. Returns the parameter. \\
// \\
// - .addToEnd() - Adds a struct instance to the end of the list. \\
// - Returns thistype. Returns the parameter. \\
// \\
// - .detachHead() - Removes the first link from the list. \\
// - Returns thistype. Returns the first link. \\
// \\
// - .detachTail() - Removes the last link from the list. \\
// - Returns thistype. Returns the last link. \\
// \\
// - .detachThis() - Removes the current link from the list. \\
// - Returns thistype. Returns the current link. \\
// \\
// - .destroyHead() - Removes the first link from the list and calls the \\
// .destroy() method. \\
// - Returns nothing. \\
// \\
// - .destroyTail() - Removes the last link from the list and calls the \\
// .destroy() method. \\
// - Returns nothing. \\
// \\
// - .destroyThis() - Removes the current link from the list and call the \\
// .destroy() method. \\
// - Returns nothing. \\
// \\
// MEMBERS: \\
// ¯¯¯¯¯¯¯¯¯ \\
// There are several members that users can access using this module, these \\
// include: \\
// \\
// Readonly members: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// - .head - Retrieves the first link in the list and returns it. \\
// - Returns thistype. \\
// \\
// - .next - Retrieves the next link in the list and returns it. \\
// - Returns thistype. Returns the next link. \\
// \\
// - .hasNext - Checks to see if the current link has a next link. \\
// - Returns boolean. Returns true is next link is there. \\
// \\
// - .tail - Retrieves the last link in the list and returns it. \\
// - Returns thistype. Returns the last link. \\
// \\
// - .prev - Retrieves the prev link in the list and returns it. \\
// - Returns thistype. Returns the previous link. \\
// \\
// - .hasPrev - Checks to see if the current link has a next link. \\
// - Returns boolean. Returns true if prev link is there. \\
// \\
// - .size - Retrieves the current size of a list (Number of links). \\
// - Returns integer. Returns the number of current links. \\
// \\
// - .empty - Checks to see if a given list is empty or not. \\
// - Returns boolean. Returns true if list is empty. \\
// \\
// - .isList - Checks to see if a given struct instance is a list. \\
// - Returns boolean. Returns true if an instance is a list. \\
// \\
// USAGE/EXAMPLES: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// To use this module within a struct you must implement it using the following: \\
// \\
// private struct Data \\
// implement LinkedList \\
// \\
// Do stuff here using the module. \\
// endstruct \\
// \\
// It is easiest to implement it right under struct declaration. \\
// \\
// There are only three methods available which use parameters. Usage for these \\
// three methods are as follows: \\
// \\
// call .addToStart(thistype value) \\
// call .addToEnd(thistype value) \\
// call .searchList(thistype value) \\
// \\
// The above take one parameter. The parameter must be a thistype value. Meaning \\
// it takes a struct instance as the parameter. \\
// \\
// PROS & CONS: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// As this module is just a simplification of struct stack syntax, there are not \\
// many negative points for it. However, just for the sake of it: \\
// \\
// Pros: \\
// ¯¯¯¯¯¯ \\
// - Simplifies syntax a fair bit. Makes it easier to read. \\
// - Allows for multiple linked lists within a single struct, generating \\
// multiple storage components. \\
// - Reduces time spent developing spells/scripts and reduces lines. \\
// - There is also a -possible- efficiency gain over the normal struct stack. \\
// But this I am not sure of. \\
// \\
// Cons: \\
// ¯¯¯¯¯¯ \\
// - A single node can only exist in one list at a time. \\
// \\
// IMPORTING: \\
// ¯¯¯¯¯¯¯¯¯¯¯ \\
// Simply create a new trigger, name it LinkedList or something along those lines. \\
// Then convert it to custom text, and paste this in its place and save. Done. \\
// \\
// THANKS/CREDITS: \\
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ \\
// - Jesus4Lyf - For basically re-inventing the module to make it far more useful \\
// and dynamic. Also for helping me understand linked lists better \\
// and helping to develop the script further. Major props to him. \\
// \\
//------------------------------------------------------------------------------------\\
library ListModule
module LinkedList
private thistype nextx = 0
private thistype prevx = 0
private thistype listx = 0
private boolean aList = false
method operator head takes nothing returns thistype
debug if not this.aList then
debug call BJDebugMsg("Linked List Module (head): Struct instance is not a list.")
debug return 0
debug endif
return this.nextx
endmethod
method operator next takes nothing returns thistype
return this.nextx
endmethod
method operator hasNext takes nothing returns boolean
return this.nextx != 0
endmethod
method operator tail takes nothing returns thistype
debug if not this.aList then
debug call BJDebugMsg("Linked List Module (last): Struct instance is not a list.")
debug return 0
debug endif
return this.prevx
endmethod
method operator prev takes nothing returns thistype
return this.prevx
endmethod
method operator hasPrev takes nothing returns boolean
return this.prevx != 0
endmethod
method operator size takes nothing returns integer
debug if not this.aList then
debug call BJDebugMsg("Linked List Module (size/empty): Struct instance is not a list.")
debug return 0
debug endif
return integer(this.listx)
endmethod
method operator empty takes nothing returns boolean
return this.size == 0
endmethod
method operator isList takes nothing returns boolean
return this.aList
endmethod
method operator[] takes integer index returns thistype
loop
set this = this.nextx
set index = index - 1
exitwhen index == 0
endloop
return this
endmethod
method destroyThis takes nothing returns nothing
call this.detachThis().destroy()
endmethod
method destroyTail takes nothing returns nothing
call this.detachTail().destroy()
endmethod
method destroyHead takes nothing returns nothing
call this.detachHead().destroy()
endmethod
method detachThis takes nothing returns thistype
debug if this.listx == 0 then
debug call BJDebugMsg("Linked List Module (detachThis): Struct instance is not attached to a list.")
debug return 0
debug endif
if this.listx.nextx == this then
call this.listx.detachHead()
elseif this.listx.prevx == this then
call this.listx.detachTail()
else
set this.prevx.nextx = this.nextx
set this.nextx.prevx = this.prevx
set this.listx.listx = integer(this.listx.listx) - 1
set this.nextx = 0
set this.prevx = 0
set this.listx = 0
endif
return this
endmethod
method detachTail takes nothing returns thistype
local thistype tail = this.prevx
debug if not this.aList then
debug call BJDebugMsg("Linked List Module (detachLast): Struct instance is not a list.")
debug return 0
debug endif
set this.prevx = this.prevx.prevx
set this.prevx.nextx = 0
set this.listx = integer(this.listx) - 1
set tail.nextx = 0
set tail.prevx = 0
set tail.listx = 0
if this.nextx == tail then
set this.nextx = 0
endif
return tail
endmethod
method detachHead takes nothing returns thistype
local thistype head = this.nextx
debug if not this.aList then
debug call BJDebugMsg("Lniked List Module (detachHead): Struct instance is not a list.")
debug return 0
debug endif
set this.nextx = this.nextx.nextx
set this.nextx.prevx = 0
set this.listx = integer(this.listx) - 1
set head.nextx = 0
set head.prevx = 0
set head.listx = 0
if this.prevx == head then
set this.prevx = 0
endif
return head
endmethod
method addToEnd takes thistype toAdd returns thistype
debug if not this.aList then
debug call BJDebugMsg("Linked List Module (addToEnd): Struct instance is not a list.")
debug return 0
debug endif
set this.prevx.nextx = toAdd
set toAdd.prevx = this.prevx
set this.prevx = toAdd
if this.nextx == 0 then
set this.nextx = toAdd
endif
set toAdd.listx = this
set this.listx = integer(this.listx) + 1
return toAdd
endmethod
method addToStart takes thistype toAdd returns thistype
debug if not this.aList then
debug call BJDebugMsg("Linked List Module (addToStart): Struct instance is not a list.")
debug return 0
debug endif
set this.nextx.prevx = toAdd
set toAdd.nextx = this.nextx
set this.nextx = toAdd
if this.prevx == 0 then
set this.prevx = toAdd
endif
set toAdd.listx = this
set this.listx = integer(this.listx) + 1
return toAdd
endmethod
method destroyList takes nothing returns nothing
debug if not this.aList then
debug call BJDebugMsg("Linked List Module (destroyList): Struct instance is not a list.")
debug return
debug endif
loop
if this.aList then
call this.deallocate()
else
call this.destroy()
endif
set this = this.nextx
exitwhen this == 0
endloop
endmethod
method searchList takes thistype toSearch returns thistype
debug if not this.aList then
debug call BJDebugMsg("Linked List Module (searchList): Struct instance is not a list.")
debug return 0
debug endif
loop
set this = this.nextx
if this == toSearch then
return this
endif
exitwhen this == 0
endloop
return 0
endmethod
static method createList takes nothing returns thistype
local thistype this = thistype.allocate()
set this.aList = true
return this
endmethod
endmodule
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_On_Suit_Drop_Conditions takes nothing returns boolean
return GetItemType(GetManipulatedItem()) == ITEM_TYPE_CAMPAIGN and IsUnitType(GetManipulatingUnit(), UNIT_TYPE_PEON) == true
endfunction
function Trig_On_Suit_Drop_Actions takes nothing returns nothing
if GetArmorNumber(GetItemTypeId(GetManipulatedItem())) == GetArmorUnitNumber(GetUnitTypeId(GetManipulatingUnit())) then
call UnitAddAbility(GetManipulatingUnit(), 'a003')
endif
endfunction
//===========================================================================
function InitTrig_On_Suit_Drop takes nothing returns nothing
set gg_trg_On_Suit_Drop = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_On_Suit_Drop, EVENT_PLAYER_UNIT_DROP_ITEM )
call TriggerAddCondition( gg_trg_On_Suit_Drop, Condition( function Trig_On_Suit_Drop_Conditions ) )
call TriggerAddAction( gg_trg_On_Suit_Drop, function Trig_On_Suit_Drop_Actions )
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_On_Suit_Use_Conditions takes nothing returns boolean
return GetItemType(GetManipulatedItem()) == ITEM_TYPE_CAMPAIGN and PlayerData[GetPlayerId(GetOwningPlayer(GetManipulatingUnit()))].AlienID != GetUnitTypeId(GetManipulatingUnit()) and IsUnitType(GetManipulatingUnit(), UNIT_TYPE_PEON) == true
endfunction
function Trig_On_Suit_Use_Actions takes nothing returns nothing
call ChangeArmor(GetManipulatingUnit(), GetItemTypeId(GetManipulatedItem()))
endfunction
//===========================================================================
function InitTrig_On_Suit_Use takes nothing returns nothing
set gg_trg_On_Suit_Use = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_On_Suit_Use, EVENT_PLAYER_UNIT_USE_ITEM )
call TriggerAddCondition( gg_trg_On_Suit_Use, Condition( function Trig_On_Suit_Use_Conditions ) )
call TriggerAddAction( gg_trg_On_Suit_Use, function Trig_On_Suit_Use_Actions )
endfunction
//TESH.scrollpos=11
//TESH.alwaysfold=0
library Suits initializer Init_Suits
function GetArmorUnitNumber takes integer ID returns integer
local integer i = 0
loop
exitwhen i > Suits
if ID == ArmorUnitID[i] then
return i
endif
set i = i + 1
endloop
return 0
endfunction
function GetArmorNumber takes integer ID returns integer
local integer i = 0
loop
exitwhen i > Suits
if ID == ArmorID[i] then
return i
endif
set i = i + 1
endloop
call BJDebugMsg("ArmorID does not match with any known armors. Please report this bug.")
return 1
endfunction
function ChangeArmor takes unit tempUnit, integer ID returns nothing
local integer ChaosLevel = GetArmorNumber(ID)
call UnitAddAbility(tempUnit, 'a004')
call SetUnitAbilityLevel(tempUnit, 'a004', ChaosLevel)
endfunction
function Init_Suits takes nothing returns nothing
set ArmorID[1] = 'w000'
set ArmorUnitID[1] = 'z000'
endfunction
endlibrary
//TESH.scrollpos=292
//TESH.alwaysfold=0
function Trig_Names takes nothing returns nothing
set udg_BlankName=" "
//Lots of Names!!
set udg_MaleFirstName[1]="Aaron"
set udg_MaleFirstName[2]="Adam"
set udg_MaleFirstName[3]="Alexander"
set udg_MaleFirstName[4]="Alan"
set udg_MaleFirstName[5]="Bruce"
set udg_MaleFirstName[6]="Benedict"
set udg_MaleFirstName[7]="Bert"
set udg_MaleFirstName[8]="Blaine"
set udg_MaleFirstName[9]="Carl"
set udg_MaleFirstName[10]="Charles"
set udg_MaleFirstName[11]="Chen"
set udg_MaleFirstName[12]="Clark"
set udg_MaleFirstName[13]="Damien"
set udg_MaleFirstName[14]="Daniel"
set udg_MaleFirstName[15]="David"
set udg_MaleFirstName[16]="Dirk"
set udg_MaleFirstName[17]="Erik"
set udg_MaleFirstName[18]="Edmond"
set udg_MaleFirstName[19]="Emmet"
set udg_MaleFirstName[20]="Ethan"
set udg_MaleFirstName[21]="Felix"
set udg_MaleFirstName[22]="Fletcher"
set udg_MaleFirstName[23]="Frederick"
set udg_MaleFirstName[24]="Feoras"
set udg_MaleFirstName[25]="Gabriel"
set udg_MaleFirstName[26]="Gareth"
set udg_MaleFirstName[27]="Gustaf"
set udg_MaleFirstName[28]="Gil"
set udg_MaleFirstName[29]="Haven"
set udg_MaleFirstName[30]="Herbert"
set udg_MaleFirstName[31]="Hideaki"
set udg_MaleFirstName[32]="Howard"
set udg_MaleFirstName[33]="Ian"
set udg_MaleFirstName[34]="Ira"
set udg_MaleFirstName[35]="Ishmael"
set udg_MaleFirstName[36]="Innis"
set udg_MaleFirstName[37]="James"
set udg_MaleFirstName[38]="Jason"
set udg_MaleFirstName[39]="Jericho"
set udg_MaleFirstName[40]="John"
set udg_MaleFirstName[41]="Kane"
set udg_MaleFirstName[42]="Karl"
set udg_MaleFirstName[43]="Knox"
set udg_MaleFirstName[44]="Kurt"
set udg_MaleFirstName[45]="Lance"
set udg_MaleFirstName[46]="Lloyd"
set udg_MaleFirstName[47]="Logan"
set udg_MaleFirstName[48]="Luther"
set udg_MaleFirstName[49]="Matthew"
set udg_MaleFirstName[50]="Mason"
set udg_MaleFirstName[51]="Marcus"
set udg_MaleFirstName[52]="Michael"
set udg_MaleFirstName[53]="Nathan"
set udg_MaleFirstName[54]="Neil"
set udg_MaleFirstName[55]="Nicholas"
set udg_MaleFirstName[56]="Noah"
set udg_MaleFirstName[57]="Omar"
set udg_MaleFirstName[58]="Orion"
set udg_MaleFirstName[59]="Owen"
set udg_MaleFirstName[60]="Otto"
set udg_MaleFirstName[61]="Patrick"
set udg_MaleFirstName[62]="Paul"
set udg_MaleFirstName[63]="Philip"
set udg_MaleFirstName[64]="Pierce"
set udg_MaleFirstName[65]="Ralph"
set udg_MaleFirstName[66]="Reece"
set udg_MaleFirstName[67]="Ren"
set udg_MaleFirstName[68]="Roger"
set udg_MaleFirstName[69]="Samiel"
set udg_MaleFirstName[70]="Scott"
set udg_MaleFirstName[71]="Sigmund"
set udg_MaleFirstName[72]="Stan"
set udg_MaleFirstName[73]="Thomas"
set udg_MaleFirstName[74]="Tristan"
set udg_MaleFirstName[75]="Travis"
set udg_MaleFirstName[76]="Tyler"
set udg_MaleFirstName[77]="Ulric"
set udg_MaleFirstName[78]="Uriel"
set udg_MaleFirstName[79]="Ulmer"
set udg_MaleFirstName[80]="Uriah"
set udg_MaleFirstName[81]="Van"
set udg_MaleFirstName[82]="Vincent"
set udg_MaleFirstName[83]="Vlad"
set udg_MaleFirstName[84]="Victor"
set udg_MaleFirstName[85]="Warren"
set udg_MaleFirstName[86]="Wolfgang"
set udg_MaleFirstName[87]="Wesley"
set udg_MaleFirstName[88]="William"
set udg_MaleFirstName[89]="Xanthus"
set udg_MaleFirstName[90]="Xavier"
set udg_MaleFirstName[91]="Xenos"
set udg_MaleFirstName[92]="Xerxes"
set udg_MaleFirstName[93]="Zarek"
set udg_MaleFirstName[94]="Zach"
set udg_MaleFirstName[95]="Zane"
set udg_MaleFirstName[96]="Zeki"
set udg_MaleFirstName[97]="Joseph"
set udg_MaleFirstName[98]="Jack"
set udg_MaleFirstName[99]="Barrack"
set udg_MaleFirstName[100]="Ben"
set udg_MaleFirstName[101]="Jeffer"
set udg_MaleFirstName[102]="Ronald"
set udg_MaleFirstName[103]="Cadd"
set udg_MaleFirstName[104]="Dave"
set udg_MaleFirstName[105]="Dan"
set udg_MaleFirstName[106]="Xiao"
//MaleJokeNames!
set udg_MaleJokeName[1]="Howard Lovecraft"
set udg_MaleJokeName[2]="Karthlak"
set udg_MaleJokeName[3]="Mr T"
set udg_MaleJokeName[4]="Professor Plum"
set udg_MaleJokeName[5]="Light"
set udg_MaleJokeName[6]="Zero"
set udg_MaleJokeName[7]="Jebus"
set udg_MaleJokeName[8]="David Langon"
set udg_MaleJokeName[9]="Rick Ashley"
set udg_MaleJokeName[10]="Kenny"
set udg_MaleJokeName[11]="Harry Bouch"
set udg_MaleJokeName[12]="Gi Joe"
set udg_MaleJokeName[13]="Snake"
set udg_MaleJokeName[14]="Cloud"
set udg_MaleJokeName[15]="Jacen"
set udg_MaleJokeName[16]="Zitty"
set udg_MaleJokeName[17]="Yagami"
set udg_MaleJokeName[18]="Cobra"
set udg_MaleJokeName[19]="Sheepy"
set udg_MaleJokeName[20]="Cador"
set udg_MaleJokeName[21]="Saucey"
set udg_MaleJokeName[22]="El Darvardo"
set udg_MaleJokeName[23]="Vexorian"
set udg_MaleJokeName[24]="Snow Gun"
set udg_MaleJokeName[25]="Alex Cooper"
set udg_MaleJokeName[26]="Prince"
set udg_MaleJokeName[27]="Jezza"
set udg_MaleJokeName[28]="Pierce Jackson"
set udg_MaleJokeName[29]="Ben Wilson"
set udg_MaleJokeName[30]="Guy Fawkes"
set udg_MaleJokeName[31]="Walker"
set udg_MaleJokeName[32]="Tintin"
set udg_MaleJokeName[33]="Jack Sparrow"
set udg_MaleJokeName[34]="Spock"
set udg_MaleJokeName[35]="Neil Armstrong"
set udg_MaleJokeName[36]="Buzz Aldrin"
set udg_MaleJokeName[37]="Tom Hanks"
set udg_MaleJokeName[38]="Colonel Mustard"
set udg_MaleJokeName[39]="Pope Benadict"
set udg_MaleJokeName[40]="Douglas Adams"
set udg_MaleJokeName[41]="Arthur Dent"
set udg_MaleJokeName[42]="Ford Prefect"
set udg_MaleJokeName[43]="Arnold Rimmer"
set udg_MaleJokeName[44]="David Lister"
set udg_MaleJokeName[45]="Sephiroth"
set udg_MaleJokeName[46]="Peter Griffen"
set udg_MaleJokeName[47]="Ben Yahtzee"
set udg_MaleJokeName[48]="Xiao Mao"
set udg_MaleJokeName[49]="Raynor"
set udg_MaleJokeName[50]="Lelouch"
set udg_MaleJokeName[51]="Igor Darl Kallard"
set udg_MaleJokeName[52]="Karl Marx"
set udg_MaleJokeName[53]="Scrotty"
set udg_MaleJokeName[54]="Theodore Peracliatus Beard"
set udg_MaleJokeName[55]="Max Fightmaster"
set udg_MaleJokeName[56]="Chuck Leopold Sunshine"
set udg_MaleJokeName[57]="Luke Skywalker"
set udg_MaleJokeName[58]="Richard Nickson"
set udg_MaleJokeName[59]="Leroy Jethro Gibbs"
set udg_MaleJokeName[60]="Micheal Jackson"
set udg_MaleJokeName[61]="Homer Sexual"
set udg_MaleJokeName[62]="Jay Zee"
//Female names!
set udg_FemaleFirstName[1]="Agatha"
set udg_FemaleFirstName[2]="Alice"
set udg_FemaleFirstName[3]="Angela"
set udg_FemaleFirstName[4]="Ayla"
set udg_FemaleFirstName[5]="Bailey"
set udg_FemaleFirstName[6]="Beverly"
set udg_FemaleFirstName[7]="Brooke"
set udg_FemaleFirstName[8]="Brandy"
set udg_FemaleFirstName[9]="Caitlin"
set udg_FemaleFirstName[10]="Charlotte"
set udg_FemaleFirstName[11]="Claire"
set udg_FemaleFirstName[12]="Czarina"
set udg_FemaleFirstName[13]="Danae"
set udg_FemaleFirstName[14]="Deanna"
set udg_FemaleFirstName[15]="Denise"
set udg_FemaleFirstName[16]="Dylana"
set udg_FemaleFirstName[17]="Ezrela"
set udg_FemaleFirstName[18]="Elaine"
set udg_FemaleFirstName[19]="Elizabeth"
set udg_FemaleFirstName[20]="Emily"
set udg_FemaleFirstName[21]="Faith"
set udg_FemaleFirstName[22]="Fiona"
set udg_FemaleFirstName[23]="Felicia"
set udg_FemaleFirstName[24]="Fay"
set udg_FemaleFirstName[25]="Gloria"
set udg_FemaleFirstName[26]="Grace"
set udg_FemaleFirstName[27]="Gretchen"
set udg_FemaleFirstName[28]="Gabrielle"
set udg_FemaleFirstName[29]="Haley"
set udg_FemaleFirstName[30]="Heather"
set udg_FemaleFirstName[31]="Helen"
set udg_FemaleFirstName[32]="Hana"
set udg_FemaleFirstName[33]="Irene"
set udg_FemaleFirstName[34]="Ivory"
set udg_FemaleFirstName[35]="Ivana"
set udg_FemaleFirstName[36]="Isabel"
set udg_FemaleFirstName[37]="Jackie"
set udg_FemaleFirstName[38]="Jamie"
set udg_FemaleFirstName[39]="Jodi"
set udg_FemaleFirstName[40]="Jenny"
set udg_FemaleFirstName[41]="Kala"
set udg_FemaleFirstName[42]="Kate"
set udg_FemaleFirstName[43]="Kim"
set udg_FemaleFirstName[44]="Kelly"
set udg_FemaleFirstName[45]="Laura"
set udg_FemaleFirstName[46]="Lena"
set udg_FemaleFirstName[47]="Lisa"
set udg_FemaleFirstName[48]="Leslie"
set udg_FemaleFirstName[49]="Mary"
set udg_FemaleFirstName[50]="Marci"
set udg_FemaleFirstName[51]="Megan"
set udg_FemaleFirstName[52]="Meso"
set udg_FemaleFirstName[53]="Nadia"
set udg_FemaleFirstName[54]="Natalie"
set udg_FemaleFirstName[55]="Nicole"
set udg_FemaleFirstName[56]="Nori"
set udg_FemaleFirstName[57]="Oprah"
set udg_FemaleFirstName[58]="Orah"
set udg_FemaleFirstName[59]="Oseye"
set udg_FemaleFirstName[60]="Oceana"
set udg_FemaleFirstName[61]="Paris"
set udg_FemaleFirstName[62]="Phoebe"
set udg_FemaleFirstName[63]="Persis"
set udg_FemaleFirstName[64]="Page"
set udg_FemaleFirstName[65]="Quinn"
set udg_FemaleFirstName[66]="Questa"
set udg_FemaleFirstName[67]="Queena"
set udg_FemaleFirstName[68]="Qubilah"
set udg_FemaleFirstName[69]="Rebecca"
set udg_FemaleFirstName[70]="Rose"
set udg_FemaleFirstName[71]="Regina"
set udg_FemaleFirstName[72]="Richelle"
set udg_FemaleFirstName[73]="Sabrina"
set udg_FemaleFirstName[74]="Samatha"
set udg_FemaleFirstName[75]="Scarlett"
set udg_FemaleFirstName[76]="Sofia"
set udg_FemaleFirstName[77]="Thea"
set udg_FemaleFirstName[78]="Tracey"
set udg_FemaleFirstName[79]="Trudy"
set udg_FemaleFirstName[80]="Una"
set udg_FemaleFirstName[81]="Ursula"
set udg_FemaleFirstName[82]="Ushi"
set udg_FemaleFirstName[83]="Umeko"
set udg_FemaleFirstName[84]="Ulani"
set udg_FemaleFirstName[85]="Valerie"
set udg_FemaleFirstName[86]="Vanessa"
set udg_FemaleFirstName[87]="Vickie"
set udg_FemaleFirstName[88]="Virginia"
set udg_FemaleFirstName[89]="Whitney"
set udg_FemaleFirstName[90]="Willow"
set udg_FemaleFirstName[91]="Wanda"
set udg_FemaleFirstName[92]="Winema"
set udg_FemaleFirstName[93]="Xandra"
set udg_FemaleFirstName[94]="Xanthe"
set udg_FemaleFirstName[95]="Xavier"
set udg_FemaleFirstName[96]="Xenia"
set udg_FemaleFirstName[97]="Yasmin"
set udg_FemaleFirstName[98]="Yachi"
set udg_FemaleFirstName[99]="Yolanda"
set udg_FemaleFirstName[100]="Yvette"
set udg_FemaleFirstName[101]="Zoe"
set udg_FemaleFirstName[102]="Zena"
set udg_FemaleFirstName[103]="Zelda"
set udg_FemaleFirstName[104]="Zara"
set udg_FemaleFirstName[105]="Clancey"
set udg_FemaleFirstName[106]="Grace"
set udg_FemaleJokeName[1]="Agatha Christie"
set udg_FemaleJokeName[2]="Amanda Hunginkiss"
set udg_FemaleJokeName[3]="Miley Cyrus"
set udg_FemaleJokeName[4]="Sarah Kerrigan"
set udg_FemaleJokeName[5]="Sigourney Weaver"
set udg_FemaleJokeName[6]="Ellen Ripley"
set udg_FemaleJokeName[7]="Bessy Ality"
set udg_FemaleJokeName[8]="Blondie"
set udg_FemaleJokeName[8]="Miranda Ginsberg"
set udg_FemaleJokeName[9]="Mother"
set udg_FemaleJokeName[10]="Juggalette"
set udg_FemaleJokeName[11]="Trinity"
set udg_FemaleJokeName[12]="Kristine Kochanski"
set udg_FemaleJokeName[13]="Kate Todd"
set udg_FemaleJokeName[14]="Abigail Sciuto"
set udg_FemaleJokeName[15]="Jenny Shepard"
//LastNames, Both male and female share these
set udg_LastName[1]="Addison"
set udg_LastName[2]="Aderet"
set udg_LastName[3]="Absalom"
set udg_LastName[4]="Algernon"
set udg_LastName[5]="Amory"
set udg_LastName[6]="Averson"
set udg_LastName[7]="Brooks"
set udg_LastName[8]="Baxter"
set udg_LastName[9]="Bond"
set udg_LastName[10]="Berkley"
set udg_LastName[11]="Barret"
set udg_LastName[12]="Baker"
set udg_LastName[13]="Cadell"
set udg_LastName[14]="Callaghan"
set udg_LastName[15]="Casimir"
set udg_LastName[16]="Cedric"
set udg_LastName[17]="Conary"
set udg_LastName[18]="Cashwell"
set udg_LastName[19]="Darnell"
set udg_LastName[20]="Dionysus"
set udg_LastName[21]="Donato"
set udg_LastName[22]="Donovan"
set udg_LastName[23]="Dudley"
set udg_LastName[24]="Durriken"
set udg_LastName[25]="Eberhard"
set udg_LastName[26]="Ebenezer"
set udg_LastName[27]="Eldridge"
set udg_LastName[28]="Everard"
set udg_LastName[29]="Erinton"
set udg_LastName[30]="Engelbert"
set udg_LastName[31]="Farley"
set udg_LastName[32]="Finley"
set udg_LastName[33]="Fuller"
set udg_LastName[34]="Feroz"
set udg_LastName[35]="Figarello"
set udg_LastName[36]="Fonzey"
set udg_LastName[37]="Garridan"
set udg_LastName[38]="Galeno"
set udg_LastName[39]="Gilahan"
set udg_LastName[40]="Grant"
set udg_LastName[41]="Gavin"
set udg_LastName[42]="Gunley"
set udg_LastName[43]="Hanley"
set udg_LastName[44]="Harvey"
set udg_LastName[45]="Hunt"
set udg_LastName[46]="Hughs"
set udg_LastName[47]="Hersh"
set udg_LastName[48]="Holic"
set udg_LastName[49]="Irving"
set udg_LastName[50]="Iris"
set udg_LastName[51]="Joel"
set udg_LastName[52]="Jackson"
set udg_LastName[53]="Johnson"
set udg_LastName[54]="Jameson"
set udg_LastName[55]="Kacey"
set udg_LastName[56]="Kenley"
set udg_LastName[57]="Kirby"
set udg_LastName[58]="Kingsley"
set udg_LastName[59]="Knoxville"
set udg_LastName[60]="Karinton"
set udg_LastName[61]="Langdon"
set udg_LastName[62]="Lambert"
set udg_LastName[63]="Langford"
set udg_LastName[64]="Lee"
set udg_LastName[65]="Lamuel"
set udg_LastName[66]="Lyron"
set udg_LastName[67]="Macbride"
set udg_LastName[68]="Macdonald"
set udg_LastName[69]="Madison"
set udg_LastName[70]="Manning"
set udg_LastName[71]="Maverick"
set udg_LastName[72]="Mayfield"
set udg_LastName[73]="Miller"
set udg_LastName[74]="Milford"
set udg_LastName[75]="Miles"
set udg_LastName[76]="Mitchell"
set udg_LastName[77]="Montgomery"
set udg_LastName[78]="Murphy"
set udg_LastName[79]="Nalren"
set udg_LastName[80]="Navarro"
set udg_LastName[81]="Nelson"
set udg_LastName[82]="Newton"
set udg_LastName[83]="Norwood"
set udg_LastName[84]="Nolan"
set udg_LastName[85]="Oakley"
set udg_LastName[86]="Octavius"
set udg_LastName[87]="Odell"
set udg_LastName[88]="Orban"
set udg_LastName[89]="Orville"
set udg_LastName[90]="Osbourne"
set udg_LastName[91]="Parker"
set udg_LastName[92]="Parr"
set udg_LastName[93]="Piper"
set udg_LastName[94]="Penley"
set udg_LastName[95]="Perkins"
set udg_LastName[96]="Prior"
set udg_LastName[97]="Quigley"
set udg_LastName[98]="Quillan"
set udg_LastName[99]="Quinn"
set udg_LastName[100]="Quinlin"
set udg_LastName[101]="Radford"
set udg_LastName[102]="Radburn"
set udg_LastName[103]="Reinhart"
set udg_LastName[104]="Ramiro"
set udg_LastName[105]="Reed"
set udg_LastName[106]="Ridley"
set udg_LastName[107]="Saber"
set udg_LastName[108]="Sawyer"
set udg_LastName[109]="Sanders"
set udg_LastName[110]="Saville"
set udg_LastName[111]="Sullivan"
set udg_LastName[112]="Sefton"
set udg_LastName[113]="Shepard"
set udg_LastName[114]="Steward"
set udg_LastName[115]="Sherman"
set udg_LastName[116]="Sherborn"
set udg_LastName[117]="Sheffield"
set udg_LastName[118]="Smith"
set udg_LastName[119]="Stanfield"
set udg_LastName[120]="Sloan"
set udg_LastName[121]="Stafford"
set udg_LastName[122]="Somerton"
set udg_LastName[123]="Stancliff"
set udg_LastName[124]="Stanislaus"
set udg_LastName[125]="Sweeney"
set udg_LastName[126]="Taggart"
set udg_LastName[127]="Tanner"
set udg_LastName[128]="Tarleton"
set udg_LastName[129]="Taylor"
set udg_LastName[130]="Tedmund"
set udg_LastName[131]="Tyrrell"
set udg_LastName[135]="Thornton"
set udg_LastName[136]="Tyson"
set udg_LastName[137]="Turner"
set udg_LastName[138]="Tucker"
set udg_LastName[139]="Upton"
set udg_LastName[140]="Urish"
set udg_LastName[141]="Valentine"
set udg_LastName[142]="Vito"
set udg_LastName[143]="Verminton"
set udg_LastName[144]="Viscera"
set udg_LastName[145]="Wade"
set udg_LastName[146]="Walker"
set udg_LastName[147]="Wagner"
set udg_LastName[148]="Ward"
set udg_LastName[149]="Webb"
set udg_LastName[150]="Wheeler"
set udg_LastName[151]="Wilcocks"
set udg_LastName[152]="Whitfield"
set udg_LastName[153]="Whistler"
set udg_LastName[154]="Wiley"
set udg_LastName[155]="Wilkinson"
set udg_LastName[156]="Winfield"
set udg_LastName[157]="Wolcott"
set udg_LastName[158]="Wright"
set udg_LastName[159]="Yates"
set udg_LastName[160]="Yazar"
set udg_LastName[161]="Yale"
set udg_LastName[162]="Yagil"
set udg_LastName[163]="Zebulon"
set udg_LastName[164]="Zuberi"
set udg_LastName[165]="Mykovsky"
set udg_LastName[166]="Halas"
set udg_LastName[167]="Mehoff"
set udg_LastName[168]="Moore"
set udg_LastName[169]="Hitler"
set udg_LastName[170]="Stalin"
set udg_LastName[171]="Depp"
set udg_LastName[172]="Travolta"
set udg_LastName[173]="Cruise"
set udg_LastName[174]="Winfree"
set udg_LastName[175]="Devito"
set udg_LastName[176]="Deniro"
set udg_LastName[177]="Mcockinhand"
set udg_LastName[178]="Swallows"
set udg_LastName[179]="Spits"
set udg_LastName[180]="Hornay"
set udg_LastName[181]="Shithouse"
set udg_LastName[182]="Obama"
set udg_LastName[183]="Cockmaster"
set udg_LastName[184]="Lister"
set udg_LastName[185]="Rimmer"
set udg_LastName[186]="Cage"
set udg_LastName[187]="Strain"
set udg_LastName[188]="Biggy"
set udg_LastName[189]="Capone"
set udg_LastName[190]="Umbrella"
set udg_LastName[191]="Simpson"
set udg_LastName[192]="Wilson"
set udg_LastName[193]="Ashley"
set udg_LastName[194]="Voltron"
set udg_LastName[195]="Spears"
set udg_LastName[196]="Lohan"
set udg_LastName[197]="Joley"
set udg_LastName[198]="Mander"
set udg_LastName[199]="Rist"
set udg_LastName[200]="Vimes"
set udg_LastName[201]="Wibbley"
//Ai Names
set udg_AIName[1]="J.A.S.S."
set udg_AIName[2]="B.S.W."
set udg_AIName[3]="Sentinel"
set udg_AIName[4]="Deep Blue"
set udg_AIName[5]="Glitch"
set udg_AIName[6]="Mk I"
set udg_AIName[7]="Mk II"
set udg_AIName[8]="R.E.M."
set udg_AIName[9]="Steam"
set udg_AIName[10]="Vista"
set udg_AIName[11]="I Robot"
set udg_AIName[12]="Nutcracker 4000"
set udg_AIName[13]="Sexbot Mk II"
set udg_AIName[14]="Juggernaut"
set udg_AIName[15]="R2-D2"
set udg_AIName[16]="Mk IV"
set udg_AIName[17]="Kryten"
set udg_AIName[18]="A.I."
set udg_AIName[19]="K-9"
set udg_AIName[20]="KITT"
set udg_AIName[21]="Mac"
set udg_AIName[22]="Windows"
set udg_AIName[23]="Iron Man"
set udg_AIName[24]="Megatron"
set udg_AIName[25]="Prime"
set udg_AIName[26]="R.O.B."
set udg_AIName[27]="Droid"
set udg_AIName[28]="EVA"
set udg_AIName[29]="Robot"
set udg_AIName[30]="Robo"
set udg_AIName[31]="Mech"
set udg_AIName[32]="XEMG"
set udg_AIName[33]="Omega"
set udg_AIName[34]="Alpha"
set udg_AIName[35]="Beta"
set udg_AIName[36]="Gamma"
set udg_AIName[37]="Zeta"
set udg_AIName[38]="Knightmare"
set udg_AIName[39]="13"
set udg_AIName[40]="Marvin"
// Colors
set udg_PlayerColors[1] = "|cFFff0303"
set udg_PlayerColors[2] = "|cFF0042ff"
set udg_PlayerColors[3] = "|cFF1ce6b9"
set udg_PlayerColors[4] = "|cFF6F2583"
set udg_PlayerColors[5] = "|cFFfffc01"
set udg_PlayerColors[6] = "|cfffe8a0e"
set udg_PlayerColors[7] = "|cFF20c000"
set udg_PlayerColors[8] = "|cFFFF00FF"
set udg_PlayerColors[9] = "|cFF959697"
set udg_PlayerColors[10] = "|cFF7ebff1"
set udg_PlayerColors[11] = "|cFF004000"
set udg_PlayerColors[12] = "|cFF4e2a04"
set udg_ColorString[1] = udg_PlayerColors[1]+"Red"
set udg_ColorString[2] = udg_PlayerColors[2]+"Blue"
set udg_ColorString[3] = udg_PlayerColors[3]+"Teal"
set udg_ColorString[4] = udg_PlayerColors[4]+"Purple"
set udg_ColorString[5] = udg_PlayerColors[5]+"Yellow"
set udg_ColorString[6] = udg_PlayerColors[6]+"Orange"
set udg_ColorString[7] = udg_PlayerColors[7]+"Green"
set udg_ColorString[8] = udg_PlayerColors[8]+"Pink"
set udg_ColorString[9] = udg_PlayerColors[9]+"Gray"
set udg_ColorString[10] = udg_PlayerColors[10]+"Light Blue"
set udg_ColorString[11] = udg_PlayerColors[11]+"Dark Green"
set udg_ColorString[12] = udg_PlayerColors[12]+"Brown"
call DestroyTrigger(GetTriggeringTrigger())
endfunction
//===========================================================================
function InitTrig_Names takes nothing returns nothing
set gg_trg_Names = CreateTrigger( )
call TriggerAddAction( gg_trg_Names, function Trig_Names)
endfunction
//TESH.scrollpos=76
//TESH.alwaysfold=0
library SlowProjectiles initializer OnInit requires Projectile, AIDS, GroupUtils, T32, Vector, AutoFly
globals
private constant integer ABIL_ID = 'A001'
private constant real DURATION = 15.00
private constant real SLOW_SPD = 64.00
private constant real RADIUS = 290.00
private constant string EFFECT = "SlowTime.mdl"
integer array Slowed
endglobals
private struct RemovalSafety extends array
//! runtextmacro AIDS()
integer id
private static method AIDS_filter takes unit whichUnit returns boolean
return GetUnitTypeId(whichUnit) == Projectile_DUMMY_ID
endmethod
private method AIDS_onCreate takes nothing returns nothing
set this.id = GetUnitId(this.unit)
endmethod
private method AIDS_onDestroy takes nothing returns nothing
set Slowed[this.id] = 0
endmethod
endstruct
struct UnitRecycler
unit recycled = null
real tick = 0.00
private method destroy takes nothing returns nothing
call RemoveUnit(this.recycled)
set this.recycled = null
call this.deallocate()
endmethod
private method periodic takes nothing returns nothing
if this.tick == T32_Tick then
call this.stopPeriodic()
call this.destroy()
endif
endmethod
implement T32x
static method add takes unit whichUnit returns nothing
local thistype this = thistype.allocate()
set this.recycled = whichUnit
set this.tick = T32_Tick + R2I(3.00 / T32_PERIOD)
call this.startPeriodic()
endmethod
endstruct
private keyword Slow
private function FinishCallback takes Projectile p, integer i returns nothing
local integer id = GetUnitId(p.proj)
if Slowed[id] > 0 then
set Slowed[id] = Slowed[id] - 1
if Slowed[id] == 0 then
call p.modifySpeed(p.originalSpeed)
endif
endif
endfunction
private function LoopCallback takes Projectile p, integer i returns nothing
local Slow s = Slow(i)
local integer id = GetUnitId(p.proj)
if p.pos.isInSphere(s.pos,RADIUS) then
if not IsUnitInGroup(p.proj,s.grp) then
if Slowed[id] == 0 then
set Slowed[id] = Slowed[id] + 1
if Slowed[id] == 1 then
set p.enableHoming = false
call p.modifySpeed(SLOW_SPD)
endif
endif
call GroupAddUnit(s.grp,p.proj)
elseif IsUnitInGroup(p.proj,s.grp) and Slowed[id] == 0 then
set p.enableHoming = false
call p.modifySpeed(SLOW_SPD)
set Slowed[id] = Slowed[id] + 1
endif
else
if IsUnitInGroup(p.proj,s.grp) then
if Slowed[id] > 0 then
set Slowed[id] = Slowed[id] - 1
if Slowed[id] == 0 then
call p.modifySpeed(p.originalSpeed)
endif
endif
call GroupRemoveUnit(s.grp,p.proj)
endif
endif
endfunction
private struct Slow
unit cas = null
unit dum = null
effect sfx = null
group grp = null
real tic = 0.00
real dur = 0.00
vector pos = 0
method destroy takes nothing returns nothing
call GroupProjectilesInRange(ENUM_GROUP,this.pos.x,this.pos.y,this.pos.z,RADIUS + 25.00)
call ForProjectileGroup(ENUM_GROUP,FinishCallback,this)
call ReleaseGroup(this.grp)
call DestroyEffect(this.sfx)
call UnitRecycler.add(this.dum)
set this.dum = null
set this.sfx = null
set this.grp = null
call this.pos.destroy()
call this.deallocate()
endmethod
private method periodic takes nothing returns nothing
if this.dur == T32_Tick then
call this.stopPeriodic()
call this.destroy()
else
call GroupProjectilesInRange(ENUM_GROUP,this.pos.x,this.pos.y,this.pos.z,RADIUS + 25.00)
call ForProjectileGroup(ENUM_GROUP,LoopCallback,this)
if this.tic == 0.00 then
call SetUnitTimeScale(this.dum,0.00)
else
set this.tic = this.tic - T32_PERIOD
endif
endif
endmethod
implement T32x
static method create takes unit cast, real x, real y returns thistype
local thistype this = thistype.allocate()
set this.cas = cast
set this.pos = vector.create(x,y,5.00)
set this.dum = CreateUnit(GetOwningPlayer(cast),'u000',x,y,0.00)
set this.sfx = AddSpecialEffectTarget(EFFECT,this.dum,"origin")
set this.dur = T32_Tick + R2I(DURATION / T32_PERIOD)
set this.tic = 1.00
set this.grp = NewGroup()
call SetUnitX(this.dum,x)
call SetUnitY(this.dum,y)
call PauseUnit(this.dum,true)
call SetUnitScale(this.dum,0.725,0.00,0.00)
call SetUnitFlyHeight(this.dum,75.00,0.00)
call this.startPeriodic()
return this
endmethod
endstruct
private function Conditions takes nothing returns boolean
if GetSpellAbilityId() == ABIL_ID then
call ClearTextMessages()
call Slow.create(GetTriggerUnit(),GetSpellTargetX(),GetSpellTargetY())
endif
return false
endfunction
private function OnInit takes nothing returns nothing
local trigger trig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(trig,Condition(function Conditions))
endfunction
endlibrary
//TESH.scrollpos=37
//TESH.alwaysfold=0
library ShipFire initializer OnInit requires Projectile
globals
private constant integer ABIL_ID = 'SAtk'
private constant real DAMAGE = 400.00
private constant real HEIGHT = 150
private constant real DURATION= 2
private constant real SPEED = 800
private constant real AOE = 60
private constant string EFFECT = "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl"
private constant attacktype ATTACKTYPE=ATTACK_TYPE_CHAOS
endglobals
private function OnUnitImpact takes Projectile inst, unit whichUnit returns nothing
if UnitAlive(whichUnit) and GetOwningPlayer(whichUnit) != inst.owner and GetUnitTypeId(whichUnit) != 'sTDc' then
if GetUnitTypeId(whichUnit) == 'sStn' then
call UnitDamageTarget(inst.caster,whichUnit,inst.unitDamage,true,false,ATTACKTYPE,DAMAGE_TYPE_UNKNOWN,WEAPON_TYPE_WHOKNOWS)
endif
call UnitDamageTarget(inst.caster,whichUnit,inst.unitDamage,true,false,ATTACKTYPE,DAMAGE_TYPE_UNKNOWN,WEAPON_TYPE_WHOKNOWS)
call inst.terminate()
endif
endfunction
private function Actions takes nothing returns nothing
local unit cast = GetTriggerUnit()
local unit targ = GetSpellTargetUnit()
local real casx = GetUnitX(cast)
local real casy = GetUnitY(cast)
local real tarx = 0.00
local real tary = 0.00
local real ang = 0.00
local Projectile proj = 0
if targ == null then
set tarx = GetSpellTargetX()
set tary = GetSpellTargetY()
else
set tarx = GetUnitX(targ)
set tary = GetUnitY(targ)
endif
set ang = Atan2((tary - casy),(tarx - casx))
set proj = Projectile.create(casx,casy,HEIGHT,ang)
set proj.caster = cast
set proj.owner = GetOwningPlayer(cast)
set proj.effectPath = EFFECT
set proj.timedLife = DURATION
set proj.showDeathFx = true
set proj.scaleSize = 0.75
set proj.unitDamage = DAMAGE
set proj.unitCollision = AOE
set proj.collideable = false
set proj.onUnit = OnUnitImpact
call proj.onStart.execute(proj)
call proj.startPeriodic()
set cast = null
set targ = null
endfunction
private function OnInit takes nothing returns nothing
local trigger trig = CreateTrigger()
call GT_RegisterStartsEffectEvent(trig,ABIL_ID)
call TriggerAddAction(trig,function Actions)
endfunction
endlibrary
//TESH.scrollpos=38
//TESH.alwaysfold=0
library Barrage initializer OnInit requires Projectile
globals
private constant integer ABIL_ID = 'A06P'
private constant integer MISSLECOUNT=4
private constant real SPRAY = 10
private constant real DAMAGE = 400.00
private constant real HEIGHT = 150
private constant real DURATION= 2
private constant real SPEED = 800
private constant real AOE = 60
private constant string EFFECT = "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl"
private constant attacktype ATTACKTYPE=ATTACK_TYPE_CHAOS
endglobals
private function OnUnitImpact takes Projectile inst, unit whichUnit returns nothing
if UnitAlive(whichUnit) and GetOwningPlayer(whichUnit) != inst.owner and GetUnitTypeId(whichUnit) != 'sTDc' then
if GetUnitTypeId(whichUnit) == 'sStn' then
call UnitDamageTarget(inst.caster,whichUnit,inst.unitDamage,true,false,ATTACKTYPE,DAMAGE_TYPE_UNKNOWN,WEAPON_TYPE_WHOKNOWS)
endif
call UnitDamageTarget(inst.caster,whichUnit,inst.unitDamage,true,false,ATTACKTYPE,DAMAGE_TYPE_UNKNOWN,WEAPON_TYPE_WHOKNOWS)
call inst.terminate()
endif
endfunction
private function Actions takes nothing returns nothing
local unit cast = GetTriggerUnit()
local unit targ = GetSpellTargetUnit()
local real casx = GetUnitX(cast)
local real casy = GetUnitY(cast)
local real tarx = 0
local real tary = 0
local real ang = 0.00
local real r
local Projectile proj = 0
local integer i = 0
if targ == null then
set tarx = GetSpellTargetX()
set tary = GetSpellTargetY()
else
set tarx = GetUnitX(targ)
set tary = GetUnitY(targ)
endif
set ang = Atan2((tary - casy),(tarx - casx))
loop
exitwhen i == MISSLECOUNT
set i = i + 1
set r = ang + GetRandomReal(0-SPRAY,SPRAY)
set proj = Projectile.create(casx,casy,HEIGHT,r)
set proj.caster = cast
set proj.owner = GetOwningPlayer(cast)
set proj.effectPath = EFFECT
set proj.timedLife = DURATION
set proj.showDeathFx = true
set proj.scaleSize = 0.75
set proj.unitDamage = DAMAGE
set proj.unitCollision = AOE
set proj.collideable = false
set proj.onUnit = OnUnitImpact
call proj.projectNormal(tarx,tary,HEIGHT,SPEED)
endloop
set cast = null
endfunction
private function OnInit takes nothing returns nothing
local trigger trig = CreateTrigger()
call GT_RegisterStartsEffectEvent(trig,ABIL_ID)
call TriggerAddAction(trig,function Actions)
endfunction
endlibrary
//TESH.scrollpos=55
//TESH.alwaysfold=0
scope home initializer i
private struct homDat
real dur
unit u
unit U
real xvel
real yvel
endstruct
globals
private constant integer HOMEID='A00R' //Insert rawcode of ability.
private constant integer MISSID='h00M' //Insert rawcode of missle.
private constant real DURATION=3 //Duration of missle.
private constant real TIMEROUT=.03 //Timeout in seconds; RECCOMENDED .03 for 33 fps.
private constant real OFFSETPE=0.7 //Speed at which the missle increases.
private constant real MAXVEL =10 //Maximum velocity of the missle
private constant real AOE =20 //Distance between missle and target for damage to be dealt
private constant real DAMAGE =650 //Damage dealt by missle
private timer time=CreateTimer()
private homDat array homDB
private integer dbIndex=-1
endglobals
private function c takes nothing returns boolean
return GetSpellAbilityId()==HOMEID
endfunction
private function p takes nothing returns nothing
local homDat tempDat
local integer index=0
local unit u
local unit U
loop
exitwhen index>dbIndex
set tempDat=homDB[index]
set u=tempDat.u
set U=tempDat.U
if GetUnitX(u) > GetUnitX(U) then
if tempDat.xvel < MAXVEL then
set tempDat.xvel = tempDat.xvel + OFFSETPE
endif
else
if tempDat.xvel > MAXVEL*-1 then
set tempDat.xvel = tempDat.xvel - OFFSETPE
endif
endif
if GetUnitY(u) > GetUnitY(U) then
if tempDat.yvel < MAXVEL then
set tempDat.yvel = tempDat.yvel + OFFSETPE
endif
else
if tempDat.yvel > MAXVEL*-1 then
set tempDat.yvel = tempDat.yvel - OFFSETPE
endif
endif
set tempDat.dur=tempDat.dur-0.03
call SetUnitX(U,GetUnitX(U)+tempDat.xvel)
call SetUnitY(U,GetUnitY(U)+tempDat.yvel)
if D2PXY(GetUnitX(U),GetUnitY(U),GetUnitX(u),GetUnitY(u)) < AOE or tempDat.dur<0 then
debug call BJDebugMsg("hit")
if D2PXY(GetUnitX(U),GetUnitY(U),GetUnitX(u),GetUnitY(u)) < AOE then
call Damage_Pure(U,u,DAMAGE)
endif
call KillUnit(U)
call tempDat.destroy()
set homDB[index]=homDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
set u = null
set U = null
endfunction
private function a takes nothing returns nothing
local homDat tempDat=homDat.create()
set tempDat.dur=DURATION
set tempDat.xvel=0
set tempDat.yvel=0
set tempDat.u=GetSpellTargetUnit()
set tempDat.U=CreateUnit(GetOwningPlayer(GetTriggerUnit()),MISSID,GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()),GetUnitFacing(GetTriggerUnit()))
set dbIndex=dbIndex+1
set homDB[dbIndex]=tempDat
debug call BJDebugMsg("fired")
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function c))
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=8
//TESH.alwaysfold=0
scope tractor initializer i
private struct traDat
real dur
unit u
unit U
endstruct
globals
private constant integer TRACTID='A055' //Insert rawcode of ability.
private constant real DURATION=3 //Duration of ability.
private constant real TIMEROUT=.03 //Timeout in seconds; RECCOMENDED .03 for 33 fps.
private constant real OFFSETPE=20 //Offset distance after each iteration.
private constant real OFFSETMU=1 //Offset (iteration) multiplyer, for changing how close the target has to be.
private constant real FORCEDIVIDER=1.4
private timer time=CreateTimer()
private traDat array traDB
private integer dbIndex=-1
endglobals
private function c takes nothing returns boolean
return GetSpellAbilityId()==TRACTID
endfunction
private function p takes nothing returns nothing
local traDat tempDat
local integer index=0
local unit u
local unit U
local real rad
loop
exitwhen index>dbIndex
set tempDat=traDB[index]
set u=tempDat.u
set U=tempDat.U
set rad = A2PXY(GetUnitX(U),GetUnitY(U),GetUnitX(u),GetUnitY(u))*bj_DEGTORAD
if udg_ForceDock == true then
call SetUnitX(u,GetUnitX(u)-(OFFSETPE/FORCEDIVIDER)*Cos(rad))
call SetUnitY(u,GetUnitY(u)-(OFFSETPE/FORCEDIVIDER)*Sin(rad))
else
call SetUnitX(u,GetUnitX(u)-(OFFSETPE)*Cos(rad))
call SetUnitY(u,GetUnitY(u)-(OFFSETPE)*Sin(rad))
endif
set tempDat.dur=tempDat.dur-0.03
if D2PXY(GetUnitX(U),GetUnitY(U),GetUnitX(u),GetUnitY(u)) < 10 or tempDat.dur<0 then
if udg_ForceDock == true then
if D2PXY(GetUnitX(U),GetUnitY(U),GetUnitX(u),GetUnitY(u)) < 10 then
set udg_TempUnit = u
call TriggerExecute( gg_trg_Tractor_Beam_Force )
endif
endif
call tempDat.destroy()
set traDB[index]=traDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
set u = null
set U = null
endfunction
private function a takes nothing returns nothing
local traDat tempDat=traDat.create()
set tempDat.dur=DURATION
set tempDat.u=GetSpellTargetUnit()
set tempDat.U=GetTriggerUnit()
set dbIndex=dbIndex+1
set traDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function c))
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=7
//TESH.alwaysfold=0
scope jumpslice initializer i
private struct jumDat
boolean anidone
effect e
unit u
real z
real radian
real speed
real distance
real maxdistance
real curve
endstruct
globals
private group g = CreateGroup()
private constant integer JUMPID= 'A015' //Insert rawcode of ability.
private constant real TIMEROUT=.03 //Timeout in seconds; RECCOMENDED .03 for 33 fps.
private constant real CURVEDIV=150 //Curve of the jump.
private constant real DAMAGEOFFSET=100 //Offset the AoE is from the user.
private constant real DURATION=1.133 //Duration of the jump
private constant real AOE=200 //AoE of the damage @ end.
private constant real BASEDAMAGE=20 //Base daamage of ability.
private constant real MULTIDAMAGE=80 //Multiplier for the damge
private constant string ANIMATION="attack slam" //Animation used for the jump.
private constant string EFFECT= "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl"//Effect created on landing.
private constant string DAMAGEEFFECT="Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
private constant string CASTEREFFECT="Abilities\\Spells\\NightElf\\SpiritOfVengeance\\SpiritOfVengeanceBirthMissile.mdl"
private timer time=CreateTimer()
private jumDat array jumDB
private integer dbIndex=-1
endglobals
private function p takes nothing returns nothing
local jumDat tempDat
local unit a
local integer index=0
local real newX
local real newY
local real newZ
local real height
loop
exitwhen index>dbIndex
set tempDat=jumDB[index]
if tempDat.anidone ==false then
call SetUnitAnimation(tempDat.u,ANIMATION)
set tempDat.e = AddSpecialEffectTarget(CASTEREFFECT,tempDat.u,"weapon")
set tempDat.anidone = true
endif
set newX=GetUnitX(tempDat.u)+tempDat.speed*Cos(tempDat.radian)
set newY=GetUnitY(tempDat.u)+tempDat.speed*Sin(tempDat.radian)
set newZ=GetXYZ(newX,newY)
set height = JumpParabola(tempDat.distance, tempDat.maxdistance, tempDat.curve, tempDat.z, newZ)
call SetUnitFlyHeight( tempDat.u, height, 0.00 )
call SetUnitPosition(tempDat.u,newX,newY) //Using position so the unit can't be ordered around. It's shittier than X/Y, but cry about it.
set tempDat.distance=tempDat.distance-tempDat.speed
if tempDat.distance<0 or newZ>tempDat.z+5 or IsUnitType(tempDat.u, UNIT_TYPE_SNARED) == true then
set newX=GetUnitX(tempDat.u)+DAMAGEOFFSET*Cos(tempDat.radian)
set newY=GetUnitY(tempDat.u)+DAMAGEOFFSET*Sin(tempDat.radian)
set g = GetUnitsInRange(AOE,newX,newY)
loop
set a = FirstOfGroup(g)
exitwhen a ==null
call GroupRemoveUnit(g,a)
if GetOwningPlayer(a) != GetOwningPlayer(tempDat.u) and UnitAlive(a) == true then
call Damage_Pure(tempDat.u,a,BASEDAMAGE+(MULTIDAMAGE*GetUnitAbilityLevel(tempDat.u,JUMPID)))
call DestroyEffect(AddSpecialEffectTarget(DAMAGEEFFECT,a,"origin"))
endif
endloop
call DestroyEffect(tempDat.e)
call DestroyEffect(AddSpecialEffect(EFFECT,newX,newY))
call SetUnitPathingEx(tempDat.u,true)
call SetUnitPosition(tempDat.u,newX,newY)
call SetUnitFlyHeight( tempDat.u, 0, 0.00 )
call tempDat.destroy()
set jumDB[index]=jumDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
set a =null
endfunction
private function a takes nothing returns nothing
local jumDat tempDat=jumDat.create()
local location targ=GetSpellTargetLoc()
call SetUnitPathingEx(GetTriggerUnit(),false)
set tempDat.anidone = false
set tempDat.u=GetSpellAbilityUnit()
set tempDat.z=GetXYZ(GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()))
set tempDat.radian=A2PXY(GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()),GetLocationX(targ),GetLocationY(targ))*bj_DEGTORAD
set tempDat.distance=D2PXY(GetLocationX(targ),GetLocationY(targ),GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()))
set tempDat.maxdistance=tempDat.distance
set tempDat.speed=tempDat.distance*TIMEROUT*DURATION
set tempDat.curve = tempDat.distance/CURVEDIV
set dbIndex=dbIndex+1
set jumDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
call RemoveLocation(targ)
set targ = null
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call GT_RegisterStartsEffectEvent(t,JUMPID)
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=46
//TESH.alwaysfold=0
scope grapple initializer i
private struct graDat
unit u
unit t
real x
real y
real z
real radian
real distance
effect fx
boolean pulling
lightning l
endstruct
globals
private group g = CreateGroup()
private constant integer GRAPID= 'A02K' //Insert rawcode of ability.
private constant real TIMEROUT=.03 //Timeout in seconds; RECCOMENDED .03 for 33 fps
private constant real AOE=150
private constant real DAMAGEBASE=20
private constant real DAMAGEMULTI=30
private constant real SPEED=1000
private constant real PULLINGSPEED=600
private constant real DISTANCEBASE=700
private constant real DISTANCEMULTI=100
private constant real MAXDIST=1200
private constant real MINDIST=75
private constant real RED=1
private constant real GREEN=0.5
private constant real BLUE=0.2
private constant string LIGHTSTRING="LEAS"
private constant string EFFECT="Abilities\\Spells\\Human\\AerialShackles\\AerialShacklesTarget.mdl"
private timer time=CreateTimer()
private graDat array graDB
private integer dbIndex=-1
endglobals
private function p takes nothing returns nothing
local graDat tempDat
local integer index=0
local unit a
local real newX
local real newY
local real newZ
loop
exitwhen index>dbIndex
set tempDat=graDB[index]
if tempDat.pulling == false then
set tempDat.x=tempDat.x+(SPEED*TIMEROUT)*Cos(tempDat.radian)
set tempDat.y=tempDat.y+(SPEED*TIMEROUT)*Sin(tempDat.radian)
set newZ=GetXYZ(tempDat.x,tempDat.y)
set tempDat.distance = tempDat.distance + (SPEED*TIMEROUT)
call MoveLightning(tempDat.l,true,GetUnitX(tempDat.u),GetUnitY(tempDat.u),tempDat.x,tempDat.y)
set g = GetUnitsInRange(AOE,tempDat.x,tempDat.y)
loop
set a = FirstOfGroup(g)
exitwhen a == null or tempDat.pulling == true
if UnitAlive(a) and GetOwningPlayer(a) != GetOwningPlayer(tempDat.u) and IsUnitType(a,UNIT_TYPE_MAGIC_IMMUNE) == false and IsUnitType(a,UNIT_TYPE_FLYING) == false and IsUnitType(a,UNIT_TYPE_STRUCTURE) == false then
set tempDat.t = a
set tempDat.pulling = true
set tempDat.fx = AddSpecialEffectTarget(EFFECT,a,"chest")
endif
call GroupRemoveUnit(g,a)
endloop
if newZ>tempDat.z+5 or UnitAlive(tempDat.u) == false or D2PXY(tempDat.x,tempDat.y,GetUnitX(tempDat.u),GetUnitY(tempDat.u)) > DISTANCEBASE +(DISTANCEMULTI*GetUnitAbilityLevel(tempDat.u,GRAPID)) or tempDat.distance > DISTANCEBASE +(DISTANCEMULTI*GetUnitAbilityLevel(tempDat.u,GRAPID)) and tempDat.pulling == false then
set tempDat.pulling = true
endif
else
if tempDat.t != null then
set tempDat.x=GetUnitX(tempDat.u)+tempDat.distance*Cos(tempDat.radian)
set tempDat.y=GetUnitY(tempDat.u)+tempDat.distance*Sin(tempDat.radian)
set tempDat.distance = tempDat.distance - (PULLINGSPEED*TIMEROUT)
call SetUnitPosition(tempDat.t,tempDat.x,tempDat.y)
call MoveLightning(tempDat.l,true,GetUnitX(tempDat.u),GetUnitY(tempDat.u),GetUnitX(tempDat.t),GetUnitY(tempDat.t))
else
set tempDat.x=GetUnitX(tempDat.u)+tempDat.distance*Cos(tempDat.radian)
set tempDat.y=GetUnitY(tempDat.u)+tempDat.distance*Sin(tempDat.radian)
set tempDat.distance = tempDat.distance - (SPEED*TIMEROUT)
call MoveLightning(tempDat.l,true,GetUnitX(tempDat.u),GetUnitY(tempDat.u),tempDat.x,tempDat.y)
endif
if D2PXY(tempDat.x,tempDat.y,GetUnitX(tempDat.u),GetUnitY(tempDat.u)) > MAXDIST or D2PXY(GetUnitX(tempDat.u),GetUnitY(tempDat.u),tempDat.x,tempDat.y) < MINDIST then
call DestroyLightning(tempDat.l)
call DestroyEffect(tempDat.fx)
call Damage_Pure(tempDat.u,tempDat.t,(DAMAGEBASE+(DAMAGEMULTI*GetUnitAbilityLevel(tempDat.u,GRAPID))))
set tempDat.t = null
call tempDat.destroy()
set graDB[index]=graDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
endif
set index=index+1
endloop
set a =null
endfunction
private function a takes nothing returns nothing
local graDat tempDat=graDat.create()
set tempDat.pulling = false
set tempDat.u = GetTriggerUnit()
set tempDat.distance=0
set tempDat.radian=A2PXY(GetUnitX(tempDat.u),GetUnitY(tempDat.u),GetSpellTargetX(),GetSpellTargetY())*bj_DEGTORAD
set tempDat.z = GetXYZ(GetUnitX(tempDat.u),GetUnitY(tempDat.u))
set tempDat.l = AddLightning(LIGHTSTRING,true,GetUnitX(tempDat.u),GetUnitY(tempDat.u),GetUnitX(tempDat.u),GetUnitY(tempDat.u))
set tempDat.x = GetUnitX(tempDat.u)
set tempDat.y = GetUnitY(tempDat.u)
call SetLightningColor(tempDat.l,RED,GREEN, BLUE, 1)
set dbIndex=dbIndex+1
set graDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call GT_RegisterStartsEffectEvent(t, GRAPID)
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=27
//TESH.alwaysfold=0
scope Drain initializer i
private struct draDat
unit u
real x
real y
real duration
endstruct
globals
private group g = CreateGroup()
private constant integer ABLIID= 'A02K' //Insert rawcode of ability.
private constant real TIMEROUT=.03 //Timeout in seconds; RECCOMENDED .03 for 33 fps
private constant real AOE=175
private constant real AOEMULTI=25
private constant real DRAIN=3
private constant real DRAINMULTI=1
private constant real DURATION=10
private constant real DURATIONMULTI=2
private constant string CASTEFFECT="Abilities\\Spells\\Other\\Drain\\ManaDrainCaster.mdl"
private timer time=CreateTimer()
private graDat array graDB
private integer dbIndex=-1
endglobals
private function p takes nothing returns nothing
local graDat tempDat
local integer index=0
loop
exitwhen index>dbIndex
set tempDat=graDB[index]
set tempDat.duration = tempDat.duration - TIMEROUT
if DURATION == 0 then
call tempDat.destroy()
set graDB[index]=graDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
set a =null
endfunction
private function a takes nothing returns nothing
local graDat tempDat=graDat.create()
set tempDat.u = GetTriggerUnit()
set tempDat.x = GetSpellTargetX()
set tempDat.y = GetSpellTargetY()
set tempDat.duration = DURATION+(DURATIONMULTI*GetUnitAbilityLevel(GetTriggerUnit(),ABLIID))
set dbIndex=dbIndex+1
set graDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call GT_RegisterStartsEffectEvent(t, ABLIID)
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=6
//TESH.alwaysfold=0
scope stalk initializer i
private struct staDat
unit u
endstruct
globals
private constant integer STALKID= 'A08D' //Insert rawcode of ability.
private constant integer BUFFID='B02L'
private constant real TIMEROUT=.50 //Timeout in seconds.
private constant integer FADEOUT=100 //Base fadeout
private constant integer FADEOUTMULTI=50
private timer time=CreateTimer()
private staDat array staDB
private integer dbIndex=-1
endglobals
private function c takes nothing returns boolean
return GetSpellAbilityId()==STALKID
endfunction
private function p takes nothing returns nothing
local staDat tempDat
local integer index=0
loop
exitwhen index>dbIndex
set tempDat=staDB[index]
if GetUnitAbilityLevel(tempDat.u,BUFFID) == 0 then
call SetUnitVertexColor(tempDat.u,255,255,255,255)
call tempDat.destroy()
set staDB[index]=staDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
endfunction
private function a takes nothing returns nothing
local staDat tempDat=staDat.create()
set tempDat.u=GetTriggerUnit()
call SetUnitVertexColor(GetTriggerUnit(),255,255,255,255-(FADEOUT+(FADEOUTMULTI*GetUnitAbilityLevel(GetTriggerUnit(),STALKID))))
set dbIndex=dbIndex+1
set staDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function c))
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=31
//TESH.alwaysfold=0
scope battlefren initializer i
private struct bioDat
unit u
unit t
integer i
real dur
effect e
trigger trig
endstruct
globals
private constant integer BATID= 'A08H' //Insert rawcode of ability.
private constant real OFFSET=125 //How far away the user is when attacking.
private constant integer HITSBASE=5
private constant integer HITSMULTI=2
private constant string EFFECT="Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl"
private constant string MOVEEFFECT="Abilities\\Spells\\Human\\FlakCannons\\FlakTarget.mdl"
private timer time=CreateTimer()
private bioDat array bioDB
private integer dbIndex=-1
endglobals
private function c takes nothing returns boolean
return GetSpellAbilityId()==BATID
endfunction
private function p takes nothing returns nothing
local bioDat tempDat
local integer index=GetHandleInt(GetEventDamageSource(),"battleint")
local real x
local real y
if GetUnitAbilityLevel(GetTriggerUnit(),'B014') == 1 then
set tempDat=bioDB[index]
set x = GetUnitX(tempDat.t)+OFFSET*Cos(GetRandomReal(0,360)*bj_DEGTORAD)
set y = GetUnitY(tempDat.t)+OFFSET*Sin(GetRandomReal(0,360)*bj_DEGTORAD)
call SetUnitX(GetEventDamageSource(),x)
call SetUnitY(GetEventDamageSource(),y)
call DestroyEffect(AddSpecialEffectTarget(MOVEEFFECT,tempDat.u,"chest"))
set tempDat.i = tempDat.i-1
if tempDat.i < 1 then
call DestroyEffect(tempDat.e)
call PauseUnit(tempDat.t,false)
call IssueTargetOrder(tempDat.u, "attack", tempDat.t )
call RemoveHandle(tempDat.u,"battleint")
call SetUnitTimeScalePercent(GetTriggerUnit(),100)
call SetUnitPathingEx(tempDat.u,true)
call tempDat.destroy()
set bioDB[index]=bioDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
endif
endfunction
private function a takes nothing returns nothing
local bioDat tempDat=bioDat.create()
set tempDat.u = GetTriggerUnit()
set tempDat.t = GetSpellTargetUnit()
set tempDat.i = HITSBASE + (HITSMULTI*GetUnitAbilityLevel(GetTriggerUnit(),BATID))
set tempDat.e = AddSpecialEffectTarget(EFFECT,GetTriggerUnit(),"weapon")
set tempDat.trig = CreateTrigger()
call TriggerRegisterUnitEvent( tempDat.trig,GetSpellTargetUnit(), EVENT_UNIT_DAMAGED )
call TriggerAddAction(tempDat.trig,function p)
call SetHandleInt(GetTriggerUnit(),"battleint",dbIndex+1)
call PauseUnit(GetSpellTargetUnit(),true)
call SetUnitTimeScale(GetTriggerUnit(),1)
call SetUnitPathingEx(GetTriggerUnit(),false)
set dbIndex=dbIndex+1
set bioDB[dbIndex]=tempDat
call TriggerSleepAction(0.01)
call IssueTargetOrder(GetTriggerUnit(),"attack",GetSpellTargetUnit())
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function c))
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=59
//TESH.alwaysfold=0
scope crippleblow initializer i
private struct cripDat
unit u
unit t
real x
real y
real dur
endstruct
globals
private constant integer CRIPPLEID='A00B' //Insert rawcode of cripple ability.
private constant real DURATION=7 //How many "ticks" before the ability ends.
private constant real TIMEROUT=.50 //Timeout in seconds
private constant real DAMAGE=17.5 //Damage dealt after the unit has moved DISTANCE space.
private constant real DISTANCE=45 //Distance to count movement and deal damage.
private constant string EFFECTID="Objects\\Spawnmodels\\Human\\HumanLargeDeathExplode\\HumanLargeDeathExplode.mdl"//Effect used when damage occurs
private timer time=CreateTimer()
private cripDat array cripDB
private integer dbIndex=-1
endglobals
private function p takes nothing returns nothing
local cripDat tempDat
local integer index=0
local unit u
loop
exitwhen index>dbIndex
set tempDat=cripDB[index]
set u = tempDat.t
if D2PXY(tempDat.x,tempDat.y,GetUnitX(u),GetUnitY(u)) > DISTANCE then
call Damage_Pure(tempDat.u,u,DAMAGE)
set tempDat.x = GetUnitX(u)
set tempDat.y = GetUnitY(u)
call DestroyEffect(AddSpecialEffect(EFFECTID,GetUnitX(u),GetUnitY(u)))
endif
set tempDat.dur = tempDat.dur - TIMEROUT
if tempDat.dur < 0 then
call tempDat.destroy()
set cripDB[index]=cripDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
set u = null
endfunction
private function a takes nothing returns nothing
local cripDat tempDat=cripDat.create()
set tempDat.t=GetSpellTargetUnit()
set tempDat.u=GetTriggerUnit()
set tempDat.x=GetUnitX(GetSpellTargetUnit())
set tempDat.y=GetUnitY(GetSpellTargetUnit())
set tempDat.dur=DURATION
set dbIndex=dbIndex+1
set cripDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call GT_RegisterStartsEffectEvent(t,CRIPPLEID)
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=67
//TESH.alwaysfold=0
scope tunnel initializer i
private struct tunDat
unit u
real z
real radian
real distance
real fxdist
endstruct
globals
private constant integer TUNNELID='A02J' //Insert rawcode of tunnel ability.
private constant integer SPAWNTUNNELID='A068'
private constant integer EFFEDIST=100 //Effect Distance.
private constant real TIMEROUT=.03 //Timeout in seconds; RECCOMENDED .03 for 33 fps.
private constant real OFFSETPE=20 //Offset distance after each iteration.
private constant real OFFSETMU=1 //Offset (iteration) multiplyer, for changing how close the target has to be.
private timer time=CreateTimer()
private tunDat array tunDB
private integer dbIndex=-1
endglobals
private function c takes nothing returns boolean
return GetSpellAbilityId()==TUNNELID or GetSpellAbilityId()==SPAWNTUNNELID
endfunction
private function p takes nothing returns nothing
local tunDat tempDat
local integer index=0
local real newX
local real newY
local real newZ
local effect fx
loop
exitwhen index>dbIndex
set tempDat=tunDB[index]
set newX=GetUnitX(tempDat.u)+OFFSETPE*Cos(tempDat.radian)
set newY=GetUnitY(tempDat.u)+OFFSETPE*Sin(tempDat.radian)
set newZ=GetXYZ(newX,newY)
if tempDat.fxdist<1 then
set fx=AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl",newX,newY)
call DestroyEffect(fx)
else
set tempDat.fxdist=tempDat.fxdist-OFFSETPE
endif
call SetUnitPosition(tempDat.u,newX,newY) //Using position so the unit can't be ordered around. It's shittier than X/Y, but cry about it.
set tempDat.distance=tempDat.distance-OFFSETPE
if tempDat.distance<OFFSETPE*OFFSETMU or newZ>tempDat.z+5 then
call tempDat.destroy()
set tunDB[index]=tunDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
endfunction
private function a takes nothing returns nothing
local tunDat tempDat=tunDat.create()
local location targ=GetSpellTargetLoc()
set tempDat.u=GetSpellAbilityUnit()
set tempDat.z=GetLocationZ(targ)
set tempDat.radian=A2PXY(GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()),GetLocationX(targ),GetLocationY(targ))*bj_DEGTORAD
set tempDat.distance=D2PXY(GetLocationX(targ),GetLocationY(targ),GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()))
set tempDat.fxdist=EFFEDIST
set dbIndex=dbIndex+1
set tunDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
call RemoveLocation(targ)
set targ = null
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function c))
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=43
//TESH.alwaysfold=0
function Trig_Pounce_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A034'
endfunction
function PounceMove takes nothing returns nothing
local timer t = GetExpiredTimer()
local unit u = GetHandleUnit(t,"u")
local real z = GetHandleReal(t,"z")
local real ang = GetHandleReal(t,"angle")
local real dist = GetHandleReal(t,"dist")
local real maxdist = GetHandleReal(t,"maxdist")
local real X = GetUnitX(u)
local real Y = GetUnitY(u)
local real newX = X + 20 * Cos(ang)
local real newY = Y + 20 * Sin(ang)
local real newZ = GetXYZ(newX,newY)
local real height = JumpParabola(dist, maxdist, 3.45, z, newZ)
local group g = CreateGroup()
local unit a
local unit ta
local boolean b = false
set g = GetUnitsInRange(120,X,Y)
loop
set a = FirstOfGroup(g)
exitwhen a ==null
call GroupRemoveUnit(g,a)
if IsUnitType(a, UNIT_TYPE_GIANT) == false and IsUnitType(a, UNIT_TYPE_ANCIENT) == false and IsPlayerInForce(GetOwningPlayer(a),udg_Parasites) != true and GetUnitState(a,UNIT_STATE_LIFE) > 0.45 and IsUnitType(a, UNIT_TYPE_STRUCTURE) == false then
set b = true
set ta = a
endif
endloop
call SetUnitFlyHeight( u, height, 0.00 )
call SetUnitPosition(u,newX,newY)
call SetHandleReal(t,"dist",dist-20)
if dist <= 0 or (z+50.00)-newZ <= 0.00 or b == true or GetUnitState(u,UNIT_STATE_LIFE) < 0.45 then
call SetUnitPathing( u, true )
if GetUnitState(u, UNIT_STATE_LIFE) > 0.405 then
call SetUnitAnimation( u, "stand" )
endif
call SetUnitFlyHeight( u, 0, 0.00 )
call IsPointWalkable(newX,newY)
call SetUnitPosition(u,GetUnitX(udg_Pathcheckunit),GetUnitY(udg_Pathcheckunit))
call PauseUnit(u, false)
call SetUnitPathing( u, true)
if b == true then
call UnitDamageTarget(u,ta,100,true,false,ATTACK_TYPE_HERO,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
call IssueTargetOrder(u,"attack",ta)
if IsUnitType(a, UNIT_TYPE_MECHANICAL) == false then
call DestroyEffect(AddSpecialEffect( "Abilities\\Weapons\\HydraliskImpact\\HydraliskImpact.mdl",GetUnitX(ta),GetUnitY(ta)))
endif
endif
call GroupRemoveUnit(udg_Nopathunits,u)
call FlushHandleLocals(t)
call DestroyTimer(t)
endif
set ta =null
set u = null
set t = null
set a = null
set g = null
endfunction
function Trig_Pounce_Actions takes nothing returns nothing
local timer t = CreateTimer()
local location l = GetSpellTargetLoc()
call PauseUnit(GetTriggerUnit(), true)
call SetHandleReal(t,"z", GetXYZ(GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit())))
call SetHandleReal(t,"maxdist",D2PXY(GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()),GetLocationX(l),GetLocationY(l)))
call SetHandleReal(t,"dist",D2PXY(GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()),GetLocationX(l),GetLocationY(l)))
call SetHandleReal(t,"angle",A2PXY(GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()),GetLocationX(l),GetLocationY(l))*3.14159/180)
call SetHandleHandle(t,"u",GetTriggerUnit())
call TimerStart(t,0.03,true,function PounceMove)
call UnitAddAbilityBJ('AEme',GetTriggerUnit())
call UnitRemoveAbilityBJ('AEme',GetTriggerUnit())
call GroupAddUnit(udg_Nopathunits,GetTriggerUnit())
call SetUnitPathing( GetTriggerUnit(), false )
call SetUnitAnimationWithRarity( GetTriggerUnit(), "victory", RARITY_RARE )
set t = null
endfunction
//===========================================================================
function InitTrig_Pounce takes nothing returns nothing
set gg_trg_Pounce = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Pounce, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Pounce, Condition( function Trig_Pounce_Conditions ) )
call TriggerAddAction( gg_trg_Pounce, function Trig_Pounce_Actions )
endfunction
//TESH.scrollpos=14
//TESH.alwaysfold=0
scope hornstrike initializer i
private struct hornDat
unit u
real rad
real dis
real z
endstruct
globals
private constant integer HORNID='A07S' //Insert rawcode of ability.
private constant real DISTANCE=400 //How far the target will fly.
private constant real TIMEROUT=.03 //Timeout in seconds
private constant real DAMAGE=125 //Damage dealt.
private constant real OFFSET=12 //Distance moved per instance
private constant real CURVE=2.5 //Curve of the throw.
private timer time=CreateTimer()
private hornDat array hornDB
private integer dbIndex=-1
endglobals
private function p takes nothing returns nothing
local hornDat tempDat
local integer index=0
local real z
local real x
local real y
loop
exitwhen index>dbIndex
set tempDat=hornDB[index]
set z = GetXYZ(GetUnitX(tempDat.u),GetUnitY(tempDat.u))
set x=GetUnitX(tempDat.u)+OFFSET*Cos(tempDat.rad)
set y=GetUnitY(tempDat.u)+OFFSET*Sin(tempDat.rad)
call SetUnitPosition(tempDat.u,x,y)
call SetUnitFlyHeight( tempDat.u,JumpParabola(tempDat.dis, DISTANCE, CURVE, tempDat.z, z), 0.00 )
set tempDat.dis = tempDat.dis - OFFSET
if tempDat.dis < 0 or z>tempDat.z+5 or GetUnitAbilityLevel(tempDat.u,'BUim') == 1 then
call tempDat.destroy()
call SetUnitFlyHeight( tempDat.u,0, 0.00 )
debug call BJDebugMsg("Hornstrike ended")
set hornDB[index]=hornDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
endfunction
private function a takes nothing returns nothing
local hornDat tempDat=hornDat.create()
debug call BJDebugMsg("Hornstrike used")
call Damage_Pure(GetTriggerUnit(),GetSpellTargetUnit(),DAMAGE)
set tempDat.u=GetSpellTargetUnit()
set tempDat.dis=DISTANCE
set tempDat.z=GetXYZ(GetUnitX(GetSpellTargetUnit()),GetUnitY(GetSpellTargetUnit()))
set tempDat.rad=A2PXY(GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()),GetUnitX(GetSpellTargetUnit()),GetUnitY(GetSpellTargetUnit()))*bj_DEGTORAD
call UnitAddAbility(GetSpellTargetUnit(),'AEme')
call UnitRemoveAbility(GetSpellTargetUnit(),'AEme')
set dbIndex=dbIndex+1
set hornDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call GT_RegisterStartsEffectEvent(t,HORNID)
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=9
//TESH.alwaysfold=0
function Trig_Mental_Shunder_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A02D'
endfunction
function ShunderEffect takes nothing returns nothing
local timer t = GetExpiredTimer()
local player p = GetHandlePlayer(t,"p")
local integer i = GetHandleInt(t,"i")
if i == 0 then
call FlushHandleLocals(t)
call DestroyTimer(t)
if GetLocalPlayer() == p then
call DisplayCineFilter(false)
endif
else
call CinematicFilterGenericForPlayer(p,0.00, BLEND_MODE_NONE,"ReplaceableTextures\\CameraMasks\\White_mask.blp",GetRandomReal(0, 100),GetRandomReal(0, 100),GetRandomReal(0, 100),1,GetRandomReal(0, 100),GetRandomReal(0, 100),GetRandomReal(0, 100),1)
call SetHandleInt(t,"i",i-1)
if GetLocalPlayer() == p then
call ClearTextMessages()
endif
endif
set t = null
set p = null
endfunction
function Trig_Mental_Shunder_Actions takes nothing returns nothing
local timer t = CreateTimer()
call IssueImmediateOrder(GetSpellTargetUnit(),"stop")
call SetHandleHandle(t,"p",GetOwningPlayer(GetSpellTargetUnit()))
call SetHandleInt(t,"i",10)
call TimerStart(t,0.5,true,function ShunderEffect)
set t = null
endfunction
//===========================================================================
function InitTrig_Mental_Shunder takes nothing returns nothing
set gg_trg_Mental_Shunder = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Mental_Shunder, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Mental_Shunder, Condition( function Trig_Mental_Shunder_Conditions ) )
call TriggerAddAction( gg_trg_Mental_Shunder, function Trig_Mental_Shunder_Actions )
endfunction
//TESH.scrollpos=16
//TESH.alwaysfold=0
function Trig_Time_Hole_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A03F'
endfunction
function TimeHole takes nothing returns nothing
local timer t = GetExpiredTimer()
local unit u = GetHandleUnit(t,"u")
call ShowUnit(u,true)
call SetUnitPosition(u,GetUnitX(u),GetUnitY(u))
call FlushHandleLocals(t)
call DestroyTimer(t)
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Items\\TomeOfRetraining\\TomeOfRetrainingCaster.mdl" ,GetUnitX(u),GetUnitY(u)))
call PauseUnit(u,false)
call SetUnitInvulnerable(u,false)
set t = null
set u = null
endfunction
function Trig_Time_Hole_Actions takes nothing returns nothing
local timer t = CreateTimer()
call PauseUnit(GetSpellTargetUnit(),true)
call SetUnitInvulnerable(GetSpellTargetUnit(),true)
call ShowUnit(GetSpellTargetUnit(),false)
call SetHandleHandle(t,"u",GetSpellTargetUnit())
call TimerStart(t,GetRandomReal(2.5,6.5),false,function TimeHole)
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\DispelMagic\\DispelMagicTarget.mdl",GetUnitX(GetSpellTargetUnit()),GetUnitY(GetSpellTargetUnit())))
set t = null
endfunction
//===========================================================================
function InitTrig_Time_Hole takes nothing returns nothing
set gg_trg_Time_Hole = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Time_Hole, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition( gg_trg_Time_Hole, Condition( function Trig_Time_Hole_Conditions ) )
call TriggerAddAction( gg_trg_Time_Hole, function Trig_Time_Hole_Actions )
endfunction
function Trig_Time_Jump_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A03G'
endfunction
function TimeJump takes nothing returns nothing
local timer t = GetExpiredTimer()
local unit u = GetHandleUnit(t,"u")
local effect e = GetHandleEffect(t,"e")
call ShowUnit(u,true)
call SetUnitPosition(u,GetUnitX(u),GetUnitY(u))
call DestroyEffect(e)
call FlushHandleLocals(t)
call DestroyTimer(t)
call SetUnitInvulnerable(u,false)
set t = null
set e = null
set u = null
endfunction
function Trig_Time_Jump_Actions takes nothing returns nothing
local timer t = CreateTimer()
call SetUnitInvulnerable(GetTriggerUnit(),true)
call ShowUnit(GetSpellTargetUnit(),false)
call SetHandleHandle(t,"u",GetTriggerUnit())
call SetHandleHandle(t,"e",AddSpecialEffect("Abilities\\Spells\\Orc\\Purge\\PurgeBuffTarget.mdl",GetUnitX(GetSpellTargetUnit()),GetUnitY(GetSpellTargetUnit())))
call TimerStart(t,4.5,false,function TimeJump)
set t = null
endfunction
//===========================================================================
function InitTrig_Time_Jump takes nothing returns nothing
set gg_trg_Time_Jump = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Time_Jump, EVENT_PLAYER_UNIT_SPELL_FINISH)
call TriggerAddCondition( gg_trg_Time_Jump, Condition( function Trig_Time_Jump_Conditions ) )
call TriggerAddAction( gg_trg_Time_Jump, function Trig_Time_Jump_Actions )
endfunction
//TESH.scrollpos=12
//TESH.alwaysfold=0
function Trig_Radiation_Trail_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A06B'
endfunction
function RadiTrail takes nothing returns nothing
local timer t = GetExpiredTimer()
local unit u = GetHandleUnit(t,"u")
local real x = GetHandleReal(t,"x")
local real x2 = GetUnitX(u)
local real y = GetHandleReal(t,"y")
local real y2 = GetUnitY(u)
if D2PXY(x,y,x2,y2) > 40 then
call SetHandleReal(t,"x",x2)
call SetHandleReal(t,"y",y2)
set bj_lastCreatedUnit = CreateUnit(GetOwningPlayer(u),'e006',x2,y2,0)
call UnitApplyTimedLife( bj_lastCreatedUnit,'BTLF', 15)
endif
if UnitHasBuffBJ(u, 'B01P') == false then
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl" ,u,"origin"))
call FlushHandleLocals(t)
call DestroyTimer(t)
endif
set u = null
set t = null
endfunction
function Trig_Radiation_Trail_Actions takes nothing returns nothing
local timer t = CreateTimer()
call SetHandleHandle(t,"u",GetTriggerUnit())
call SetHandleReal(t,"x",GetUnitX(GetTriggerUnit()))
call SetHandleReal(t,"y",GetUnitY(GetTriggerUnit()))
call TimerStart(t,0.25,true,function RadiTrail)
set t = null
endfunction
//===========================================================================
function InitTrig_Radiation_Trail takes nothing returns nothing
set gg_trg_Radiation_Trail = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Radiation_Trail, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Radiation_Trail, Condition( function Trig_Radiation_Trail_Conditions ) )
call TriggerAddAction( gg_trg_Radiation_Trail, function Trig_Radiation_Trail_Actions )
endfunction
//TESH.scrollpos=3
//TESH.alwaysfold=0
scope timestop initializer i
private struct chrDat
unit u
real duration
effect e
endstruct
globals
private constant integer STOPID='A01I' //Insert rawcode of ability.
private constant real TIMEROUT=.25 //Timeout in seconds
private constant real DURATION=3.5 //Duration of freeze
private constant string FXPOINT="chest" //The point on the target that the effect is attached to
private constant string EFFECT="Haste.mdx"//Special effect created.
private timer time=CreateTimer()
private chrDat array chrDB
private integer dbIndex=-1
endglobals
private function c takes nothing returns boolean
return GetSpellAbilityId()==STOPID
endfunction
private function p takes nothing returns nothing
local chrDat tempDat
local integer index=0
loop
exitwhen index>dbIndex
set tempDat=chrDB[index]
set tempDat.duration=tempDat.duration-0.25
if UnitAlive(tempDat.u) == false then
set tempDat.duration = 0
call SafePause(tempDat.u,false)
call SetUnitAnimation(tempDat.u,"death")
endif
if tempDat.duration < 0 then
call SafePause(tempDat.u,false)
call DestroyEffect(tempDat.e)
call tempDat.destroy()
set chrDB[index]=chrDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
endfunction
private function a takes nothing returns nothing
local chrDat tempDat=chrDat.create()
call IssueImmediateOrder(GetSpellTargetUnit(),"stop")
set tempDat.u=GetSpellTargetUnit()
set tempDat.duration=4
set tempDat.e=AddSpecialEffectTarget(EFFECT,GetSpellTargetUnit(),FXPOINT)
set dbIndex=dbIndex+1
set chrDB[dbIndex]=tempDat
call SafePause(GetSpellTargetUnit(),true)
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function c))
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=2
//TESH.alwaysfold=0
scope ampdense initializer i
private struct ampDat
unit u
unit t
endstruct
globals
private group g = CreateGroup()
private constant integer AMPID='A00S' //Insert rawcode of ability.
private constant integer BUFFID='B02G' //Insert rawcode of buff.
private constant real TIMEROUT=.03 //Timeout in seconds.
private constant real DAMAGE=15 //Damage per second.
private constant real AOE=300 //AoE of the ability.
private constant real DRAG=2 //Ammount the target is dragged by per timeout.
private timer time=CreateTimer()
private ampDat array ampDB
private integer dbIndex=-1
endglobals
private function c takes nothing returns boolean
return GetSpellAbilityId()==AMPID
endfunction
private function p takes nothing returns nothing
local ampDat tempDat
local integer index=0
local unit a
local real x
local real y
local real x2
local real y2
loop
exitwhen index>dbIndex
set tempDat=ampDB[index]
set g = GetUnitsInRange(AOE,GetUnitX(tempDat.t),GetUnitY(tempDat.t))
set x = GetUnitX(tempDat.t)
set y = GetUnitY(tempDat.t)
if IsUnitType(tempDat.t,UNIT_TYPE_ANCIENT) == false and IsUnitType(tempDat.t,UNIT_TYPE_GIANT) == false then
call Damage_Pure(tempDat.u,tempDat.t,DAMAGE*TIMEROUT)
endif
loop
set a = FirstOfGroup(g)
exitwhen a == null
call GroupRemoveUnit(g,a)
if IsUnitType(a,UNIT_TYPE_MAGIC_IMMUNE) == false and IsUnitType(a,UNIT_TYPE_ANCIENT) == false and UnitAlive(a) == true and a != tempDat.t then
set x2 = GetUnitX(a) + (DRAG+I2R(GetUnitLevel(tempDat.t))) * Cos(A2PXY(GetUnitX(a),GetUnitY(a),x,y)*3.14159/180)
set y2 = GetUnitY(a) + (DRAG+I2R(GetUnitLevel(tempDat.t))) * Sin(A2PXY(GetUnitX(a),GetUnitY(a),x,y)*3.14159/180)
if IsPointWalkable(x2,y2) == false then
call SetUnitX(a,x2)
call SetUnitY(a,y2)
endif
endif
endloop
if GetUnitAbilityLevel(tempDat.t,BUFFID) == 0 then
call tempDat.destroy()
set ampDB[index]=ampDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
set a = null
endfunction
private function a takes nothing returns nothing
local ampDat tempDat=ampDat.create()
debug call BJDebugMsg("triggered Ampdense")
set tempDat.u = GetTriggerUnit()
set tempDat.t = GetSpellTargetUnit()
set dbIndex=dbIndex+1
set ampDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function c))
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=49
//TESH.alwaysfold=0
scope vortex initializer i
private struct vorDat
unit u
integer ammount
real duration
unit array object[12]
real array angle[12]
endstruct
globals
private group g = CreateGroup()
private constant integer VORTID='A029' //Insert rawcode of ability.
private constant integer DUMMYID='e007' //Insert rawcode of dummy unit.
private constant integer AMMOUNT=4 //Ammount of objects moving around the user.
private constant real TIMEROUT=.03 //Timeout in seconds.
private constant real DURATION=15 //Duration of ability.
private constant real DAMAGE=75 //Damage done.
private constant real HEIGHT=100 //Height of the objects moving around the user
private constant real AOE=90 //AoE of the objects moving around the user.
private constant real DISTANCE=350 //Distance of the objects moving around the user.
private constant real SPEED=2.5 //Speed of the objects moving around the user.
private constant string EFFECT="Abilities\\Spells\\Undead\\OrbOfDeath\\AnnihilationMissile.mdl" //Model used by the objects moving around the user.
private timer time=CreateTimer()
private vorDat array vorDB
private integer dbIndex=-1
endglobals
private function c takes nothing returns boolean
return GetSpellAbilityId()==VORTID
endfunction
private function p takes nothing returns nothing
local vorDat tempDat
local integer index=0
local unit a
local integer i
local real x
local real y
loop
exitwhen index>dbIndex
set tempDat=vorDB[index]
set i = 0
loop
exitwhen i==tempDat.ammount
set i = i + 1
if GetUnitState(tempDat.object[i],UNIT_STATE_LIFE) > 0.349 then
set x = GetUnitX(tempDat.u) + DISTANCE * Cos(tempDat.angle[i]*3.14159/180)
set y = GetUnitY(tempDat.u) + DISTANCE * Sin(tempDat.angle[i]*3.14159/180)
set tempDat.angle[i] = tempDat.angle[i]+SPEED
call SetUnitFacing(tempDat.object[i],tempDat.angle[i]+110)
call SetUnitPosition(tempDat.object[i],x,y)
set g = GetUnitsInRange(AOE,x,y)
loop
set a = FirstOfGroup(g)
exitwhen a==null
call GroupRemoveUnit(g,a)
if IsUnitType(a,UNIT_TYPE_ANCIENT) == false and IsUnitType(a,UNIT_TYPE_GIANT) == false and UnitAlive(a)==true and IsUnitType(a,UNIT_TYPE_MAGIC_IMMUNE) == false and GetUnitTypeId(a) != 'e000' then
call KillUnit(tempDat.object[i])
call Damage_Pure(tempDat.u,a,DAMAGE)
endif
endloop
else
if tempDat.object[i] != null then
call DestroyEffect(AddSpecialEffect(EFFECT,GetUnitX(tempDat.object[i]),GetUnitY(tempDat.object[i])))
endif
call RemoveUnit(tempDat.object[i])
endif
endloop
set tempDat.duration = tempDat.duration - TIMEROUT
if tempDat.duration < 0 then
set i = 0
loop
exitwhen i==tempDat.ammount
set i = i + 1
call DestroyEffect(AddSpecialEffect(EFFECT,GetUnitX(tempDat.object[i]),GetUnitY(tempDat.object[i])))
call RemoveUnit(tempDat.object[i])
endloop
call tempDat.destroy()
set vorDB[index]=vorDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
set a = null
endfunction
private function a takes nothing returns nothing
local vorDat tempDat=vorDat.create()
local integer i =0
local real x
local real y
loop
exitwhen i==AMMOUNT
set i = i + 1
set x = GetUnitX(GetTriggerUnit()) + DISTANCE * Cos(((360/I2R(AMMOUNT)*I2R(i))+GetUnitFacing(GetTriggerUnit()))*3.14159/180)
set y = GetUnitX(GetTriggerUnit()) + DISTANCE * Sin(((360/I2R(AMMOUNT)*I2R(i))+GetUnitFacing(GetTriggerUnit()))*3.14159/180)
set tempDat.object[i] = CreateUnit(GetOwningPlayer(GetTriggerUnit()),DUMMYID,x,y,0)
set tempDat.angle[i] = 360/I2R(AMMOUNT)*I2R(i)
call SetUnitPathing(tempDat.object[i],false)
call SetUnitFlyHeight(tempDat.object[i],HEIGHT,0)
endloop
set tempDat.u = GetTriggerUnit()
set tempDat.ammount = AMMOUNT
set tempDat.duration = DURATION
set dbIndex=dbIndex+1
set vorDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function c))
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=9
//TESH.alwaysfold=0
scope nullgrav initializer i
private struct nulDat
unit u
real x
real y
boolean rise
boolean falling
endstruct
globals
private constant integer NULLID='A01V' //Insert rawcode of ability.
private constant integer BUFFID='B00X' //Insert rawcode of buff.
private constant real TIMEROUT=.03 //Timeout in seconds.
private constant real MAXHEIGHT=140 //Maximum height a unit can reach.
private constant real MINHEIGHT=70 //Minimum height a unit can reach.
private constant real HEIGHTMOD=2.5 //Rate at which a units height is changed
private constant string EFFECT="Abilities\\Spells\\NightElf\\ManaBurn\\ManaBurnTarget.mdl"//Effect created on target unit
private timer time=CreateTimer()
private nulDat array nulDB
private integer dbIndex=-1
endglobals
private function c takes nothing returns boolean
return GetSpellAbilityId()==NULLID
endfunction
private function p takes nothing returns nothing
local nulDat tempDat
local integer index=0
loop
exitwhen index>dbIndex
set tempDat=nulDB[index]
if tempDat.falling == false then
call SetUnitX(tempDat.u,tempDat.x)
call SetUnitY(tempDat.u,tempDat.y)
if tempDat.rise == true then
call SetUnitFlyHeight(tempDat.u,GetUnitFlyHeight(tempDat.u)+HEIGHTMOD,0)
if GetUnitFlyHeight(tempDat.u) > MAXHEIGHT then
set tempDat.rise = false
endif
else
call SetUnitFlyHeight(tempDat.u,GetUnitFlyHeight(tempDat.u)-(HEIGHTMOD*2),0)
if GetUnitFlyHeight(tempDat.u) < MINHEIGHT then
set tempDat.rise = true
endif
endif
if GetUnitAbilityLevel(tempDat.u,BUFFID) == 0 then
set tempDat.falling = true
call DestroyEffect(AddSpecialEffectTarget(EFFECT,tempDat.u,"origin"))
endif
else
call SetUnitFlyHeight(tempDat.u,GetUnitFlyHeight(tempDat.u)-HEIGHTMOD,0)
if GetUnitFlyHeight(tempDat.u) < HEIGHTMOD then
call SetUnitFlyHeight(tempDat.u,0,0)
call tempDat.destroy()
set nulDB[index]=nulDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
endif
set index=index+1
endloop
endfunction
private function a takes nothing returns nothing
local nulDat tempDat=nulDat.create()
set tempDat.u = GetSpellTargetUnit()
set tempDat.rise = true
set tempDat.falling = false
set tempDat.x = GetUnitX(GetSpellTargetUnit())
set tempDat.y = GetUnitY(GetSpellTargetUnit())
set dbIndex=dbIndex+1
set nulDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function c))
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=73
//TESH.alwaysfold=0
function Trig_Sonic_Boom_H2I_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'Sbom'
endfunction
function SonicBoom_Filter takes nothing returns boolean
if ( not ( IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false ) ) then
return false
endif
if ( not ( IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false ) ) then
return false
endif
return true
endfunction
function SonicBoom_PushGroup takes nothing returns nothing
local unit target = GetEnumUnit()
local real angle = GetHandleReal(target,"sonicangle")
local real speed = GetHandleReal(target,"sonicspeed")
local real targetX = GetUnitX(target)
local real targetY = GetUnitY(target)
local real newX
local real newY
set speed = speed - 0.3
call SetHandleReal(target, "sonicspeed", speed)
set newX = targetX + speed * Cos(angle)
set newY = targetY + speed * Sin(angle)
call SetUnitPosition(target, newX, newY)
if speed <= 0 then
call RemoveReal(target, "sonicangle")
call RemoveReal(target, "sonicspeed")
call GroupRemoveUnit(udg_TempGroup, target)
endif
set target = null
endfunction
function SonicBoom_Push takes nothing returns nothing
local timer sonictime = GetExpiredTimer()
set udg_TempGroup = GetHandleGroup(sonictime, "targs")
call ForGroup(udg_TempGroup, function SonicBoom_PushGroup)
if CountUnitsInGroup(udg_TempGroup) <= 0 then
call FlushHandleLocals(sonictime)
call PauseTimer(sonictime)
call DestroyTimer(sonictime)
call DestroyGroup(udg_TempGroup)
endif
set sonictime = null
endfunction
function Set_SonicBoom takes nothing returns nothing
local unit caster = GetTriggerUnit()
local unit picked = GetEnumUnit()
local real dx = GetUnitX(picked) - GetUnitX(caster)
local real dy = GetUnitY(picked) - GetUnitY(caster)
call UnitDamageTarget (caster,picked,75,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
if GetUnitLevel(GetEnumUnit()) > 4 then
call SetHandleReal(picked,"sonicspeed",30-I2R(GetUnitLevel(GetEnumUnit()))*5 )
else
call SetHandleReal(picked,"sonicspeed",30-I2R(GetUnitLevel(GetEnumUnit()))*3 )
endif
call SetHandleReal(picked,"sonicangle", Atan2(dy, dx))
set caster = null
set picked = null
endfunction
function Trig_Sonic_Boom_H2I_Actions takes nothing returns nothing
local unit caster = GetTriggerUnit()
local group targs = CreateGroup()
local timer sonictime = CreateTimer()
call GroupEnumUnitsInRange(targs, GetUnitX(caster), GetUnitY(caster), 500.00, Condition(function SonicBoom_Filter))
call GroupRemoveUnit(targs, GetTriggerUnit())
call ForGroup(targs, function Set_SonicBoom)
call SetHandleHandle(sonictime,"targs",targs)
call TimerStart(sonictime,0.03,true,function SonicBoom_Push)
set caster = null
set targs = null
set sonictime = null
endfunction
//===========================================================================
function InitTrig_Sonic_Boom takes nothing returns nothing
set gg_trg_Sonic_Boom = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Sonic_Boom, EVENT_PLAYER_UNIT_SPELL_FINISH )
call TriggerAddCondition( gg_trg_Sonic_Boom, Condition( function Trig_Sonic_Boom_H2I_Conditions ) )
call TriggerAddAction( gg_trg_Sonic_Boom, function Trig_Sonic_Boom_H2I_Actions )
endfunction
//TESH.scrollpos=45
//TESH.alwaysfold=0
function Trig_Aquire_Conditions takes nothing returns boolean
if ( not (GetUnitAbilityLevel(GetAttacker(),'A00D') == 1 ) ) then
return false
endif
return true
endfunction
function Aquire_Fire takes nothing returns nothing
local timer aquiretime = GetExpiredTimer()
local unit u = GetHandleUnit(aquiretime,"user")
local unit t = GetHandleUnit(u,"target")
local unit dummy
local real dist = D2PXY(GetUnitX(u),GetUnitY(u),GetUnitX(t),GetUnitY(t))
local real ang = A2PXY(GetUnitX(u),GetUnitY(u),GetUnitX(t),GetUnitY(t))
local real height = GetUnitFlyHeight(u)
if dist >= 650 or IsUnitInvisible(t,GetOwningPlayer(u)) == true or UnitAlive(t) == false or UnitAlive(u) == false or GetUnitTypeId(u) != 'h00A' or IsUnitPaused(u) == true or IsUnitPaused(t) == true or IsUnitIdType(GetUnitTypeId(u), UNIT_TYPE_STUNNED) == true then
call RemoveHandle(u,"aquiretimer")
call SetHandleHandle(u,"target",null)
call FlushHandleLocals(aquiretime)
call DestroyTimer(aquiretime)
else
if IsTriggerEnabled(gg_trg_Fade) == false then
call EnableTrigger( gg_trg_Fade )
endif
set dummy = CreateUnit( GetOwningPlayer(u), 'h010', GetUnitX(u),GetUnitY(u),ang-30 )
call StopSoundBJ( gg_snd_TMaFir00, false )
call PlaySoundOnUnitBJ( gg_snd_TMaFir00, 100,dummy )
call SetUnitPathing( GetLastCreatedUnit(), false )
call SetUnitX(dummy,GetUnitX(u))
call SetUnitY(dummy,GetUnitY(u))
call SetUnitFlyHeight(dummy,height,0.00)
call IssueTargetOrderBJ( dummy, "attack", t )
call GroupAddUnitSimple(dummy, udg_Images )
call SetUnitUserData(dummy,1)
call UnitDamageTargetBJ( u, t, 0.01, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL )
endif
set u = null
set t = null
set dummy = null
set aquiretime = null
endfunction
function Trig_Aquire_Actions takes nothing returns nothing
local unit u = GetAttacker()
local unit t = GetTriggerUnit()
local timer aquiretime = CreateTimer()
local timer oldtimer = GetHandleTimer(u,"aquiretimer")
call DestroyTimer(oldtimer)
call RemoveHandle(u,"aquiretimer")
call SetHandleHandle(u,"target",t)
call SetHandleHandle(aquiretime,"user",u)
call SetHandleHandle(u,"aquiretimer",aquiretime)
call TimerStart(aquiretime,0.50,true,function Aquire_Fire)
set u = null
set t = null
set aquiretime = null
set oldtimer = null
endfunction
//===========================================================================
function InitTrig_Aquire takes nothing returns nothing
set gg_trg_Aquire = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Aquire, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddCondition( gg_trg_Aquire, Condition( function Trig_Aquire_Conditions ) )
call TriggerAddAction( gg_trg_Aquire, function Trig_Aquire_Actions )
endfunction
//TESH.scrollpos=11
//TESH.alwaysfold=0
function Trig_Jump_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A00I'
endfunction
function Jump_Move takes nothing returns nothing
local timer jumptime = GetExpiredTimer()
local real height
local real startZ = GetHandleReal(jumptime,"startZ")
local real jumpangle = GetHandleReal(jumptime,"angle")
local real jumpdist = GetHandleReal(jumptime,"dist")
local real jumpmaxdist = GetHandleReal(jumptime,"maxdist")
local unit jumper = GetHandleUnit(jumptime,"jumper")
local real x = GetUnitX(jumper)
local real y = GetUnitY(jumper)
local real X = x + 20 * Cos(jumpangle)
local real Y = y + 20 * Sin(jumpangle)
local real currentZ = GetXYZ(x,y)
set jumpdist = jumpdist-20
set height = JumpParabola(jumpdist, jumpmaxdist, 2.5, startZ, currentZ)
call SetUnitPosition(jumper, X, Y)
call SetUnitFlyHeight( jumper, height, 0.00 )
call SetHandleReal(jumptime,"dist",jumpdist)
if (startZ+20.00)-currentZ <= 0.00 or height <=10 then
call GroupRemoveUnit(udg_Nopathunits,jumper)
call SetUnitFlyHeight( jumper,0.00, 0.00 )
call UnitRemoveAbilityBJ( 'A00A', jumper )
call FlushHandleLocals(jumptime)
call DestroyTimer(jumptime)
call SetUnitPathing( jumper, true )
call PauseUnit(jumper, false)
call SetUnitPosition(jumper,x,y)
endif
set jumptime = null
set jumper = null
endfunction
function Trig_Jump_Actions takes nothing returns nothing
local real x = GetUnitX(GetTriggerUnit())
local real y = GetUnitY(GetTriggerUnit())
local real x2 = GetSpellTargetX()
local real y2 = GetSpellTargetY()
local timer jumptime = CreateTimer()
call PauseUnit(GetTriggerUnit(), true)
call SetHandleReal(jumptime,"startZ", GetXYZ(x,y))
call SetHandleReal(jumptime,"maxdist",D2PXY(x,y,x2,y2))
call SetHandleReal(jumptime,"dist",D2PXY(x,y,x2,y2))
call SetHandleReal(jumptime,"angle",A2PXY(x,y,x2,y2)*3.14159/180)
call SetHandleHandle(jumptime,"jumper",GetTriggerUnit())
call TimerStart(jumptime,0.03,true,function Jump_Move)
call UnitAddAbility(GetTriggerUnit(),'AEme')
call UnitRemoveAbility(GetTriggerUnit(),'AEme')
call SetUnitPathing( GetTriggerUnit(), false )
call UnitAddAbility( GetTriggerUnit(),'A00A' )
call GroupAddUnit(udg_Nopathunits,GetTriggerUnit())
set jumptime = null
endfunction
//===========================================================================
function InitTrig_Jump takes nothing returns nothing
set gg_trg_Jump = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Jump, EVENT_PLAYER_UNIT_SPELL_CAST )
call TriggerAddCondition( gg_trg_Jump, Condition( function Trig_Jump_Conditions ) )
call TriggerAddAction( gg_trg_Jump, function Trig_Jump_Actions )
endfunction
//TESH.scrollpos=123
//TESH.alwaysfold=0
//Requires AIDS, Damage, Recycle, optional ABC
scope burstfire initializer Init
globals
private constant integer ATKER_ID = 'h038'
private constant integer BUFF_ID = 'B014'
private constant integer DUMMY_ID = 0
private constant integer ATTACKS = 5
private constant real DURATION = 1
private hashtable hasht = InitHashtable()
endglobals
private keyword Data
private struct TimerList
timer t
thistype next
thistype prev
method onDestroy takes nothing returns nothing
//Remove attached stuffs.
static if LIBRARY_ABC then
//If ABC is available, use ABC instead of hashtable.
call ClearTimerStructA(.t)
call ClearTimerStructB(.t)
call ClearTimerStructC(.t)
else
call FlushChildHashtable(hasht,GetHandleId(.t))
endif
//Recycle the timer.
call Timer.release(.t)
//Unlink.
set .prev.next = .next
set .next.prev = .prev
//Who can guess why I didn't nullify the timer here? =P
endmethod
method chainDestroy takes nothing returns nothing
loop
set this = this.next
exitwhen this == 0
call .destroy()
endloop
endmethod
static method onExpired takes nothing returns nothing
//Get struct from timer
static if LIBRARY_ABC then
local timer t = GetExpiredTimer()
local thistype this = LoadTimerStructA(t)
local integer damagedUnitId = LoadTimerStructB(t)
local integer atkerId = LoadTimerStructC(t)
//Use ABC if available.
else
local integer tId = GetHandleId(GetExpiredTimer())
local thistype this = LoadInteger(hasht,tId,0)
local integer damagedUnitId = LoadInteger(hasht,tId,1)
local integer atkerId = LoadInteger(hasht,tId,2)
endif
local real r = LoadReal(hasht,damagedUnitId,atkerId)
//Prevent bug, so we get the value again instead of storing it in struct.
set r = r - DAMAGE_INCREASE
//Decrease the damage stack amount
call SaveReal(hasht,damagedUnitId,atkerId,r)
//Set it.
call .destroy()
//destroy the struct.
endmethod
static method add takes Data d, integer id, real r returns nothing
local thistype this = .allocate()
//Get a new instance.
local integer tId
set .t = Timer.get()
//Get a timer from timer stack.
set d.head.prev.next = this
set .prev = d.head.prev
set d.head.prev = this
set .next = 0
//LinkedList
call SaveReal(hasht,d,id,r)
//Set the damage stack value.
static if LIBRARY_ABC then
call SetTimerStructA(.t,this)
call SetTimerStructB(.t,d)
call SetTimerStructC(.t,id)
else
set tId = GetHandleId(.t)
call SaveInteger(hasht,tId,0,this)
call SaveInteger(hasht,tId,1,d)
call SaveInteger(hasht,tId,2,id)
endif
//Attach stuffs to timer.
call TimerStart(.t,DURATION,false,function thistype.onExpired)
//Start the timer.
endmethod
endstruct
private struct Data extends array
boolean isCapped
TimerList head
method AIDS_onCreate takes nothing returns nothing
//Create list for timer
set .head = TimerList.create()
//LinkedList.
set .head.next = .head
set .head.prev = .head
endmethod
method AIDS_onDestroy takes nothing returns nothing
call .head.chainDestroy()
call FlushChildHashtable(hasht,this)
set .isCapped = false
//Remove all stacked damage from all source
//Remove the cap, ready for later usage
//Force removing the timers, since the unit is removed, the timers are
//useless and may cause bug.
endmethod
//! runtextmacro AIDS()
endstruct
private function Act takes nothing returns nothing
local Data d = Data[GetTriggerUnit()] //Struct of attaacked unit.
local integer id = GetUnitId(GetEventDamageSource()) //Id of attacker.
call UnitAddAbility(GetEventDamageSource(),DUMMY_ID)
call
endfunction
private function Cond takes nothing returns boolean
if GetUnitAbilityLevel(GetTriggerUnit(),BUFF_ID) > 0 and GetUnitAbilityLevel(GetTriggerUnit(),DUMMY_ID) != 0 and GetUnitTypeId(GetEventDamageSource()) == ATKER_ID and Damage_IsAttack() then
//Condition : Unit type stuffs and the important : Damage_IsAttack(), it can prevent recursion/ infinite loop.
call Act()
endif
return false
endfunction
private function Init takes nothing returns nothing
local trigger t=CreateTrigger()
call Damage_RegisterEvent(t)
call TriggerAddCondition(t,Condition(function Cond))
endfunction
endscope
//TESH.scrollpos=34
//TESH.alwaysfold=0
scope jump initializer i
private struct jumDat
unit u
real z
real radian
real distance
real maxdistance
endstruct
globals
private constant integer JUMPID= 'A00I' //Insert rawcode of tunnel ability.
private constant integer ARMORID='A00A' //Insert rawcode of dummy armor ability.
private constant real TIMEROUT=.03 //Timeout in seconds; RECCOMENDED .03 for 33 fps.
private constant real OFFSETPE=20 //Offset distance after each iteration.
private constant real CURVE=2 //Curve of the jump.
private constant real OFFSETMU=10 //Offset (iteration) multiplyer, for changing how close the target has to be.
private timer time=CreateTimer()
private jumDat array jumDB
private integer dbIndex=-1
endglobals
private function p takes nothing returns nothing
local jumDat tempDat
local integer index=0
local real newX
local real newY
local real newZ
local real height
loop
exitwhen index>dbIndex
set tempDat=jumDB[index]
set newX=GetUnitX(tempDat.u)+OFFSETPE*Cos(tempDat.radian)
set newY=GetUnitY(tempDat.u)+OFFSETPE*Sin(tempDat.radian)
set newZ=GetXYZ(newX,newY)
set height = JumpParabola(tempDat.distance, tempDat.maxdistance, CURVE, tempDat.z, newZ)
call SetUnitFlyHeight( tempDat.u, height, 0.00 )
call SetUnitPosition(tempDat.u,newX,newY) //Using position so the unit can't be ordered around. It's shittier than X/Y, but cry about it.
set tempDat.distance=tempDat.distance-OFFSETPE
if tempDat.distance<OFFSETMU or newZ>tempDat.z+5 or IsUnitType(tempDat.u, UNIT_TYPE_SNARED) == true then
call UnitRemoveAbility(tempDat.u,ARMORID)
call SetUnitPathingEx(tempDat.u,true)
call SetUnitFlyHeight( tempDat.u, 0, 0.00 )
call SetUnitPosition(tempDat.u,newX,newY)
call tempDat.destroy()
set jumDB[index]=jumDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
endfunction
private function a takes nothing returns nothing
local jumDat tempDat=jumDat.create()
local location targ=GetSpellTargetLoc()
call UnitAddAbility(GetTriggerUnit(),ARMORID)
call SetUnitPathingEx(GetTriggerUnit(),false)
call UnitAddAbility(GetTriggerUnit(),'AEme')
call UnitRemoveAbility(GetTriggerUnit(),'AEme')
set tempDat.u=GetSpellAbilityUnit()
set tempDat.z=GetXYZ(GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()))
set tempDat.radian=A2PXY(GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()),GetLocationX(targ),GetLocationY(targ))*bj_DEGTORAD
set tempDat.distance=D2PXY(GetLocationX(targ),GetLocationY(targ),GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()))
set tempDat.maxdistance=tempDat.distance
set dbIndex=dbIndex+1
set jumDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
call RemoveLocation(targ)
set targ = null
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call GT_RegisterStartsEffectEvent(t,JUMPID)
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=18
//TESH.alwaysfold=0
scope omegapara initializer i
private struct paraDat
unit u
unit t
endstruct
globals
private constant integer ABLIID= 'A03N' //Insert rawcode of ability
private constant integer BUFFID='B00A'
private constant real TIMEROUT=.25 //Timeout in seconds; RECCOMENDED .03 for 33 fps.
private constant real DAMAGE=12
private constant real EXTRADAMAGE=15
private timer time=CreateTimer()
private paraDat array paraDB
private integer dbIndex=-1
endglobals
private function p takes nothing returns nothing
local paraDat tempDat
local integer index=0
loop
exitwhen index>dbIndex
set tempDat=paraDB[index]
call Damage_Pure(tempDat.u,tempDat.t,DAMAGE*TIMEROUT)
if IsUnitType(tempDat.t,UNIT_TYPE_ANCIENT) == true or IsUnitType(tempDat.t,UNIT_TYPE_GIANT) == true then
call Damage_Pure(tempDat.u,tempDat.t,EXTRADAMAGE*TIMEROUT)
endif
call UnitRemoveAbility(tempDat.t,'B008')
if GetUnitAbilityLevel(tempDat.t,BUFFID) == 0 then
call tempDat.destroy()
set paraDB[index]=paraDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
endfunction
private function a takes nothing returns nothing
local paraDat tempDat=paraDat.create()
set tempDat.u = GetTriggerUnit()
set tempDat.t = GetSpellTargetUnit()
call UnitRemoveAbility(tempDat.t,'B008')
debug call BJDebugMsg("casted")
set dbIndex=dbIndex+1
set paraDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call GT_RegisterStartsEffectEvent(t,ABLIID)
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=60
//TESH.alwaysfold=0
scope crushingwave initializer i
private struct Dat
unit u
unit wave
real rad
real dist
real AOE
group effected
effect fx
endstruct
globals
private group g = CreateGroup()
private constant integer WAVEID= 'A08Q' //Insert rawcode of tunnel ability.
private constant real TIMEROUT=.03 //Timeout in seconds; RECCOMENDED .03 for 33 fps.
private constant real SPEED=900 //Speed of the missle.
private constant real DISTANCE=650
private constant real MAXAOE=250 //The max AoE of the missle.
private constant real STARTAOE=50
private constant real DAMAGE=70
private constant string EFFECT="Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveMissile.mdl"
private constant string DAMAGEEFFECT="Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl"
private timer time=CreateTimer()
private Dat array DB
private integer dbIndex=-1
endglobals
private function p takes nothing returns nothing
local Dat tempDat
local integer index=0
local real x
local real y
local unit a
loop
exitwhen index>dbIndex
set tempDat=DB[index]
set tempDat.dist=tempDat.dist-(SPEED*TIMEROUT)
set x=GetUnitX(tempDat.wave)+(SPEED*TIMEROUT)*Cos(tempDat.rad)
set y=GetUnitY(tempDat.wave)+(SPEED*TIMEROUT)*Sin(tempDat.rad)
call SetUnitPosition(tempDat.wave,x,y)
set tempDat.AOE = tempDat.AOE + (MAXAOE/(DISTANCE/(SPEED*TIMEROUT)))
set g = GetUnitsInRange(tempDat.AOE,x,y)
loop
set a = FirstOfGroup(g)
exitwhen a == null
if UnitAlive(a) == true and IsUnitType(a,UNIT_TYPE_STRUCTURE) == false and GetUnitAbilityLevel(a,'A03V') == 0 and GetOwningPlayer(a) != GetOwningPlayer(tempDat.u) then
if IsUnitInGroup(a,tempDat.effected) == false then
call Damage_Pure(tempDat.u,a,DAMAGE)
call GroupAddUnit(tempDat.effected,a)
endif
set x=GetUnitX(a)+(SPEED*TIMEROUT)*Cos(tempDat.rad)
set y=GetUnitY(a)+(SPEED*TIMEROUT)*Sin(tempDat.rad)
call SetUnitPosition(a,x,y)
call DestroyEffect(AddSpecialEffect(DAMAGEEFFECT,x,y))
endif
call GroupRemoveUnit(g,a)
endloop
if tempDat.dist < 0 then
debug call BJDebugMsg(R2S(tempDat.AOE))
call DestroyEffect(tempDat.fx)
call KillUnit(tempDat.wave)
call DestroyGroup(tempDat.effected)
call tempDat.destroy()
set DB[index]=DB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
set a = null
endfunction
private function a takes nothing returns nothing
local Dat tempDat=Dat.create()
local real x = GetSpellTargetX()
local real y = GetSpellTargetY()
set tempDat.u = GetTriggerUnit()
set tempDat.AOE=STARTAOE
set tempDat.dist = DISTANCE
set tempDat.effected = CreateGroup()
set tempDat.rad=A2PXY(GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()),x,y)
set tempDat.wave = CreateUnit(GetOwningPlayer(GetTriggerUnit()),'hpea',GetUnitX(tempDat.u),GetUnitY(tempDat.u),tempDat.rad)
set tempDat.fx = AddSpecialEffectTarget(EFFECT,tempDat.wave,"origin")
set tempDat.rad = tempDat.rad*bj_DEGTORAD
set dbIndex=dbIndex+1
set DB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call GT_RegisterStartsEffectEvent(t,WAVEID)
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=88
//TESH.alwaysfold=0
//Requires AIDS, Damage, Recycle, optional ABC
scope HighPressure initializer Init
globals
private constant integer ATKER_ID = 'h038'
private constant integer BUFF_ID = 'B014'
private constant real DAMAGE_CAP = 15.
private constant real DAMAGE_INCREASE = .5
private constant real DURATION = 1.5
private constant string GFX = "Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl"
private hashtable hasht = InitHashtable()
endglobals
private keyword Data
private struct TimerList
timer t
thistype next
thistype prev
method onDestroy takes nothing returns nothing
//Remove attached stuffs.
static if LIBRARY_ABC then
//If ABC is available, use ABC instead of hashtable.
call ClearTimerStructA(.t)
call ClearTimerStructB(.t)
call ClearTimerStructC(.t)
else
call FlushChildHashtable(hasht,GetHandleId(.t))
endif
//Recycle the timer.
call Timer.release(.t)
//Unlink.
set .prev.next = .next
set .next.prev = .prev
//Who can guess why I didn't nullify the timer here? =P
endmethod
method chainDestroy takes nothing returns nothing
loop
set this = this.next
exitwhen this == 0
call .destroy()
endloop
endmethod
static method onExpired takes nothing returns nothing
//Get struct from timer
static if LIBRARY_ABC then
local timer t = GetExpiredTimer()
local thistype this = LoadTimerStructA(t)
local integer damagedUnitId = LoadTimerStructB(t)
local integer atkerId = LoadTimerStructC(t)
//Use ABC if available.
else
local integer tId = GetHandleId(GetExpiredTimer())
local thistype this = LoadInteger(hasht,tId,0)
local integer damagedUnitId = LoadInteger(hasht,tId,1)
local integer atkerId = LoadInteger(hasht,tId,2)
endif
local real r = LoadReal(hasht,damagedUnitId,atkerId)
//Prevent bug, so we get the value again instead of storing it in struct.
set r = r - DAMAGE_INCREASE
//Decrease the damage stack amount
call SaveReal(hasht,damagedUnitId,atkerId,r)
//Set it.
call .destroy()
//destroy the struct.
endmethod
static method add takes Data d, integer id, real r returns nothing
local thistype this = .allocate()
//Get a new instance.
local integer tId
set .t = Timer.get()
//Get a timer from timer stack.
set d.head.prev.next = this
set .prev = d.head.prev
set d.head.prev = this
set .next = 0
//LinkedList
call SaveReal(hasht,d,id,r)
//Set the damage stack value.
static if LIBRARY_ABC then
call SetTimerStructA(.t,this)
call SetTimerStructB(.t,d)
call SetTimerStructC(.t,id)
else
set tId = GetHandleId(.t)
call SaveInteger(hasht,tId,0,this)
call SaveInteger(hasht,tId,1,d)
call SaveInteger(hasht,tId,2,id)
endif
//Attach stuffs to timer.
call TimerStart(.t,DURATION,false,function thistype.onExpired)
//Start the timer.
endmethod
endstruct
private struct Data extends array
boolean isCapped
TimerList head
method AIDS_onCreate takes nothing returns nothing
//Create list for timer
set .head = TimerList.create()
//LinkedList.
set .head.next = .head
set .head.prev = .head
endmethod
method AIDS_onDestroy takes nothing returns nothing
call .head.chainDestroy()
call FlushChildHashtable(hasht,this)
set .isCapped = false
//Remove all stacked damage from all source
//Remove the cap, ready for later usage
//Force removing the timers, since the unit is removed, the timers are
//useless and may cause bug.
endmethod
//! runtextmacro AIDS()
endstruct
private function Act takes nothing returns nothing
local Data d = Data[GetTriggerUnit()] //Struct of attaacked unit.
local integer id = GetUnitId(GetEventDamageSource()) //Id of attacker.
local real r = LoadReal(hasht,d,id) //Damage stack count.
set r = RMinBJ(r + DAMAGE_INCREASE, DAMAGE_CAP) //Limit the amount of damage stacking.
call Damage_Pure(GetIndexUnit(id),d.unit,r) //Deal damage.
if r < DAMAGE_CAP or (r >= DAMAGE_CAP and d.isCapped == false) then
//If current value less than capped value
//or first reach to capped value then
call TimerList.add(d,id,r)
//make timer and callback.
if r >= DAMAGE_CAP then
set d.isCapped = true
//Flag it.
endif
endif
call DestroyEffect(AddSpecialEffectTarget(GFX,d.unit,"chest"))
//visual effect.
endfunction
private function Cond takes nothing returns boolean
if GetUnitAbilityLevel(GetTriggerUnit(),'B014') > 0 and GetUnitTypeId(GetEventDamageSource()) == ATKER_ID and Damage_IsAttack() then
//Condition : Unit type stuffs and the important : Damage_IsAttack(), it can prevent recursion/ infinite loop.
call Act()
endif
return false
endfunction
private function Init takes nothing returns nothing
local trigger t=CreateTrigger()
call Damage_RegisterEvent(t)
call TriggerAddCondition(t,Condition(function Cond))
endfunction
endscope
//TESH.scrollpos=31
//TESH.alwaysfold=0
scope round initializer i
private struct rouDat
unit u
unit t
real aoe
real dmg
endstruct
globals
private constant integer ROUNDID= 'A03H' //Insert rawcode of tunnel ability.
private constant integer BUFFID='B02E' //Insert rawcode of dummy armor ability.
private constant real TIMEROUT=.25 //Timeout in seconds
private constant real AOEINC=10 //AoE increase after each iteration.
private constant real DAMAGEINC=4.68 //Damage increase after each iteration.
private constant string EFFECT= "Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl"//Effect used.
private timer time=CreateTimer()
private rouDat array rouDB
private integer dbIndex=-1
private group g = CreateGroup()
endglobals
private function c takes nothing returns boolean
return GetSpellAbilityId()==ROUNDID
endfunction
private function filter takes nothing returns boolean
if UnitAlive(GetFilterUnit()) == true and IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false and GetOwningPlayer(GetFilterUnit()) != GetOwningPlayer(udg_TempUnit) then
call Damage_Pure(udg_TempUnit,GetFilterUnit(),udg_TempReal)
return true
endif
return false
endfunction
private function p takes nothing returns nothing
local rouDat tempDat
local integer index=0
local unit a
loop
exitwhen index>dbIndex
set tempDat=rouDB[index]
set tempDat.aoe = tempDat.aoe + AOEINC
set tempDat.dmg = tempDat.dmg + DAMAGEINC
if GetUnitAbilityLevel(tempDat.t,BUFFID) == 0 then
if IsUnitType(tempDat.t, UNIT_TYPE_MAGIC_IMMUNE) == true then
call Damage_Pure(tempDat.u,tempDat.t,tempDat.dmg/2)
endif
call DestroyEffect(AddSpecialEffect(EFFECT,GetUnitX(tempDat.t),GetUnitY(tempDat.t)))
set udg_TempUnit = tempDat.u
set udg_TempReal = tempDat.dmg
call GroupEnumUnitsInRange(g,GetUnitX(tempDat.t),GetUnitY(tempDat.t),tempDat.aoe,Condition(function filter))// set g = GetUnitsInRange(tempDat.aoe,GetUnitX(tempDat.t),GetUnitY(tempDat.t))
debug call BJDebugMsg(I2S(CountUnitsInGroup(g)))
call GroupClear(g)
call tempDat.destroy()
set rouDB[index]=rouDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
set a = null
endfunction
private function a takes nothing returns nothing
local rouDat tempDat=rouDat.create()
set tempDat.u = GetTriggerUnit()
set tempDat.t = GetSpellTargetUnit()
set tempDat.aoe = 0
set tempDat.dmg = 0
set dbIndex=dbIndex+1
set rouDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call GT_RegisterStartsEffectEvent(t,ROUNDID)
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=63
//TESH.alwaysfold=0
function Trig_Napam_Grenade_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A024'
endfunction
function GrenadeDamage takes nothing returns nothing
if GetOwningPlayer(GetEnumUnit()) != GetOwningPlayer(udg_TempUnit) then
call UnitDamageTargetBJ( udg_TempUnit, GetEnumUnit(), 100-(I2R(udg_TempInt01)*15), ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
endif
endfunction
function GrenadeMove takes nothing returns nothing
local timer t = GetExpiredTimer()
local unit fire
local unit u = GetHandleUnit(t,"grenade")
local real dist = GetHandleReal(t,"dist")
local real maxdist = GetHandleReal(t,"maxdist")
local real angle = GetHandleReal(t,"ang")
local integer bounces = GetHandleInt(t,"bounces")
local real curve = GetHandleReal(t,"curve")
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local real newX
local real newY
local real height
local effect e
local group g = CreateGroup()
local unit a
set udg_TempInt01 = bounces
call SetHandleReal(t,"dist",dist-(maxdist/45))
set newX = x + (maxdist/45) * Cos(angle)
set newY = y + (maxdist/45) * Sin(angle)
call SetUnitPosition(u,newX,newY)
set height = JumpParabola(dist, maxdist,curve+I2R(bounces), 0.00,0.00)
call SetUnitFlyHeight(u,height,0.00)
if dist < 0.00 then
set fire = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),'e002',newX,newY,angle)
call UnitApplyTimedLifeBJ( 140-(I2R(bounces)*40), 'BTLF', fire )
call AddLocust(fire)
call GroupEnumUnitsInRange(g,newX,newY,200-(I2R(bounces)*15),Filter(function Enum_AntiLeak))
loop
set a=FirstOfGroup(g)
call GroupRemoveUnit(g,a)
exitwhen a==null
if GetOwningPlayer(u) != GetOwningPlayer(a) then
call Damage_Spell( u, a, 100-(I2R(bounces)*14))
endif
endloop
set e = AddSpecialEffect("Abilities\\Weapons\\DemolisherFireMissile\\DemolisherFireMissile.mdl",newX,newY)
call DestroyEffect(e)
call SetHandleInt(t,"bounces",bounces+1)
call SetHandleReal(t,"dist",maxdist/1.55)
call SetHandleReal(t,"maxdist",maxdist/1.55)
if bounces == 3 then
call KillUnit(u)
call FlushHandleLocals(t)
call DestroyTimer(t)
endif
endif
call DestroyGroup(g)
set e = null
set u = null
set t = null
set g = null
set fire = null
endfunction
function Trig_Napam_Grenade_Actions takes nothing returns nothing
local unit u
local timer t = CreateTimer()
local real x = GetSpellTargetX()
local real y = GetSpellTargetY()
local real ang =A2PXY(GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()),x,y)*3.14159/180
local real dist = D2PXY(GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()),x,y)
set u = CreateUnit(GetOwningPlayer(GetTriggerUnit()),'h01D',GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()),ang)
call SetHandleHandle(t,"grenade",u)
call SetHandleReal(t,"curve",(550/dist)/5)
if dist < 150 then
call SetHandleReal(t,"dist",150)
call SetHandleReal(t,"maxdist",150)
else
call SetHandleReal(t,"dist",dist)
call SetHandleReal(t,"maxdist",dist)
endif
call SetHandleReal(t,"ang",ang)
call SetHandleInt(t,"bounces",1)
call TimerStart(t,0.03125,true,function GrenadeMove)
set t = null
set u = null
endfunction
//===========================================================================
function InitTrig_Napam_Grenade takes nothing returns nothing
set gg_trg_Napam_Grenade = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Napam_Grenade, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Napam_Grenade, Condition( function Trig_Napam_Grenade_Conditions ) )
call TriggerAddAction( gg_trg_Napam_Grenade, function Trig_Napam_Grenade_Actions )
endfunction
//TESH.scrollpos=16
//TESH.alwaysfold=0
scope darkness initializer i
private struct bioDat
unit u
real dur
real size
integer lvl
effect e
endstruct
globals
private group g = CreateGroup()
private constant integer BIOID= 'A090' //Insert rawcode of ability.
private constant real TIMEROUT=.03 //Timeout in seconds.
private constant real GROWTHRATE=0.03 //Rate at which the bomb grows
private constant real DURATION=3 //How long the bomb lasts before exploding
private constant real BASEAOE=220 //The base AoE of the explosion
private constant real MULTIAOE=0
private constant real BASEDAMAGE=200
private constant real MULTIDAMAGE=0
private constant string DUMMYEFFECT="Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl"
private constant string EXPLOSIONEFFECT="Abilities\\Spells\\Undead\\OrbOfDeath\\AnnihilationMissile.mdl"
private timer time=CreateTimer()
private bioDat array bioDB
private integer dbIndex=-1
endglobals
private function c takes nothing returns boolean
return GetSpellAbilityId()==BIOID
endfunction
private function p takes nothing returns nothing
local bioDat tempDat
local integer index=0
local unit a
loop
exitwhen index>dbIndex
set tempDat=bioDB[index]
set tempDat.dur = tempDat.dur - TIMEROUT
set tempDat.size = tempDat.size + GROWTHRATE
call SetUnitFlyHeight(tempDat.u,tempDat.size*10,0)
call SetUnitScale(tempDat.u,tempDat.size,tempDat.size,tempDat.size)
if tempDat.dur < 0 then
set g = GetUnitsInRange(BASEAOE+(MULTIAOE*tempDat.lvl),GetUnitX(tempDat.u),GetUnitY(tempDat.u))
loop
set a = FirstOfGroup(g)
exitwhen a ==null
call GroupRemoveUnit(g,a)
if GetOwningPlayer(a) != GetOwningPlayer(tempDat.u) and UnitAlive(a) == true then
call Damage_Pure(tempDat.u,a,BASEDAMAGE+(MULTIDAMAGE*tempDat.lvl))
call DestroyEffect(AddSpecialEffectTarget(DUMMYEFFECT,a,"chest"))
endif
endloop
call SetUnitFlyHeight(tempDat.u,0,0)
call DestroyEffect(tempDat.e)
call DestroyEffect(AddSpecialEffectTarget(EXPLOSIONEFFECT,tempDat.u,"origin"))
call KillUnit(tempDat.u)
call tempDat.destroy()
set bioDB[index]=bioDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
set a = null
endfunction
private function a takes nothing returns nothing
local bioDat tempDat=bioDat.create()
set tempDat.u = CreateUnit(GetOwningPlayer(GetTriggerUnit()),'hpea',GetSpellTargetX(),GetSpellTargetY(),0)
set tempDat.dur = DURATION
set tempDat.e = AddSpecialEffectTarget(DUMMYEFFECT,tempDat.u,"origin")
set tempDat.size = 1
set tempDat.lvl = GetUnitAbilityLevel(GetTriggerUnit(),BIOID)
set dbIndex=dbIndex+1
set bioDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function c))
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=81
//TESH.alwaysfold=0
scope gravorb initializer i
private struct staDat
unit u
unit missle
real rad
real distance
effect fx
endstruct
globals
private group g = CreateGroup()
private constant integer GRAVID= 'A07C' //Insert rawcode of ability.
private constant real TIMEROUT=.03 //Timeout in seconds.
private constant real SPEED=900 //Speed of the missle.
private constant real HEIGHT=100 //Height of missle.
private constant real DRAG=500 //Rate at which units get dragged by the missle.
private constant real AOE=250 //AoE of the missle.
private constant real DAMAGE=100 //Damage of the missle.
private constant string MISSLEEFFECT= "Abilities\\Spells\\Undead\\OrbOfDeath\\AnnihilationMissile.mdl"
private constant string DAMAGEEFFECT= "Units\\NightElf\\Wisp\\WispExplode.mdl"
private timer time=CreateTimer()
private staDat array staDB
private integer dbIndex=-1
endglobals
private function c takes nothing returns boolean
return GetSpellAbilityId()==GRAVID
endfunction
private function p takes nothing returns nothing
local staDat tempDat
local integer index=0
local real rad
local real x
local real x2
local real y
local real y2
local unit a
loop
exitwhen index>dbIndex
set tempDat=staDB[index]
set tempDat.distance=tempDat.distance-(SPEED*TIMEROUT)
set x=GetUnitX(tempDat.missle)+(SPEED*TIMEROUT)*Cos(tempDat.rad)
set y=GetUnitY(tempDat.missle)+(SPEED*TIMEROUT)*Sin(tempDat.rad)
call SetUnitPosition(tempDat.missle,x,y)
call GroupEnumUnitsInRange(g,x,y,AOE,null)
loop
set a = FirstOfGroup(g)
exitwhen a == null
if UnitAlive(a) == true and IsUnitType(a, UNIT_TYPE_MAGIC_IMMUNE) == false and IsUnitType(a, UNIT_TYPE_STRUCTURE) == false and IsUnitType(a, UNIT_TYPE_FLYING) == false and GetOwningPlayer(a) != GetOwningPlayer(tempDat.u) then
set rad = A2PXY(GetUnitX(a),GetUnitY(a),x,y)*bj_DEGTORAD
set x2=GetUnitX(a)+(DRAG*TIMEROUT)*Cos(rad)
set y2=GetUnitY(a)+(DRAG*TIMEROUT)*Sin(rad)
if Check_pathability(x2,y2) == true then
call SetUnitX(a,x2)
call SetUnitY(a,y2)
endif
endif
call GroupRemoveUnit(g,a)
endloop
if tempDat.distance < 0 then
call DestroyEffect(tempDat.fx)
call DestroyEffect(AddSpecialEffect(DAMAGEEFFECT,x,y))
call KillDummy(tempDat.missle)
call GroupEnumUnitsInRange(g,x,y,AOE,null)
loop
set a = FirstOfGroup(g)
exitwhen a == null
if UnitAlive(a) == true and IsUnitType(a, UNIT_TYPE_MAGIC_IMMUNE) == false and IsUnitType(a, UNIT_TYPE_FLYING) == false and GetOwningPlayer(a) != GetOwningPlayer(tempDat.u) then
call Damage_Spell(tempDat.u,a,DAMAGE)
endif
call GroupRemoveUnit(g,a)
endloop
call tempDat.destroy()
set staDB[index]=staDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
set a = null
endfunction
private function a takes nothing returns nothing
local staDat tempDat=staDat.create()
local real x = GetSpellTargetX()
local real y = GetSpellTargetY()
set tempDat.u = GetTriggerUnit()
set tempDat.distance = D2PXY(GetUnitX(tempDat.u),GetUnitY(tempDat.u),x,y)
set tempDat.rad=A2PXY(GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()),x,y)
set tempDat.missle = CreateUnit(GetOwningPlayer(GetTriggerUnit()),'hpea',GetUnitX(tempDat.u),GetUnitY(tempDat.u),tempDat.rad)
set tempDat.fx = AddSpecialEffectTarget(MISSLEEFFECT,tempDat.missle,"origin")
set tempDat.rad = tempDat.rad*bj_DEGTORAD
call SetUnitFlyHeight(tempDat.missle,HEIGHT,0)
set dbIndex=dbIndex+1
set staDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function c))
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=50
//TESH.alwaysfold=0
scope countdown initializer i
private struct countDat
unit u
texttag text
real counter
integer duration
endstruct
globals
private constant integer DETOID= 'A004' //Insert rawcode of ability.
private constant real TIMEROUT=.03 //Timeout in seconds; RECCOMENDED .03 for 33 fps.
private constant integer DURATION=3 //Duration of the bomb.
private constant real TEXTSIZE=10
private timer time=CreateTimer()
private countDat array countDB
private integer dbIndex=-1
endglobals
private function c takes nothing returns boolean
return GetSpellAbilityId()==DETOID
endfunction
private function p takes nothing returns nothing
local countDat tempDat
local integer index=0
loop
exitwhen index>dbIndex
set tempDat=countDB[index]
set tempDat.counter = tempDat.counter - TIMEROUT
if tempDat.counter <= TIMEROUT then
set tempDat.counter = 1.00
set tempDat.duration = tempDat.duration - 1
call PlaySoundOnUnitBJ( gg_snd_BombTick, 100,tempDat.u )
call DestroyTextTag(tempDat.text)
set tempDat.text = CreateTextTagUnitBJ(I2S(tempDat.duration), tempDat.u, 0, TEXTSIZE, 100, 100, 100, 0 )
endif
call SetTextTagPos(tempDat.text,GetUnitX(tempDat.u),GetUnitY(tempDat.u),0)
if tempDat.duration == -1 or tempDat.u == null then
if tempDat.u != null then
call SetUnitAbilityLevel(tempDat.u,DETOID,2)
call KillUnit(tempDat.u)
call DestroyTextTag(tempDat.text)
call tempDat.destroy()
endif
set countDB[index]=countDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
endfunction
private function a takes nothing returns nothing
local countDat tempDat=countDat.create()
set tempDat.u = GetTriggerUnit()
set tempDat.counter = 1.00
set tempDat.duration = DURATION
set tempDat.text = CreateTextTagUnitBJ(I2S(DURATION), GetTriggerUnit(), 0, TEXTSIZE, 100, 100, 100, 0 )
call PlaySoundOnUnitBJ( gg_snd_BombTick, 100, GetTriggerUnit() )
set dbIndex=dbIndex+1
set countDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function c))
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=60
//TESH.alwaysfold=0
scope bombdeath initializer i
globals
private group g = CreateGroup()
private boolexpr filt
private real X
private real Y
private constant integer BOMBID = 'n008'
private constant integer EXPLODEID = 'n00B'
private constant integer ITEMID = 'I00Y'
private constant integer ROCKID = 'LTrc'
private constant integer FIREID = 'e005'
private constant real SPAWNAOE = 850
private constant real AOE = 1000
private constant real MAXDAMAGE = 1500
private constant real MINDAMAGE = 1
private constant real SECONDARYDAMAGE = 200
private constant real SECONDARYAOE = 250
private constant real SHAKEINC = 10
private constant real STATIONDAMAGE = 3000
private constant real KNOCKBACKDISTANCE=1500
private constant integer FIRESPAWN = 19
private constant integer ROCKSPAWN = 16
private constant integer EXPLODECOUNT = 9
private constant sound SOUND = gg_snd_BombExplode
private constant string TEXT = "|cffFF8000A Remote Bomb has been detonated!|r"
private constant string DAMAGEEFFECT = "Abilities\\Weapons\\DemolisherFireMissile\\DemolisherFireMissile.mdl"
private constant string EXPLODEEFFECT = "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl"
endglobals
private function filter takes nothing returns boolean
return UnitAlive(GetFilterUnit()) and not(IsUnitType(GetFilterUnit(),UNIT_TYPE_ETHEREAL))
endfunction
private function c takes nothing returns boolean
return GetUnitTypeId(GetTriggerUnit()) == BOMBID
endfunction
private function destkill takes nothing returns nothing
local real x = GetWidgetX(GetEnumDestructable())
local real y = GetWidgetY(GetEnumDestructable())
if GetDestructableTypeId(GetEnumDestructable()) == ROCKID then
call SetDestructableLife(GetEnumDestructable(),GetDestructableMaxLife(GetEnumDestructable()))
else
if D2PXY(x,y,X,Y) <= AOE and GetDestructableLife(GetEnumDestructable()) > 0 then
call UnitDamageTarget(GetTriggerUnit(),GetEnumDestructable(),MAXDAMAGE-(((MAXDAMAGE/AOE)-(MINDAMAGE/AOE))*D2PXY(x,y,X,Y)),false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
call DestroyEffect(AddSpecialEffectTarget(DAMAGEEFFECT,GetEnumDestructable(),"origin"))
endif
endif
endfunction
private function actions takes nothing returns nothing
local real x = GetUnitX(GetTriggerUnit())
local real y = GetUnitY(GetTriggerUnit())
local integer i = 0
local real x2
local real y2
local real rad
local unit a
local unit explode
local rect r
if GetUnitAbilityLevel(GetTriggerUnit(),'A004') == 2 then
set r = Rect(x - AOE, y - AOE, x + AOE, y + AOE)
set explode = CreateUnit(GetOwningPlayer(GetTriggerUnit()),EXPLODEID,x,y,0)
call SetUnitTimeScale(explode,1.25)
call DisplayTextToForce(bj_FORCE_ALL_PLAYERS,TEXT)
if RectContainsUnit(gg_rct_Station_1, GetTriggerUnit()) == true or RectContainsUnit(gg_rct_Station_2, GetTriggerUnit()) == true then
call Damage_Pure(GetTriggerUnit(),udg_Station,STATIONDAMAGE)
set udg_ScreenShakeLevel = ( udg_ScreenShakeLevel + SHAKEINC )
endif
call PlaySoundBJ(SOUND)
loop
exitwhen i == 10
call UnitShareVision(explode,Player(i),true)
set i = i + 1
endloop
set i = 0
call GroupEnumUnitsInRange(g,x,y,AOE,Condition (function filter))
loop
set a = FirstOfGroup(g)
exitwhen a == null
call GroupRemoveUnit(g,a)
set x2 = GetUnitX(a)
set y2 = GetUnitY(a)
call DestroyEffect(AddSpecialEffectTarget(DAMAGEEFFECT,a,"origin"))
if IsUnitType(a,UNIT_TYPE_TAUREN) == true then
call SetUnitAbilityLevel(a,'A004',2)
call KillUnit(a)
else
if IsUnitType(a,UNIT_TYPE_MAGIC_IMMUNE) == false then
call Damage_Pure(GetTriggerUnit(),a,MAXDAMAGE-(((MAXDAMAGE/AOE)-(MINDAMAGE/AOE))*D2PXY(x,y,x2,y2)))
debug call BJDebugMsg(R2S( MAXDAMAGE-(((MAXDAMAGE/AOE)-(MINDAMAGE/AOE))*D2PXY(x,y,x2,y2)))+"Damage Dealt")
else
if D2PXY(x,y,x2,y2) < SECONDARYAOE then
call Damage_Pure(GetTriggerUnit(),a,SECONDARYDAMAGE)
endif
endif
call KBS_BeginEx(a,KNOCKBACKDISTANCE-D2PXY(x,y,x2,y2),(KNOCKBACKDISTANCE-D2PXY(x,y,x2,y2))/KNOCKBACKDISTANCE,A2PXY(x,y,x2,y2),"",0,false,true)
call DestroyEffect(AddSpecialEffect(DAMAGEEFFECT,x2,y2))
endif
endloop
call EnumDestructablesInRect(r,null,function destkill)
call RemoveRect(r)
loop
exitwhen i == EXPLODECOUNT
set i = i + 1
set X = x+GetRandomReal(AOE/10,SPAWNAOE)*Cos(GetRandomReal(0,360)*bj_DEGTORAD)
set Y = y+GetRandomReal(AOE/10,SPAWNAOE)*Cos(GetRandomReal(0,360)*bj_DEGTORAD)
call DestroyEffect(AddSpecialEffect(EXPLODEEFFECT,X,Y))
endloop
set i = 0
loop
exitwhen i == FIRESPAWN
set X = x+GetRandomReal(AOE/50,SPAWNAOE)*Cos(GetRandomReal(0,360)*bj_DEGTORAD)
set Y = y+GetRandomReal(AOE/50,SPAWNAOE)*Cos(GetRandomReal(0,360)*bj_DEGTORAD)
set a = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),FIREID,X,Y,GetRandomReal(0,360))
call SetUnitState(a,UNIT_STATE_LIFE,GetRandomReal(50,200))
call DestroyEffect(AddSpecialEffect(DAMAGEEFFECT,X,Y))
set i = i + 1
endloop
set i = 0
loop
exitwhen i == ROCKSPAWN
set X = x+GetRandomReal(AOE/50,SPAWNAOE)*Cos(GetRandomReal(0,360)*bj_DEGTORAD)
set Y = y+GetRandomReal(AOE/50,SPAWNAOE)*Cos(GetRandomReal(0,360)*bj_DEGTORAD)
call CreateDestructable(ROCKID,X,Y,GetRandomReal(0,360),1,0)
set i = i + 1
endloop
else
call RemoveUnit(GetTriggerUnit())
call CreateItem(ITEMID,x,y)
call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl",x,y))
endif
set a = null
set r = null
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DEATH)
call TriggerAddCondition(t,Condition(function c))
call TriggerAddAction(t,function actions)
endfunction
endscope
//TESH.scrollpos=12
//TESH.alwaysfold=0
scope plasmabombdeath initializer i
globals
private group g = CreateGroup()
private boolexpr filt
private real X
private real Y
private constant integer BOMBID = 'n01D'
private constant integer EXPLODEID = 'n01C'
private constant integer ITEMID = 'I02E'
private constant integer ROCKID = 'LTrc'
private constant integer FIREID = 'e005'
private constant real SPAWNAOE = 500
private constant real AOE = 650
private constant real MAXDAMAGE = 5000
private constant real MINDAMAGE = 100
private constant real SECONDARYDAMAGE = 400
private constant real SECONDARYAOE = 300
private constant real SHAKEINC = 20
private constant real STATIONDAMAGE = 4500
private constant real KNOCKBACKDISTANCE=1600
private constant integer FIRESPAWN = 10
private constant integer ROCKSPAWN = 8
private constant integer EXPLODECOUNT = 17
private constant sound SOUND = gg_snd_BombExplode
private constant string TEXT = "|cFF00FF00A Remote Bomb has been detonated!|r"
private constant string DAMAGEEFFECT = "Abilities\\Spells\\NightElf\\ManaBurn\\ManaBurnTarget.mdl"
private constant string EXPLODEEFFECT = "war3mapImported\\Fireworksgreen.mdx"
endglobals
private function filter takes nothing returns boolean
return UnitAlive(GetFilterUnit()) and not(IsUnitType(GetFilterUnit(),UNIT_TYPE_ETHEREAL))
endfunction
private function c takes nothing returns boolean
return GetUnitTypeId(GetTriggerUnit()) == BOMBID
endfunction
private function destkill takes nothing returns nothing
local real x = GetWidgetX(GetEnumDestructable())
local real y = GetWidgetY(GetEnumDestructable())
if GetDestructableTypeId(GetEnumDestructable()) == ROCKID then
call SetDestructableLife(GetEnumDestructable(),GetDestructableMaxLife(GetEnumDestructable()))
else
if D2PXY(x,y,X,Y) <= AOE and GetDestructableLife(GetEnumDestructable()) > 0 then
call UnitDamageTarget(GetTriggerUnit(),GetEnumDestructable(),MAXDAMAGE-(((MAXDAMAGE/AOE)-(MINDAMAGE/AOE))*D2PXY(x,y,X,Y)),false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
call DestroyEffect(AddSpecialEffectTarget(DAMAGEEFFECT,GetEnumDestructable(),"origin"))
endif
endif
endfunction
private function actions takes nothing returns nothing
local real x = GetUnitX(GetTriggerUnit())
local real y = GetUnitY(GetTriggerUnit())
local integer i = 0
local real x2
local real y2
local real rad
local unit a
local unit explode
local rect r
if GetUnitAbilityLevel(GetTriggerUnit(),'A004') == 2 then
set r = Rect(x - AOE, y - AOE, x + AOE, y + AOE)
set explode = CreateUnit(GetOwningPlayer(GetTriggerUnit()),EXPLODEID,x,y,0)
call SetUnitTimeScale(explode,1.25)
call DisplayTextToForce(bj_FORCE_ALL_PLAYERS,TEXT)
if RectContainsUnit(gg_rct_Station_1, GetTriggerUnit()) == true or RectContainsUnit(gg_rct_Station_2, GetTriggerUnit()) == true then
call Damage_Pure(GetTriggerUnit(),udg_Station,STATIONDAMAGE)
set udg_ScreenShakeLevel = ( udg_ScreenShakeLevel + SHAKEINC )
endif
call PlaySoundBJ(SOUND)
loop
exitwhen i == 10
call UnitShareVision(explode,Player(i),true)
set i = i + 1
endloop
set i = 0
call GroupEnumUnitsInRange(g,x,y,AOE,Condition (function filter))
loop
set a = FirstOfGroup(g)
exitwhen a == null
call GroupRemoveUnit(g,a)
set x2 = GetUnitX(a)
set y2 = GetUnitY(a)
call DestroyEffect(AddSpecialEffectTarget(DAMAGEEFFECT,a,"origin"))
if IsUnitType(a,UNIT_TYPE_TAUREN) == true then
call SetUnitAbilityLevel(a,'A004',2)
call KillUnit(a)
else
if IsUnitType(a,UNIT_TYPE_MAGIC_IMMUNE) == false then
call Damage_Pure(GetTriggerUnit(),a,MAXDAMAGE-(((MAXDAMAGE/AOE)-(MINDAMAGE/AOE))*D2PXY(x,y,x2,y2)))
debug call BJDebugMsg(R2S( MAXDAMAGE-(((MAXDAMAGE/AOE)-(MINDAMAGE/AOE))*D2PXY(x,y,x2,y2)))+"Damage Dealt")
else
if D2PXY(x,y,x2,y2) < SECONDARYAOE then
call Damage_Pure(GetTriggerUnit(),a,SECONDARYDAMAGE)
endif
endif
call KBS_BeginEx(a,KNOCKBACKDISTANCE-D2PXY(x,y,x2,y2),(KNOCKBACKDISTANCE-D2PXY(x,y,x2,y2))/KNOCKBACKDISTANCE,A2PXY(x,y,x2,y2),"",0,false,true)
call DestroyEffect(AddSpecialEffect(DAMAGEEFFECT,x2,y2))
endif
endloop
call EnumDestructablesInRect(r,null,function destkill)
call RemoveRect(r)
loop
exitwhen i == EXPLODECOUNT
set i = i + 1
set X = x+GetRandomReal(AOE/10,SPAWNAOE)*Cos(GetRandomReal(0,360)*bj_DEGTORAD)
set Y = y+GetRandomReal(AOE/10,SPAWNAOE)*Cos(GetRandomReal(0,360)*bj_DEGTORAD)
call DestroyEffect(AddSpecialEffect(EXPLODEEFFECT,X,Y))
endloop
set i = 0
loop
exitwhen i == FIRESPAWN
set X = x+GetRandomReal(AOE/50,SPAWNAOE)*Cos(GetRandomReal(0,360)*bj_DEGTORAD)
set Y = y+GetRandomReal(AOE/50,SPAWNAOE)*Cos(GetRandomReal(0,360)*bj_DEGTORAD)
set a = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),FIREID,X,Y,GetRandomReal(0,360))
call SetUnitState(a,UNIT_STATE_LIFE,GetRandomReal(50,200))
call DestroyEffect(AddSpecialEffect(DAMAGEEFFECT,X,Y))
set i = i + 1
endloop
set i = 0
loop
exitwhen i == ROCKSPAWN
set X = x+GetRandomReal(AOE/50,SPAWNAOE)*Cos(GetRandomReal(0,360)*bj_DEGTORAD)
set Y = y+GetRandomReal(AOE/50,SPAWNAOE)*Cos(GetRandomReal(0,360)*bj_DEGTORAD)
call CreateDestructable(ROCKID,X,Y,GetRandomReal(0,360),1,0)
set i = i + 1
endloop
else
call RemoveUnit(GetTriggerUnit())
call CreateItem(ITEMID,x,y)
call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl",x,y))
endif
set a = null
set r = null
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DEATH)
call TriggerAddCondition(t,Condition(function c))
call TriggerAddAction(t,function actions)
endfunction
endscope
//TESH.scrollpos=33
//TESH.alwaysfold=0
scope medkit initializer i
private struct medDat
unit u
unit t
effect e
integer order
endstruct
globals
private constant integer MEDID = 'A08Y'
private constant real HEALRATE = 50
private constant real BREAKRANGE = 325
private constant string EFFECT = "Abilities\\Spells\\NightElf\\Rejuvenation\\RejuvenationTarget.mdl"
private constant string ATTACHPOINT = "chest"
private constant real TIMEROUT = 0.3
private timer time = CreateTimer()
private integer dbIndex = -1
private medDat array medDB
endglobals
private function c takes nothing returns boolean
return GetSpellAbilityId() == MEDID
endfunction
private function p takes nothing returns nothing
local medDat tempDat
local integer index=0
local boolean b
loop
exitwhen index>dbIndex
set tempDat=medDB[index]
call SetUnitState(tempDat.t,UNIT_STATE_LIFE,GetUnitState(tempDat.t,UNIT_STATE_LIFE)+(HEALRATE*TIMEROUT))
if tempDat.t != tempDat. u then
call SetUnitFacingTimed(tempDat.u,A2PXY(GetUnitX(tempDat.u),GetUnitY(tempDat.u),GetUnitX(tempDat.t),GetUnitY(tempDat.t)),0)
endif
if D2PXY(GetUnitX(tempDat.t),GetUnitY(tempDat.t),GetUnitX(tempDat.u),GetUnitY(tempDat.u)) < BREAKRANGE and GetUnitCurrentOrder(tempDat.u) == tempDat.order then
else
if GetUnitCurrentOrder(tempDat.u) == tempDat.order then
call IssueImmediateOrder(tempDat.u,"stop")
endif
call DestroyEffect(tempDat.e)
call tempDat.destroy()
set medDB[index]=medDB[dbIndex]
set dbIndex=dbIndex-1
if dbIndex==-1 then
call PauseTimer(time)
endif
endif
set index=index+1
endloop
endfunction
private function a takes nothing returns nothing
local medDat tempDat=medDat.create()
set tempDat.u = GetTriggerUnit()
set tempDat.t = GetSpellTargetUnit()
set tempDat.e = AddSpecialEffectTarget(EFFECT,tempDat.t,ATTACHPOINT)
set tempDat.order = GetUnitCurrentOrder(tempDat.u)
set dbIndex=dbIndex+1
set medDB[dbIndex]=tempDat
if dbIndex==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function c))
call TriggerAddAction(t,function a)
endfunction
endscope
//TESH.scrollpos=4
//TESH.alwaysfold=0
function Trig_Stigma_Spawn_Conditions takes nothing returns boolean
if GetItemTypeId(GetManipulatedItem()) == 'I007' and IsUnitType(GetTriggerUnit(), UNIT_TYPE_SAPPER) == true and GetUnitAbilityLevel(GetTriggerUnit(),'A08J') == 0 then
return true
endif
return false
endfunction
function StigmaSpawnEnd takes nothing returns nothing
local timer t = GetExpiredTimer()
local unit u = GetHandleUnit(t,"u")
if GetUnitTypeId(u) =='h03B' then
call UnitAddAbility( u,'S000' )
call SetUnitAbilityLevel( u,'S000', 1 )
call PolledWait(0.00)
call DestroyEffect(AddSpecialEffect("Units\\Undead\\Abomination\\AbominationExplosion.mdl",GetUnitX(u),GetUnitY(u)))
call SetUnitColor( u, GetPlayerColor(GetOwningPlayer(u)) )
call FlushHandleLocals(t)
call DestroyTimer(t)
else
call UnitAddAbility( u,'S000' )
call SetUnitAbilityLevel( u,'S000', 36 )
call PolledWait(0.00)
call DestroyEffect(AddSpecialEffect("Units\\Undead\\Abomination\\AbominationExplosion.mdl",GetUnitX(u),GetUnitY(u)))
call TimerStart(t,10,false,function StigmaSpawnEnd)
endif
set t = null
set u = null
endfunction
function Trig_Stigma_Spawn_Actions takes nothing returns nothing
local timer t = CreateTimer()
call SetHandleHandle(t,"u",GetTriggerUnit())
call UnitAddAbility( GetTriggerUnit() , 'S000')
call SetUnitAbilityLevel( GetTriggerUnit(),'S000', 35 )
call TimerStart(t,45,false,function StigmaSpawnEnd)
call TriggerSleepAction(0.00)
call SetUnitColor( GetTriggerUnit(), ConvertPlayerColor(12) )
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl",GetTriggerUnit(),"origin"))
set t = null
endfunction
//===========================================================================
function InitTrig_Stigma_Can takes nothing returns nothing
set gg_trg_Stigma_Can = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Stigma_Can, EVENT_PLAYER_UNIT_USE_ITEM )
call TriggerAddCondition( gg_trg_Stigma_Can, Condition( function Trig_Stigma_Spawn_Conditions ) )
call TriggerAddAction( gg_trg_Stigma_Can, function Trig_Stigma_Spawn_Actions )
endfunction
//TESH.scrollpos=9
//TESH.alwaysfold=0
function Trig_Parasite_Buster_Actions takes nothing returns nothing
local group paras = CreateGroup()
local unit a
local real r = 500
local group g = CreateGroup()
call GroupEnumUnitsInRange(paras,GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()),250,Filter(function Enum_AntiLeak))
loop
set a =FirstOfGroup(paras)
call GroupRemoveUnit(paras,a)
if IsUnitType(a,UNIT_TYPE_GIANT) == true or IsUnitType(a,UNIT_TYPE_ANCIENT) == true and GetUnitState(a,UNIT_STATE_LIFE) > 0.305 then
call GroupAddUnit(g,a)
endif
exitwhen a==null
endloop
set r = r/CountUnitsInGroup(g)
loop
set a = FirstOfGroup(g)
call GroupRemoveUnit(g,a)
exitwhen a == null
if IsUnitType(a,UNIT_TYPE_GIANT) == true then
call UnitDamageTargetBJ( GetTriggerUnit(), a, r, ATTACK_TYPE_SIEGE, DAMAGE_TYPE_NORMAL )
else
if IsPlayerInForce(GetOwningPlayer(GetTriggerUnit()),udg_Parasites) == false then
call UnitDamageTargetBJ( GetTriggerUnit(),a, r/3, ATTACK_TYPE_SIEGE, DAMAGE_TYPE_NORMAL )
endif
endif
endloop
call DestroyGroup(paras)
set paras = null
set g = null
set a =null
endfunction
//===========================================================================
function InitTrig_Parasite_Buster takes nothing returns nothing
set gg_trg_Parasite_Buster = CreateTrigger( )
call GT_RegisterItemUsedEvent( gg_trg_Parasite_Buster, 'I03A')
call TriggerAddAction( gg_trg_Parasite_Buster, function Trig_Parasite_Buster_Actions )
endfunction
//TESH.scrollpos=9
//TESH.alwaysfold=0
function Trig_Book_Initialization_Actions takes nothing returns nothing
local integer i = 0
set udg_BookString1[1] = "June 21st:Stardate 2070.
The Parasites at XGRM are amazing, I can see great potential in them as a weapon. However a new strain has been found scratching a poor living off the arid soil of XGRM. Having survived for so long in such harsh conditions I wondered, surely such a lifeform was made for greater things?
I have decided to begin my own specal research into them immediately."
set udg_BookString2[1] = "October 1st:Stardate 2070.
The 'Cyo' parasites as we have named them have shown great progress, and they have responded amazingly to the tests we have put them though, they also show great adaptability to the enviroment around them.
They have also shown great mental and physical improvments since they arrived on the station, I have seen parasites form together to break down a steel door, or a single parasite to use logic to escape a large maze.
I pitty those who have to face the Cyos in combat."
set udg_BookString3[1] = "January 14th:Stardate 2071.
Another year has passed, and my health is none the better for it, I am returning to earth with my findings, and hope to find more investors for this project. However we have had afew cases of Cyo's breaking out of their habitats in the Bio Deck.
I do not fear for the crews safety as the Cyo Strain ultimately needs a host in order to do major damage. Dispite this, afew of the more paranoid members of the crew are creating another parasite strain to contain a potential Cyo outbreak.
Indeed, in such a situtation, the crew would have an advantage provided they used common sense and logic, rather than the many weapons on this station to combat the Cyo."
set udg_BookString1[2] = "
After humanity colonised planets outside of the solar system, there was a huge demand for minerals and energy. These could not be sufficiently provided on any of the occupied planets, so the major industrial centers of the world began developing and constructing space stations which could mine asteroids and barren planets. This grew into a thriving business within decades, and within the turn of the century there were several space stations operating further than humanity had ever reached before.
This system worked so well that space stations grew to titanic proportions, and soon became the base of operations for many occupations, including weapons manufacture, technology development and A.I. design. Eventually Ares, a space station launched by China as a research and mining outpost came across a world with a thriving ecosystem on its way to the mineral world of XGRM. After briefly landing on the planet so that biologists on board could capture and research this exotic life, the station neared XGRM."
set udg_BookString2[2] = "Page 2"
set udg_BookString3[3] = "Page 3"
set udg_Book[1] = 'I00L'
set udg_Book[2] = 'I00O'
call DestroyTrigger(GetTriggeringTrigger())
endfunction
//===========================================================================
function InitTrig_Book_Initialization takes nothing returns nothing
set gg_trg_Book_Initialization = CreateTrigger( )
call TriggerAddAction( gg_trg_Book_Initialization, function Trig_Book_Initialization_Actions )
endfunction
//TESH.scrollpos=4
//TESH.alwaysfold=0
library DrunkSys initializer i
globals
private integer array IntoxLvl
private unit dummy
private timer Timer = CreateTimer()
private constant integer DummyID='hpea' //ID of dummy unit.
private constant integer DummyOwner=bj_PLAYER_NEUTRAL_EXTRA
private constant integer SleepID=0 //ID used by dummy ability that makes units pass out when they get over a certain intox lvl
private constant integer IntoxDecrease = 2 //How much the intox lvl decreases per second
private constant integer PassoutLvl = 200 //If you drink and your intox lvl is past this int, then you have chance of passing out
private constant integer SwayLvl = 40 //If you drink and your intox lvl is past this int, then your screen will start to sway
private constant integer PassoutChance = 15 //Base chance of passing out after you go over the limit
private constant integer PassoutDivider = 50 //The players intox lvl divided by this is added onto the passout chance.
private constant real SwayDivider = 40 //Effects the swaying of the screen for drunk players. The lower this is, the less swaying you will get.
private constant real TimerOut = 0.5
endglobals
private function periodic takes nothing returns nothing
local integer i = 0
loop
exitwhen i == 11
if IntoxLvl[i] > 0 then
set IntoxLvl[i] = IntoxLvl[i] - IntoxDecrease*R2I(TimerOut)
else
if GetLocalPlayer() == Player(i) then
call CameraSetSourceNoise(0, 0)
endif
endif
set i = i + 1
endloop
endfunction
function AddIntox takes player owner, unit drinker, integer ammount returns nothing
set IntoxLvl[GetPlayerId(owner)] = IntoxLvl[GetPlayerId(owner)] + ammount
if IntoxLvl[GetPlayerId(owner)] > SwayLvl then
if IntoxLvl[GetPlayerId(owner)] > PassoutLvl and PassoutChance+(IntoxLvl[GetPlayerId(owner)]/PassoutDivider) > GetRandomInt(0, 100) then
call IssueTargetOrder(dummy,"sleep",drinker)
call SetUnitAnimation(drinker,"death")
endif
call CameraSetTargetNoiseForPlayer(owner,I2R(IntoxLvl[GetPlayerId(owner)]),I2R(IntoxLvl[GetPlayerId(owner)]))
endif
debug call BJDebugMsg(I2S(IntoxLvl[GetPlayerId(owner)]))
endfunction
private function i takes nothing returns nothing
set dummy = CreateUnit(Player(DummyOwner),DummyID,0,0,0)
call UnitAddAbility(dummy,DummyID)
call TimerStart(Timer, TimerOut, true, function periodic)
endfunction
endlibrary
//TESH.scrollpos=54
//TESH.alwaysfold=0
globals
boolean udg_LOCKED=false
integer udg_KEY=0x96E0000
integer udg_KEYDEPTH=0x10000000 // Add/remove 0's to change key's max length.
string array udg_TOCHAR
endglobals
function InitTOCHAR takes nothing returns nothing
set udg_TOCHAR[0]="0"
set udg_TOCHAR[1]="1"
set udg_TOCHAR[2]="2"
set udg_TOCHAR[3]="3"
set udg_TOCHAR[4]="4"
set udg_TOCHAR[5]="5"
set udg_TOCHAR[6]="6"
set udg_TOCHAR[7]="7"
set udg_TOCHAR[8]="8"
set udg_TOCHAR[9]="9"
set udg_TOCHAR[10]="A"
set udg_TOCHAR[11]="B"
set udg_TOCHAR[12]="C"
set udg_TOCHAR[13]="D"
set udg_TOCHAR[14]="E"
set udg_TOCHAR[15]="F"
endfunction
function ToHex takes integer i returns string
local integer r
local string result=""
call InitTOCHAR()
loop
exitwhen i==0
set r=i-(i/16)*16
set result=udg_TOCHAR[r]+result
set i=(i-r)/16
endloop
return "0x"+result // Hex Key
endfunction
function GetKey takes code f returns integer
local integer key=C2I(f)-GetIndex()
return key-(key/udg_KEYDEPTH)*udg_KEYDEPTH // Modulo
endfunction
function FatalError takes nothing returns nothing
call C2I(function IsNoVictoryCheat) // Fatal error
endfunction
function CheckLock takes nothing returns nothing
if udg_LOCKED then // Script locked?
if GetKey(function CheckLock)!=udg_KEY then // Not same as KEY?
call FatalError() // Crash
endif
else
call BJDebugMsg("K"+"e"+"y"+":"+" "+ToHex(GetKey(function CheckLock))) //Show key
endif
endfunction
//===========================================================================
function InitTrig_Msc takes nothing returns nothing
set gg_trg_Msc = CreateTrigger( )
call TriggerRegisterTimerEventSingle( gg_trg_Msc, 5.00 )
call TriggerAddAction( gg_trg_Msc, function ToHex )
endfunction