vJass: Yes.
MUI: Yes.
Laggless: Yes.
Leakless: Yes
Requires: NewGen Editor
Description: (Is copied from tooltip)
Screenshot:
Code:
MUI: Yes.
Laggless: Yes.
Leakless: Yes
Requires: NewGen Editor
Description: (Is copied from tooltip)
Summons a lightning ball that moves towards a target point enlarging and moves upwards.
When the ball reaches its target it crashes down and deals damage in an AoE
The damage increases the further from the caster the target is.
When the ball reaches its target it crashes down and deals damage in an AoE
The damage increases the further from the caster the target is.
JASS:
struct LightningBlastBall // Requires TimerUtils
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Implementing Instructions:
// 1: Create a trigger named LightningBlastBall and copy all this code into that trigger.
// 2: Import TimerUtils if you haven't them already imported into your map already.
// 3: Create the dummy unit and the ability
// 4: Set the SPELL_ID and DUMMY_ID to the ID's of your created dummy and ability.
// 5: Configure the spell the way you want it.
//
//
// WARNING: If you see that the handle amount goes up in the handle counter that is NOT because this spell leaks.
// It is because I do not remove the units, I kill them and then lets WC3 take care of them as they should be taken care of
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Configuration vars:
private static constant integer SPELL_ID = 039;A000039; //the ID of the spell.
private static constant integer DUMMY_ID = 039;h001039; // the dummys ID
private static constant real TIMER_PERIOD = 0.025 // How often the timer runs, increasing this will lower the speed of the balls.
private static constant real SPEED = 10 // The speed of the lightning ball.
private static constant real DAMAGE_INCREASE = 1.6 // This value is used to calculate the damage, the damage is calculated this way
// lvl*DAMAGE_INCREASE
private static constant real HEIGHT_INCREASE = 7 // How much the dummy's height increases per interval.
private static constant real DROP_SPEED_INCREASE = 7 // How much the drop speed increases per interval
private static constant real START_SCALING = 0.40 // The size of the unit when the spell starts
private static constant real SCALE_INCREASE = 0.03 // How much the units size increases every interval
private static constant real NOVA_RADIUS = 300 // The size of the nova that units gets damaged inside.
private static constant integer NOVA_DUMMY_AMOUNT = 20 // The amount of dummies used in the Nova.
private static constant real NOVA_SPEED = 15 // The speed of the units in the nova.
private static constant real DAMAGE_RADIUS = 30 // The radius around the nova units that get damaged.
private static constant real NOVA_DUMMY_SIZE = 8 // The size of the dummies used in the nova.
private static constant string SOUND_PATH = "Abilities\\Spells\\Human\\StormBolt\\ThunderBoltMissileDeath.wav"
// The sound you want this spell to use.
// The damage filter, Edit this to make it target the types of units you want to
private static constant method DamageFilter takes unit caster, unit target returns boolean
return (IsUnitEnemy(target, GetOwningPlayer(caster))) and (IsUnitType(target, UNIT_TYPE_GROUND)) and (GetUnitState(target, UNIT_STATE_LIFE) > 0.405)
endmethod
// The Damage amount this spell deas, edit this to configure the damage you want it to deal.
private static constant method DamageAmount takes integer lvl returns real
return lvl*.DAMAGE_INCREASE
endmethod
// Don't edit below this line if you don't know what you're doing.
private static boolexpr RETURN_TRUE
private static location globalLoc = Location(0,0)
private static LightningBlastBall array LBB
private real currX
private real currY
private real distdone = 0
private real totaldist
private real cos
private real sin
private real angle
private real currheight = 0
private real totaldrop
private unit whichUnit
private real currscale = .START_SCALING
private real dropspeed = .DROP_SPEED_INCREASE
private unit damager
private real currdamage = 0
private unit array novaUnits[.NOVA_DUMMY_AMOUNT]
private real array novasin[.NOVA_DUMMY_AMOUNT]
private real array novacos[.NOVA_DUMMY_AMOUNT]
private real array novaUnitsX[.NOVA_DUMMY_AMOUNT]
private real array novaUnitsY[.NOVA_DUMMY_AMOUNT]
private boolean novaStarted = false
private group damagedUnits
private timer t
private static method H2I takes handle h returns integer i
return h
return 0
endmethod
private static method create takes nothing returns LightningBlastBall
local LightningBlastBall LBBT = .allocate()
set LBBT.damagedUnits = CreateGroup()
return LBBT
endmethod
private method onDestroy takes nothing returns nothing
local integer i = 0
loop
exitwhen i >= .NOVA_DUMMY_AMOUNT
call ShowUnit(.novaUnits<i>, false)
call KillUnit(.novaUnits<i>)
set .novaUnits<i> = null
set i = i+1
endloop
call DestroyGroup(.damagedUnits)
set .damagedUnits = null
set .whichUnit = null
set .damager = null
call ReleaseTimer(.t)
endmethod
private static method Nova takes nothing returns nothing
local timer t = GetExpiredTimer()
local LightningBlastBall l = .LBB[.H2I(t)-0x100000]
local real totalAngle = 0
local real between
local integer i = 0
local real scale = (l.currscale/.NOVA_DUMMY_AMOUNT)*.NOVA_DUMMY_SIZE
local group unitsInRange = CreateGroup()
local unit u
if l.novaStarted == false then
set between = 360/.NOVA_DUMMY_AMOUNT
loop
exitwhen totalAngle >= 360
set l.novacos<i> = .NOVA_SPEED * Cos(bj_DEGTORAD * totalAngle)
set l.novasin<i> = .NOVA_SPEED * Sin(bj_DEGTORAD * totalAngle)
set l.novaUnits<i> = CreateUnit(GetOwningPlayer(l.damager), .DUMMY_ID, l.currX, l.currY, totalAngle)
set l.novaUnitsX<i> = GetUnitX(l.novaUnits<i>)
set l.novaUnitsY<i> = GetUnitY(l.novaUnits<i>)
call SetUnitScale(l.novaUnits<i>, scale,scale,scale)
set totalAngle = totalAngle+between
set i = i+1
endloop
set i = 1
set l.novaStarted = true
endif
if l.distdone >= .NOVA_RADIUS then
call l.destroy()
else
loop
exitwhen i >= .NOVA_DUMMY_AMOUNT
set l.novaUnitsX<i> = l.novaUnitsX<i> + l.novacos<i>
set l.novaUnitsY<i> = l.novaUnitsY<i> + l.novasin<i>
call SetUnitX(l.novaUnits<i>, l.novaUnitsX<i>)
call SetUnitY(l.novaUnits<i>, l.novaUnitsY<i>)
call GroupClear(unitsInRange)
call GroupEnumUnitsInRange(unitsInRange, l.novaUnitsX<i>, l.novaUnitsY<i>, .DAMAGE_RADIUS, .RETURN_TRUE)
loop
set u = FirstOfGroup(unitsInRange)
exitwhen u == null
if .DamageFilter(l.damager, u) == true and IsUnitInGroup(u, l.damagedUnits) == false then
call UnitDamageTarget(l.damager, u, l.currdamage , false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, null)
endif
call GroupRemoveUnit(unitsInRange, u)
call GroupAddUnit(l.damagedUnits, u)
set u = null
endloop
set i = i+1
endloop
set l.distdone = l.distdone + .NOVA_SPEED
endif
set unitsInRange = null
set u = null
set t = null
endmethod
private static method Drop takes nothing returns nothing
local timer t = GetExpiredTimer()
local sound s
local LightningBlastBall l = .LBB[.H2I(t)-0x100000]
if l.currheight >= l.totaldrop-.DROP_SPEED_INCREASE then
set l.distdone = 0
call PauseTimer(l.t)
call TimerStart(l.t, .TIMER_PERIOD, true, function LightningBlastBall.Nova)
call ShowUnit(l.whichUnit, false)
call KillUnit(l.whichUnit)
set s = CreateSound(.SOUND_PATH, false, true, true, 0,0,"a")
call SetSoundPosition(s, l.currX, l.currY, 0)
call SetSoundVolume(s, 110)
if (s != null) then
call StartSound(s)
endif
call KillSoundWhenDone(s)
else
call SetUnitFlyHeight(l.whichUnit, l.totaldrop-l.currheight, 0)
set l.currheight = l.currheight + l.dropspeed
set l.dropspeed = l.dropspeed + .DROP_SPEED_INCREASE
endif
set t = null
set s = null
endmethod
private static method TimerAct takes nothing returns nothing
local timer t = GetExpiredTimer()
local LightningBlastBall l = .LBB[.H2I(t)-0x100000]
if l.distdone >= l.totaldist then
set l.totaldrop = l.currheight
set l.currheight = 0
call PauseTimer(l.t)
call TimerStart(l.t, .TIMER_PERIOD, true, function LightningBlastBall.Drop)
else
set l.currX = l.currX + l.cos
set l.currY = l.currY + l.sin
call SetUnitX(l.whichUnit, l.currX)
call SetUnitY(l.whichUnit, l.currY)
call SetUnitFlyHeight(l.whichUnit, l.currheight, 0)
call SetUnitScale(l.whichUnit, l.currscale , l.currscale , l.currscale)
set l.currscale = l.currscale + .SCALE_INCREASE
set l.distdone = l.distdone + .SPEED
set l.currheight = l.currheight + .HEIGHT_INCREASE
set l.currdamage = l.currdamage + .DamageAmount(GetUnitAbilityLevel(l.damager, .SPELL_ID))
endif
set t = null
endmethod
private static method Actions takes nothing returns nothing
local real tarx
local real tary
local LightningBlastBall l = .create()
local unit caster = GetSpellAbilityUnit()
set l.t = NewTimer()
set l.damager = caster
set .globalLoc = GetSpellTargetLoc()
set tarx = GetLocationX(.globalLoc)
set tary = GetLocationY(.globalLoc)
set l.currX = GetUnitX(caster)
set l.currY = GetUnitY(caster)
set l.angle = Atan2((tary - l.currY), (tarx - l.currX))
set l.totaldist = SquareRoot((tarx-l.currX)*(tarx-l.currX) + (tary-l.currY)*(tary-l.currY))
set l.sin = .SPEED * Sin(l.angle)
set l.cos = .SPEED * Cos(l.angle)
set l.whichUnit = CreateUnit(GetOwningPlayer(caster), .DUMMY_ID, l.currX, l.currY, l.angle*bj_RADTODEG)
call SetUnitScale(l.whichUnit, .START_SCALING , .START_SCALING , .START_SCALING)
set .LBB[.H2I(l.t)-0x100000] = l
call TimerStart(l.t, .TIMER_PERIOD, true, function LightningBlastBall.TimerAct)
set caster = null
call RemoveLocation(.globalLoc)
set .globalLoc = null
endmethod
private static method Cond takes nothing returns boolean
return GetSpellAbilityId() == .SPELL_ID
endmethod
private static method BoolexprReturnTrue takes nothing returns boolean
return true
endmethod
private static method onInit takes nothing returns nothing
local trigger Trig = CreateTrigger()
local integer i = 0
set .RETURN_TRUE=Condition(function LightningBlastBall.BoolexprReturnTrue)
loop
call TriggerRegisterPlayerUnitEvent(Trig, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
set i = i+1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddCondition(Trig, Condition(function LightningBlastBall.Cond))
call TriggerAddAction(Trig, function LightningBlastBall.Actions)
endmethod
endstruct</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>