Name | Type | is_array | initial_value |
//TESH.scrollpos=170
//TESH.alwaysfold=0
scope AerialStrike
/*********************************************************************************/
/* */
/* Aerial Strike v1.1 */
/* by: msongyyy */
/* */
/* HOW TO IMPORT: */
/* 1. Import everything in the Import Manager to the correct paths */
/* 2. Import the Aerial Strike - Missile, Plane units and ability */
/* 3. Set the rawcode ID's below to the correct ones */
/* */
/* ENJOY ^^ */
/* */
/* THANKS TO: */
/* 1. Cohadar for TT */
/* 2. Nestharus for WorldBounds */
/* 3. Adikutz for MapBounds */
/* 3. Mechanical Man & Crusad3r91 for the Fireprism model(bombship) */
/* 4. zboc for BTNExplosion used */
/* 5. Fingolfin for Marauder missile(bombs) */
/* */
/*********************************************************************************/
globals
private constant integer ABIL_ID = 'A000' // Rawcode ID of Aerial Strike Spell
private constant integer MISS_ID = 'h003' // Rawcode ID of Aerial Strike - Missiles unit
private constant integer PLANE_ID = 'h002' // Rawcode ID of Aerial Strike - Plane unit
private constant string FX = "Abilities\\Weapons\\Mortar\\MortarMissile.mdl" // Effect created when a bomb explodes
private constant timer SPEED_TIMER = CreateTimer()
private constant real DEPLOY_PERIOD = .1 // How often the bombship drops bombs
private constant real SPEED_PERIOD = .0312500 // How often the bombship, and bombs move
private constant real PLANE_SPEED = 700.00 * SPEED_PERIOD // Speed of the bombship
private constant real MISSILE_SPEED = 300.00 * SPEED_PERIOD // Speed of the bombs
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_MAGIC
private constant weapontype WEAPON_TYPE = null
private group g = CreateGroup()
private unit fog
endglobals
// How many bombs dropped per DEPLOY_PERIOD
private constant function MISSILE_COUNT takes integer i returns integer
return 5
endfunction
// Distance travelled by plane
private constant function DIST takes integer i returns real
return i * 300. + 500.
endfunction
// Damage dealt by bombs
private constant function DMG takes integer i returns real
return i * 25. + 30.
endfunction
// Damage aoe of bombs
private constant function DMG_AOE takes integer i returns real
return 135.
endfunction
private function FILTER takes nothing returns boolean
if IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING) then
return false
endif
return true
endfunction
/*********************************************************************************/
/* END OF CONFIGURABLES */
/*********************************************************************************/
private struct Bombs extends array
private unit caster
private player play
private unit missile
private real ex
private real ey
private real ang
private real dmg
private real aoe
private real hinc
private static integer array prev
private static integer array next
private static integer array rn
private static integer ic = 0
static method Drop takes nothing returns nothing
local thistype this = next[0]
local real x
local real y
loop
exitwhen this == 0
if GetUnitFlyHeight(.missile) <= 15 then
call DestroyEffect(AddSpecialEffect(FX, .ex, .ey))
call GroupEnumUnitsInRange(g, .ex, .ey, .aoe, null)
loop
set fog = FirstOfGroup(g)
exitwhen fog == null
if IsUnitEnemy(fog, .play) then
call UnitDamageTarget(.caster, fog, .dmg, false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
endif
call GroupRemoveUnit(g, fog)
endloop
call RemoveUnit(.missile)
set .missile = null
set .caster = null
set .play = null
set prev[next[this]] = prev[this]
set next[prev[this]] = next[this]
set rn[this] = rn[0]
set rn[0] = this
else
set x = GetUnitX(.missile) + MISSILE_SPEED * Cos(.ang)
set y = GetUnitY(.missile) + MISSILE_SPEED * Sin(.ang)
set x = GetBoundedX(x)
set y = GetBoundedY(y)
call SetUnitX(.missile, x)
call SetUnitY(.missile, y)
call SetUnitFlyHeight(.missile, GetUnitFlyHeight(.missile) - .hinc, 0)
endif
set this = next[this]
if next[0] == 0 then
call PauseTimer(SPEED_TIMER)
endif
endloop
endmethod
static method Start takes unit caster, unit plane, player play returns nothing
local thistype this = rn[0]
local real sx = GetUnitX(plane)
local real sy = GetUnitY(plane)
local real rang = GetRandomReal(-90,90)
if this == 0 then
set ic = ic + 1
set this = ic
else
set rn[0] = rn[this]
endif
set .caster = caster
set .play = play
set .ex = sx + 300.00 * Cos((GetUnitFacing(plane) + rang) * bj_DEGTORAD)
set .ey = sy + 300.00 * Sin((GetUnitFacing(plane) + rang) * bj_DEGTORAD)
set .ang = Atan2(.ey-sy, .ex- sx)
set .hinc = 300/(SquareRoot((.ex-sx)*(.ex-sx) + (.ey-sy)*(.ey-sy))/MISSILE_SPEED)
set .missile = CreateUnit(.play, MISS_ID, sx, sy, .ang * bj_RADTODEG)
set .dmg = DMG(GetUnitAbilityLevel(.caster, ABIL_ID))
set .aoe = DMG_AOE(GetUnitAbilityLevel(.caster, ABIL_ID))
set .ex = GetBoundedX(.ex)
set .ey = GetBoundedY(.ey)
call UnitAddAbility(.missile, 'Amrf')
call UnitRemoveAbility(.missile, 'Amrf')
set prev[this] = prev[0]
set next[this] = 0
set next[prev[0]] = this
set prev[0] = this
if prev[this] == 0 then
call TimerStart(SPEED_TIMER, SPEED_PERIOD, true, function thistype.Drop)
endif
endmethod
endstruct
private struct Aerial extends array
private unit caster
private unit plane
private player play
private real ang
private real sx
private real sy
private real dist
private real tdist
private integer maxCount
private static integer array rn
private static integer ic = 0
static method Strike takes nothing returns boolean
local thistype this = TT_GetData()
local real tempx
local real tempy
if .dist > .tdist then
call RemoveUnit(.plane)
set .play = null
set .plane = null
set .caster = null
set rn[this] = rn[0]
set rn[0] = this
return true
else
set tempx = GetUnitX(.plane) + PLANE_SPEED * Cos(.ang)
set tempy = GetUnitY(.plane) + PLANE_SPEED * Sin(.ang)
set tempx = GetBoundedX(tempx)
set tempy = GetBoundedY(tempy)
call SetUnitX(.plane, tempx)
call SetUnitY(.plane, tempy)
set .dist = .dist + PLANE_SPEED
endif
return false
endmethod
static method Deploy takes nothing returns boolean
local thistype this = TT_GetData()
local integer i = 0
if .plane == null then
return true
endif
loop
exitwhen i == maxCount
call Bombs.Start(.caster, .plane, .play)
set i = i + 1
endloop
return false
endmethod
static method Start takes unit caster, real radians returns nothing
local thistype this = rn[0]
if this == 0 then
set ic = ic + 1
set this = ic
else
set rn[0] = rn[this]
endif
set .caster = caster
set .play = GetTriggerPlayer()
set .ang = radians
set .sx = GetUnitX(.caster) - 300 * Cos(.ang)
set .sy = GetUnitY(.caster) - 300 * Sin(.ang)
set .plane = CreateUnit(.play, PLANE_ID, .sx, .sy, .ang * bj_RADTODEG)
set .dist = 0
set .tdist = DIST(GetUnitAbilityLevel(.caster, ABIL_ID))
set .maxCount = MISSILE_COUNT(GetUnitAbilityLevel(.caster, ABIL_ID))
call TT_StartEx(function thistype.Strike, this, SPEED_PERIOD)
call TT_StartEx(function thistype.Deploy, this, DEPLOY_PERIOD)
endmethod
static method Cond takes nothing returns boolean
local unit lvCaster
if GetSpellAbilityId() == ABIL_ID then
set lvCaster = GetTriggerUnit()
call Aerial.Start(lvCaster, Atan2(GetSpellTargetY() - GetUnitY(lvCaster), GetSpellTargetX() - GetUnitX(lvCaster)))
set lvCaster = null
endif
return false
endmethod
static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function thistype.Cond))
set t = null
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
library_once WorldBounds /* v2.0.0.0
************************************************************************************
*
* struct WorldBounds extends array
* readonly static integer maxX
* readonly static integer maxY
* readonly static integer minX
* readonly static integer minY
* readonly static integer centerX
* readonly static integer centerY
* readonly static rect world
* readonly static region worldRegion
*
************************************************************************************/
private module WorldBoundInit
private static method onInit takes nothing returns nothing
set world=bj_mapInitialPlayableArea
set maxX=R2I(GetRectMaxX(world))
set maxY=R2I(GetRectMaxY(world))
set minX=R2I(GetRectMinX(world))
set minY=R2I(GetRectMinY(world))
set centerX=R2I((maxX+minX)/2)
set centerY=R2I((minY+maxY)/2)
set worldRegion=CreateRegion()
call RegionAddRect(worldRegion,world)
endmethod
endmodule
struct WorldBounds extends array
readonly static integer maxX
readonly static integer maxY
readonly static integer minX
readonly static integer minY
readonly static integer centerX
readonly static integer centerY
readonly static rect world
readonly static region worldRegion
implement WorldBoundInit
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
/*
*=================================================================================*
* Map Bounds 1.2 *
* By Adiktuz *
* *
* *
* This is a short snippet that provides some useful functions utilizing *
* the WorldBounds library created by Nestharus *
* *
* *
* Credits: *
* Nestharus for the WorldBounds library *
* Magtheridon96 for suggestions *
* *
* Functions: *
* *
* -> MapContainsX(real x) returns boolean *
* -> MapContainsY(real y) returns boolean *
* -> GetBoundedX(real x) returns real *
* -> GetBoundedY(real y) returns real *
* *
* *
* The MapContainsX/Y functions return if the given x/y value is inside the map *
* *
* The GetBoundedX/Y checks if the given value is within the map. If it's *
* within the map, it will return the value given and if Not *
* it will return the value of the border that it will exceed *
* *
*=================================================================================*
*/
library MapBounds requires WorldBounds
function MapContainsX takes real x returns boolean
return x < WorldBounds.maxX and x > WorldBounds.minX
endfunction
function MapContainsY takes real y returns boolean
return y < WorldBounds.maxY and y > WorldBounds.minY
endfunction
function GetBoundedX takes real x returns real
if x > WorldBounds.maxX then
return I2R(WorldBounds.maxX)
elseif x < WorldBounds.minX then
return I2R(WorldBounds.minX)
endif
return x
endfunction
function GetBoundedY takes real y returns real
if y > WorldBounds.maxY then
return I2R(WorldBounds.maxY)
elseif y < WorldBounds.minY then
return I2R(WorldBounds.minY)
endif
return y
endfunction
endlibrary
//TESH.scrollpos=48
//TESH.alwaysfold=0
library Setup initializer init
globals
constant timer S_TMR = CreateTimer()
constant integer array CREEPS
private group g = CreateGroup()
private unit fog
endglobals
private function sCond takes nothing returns boolean
call SetUnitState(gg_unit_H000_0001, UNIT_STATE_LIFE, 99999)
call SetUnitState(gg_unit_H000_0001, UNIT_STATE_MANA, 99999)
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\HolyBolt\\HolyBoltSpecialArt.mdl", gg_unit_H000_0001, "origin"))
return false
endfunction
private function rCond takes nothing returns boolean
local unit lvUnit = GetTriggerUnit()
if IsUnitType(lvUnit, UNIT_TYPE_HERO) then
call ReviveHero(lvUnit, 0, 0, true)
call PanCameraToTimed(0, 0, .5)
endif
set lvUnit = null
return false
endfunction
private function createCreeps takes nothing returns nothing
local integer i = 0
local integer i2 = GetRandomInt(3, 6)
local location lvLoc = GetRandomLocInRect(GetPlayableMapRect())
call GroupEnumUnitsOfPlayer(g, Player(12), null)
loop
set fog = FirstOfGroup(g)
exitwhen fog == null
if GetUnitState(fog, UNIT_STATE_LIFE) > 0 then
set i = i + 1
endif
call GroupRemoveUnit(g, fog)
endloop
if i < 50 then
loop
exitwhen i2 == 0 or i >= 50
call CreateUnitAtLoc(Player(12), CREEPS[GetRandomInt(0,5)], lvLoc, 0)
set i2 = i2 - 1
endloop
endif
call RemoveLocation(lvLoc)
set lvLoc = null
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
local trigger t2 = CreateTrigger()
set CREEPS[0] = 'nanm'
set CREEPS[1] = 'nenc'
set CREEPS[2] = 'nftr'
set CREEPS[3] = 'nfrl'
set CREEPS[4] = 'nltc'
set CREEPS[5] = 'nslr'
call TimerStart(S_TMR, 5, true, function createCreeps)
call DisplayTimedTextToPlayer(Player(0), 0, 0, 99999999, "Aerial Strike by msongyyy")
call DisplayTimedTextToPlayer(Player(0), 0, 0, 99999999, "Fireprism model by Mechanical Man & Crusad3r91")
call DisplayTimedTextToPlayer(Player(0), 0, 0, 99999999, "Marauder missile model by Fingolfin")
call DisplayTimedTextToPlayer(Player(0), 0, 0, 99999999, "Enjoy!!!!")
call DisplayTimedTextToPlayer(Player(0), 0, 0, 99999999, "Press ESC to heal fully")
call TriggerRegisterPlayerEvent(t, Player(0), EVENT_PLAYER_END_CINEMATIC)
call TriggerAddCondition(t, function sCond)
call TriggerRegisterAnyUnitEventBJ(t2, EVENT_PLAYER_UNIT_DEATH)
call TriggerAddCondition(t2, function rCond)
set t = null
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
//==============================================================================
// TT -- TIMER TICKER SYSTEM BY COHADAR -- v4.1
//==============================================================================
//
// PURPOUSE OF TT:
// * Passing data to timers
// * Avoiding direct use of timer handles
//
// PROS:
// * It is easier than using attaching
// * It is optimized to use only one timer on default high frequency
// * GetData method is the same for all timer frequencies
//
// CONS:
// * You must remember to always return true from your function
// when you want to stop timer, even if it is of one-shot type.
// (otherwise it will leak)
//
// START FUNCTIONS:
// * TT_Start(userFunc, struct)
// * TT_StartEx(userFunc, struct, period)
// * TT_Once(userFunc, struct, timeout)
// * TT_StartTimerDialog(userFunc, struct, timeout) -> timerdialog
//
// * userFunc is a user function that takes nothing and returns boolean
// it will be periodically called by the system until it returns true.
//
// GET FUNCTIONS:
// * TT_GetData() -> struct
// * TT_GetTimerDialog() -> timerdialog
//
// * These functions can only be called from inside userFunc
// TT_GetData() will return struct passed to any of the start functions
// TT_GetTimerDialog() returns timerdialog created by TT_StartTimerDialog
//
// DETAILS:
// * On default frequency all user functions are stored in an array.
// Timer will call all those functions each period.
//
// * While user function returns false timer will continue to call it each period
// Once user function returns true it will be removed from system
//
// * TT is using smart timer preloading and simple hash
// When colliding timer handle is found that timer is simply discarded
//
// REQUIREMENTS:
// * NewGen v4c and above (there might be some problems with older NewGen's)
//
// HOW TO IMPORT:
// * Just create a trigger named TT
// * convert it to text and replace the whole trigger text with this one
//
//==============================================================================
library TT initializer Init
//==============================================================================
// Configuration
//==============================================================================
globals
// List of recommended periods for high-frequency timer:
// 0.04 = 25 calls per second
// 0.03125 = 32 calls per second
// 0.025 = 40 calls per second
// 0.02 = 50 calls per second
public constant real PERIOD = 0.03125
// how many low-frequency timers to preload
// system can safely extend beyond this limit
private constant integer PRELOAD = 32
endglobals
//==============================================================================
// End of Configuration
//==============================================================================
//==============================================================================
globals
// "frames per second" of high-frequency timer
public constant integer FPS = R2I(1.0/PERIOD)
// globals for passing data to userFunc
private integer Data
private timerdialog timerDialog
// One Timer to rule them all, One Timer to find them,
// One Timer to call them all and in the jass bind them
// In the land of warcraft where the desyncs lie.
private timer HF_Timer = CreateTimer()
private integer HF_Counter = 0
private trigger array HF_Triggz
private integer array HF_Dataz
// we can safely use dummy hashing here because timers are preloaded
private constant integer LF_HASH = 8191
private integer array LF_Dataz
private trigger array LF_Triggz
private timer array LF_Timerz
private timerdialog array LF_Dialogz
// recycling
private integer array LF_Indexz
private integer LF_Counter = PRELOAD
endglobals
//==============================================================================
// note how colliding timer handles are discarded
// so TT would work properly even after preload limit break
//==============================================================================
private function NewIndex takes nothing returns integer
local integer i
local timer t
if (LF_Counter==0) then
loop
debug call BJDebugMsg("WARNING: TT reached preloaded timer limit!")
set t = CreateTimer()
set i = GetHandleId(t)
set i = i - (i / LF_HASH) * LF_HASH // dummy modulo hash
if LF_Timerz[i] == null then
set LF_Timerz[i] = t
set LF_Triggz[i] = CreateTrigger()
return i
endif
endloop
endif
set LF_Counter = LF_Counter - 1
return LF_Indexz[LF_Counter]
endfunction
//==============================================================================
private function HF_Handler takes nothing returns nothing
local trigger swap
local integer i = HF_Counter
loop
exitwhen i<=0
set Data = HF_Dataz[i]
if TriggerEvaluate(HF_Triggz[i]) then
set swap = HF_Triggz[i]
call TriggerClearConditions(swap)
set HF_Triggz[i] = HF_Triggz[HF_Counter]
set HF_Triggz[HF_Counter] = swap
set HF_Dataz[i] = HF_Dataz[HF_Counter]
set HF_Counter = HF_Counter - 1
endif
set i = i - 1
endloop
// who can guess why am I not nulling swap here?
endfunction
//==============================================================================
private function LF_Handler takes nothing returns nothing
local integer i = GetHandleId(GetExpiredTimer())
set i = i - (i / LF_HASH) * LF_HASH // dummy modulo hash
set Data = LF_Dataz[i]
if TriggerEvaluate(LF_Triggz[i]) then
// recycle the trigger and timer
call TriggerClearConditions(LF_Triggz[i])
call PauseTimer(LF_Timerz[i])
set LF_Indexz[LF_Counter] = i
set LF_Counter = LF_Counter + 1
endif
endfunction
//==============================================================================
// Periodic timer that runs on TT_PERIOD
//==============================================================================
public function Start takes code userFunc, integer data returns nothing
debug if userFunc == null then
debug call BJDebugMsg("ERROR: TT_Start - null userFunc")
debug return
debug endif
set HF_Counter = HF_Counter + 1
if HF_Triggz[HF_Counter] == null then
set HF_Triggz[HF_Counter] = CreateTrigger()
endif
set HF_Dataz[HF_Counter] = data
call TriggerAddCondition(HF_Triggz[HF_Counter], Condition(userFunc))
endfunction
//==============================================================================
// Periodic timer with custom period
//==============================================================================
public function StartEx takes code userFunc, integer data, real period returns nothing
local integer i
debug if userFunc == null then
debug call BJDebugMsg("ERROR: TT_StartEx - null userFunc")
debug return
debug endif
set i = NewIndex()
call TriggerAddCondition(LF_Triggz[i], Condition(userFunc))
set LF_Dataz[i] = data
call TimerStart(LF_Timerz[i], period, true, function LF_Handler)
endfunction
//==============================================================================
// One shot timer, remember to return true in userFunc
//==============================================================================
public function Once takes code userFunc, integer data, real timeout returns nothing
local integer i
debug if userFunc == null then
debug call BJDebugMsg("ERROR: TT_Once - null userFunc")
debug return
debug endif
set i = NewIndex()
call TriggerAddCondition(LF_Triggz[i], Condition(userFunc))
set LF_Dataz[i] = data
call TimerStart(LF_Timerz[i], timeout, false, function LF_Handler)
endfunction
//==============================================================================
public function StartTimerDialog takes code userFunc, integer data, real timeout returns timerdialog
local integer i
debug if userFunc == null then
debug call BJDebugMsg("ERROR: TT_StartTimerDialog - null userFunc")
debug return null
debug endif
set i = NewIndex()
call TriggerAddCondition(LF_Triggz[i], Condition(userFunc))
set LF_Dataz[i] = data
call TimerStart(LF_Timerz[i], timeout, false, function LF_Handler)
set bj_lastCreatedTimerDialog = CreateTimerDialog(LF_Timerz[i])
set LF_Dialogz[i] = bj_lastCreatedTimerDialog
return bj_lastCreatedTimerDialog
endfunction
//==============================================================================
// Call this function only inside the userFunc
//==============================================================================
public function GetData takes nothing returns integer
return Data
endfunction
//==============================================================================
// Call this function only inside the userFunc
//==============================================================================
public function GetTimerDialog takes nothing returns timerdialog
local integer i = GetHandleId(GetExpiredTimer())
set i = i - (i / LF_HASH) * LF_HASH // dummy modulo hash
return LF_Dialogz[i]
endfunction
//==============================================================================
// Preload LF timers and start HF timer.
//==============================================================================
private function Init takes nothing returns nothing
local integer i
local timer t
local integer j = 0
loop
exitwhen j>=PRELOAD
set t = CreateTimer()
set i = GetHandleId(t)
set i = i - (i / LF_HASH) * LF_HASH // dummy modulo hash
if LF_Timerz[i] == null then
set LF_Timerz[i] = t
set LF_Triggz[i] = CreateTrigger()
set LF_Indexz[j] = i
set j = j + 1
endif
endloop
call TimerStart(HF_Timer, PERIOD, true, function HF_Handler)
endfunction
endlibrary
//==============================================================================
// END OF TIMER TICKER SYSTEM
//==============================================================================