library ImpBomb
// Implosion Bomb Spell made by deathismyfriend
// Alloc by Nestharus can be found here. http://www.hiveworkshop.com/forums/jass-resources-412/snippet-alloc-alternative-221493/
// vJass version 1.2.0
globals
// These are the base values that u can set.
// Here u can set the Aoe base radius. Its a real variable. This does not increase per lvl
private constant real AOE_BASE = 400.00
// This is the damage Base of the spell.
private constant real DAM_BASE = 200.00
// This is the duration Base of the spell. This is important as it sets the intervals for the spell. Put it in seconds.
private constant integer DUR_BASE = 200
// These are the values that get added to the base per lvl that u can set.
// Here u can set the Aoe radius. Its a real variable. This increases per lvl So dont go to high
private constant real AOE_PER_LVL = 200.00
// This is the damage of the spell.
private constant real DAM_PER_LVL = 100.00
// This is the duration of the spell. This is important as it sets the intervals for the spell. Put it in seconds.
private constant integer DUR_PER_LVL = 100
// These are the other values that u can change
// This is the VELOCITY the unit moves at. Towards the Implosion
private constant real VELOCITY = 2.00
// Set the dummy unit type here.
private constant integer DUMMY_UNIT = 'h000'
// This is the explosion effect that gets played.when units get damaged.
private constant string DAMAGE_EFF = "Abilities\\Spells\\Human\\MarkOfChaos\\MarkOfChaosTarget.mdl"
// Here is were you can set the effect that gets attached to the Dummy Unit.
private constant string DUMMY_EFF = "Abilities\\Spells\\Orc\\Voodoo\\VoodooAura.mdl" //caster
// Here is were you set the attachment point for the dummy unit.
private constant string ATTACH_POINT_DUMMY = "origin"
// Here is were you can set the effect that gets attached to the Units that get damaged.
private constant string UNIT_EFF = "Abilities\\Spells\\Orc\\Purge\\PurgeBuffTarget.mdl"
// Here is were you set the attachment point for the effect that gets attached to the units that get damaged.
private constant string ATTACH_POINT_UNIT = "origin"
// Here is the ability id
private constant integer SPELL_ID = 'A000'
// Here is the attack type
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_CHAOS
// Here is the damage type
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL
// dont change anything below here.
private integer array structIndex
private timer tmr
private integer maxIndex = 0
private group grp
endglobals
private struct impBombSpell extends array
implement Alloc
private real aoeTotal
private unit caster
private real casterX
private real casterY
private real decScale
private real damToDeal
private unit dummy
private integer durCounter
private integer durInt1
private integer durInt2
private effect eff
private real propWindow
private real scale
private unit target
private real distanceMX
private real distanceMY
private real targetMX
private real targetMY
private real targetSX
private real targetSY
static method distBetweenXY takes real x1, real y1, real x2, real y2 returns real
local real x = x2 - x1
local real y = y2 - y1
return SquareRoot(x*x + y*y)
endmethod
private static method getAngleBetweenXY takes real x1, real y1, real x2, real y2 returns real
return Atan2( y1 - y2, x1 - x2)
endmethod
private static method polarProjectionX takes real x, real dist, real angle returns real // returns x
return x + dist * Cos( angle)
endmethod
private static method polarProjectionY takes real y, real dist, real angle returns real // returns y
return y + dist * Sin( angle)
endmethod
private method changeScale takes nothing returns nothing
set this.scale = this.scale - this.decScale
call SetUnitScale( this.target, this.scale, this.scale, this.scale)
endmethod
private method movingUnits takes real vel returns nothing
set this.targetMX = this.targetMX - this.distanceMX
set this.targetMY = this.targetMY - this.distanceMY
call SetUnitX( this.target, this.targetMX)
call SetUnitY( this.target, this.targetMY)
endmethod
private method destroy takes nothing returns nothing // de-index
call SetUnitPropWindow( this.target, this.propWindow)
set this.caster = null
set this.target = null
set this.dummy = null
call DestroyEffect( this.eff)
set this.eff = null
set maxIndex = maxIndex - 1
call this.deallocate()
endmethod
private static method timerActions takes nothing returns nothing
local thistype this
local integer L = 1
local real x
local real y
local real d
local real v = VELOCITY/2
loop
exitwhen L > maxIndex
set this = structIndex[ L]
set this.durCounter = this.durCounter + 1
if this.target == null then
if this.durCounter == this.durInt1 - 32 then // sets the variables for second stage on. damage units here
call DestroyEffect( AddSpecialEffectTarget( DAMAGE_EFF, this.dummy, ATTACH_POINT_DUMMY))
elseif this.durCounter >= this.durInt2 + 1 then // de-index the caster here.
call SetUnitPropWindow( this.caster,this.propWindow)
call RemoveUnit( this.dummy)
set structIndex[ L] = structIndex[ maxIndex]
call this.destroy()
set L = L - 1
endif
elseif this.durCounter < this.durInt1 then // first faze. pull units into implosion
if distBetweenXY( this.casterX, this.casterY, this.targetMX, this.targetMY) >= v then
call this.movingUnits( v)
endif
call this.changeScale()
elseif this.durCounter == this.durInt1 then // sets the variables for second stage on. damage units here
set d = distBetweenXY( this.casterX, this.casterY, this.targetMX, this.targetMY)
if d >= v then
call this.movingUnits( v)
endif
call this.changeScale()
set d = this.aoeTotal - d
call UnitDamageTarget( this.caster, this.target, ( d/this.aoeTotal)*this.damToDeal, false, false, ATTACK_TYPE, DAMAGE_TYPE, null)
set this.eff = AddSpecialEffectTarget( UNIT_EFF, this.target, ATTACH_POINT_UNIT)
set this.distanceMX = this.distanceMX * -2
set this.distanceMY = this.distanceMY * -2
set this.decScale = -1.00/I2R( this.durInt2 - this.durInt1)
if IsUnitType( this.target, UNIT_TYPE_DEAD) or GetUnitTypeId( this.target) == 0 then
set structIndex[ L] = structIndex[ maxIndex]
call this.destroy()
set L = L - 1
endif
elseif this.durCounter < this.durInt2 then // final faze. moving units to there original position
if distBetweenXY( this.targetMX, this.targetMY, this.targetSX, this.targetSY) >= v then
call this.movingUnits( VELOCITY)
elseif this.targetMX != this.targetSX and this.targetMY != this.targetSY then
call SetUnitX( this.target, this.targetSX)
call SetUnitY( this.target, this.targetSY)
endif
call this.changeScale()
elseif this.durCounter >= this.durInt2 then // de-index here
call this.changeScale()
set structIndex[ L] = structIndex[ maxIndex]
call this.destroy()
set L = L - 1
endif
set L = L + 1
endloop
if maxIndex <= 0 then
call PauseTimer( tmr)
endif
endmethod
private static method create takes unit c, real x, real y, integer i, integer i2, real dam, real r returns thistype
local thistype this = thistype.allocate()
set this.caster = c
set this.casterX = x
set this.casterY = y
set this.durCounter = 0
set this.durInt1 = i2 // first effect stage
set this.durInt2 = i // second effect stage
set this.damToDeal = dam
set this.aoeTotal = r
set maxIndex = maxIndex + 1
return this
endmethod
private static method setup takes nothing returns nothing
local thistype this
local thistype data
local unit c = GetTriggerUnit()
local unit u
local unit dum
local integer abiLvl = GetUnitAbilityLevel( c, SPELL_ID)
local real r = AOE_BASE + ( AOE_PER_LVL*I2R( abiLvl))
local real x = GetUnitX( c)
local real y = GetUnitY( c)
local integer i = ( DUR_BASE + ( DUR_PER_LVL*abiLvl))
local integer i2 = R2I( I2R( i)*0.75)
local real dam = DAM_BASE + ( DAM_PER_LVL*abiLvl)
local real angle
local real v = VELOCITY/2
set this = thistype.create( c, x, y, i, i2, dam, r)
set this.target = null
set this.propWindow = GetUnitPropWindow( this.caster)
set this.dummy = CreateUnit( GetOwningPlayer( c), DUMMY_UNIT, x, y, 0)
call SetUnitPropWindow( this.dummy, 0.00)
call SetUnitX( this.dummy, x)
call SetUnitY( this.dummy, y)
set this.eff = AddSpecialEffectTarget( DUMMY_EFF, this.dummy, ATTACH_POINT_DUMMY)
set dum = this.dummy
set structIndex[ maxIndex] = this
if maxIndex == 1 then
call TimerStart( tmr, 0.031250000, true, function thistype.timerActions)
endif
call GroupEnumUnitsInRange( grp, x, y, r, null)
loop
set u = FirstOfGroup( grp)
exitwhen u == null
if u != c and u != UNIT_TYPE_STRUCTURE and not IsUnitType( u, UNIT_TYPE_DEAD) and u != dum then
set this = thistype.create( c, x, y, i, i2, dam, r)
set this.target = u
set this.targetSX = GetUnitX( this.target)
set this.targetSY = GetUnitY( this.target)
set this.targetMX = this.targetSX
set this.targetMY = this.targetSY
set this.propWindow = GetUnitPropWindow( this.target)
call SetUnitPropWindow( this.target, 0.00)
set this.scale = 1.00
set this.decScale = 1.00/i2
set angle = getAngleBetweenXY( x, y, this.targetSX, this.targetSY)
set this.distanceMX = this.targetSX - polarProjectionX( this.targetMX, v, angle)
set this.distanceMY = this.targetSY - polarProjectionY( this.targetMY, v, angle)
set structIndex[ maxIndex] = this
endif
call GroupRemoveUnit( grp, u)
endloop
set c = null
set dum = null
endmethod
private static method conditions takes nothing returns boolean
if GetSpellAbilityId() == SPELL_ID then
call setup()
endif
return false
endmethod
//===========================================================================
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
set tmr = CreateTimer()
set grp = CreateGroup()
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition( t, Condition( function thistype.conditions))
set t = null
endmethod
endstruct
endlibrary