library FireVortex /* v1.6
*************************************************************************************
*
* by mckill2009
*
*************************************************************************************
*
* */ uses /*
*
* */ Table /* www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084
* */ CTL /* www.hiveworkshop.com/forums/jass-resources-412/snippet-constant-timer-loop-32-a-201381/index7.html#post2389697
*
*************************************************************************************
*
* Installation:
* - Import/copy the required libraries and FireVortex code to your map
* - Import/copy the custom ability and unit to your map and change the SPELL_ID and FIRE_ID if needed
* - You may view the raw ID of the objects by pressing CTRL+D in the object editor
* - You may play with the configurables below
*
*************************************************************************************/
globals
/********************************************************
* Configurables: default and recommended settings
*********************************************************/
//change raw id if needed
private constant integer SPELL_ID = 'A000'
//change raw id if needed
private constant integer FIRE_ID = 'h000'
//uses default lava spawn level 2, this is totally optional
private constant integer ELEMENTAL_ID = 'nlv2'
//the effect when fire lands the ground
private constant string EXPLODE_SFX = "Objects\\Spawnmodels\\Undead\\UDeathSmall\\UDeathSmall.mdl"
//the damage aoe when fire lands the ground
private constant real EXPLODE_AOE_DAMAGE = 150.
//the damage aoe when fire is spinning
private constant real TOUCH_AOE_DAMAGE = 80.
//max fly height
private constant real FLY_HEIGHT = 500.
//the fly or up speed
private constant real FLY_SPEED = 15.
//the impact to the ground speed, this is added to the impactDamage
private constant real DROP_SPEED = 30.
//how fast the fire be created
private constant real CREATION_DELAY = 0.5
//the higher the number, the faster
private constant real SPIN_SPEED = 0.07 //in radians
//allows the creation of a unit, see ELEMENTAL_ID
private constant boolean ENABLE_ELEMENTAL_CREATION = true
//set to false for elemental to live until dies
//ENABLE_ELEMENTAL_CREATION should be true also
private constant boolean ELEMENTAL_HAS_TIMER = true
private attacktype ATK = ATTACK_TYPE_MAGIC
private damagetype DMG = DAMAGE_TYPE_MAGIC
/********************************************************
* Non-configurables
********************************************************/
private real CreationGap
private Table sp
private group TempG = CreateGroup()
endglobals
/********************************************************
* Configurables
*********************************************************/
private function GetDamage takes integer level returns real
return (10 * level + 20.)
endfunction
private function GetFireCount takes integer level returns integer
return 2 * level + 2
endfunction
private function GetElementalTimer takes integer level returns real
return 15.
endfunction
/********************************************************
* End of configurables
*********************************************************/
private function UnitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD)
endfunction
struct FireSpin extends array
unit fire
real angle
real damage
real impactDamage
real duration
real dist
real height
real elementalLife
real x
real y
boolean direction
boolean fly
group g
implement CTL
local unit first
local real xFire
local real yFire
implement CTLExpire
if .fire==null then
call .destroy()
else
set xFire = GetUnitX(.fire)
set yFire = GetUnitY(.fire)
if .duration > 0 then
set .duration = .duration - 0.03125
if .direction then
set .angle = .angle + SPIN_SPEED
else
set .angle = .angle - SPIN_SPEED
endif
call SetUnitX(.fire, .x+.dist*Cos(.angle))
call SetUnitY(.fire, .y+.dist*Sin(.angle))
call GroupEnumUnitsInRange(TempG, xFire, yFire, TOUCH_AOE_DAMAGE, null)
loop
set first = FirstOfGroup(TempG)
exitwhen first==null
if UnitAlive(first) and IsUnitEnemy(first, GetOwningPlayer(.fire)) then
call UnitDamageTarget(.fire, first, .damage, false, false, ATK, DMG, null)
endif
call GroupRemoveUnit(TempG, first)
endloop
else
if .fly then
set .height = .height + FLY_SPEED
if .height > FLY_HEIGHT then
set .fly = false
endif
else
set .height = .height - DROP_SPEED
endif
call SetUnitFlyHeight(.fire, .height, 0)
if 0 > .height then
call DestroyEffect(AddSpecialEffect(EXPLODE_SFX, xFire, yFire))
call GroupEnumUnitsInRange(TempG, xFire, yFire, EXPLODE_AOE_DAMAGE, null)
loop
set first = FirstOfGroup(TempG)
exitwhen first==null
if UnitAlive(first) and IsUnitEnemy(first, GetOwningPlayer(.fire)) then
call UnitDamageTarget(.fire, first, .impactDamage, false, false, ATK, DMG, null)
endif
call GroupRemoveUnit(TempG, first)
endloop
static if ENABLE_ELEMENTAL_CREATION then
set first = CreateUnit(GetOwningPlayer(.fire), ELEMENTAL_ID, xFire, yFire, 0)
call UnitAddType(first, UNIT_TYPE_SUMMONED)
static if ELEMENTAL_HAS_TIMER then
call UnitApplyTimedLife(first, 'BTLF', .elementalLife)
endif
set first = null
endif
call KillUnit(.fire)
set .fire = null
endif
endif
endif
implement CTLEnd
static method spin takes unit f, real damage, real x, real y, real el returns nothing
local thistype this = create()
local integer id = GetHandleId(f)
set .fire = f
set .direction = false
if sp.boolean[id] then
set .direction = true
endif
set .duration = GetRandomReal(7, 12)
set .elementalLife = el
set .fly = true
set .height = GetUnitFlyHeight(f)
set .x = x
set .y = y
set .angle = Atan2(GetUnitY(f)-y, GetUnitX(f)-x)
set .dist = SquareRoot((GetUnitX(f)-x)*(GetUnitX(f)-x)+(GetUnitY(f)-y)*(GetUnitY(f)-y))
set .impactDamage = (damage*2)+(DROP_SPEED*2)
set .damage = damage*0.3125
call UnitAddAbility(f, 'Arav')
endmethod
endstruct
private struct FireVortexCast extends array
player p
real a
real damage
real elementalLife
real delay
real down
real up
real x
real y
integer count
integer index
boolean check
boolean directionUp
boolean directionDown
group g
static thistype DATA
private static method startSpinning takes nothing returns nothing
local thistype this = DATA
call FireSpin.spin(GetEnumUnit(), this.damage, this.x, this.y, this.elementalLife)
endmethod
implement CTL
local unit fire
local integer id
implement CTLExpire
if .count > .index then
set .delay = .delay + 0.03125
if .delay > CREATION_DELAY then
set .delay = 0
set .index = .index + 1
if .check then
set .check = false
set fire = CreateUnit(.p, FIRE_ID, .x+.up*Cos(.a), .y+.up*Sin(.a), 0)
set .up = .up - CreationGap
set id = GetHandleId(fire)
if .directionUp then
set .directionUp = false
set sp.boolean[id] = true
else
set .directionUp = true
endif
else
set .check = true
set fire = CreateUnit(.p, FIRE_ID, .x+.down*Cos(.a), .y+.down*Sin(.a), 0)
set .down = .down + CreationGap
set id = GetHandleId(fire)
if .directionDown then
set .directionDown = false
set sp.boolean[id] = true
else
set .directionDown = true
endif
endif
set sp.real[id] = .a
call GroupAddUnit(.g, fire)
set fire = null
endif
else
set DATA = this
call ForGroup(.g, function thistype.startSpinning)
call DestroyGroup(.g)
set .p = null
set .g = null
call .destroy()
endif
implement CTLEnd
static method run takes unit u, real x, real y returns nothing
local thistype this = create()
local integer level = GetUnitAbilityLevel(u, SPELL_ID)
set .p = GetTriggerPlayer()
set .a = Atan2(GetUnitY(u)-y, GetUnitX(u)-x)
set .damage = GetDamage(level)
set .elementalLife = GetElementalTimer(level)
set .delay = 0
set .down = CreationGap
set .up = -CreationGap
set .x = x
set .y = y
set .count = GetFireCount(level)
set .index = 0
set .check = true
set .directionUp = true
set .directionDown = true
set .g = CreateGroup()
endmethod
static method cast takes nothing returns boolean
if GetSpellAbilityId()==SPELL_ID then
call thistype.run(GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY())
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.cast))
set t = null
set CreationGap = TOUCH_AOE_DAMAGE + 20.
set sp = Table.create()
endmethod
endstruct
endlibrary