Tom Jones
N/A
- Reaction score
- 437
Dark Lightning Array.
MUI: Yep.
Leaks: Not that I'm aware off.
Code: vJass.
JASS:
//#######################################################################################################
//#Dark Lightning Array - By Tom Jones.
//#######################################################################################################
//#Requirements:
//#1) vJass.
//#2) Alternatively SAS.
//#
//#Implementation:
//#1) Copy/paste this trigger from this map to your map.
//#2) Copy/paste the SAS trigger from this map to your map. Alternatively you could change the calls to
//# SAS with your prefered struct passing system and copy/paste the Struct Stack section of SAS into
//# this trigger's spell code section or use the independent version of the spell.
//#3) Copy/paste object editor stuff from this map to your map. Alternatively you could
//# create new abilities, units or buffs, or you use existing ones.
//#4) Modifiy the variables in the Setup section below. Variables expecting raw codes is important, so
//# make sure the values match those from you map. You can view your map's raw data by pressing ctrl+d
//# in the object editor.
//#
//#Notes:
//# Thanks to Tinki3 for his Map Template.
//#######################################################################################################
scope LaserArray initializer Init
//#######################################################################################################
//#Setup.
//#######################################################################################################
globals
private integer SPELL_ID = 039;A000039; //Rawdata of the main spell.
private real AOE = 200. //This should match the main spell's aoe in the object editor.
private string AOE_ART = "Abilities\\Spells\\Human\\FlameStrike\\FlameStrikeEmbers.mdl"
private string TARGET_ART = "Abilities\\Spells\\Demon\\DemonBoltImpact\\DemonBoltImpact.mdl"
private string LIGHTNING_ART = "AFOD" //Desired lightning
private real LIGHTNING_SPEED = 250.
private real LIGHTNING_INTERVAL = 0.75 //Time bewteen creation of lightning.
private real LIGHTNING_LIFE = 2.5 //Duration of each lightning.
private real CHANCE_FOR_HOMING = 0.15 //Chance that a lightning will focus a unit.
private real DAMAGE = 40.
private real DAMAGE_SUSPENSION = 0.75 //Time between a unit is able to take damage.
private real STRUCTURE_FACTOR = 2.0 //Structure damage multiplier
private real MECHANICAL_FACTOR = 2.0 //Mechanical damage multiplier.
endglobals
//##############################
//#Spell level data controllers.
//##############################
private function Damage takes integer lvl returns real
return DAMAGE+(lvl*20.)
endfunction
private function Damage_Suspension takes integer lvl returns real
return DAMAGE_SUSPENSION-(lvl*0.05)
endfunction
private function AoE takes integer lvl returns real
return AOE
endfunction
private function Lightning_Interval takes integer lvl returns real
return LIGHTNING_INTERVAL
endfunction
private function Lightning_Life takes integer lvl returns real
return LIGHTNING_LIFE
endfunction
private function Chance_For_Homing takes integer lvl returns real
return CHANCE_FOR_HOMING+(lvl*0.02)
endfunction
//#######################################################################################################
//#Spell code - Do not modify below here unless you know what you're doing!
//#######################################################################################################
//! runtextmacro SAS_Instance()
globals
private timer array T
private integer INDEX = 0
private real INTERVAL = 0.01
private group G = CreateGroup()
private boolexpr FILTER
private integer FILTER_STRUCT
endglobals
private struct victim extends stackobject
unit u
real suspension
endstruct
private struct laser extends stackobject
lightning light
real life
real alpha
real angle
real x
real y
real z
victim v
endstruct
private struct data
unit u
player p
integer lvl
real tick
real x
real y
stack lasers
stack victims
boolean end
timer t
static method Filter takes nothing returns boolean
local data this = FILTER_STRUCT
if IsUnitAlly(GetFilterUnit(),.p) == true then
return false
elseif IsUnitType(GetFilterUnit(),UNIT_TYPE_DEAD) == true then
return false
endif
return true
endmethod
static method KillTrees takes nothing returns nothing
call KillDestructable(GetEnumDestructable())
endmethod
static method onTick takes nothing returns nothing
local data this = GetFrom(GetExpiredTimer())
local sound s = null
local real r = Lightning_Interval(.lvl)
local real xx = 0
local real yy = 0
local rect area = Rect(-100,-100,100,100)
local laser l = 0
local victim v = 0
if .end == false then
set .tick = .tick+INTERVAL
set r = .tick-I2R(R2I(.tick/r))*r
elseif .lasers.first == 0 then
call PauseTimer(.t)
set T[INDEX] = .t
set INDEX = INDEX+1
call .lasers.destroy()
call .victims.destroy()
call .destroy()
return
endif
if r <= 0.01 then
set l = .lasers.add()
set l.x = .x+GetRandomReal(0,AoE(.lvl))
set l.y = .y+GetRandomReal(0,AoE(.lvl))
set l.z = 1400
set l.angle = GetRandomReal(0,6.28)
set l.alpha = 1.
set l.life = Lightning_Life(.lvl)
set l.light = AddLightningEx(LIGHTNING_ART,false,l.x,l.y,l.z,.x,.y,1400)
set s = CreateSound("Abilities\\Spells\\Other\\Monsoon\\MonsoonLightningHit.wav",false,true,true,17400,17400,"SpellsEAX")
call SetSoundDuration(s,2415)
call AttachSoundToUnit(s,.u)
call StartSound(s)
call KillSoundWhenDone(s)
set s = null
endif
set l = .lasers.first
loop
exitwhen l == 0
if l.z <= 0 then
set l.life = l.life-INTERVAL
if l.life <= 0. then
call DestroyLightning(l.light)
call .lasers.remove(l)
call l.destroy()
else
set xx = l.x-.x
set yy = l.y-.y
set r = SquareRoot(xx*xx+yy*yy)
if r >= AoE(.lvl) then
set l.angle = l.angle-3.14
if l.v != 0 then
set l.v = 0
set l.z = 0
endif
endif
if l.v == 0 then
set r = LIGHTNING_SPEED*INTERVAL
set l.x = l.x+r*Cos(l.angle)
set l.y = l.y+r*Sin(l.angle)
else
set l.x = GetUnitX(l.v.u)
set l.y = GetUnitY(l.v.u)
endif
call MoveLightningEx(l.light,true,l.x,l.y,l.z,.x,.y,1400)
set r = l.life-I2R(R2I(l.life/0.15))*0.15
if r <= 0.01 then
call DestroyEffect(AddSpecialEffect(AOE_ART,l.x,l.y))
endif
if l.life <= 1 then
set l.alpha = l.alpha-INTERVAL
call SetLightningColor(l.light,1,1,1,l.alpha)
endif
loop
if l.v == 0 then
if v == 0 then
call MoveRectTo(area,l.x,l.y)
set FILTER_STRUCT = this
call GroupEnumUnitsInRect(G,area,FILTER)
endif
set victim(0).u = FirstOfGroup(G)
exitwhen victim(0).u == null
set v = .victims.first
loop
exitwhen v == 0 or v.u == victim(0).u
set v = v.next
endloop
if v == 0 then
set v = .victims.add()
set v.u = victim(0).u
set v.suspension = 0
endif
if GetRandomReal(0,1) <= Chance_For_Homing(.lvl) then
set l.v = v
set l.z = 40
endif
call GroupRemoveUnit(G,victim(0).u)
else
exitwhen v == l.v
set v = l.v
endif
if v.suspension <= 0 then
set r = Damage(.lvl)
if IsUnitType(v.u,UNIT_TYPE_STRUCTURE) == true then
set r = r*STRUCTURE_FACTOR
elseif IsUnitType(v.u,UNIT_TYPE_MECHANICAL) == true then
set r = r*MECHANICAL_FACTOR
endif
if l.life <= 0.25 then
set r = r*0.25
elseif l.life <= 0.5 then
set r = r*0.5
elseif l.life <= 1 then
set r = r*0.75
endif
if r >= GetUnitState(v.u,UNIT_STATE_LIFE) then
call SetUnitExploded(v.u,true)
endif
call DestroyEffect(AddSpecialEffectTarget(TARGET_ART,v.u,"origin"))
call UnitDamageTargetBJ(.u,v.u,r,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_NORMAL)
set v.suspension = Damage_Suspension(.lvl)
endif
endloop
call EnumDestructablesInRect(area,null,function data.KillTrees)
endif
else
set l.z = l.z-(1400*INTERVAL*10)
call MoveLightningEx(l.light,true,l.x,l.y,l.z,.x,.y,1400)
endif
set l = l.next
endloop
if area != null then
call RemoveRect(area)
set area = null
endif
set v = .victims.first
loop
exitwhen v == 0
if IsUnitType(v.u,UNIT_TYPE_DEAD) == true then
set l = .lasers.first
loop
exitwhen l == 0
if l.v == v then
set l.v = 0
set l.z = 0
endif
set l = l.next
endloop
call .victims.remove(v)
call v.destroy()
else
if v.suspension > 0 then
set v.suspension = v.suspension-INTERVAL
endif
endif
set v = v.next
endloop
endmethod
static method onCast_Conditions takes nothing returns boolean
return GetSpellAbilityId() == SPELL_ID
endmethod
static method onCast takes nothing returns nothing
local data this
local location loc
if GetTriggerEventId() == EVENT_PLAYER_UNIT_SPELL_EFFECT then
set this = data.allocate()
set loc = GetSpellTargetLoc()
set .u = GetTriggerUnit()
call AttachTo(.u,this)
set .p = GetTriggerPlayer()
set .lvl = GetUnitAbilityLevel(.u,SPELL_ID)-1
set .end = false
set .tick = Lightning_Interval(.lvl)
set .x = GetLocationX(loc)
set .y = GetLocationY(loc)
set .lasers = stack.create(laser.typeid)
set .victims = stack.create(victim.typeid)
if INDEX == 0 then
set T[0] = CreateTimer()
else
set INDEX = INDEX-1
endif
set .t = T[INDEX]
call AttachTo(.t,this)
call TimerStart(.t,INTERVAL,true,function data.onTick)
call RemoveLocation(loc)
set loc = null
else
set this = GetFrom(GetTriggerUnit())
set .end = true
endif
endmethod
endstruct
//#######################################################################################################
//#Initialization.
//#######################################################################################################
private function Init takes nothing returns nothing
local trigger trig = CreateTrigger()
local unit u = CreateUnit(Player(15),039;hfoo039;,0,0,0)
call UnitAddAbility(u,SPELL_ID)
call Preload(TARGET_ART)
call Preload(AOE_ART)
set FILTER = Condition(function data.Filter)
call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_SPELL_ENDCAST)
call TriggerAddCondition(trig,Condition(function data.onCast_Conditions))
call TriggerAddAction(trig,function data.onCast)
call RemoveUnit(u)
set u = null
set trig = null
endfunction
endscope
Description:
Lightning strikes from the sky, damaging unfortunate enemy units who gets near it.
Units struck by lightning will have a short period of time where they can't get struck by the same lightning again.
The lightning strikes have a chance to target a single unit.
Level 1 - 20 damage, 0.75 suspension time, 15% chance of targeting a single unit.
Level 2 - 40 damage, 0.70 suspension time, 17% chance of targeting a single unit.
Level 3 - 60 damage, 0.65 suspension time, 19% chance of targeting a single unit.
Screenie:
Notes:
Thanks to Tinki3 for his map template.
Also included in the map is a independent version of the spell.
If you find any bugs or leaks, please do report them, I don't mind being corrected