```
scope HoD
//==========================================================================\\
//============================ Hammer of Dawn ==============================\\
//============================ Documentation ===============================\\
//==========================================================================\\
// * Concept: You call the Satalite for help. The satalite shoots a \\
// lightning to the Earth, pulling more lightnings to it, \\
// which all leave a trail of electricity behind, damaging \\
// units in range. \\
// \\
// * Execution: This is my very first vJass spell. I have had quite some \\
// problems with the execution. Those problems all seemed \\
// to be rather newbish. That is why i want to thank one \\
// person in special. \\
// xxdingo93xx \\
// He has not only helped me with the code, but with vJass \\
// in General. Thanks and credit to him! \\
// \\
// * Credits: - xxdingo93xx = For helping and teaching me \\
// - My friends = For playing way too much Gears of War \\
// with me, which brought me to this idea \\
// \\
// * Import: How to import this in your map: \\
// IMPORTANT NOTICE: You need JNGP to import this!!!! \\
// Also known as: Jass New Gen Pack \\
// - First of all, make sure you have TimerUtils in your map \\
// I used the Blue flavor, because I was told it is best \\
// for spells. To do this, make a custom script trigger by \\
// clicking 'Edit > Convert to Custom Text' and paste the \\
// TimerUtils library in it \\
// - Secondly, make a trigger in your map, and convert it to \\
// custom text by: 'Edit > Convert to Custom Text' this will \\
// show a message, but just click ok. Paste the code of this \\
// map in that trigger, which means from: \\
// 'scope HoD initializer Init' until 'endscope' \\
// that is all =) \\
// \\
// * Editing: This spell is made to be able to be edited as easy as \\
// possible. I will tell you the parts that are to be edited \\
// and i have also highlighted them in the script. \\
// Parts to be edited: \\
// - The first globals block. This block is full of editable \\
// variables. All are explained in the next block. \\
// - The five functions under the first globals block. They \\
// are named: DamageF,RadiusF,AmountF,TimeF and DistanceF \\
// They calculate the Damage, Damage Radius, Lightning \\
// Amount, Time of the spell, and Starting Distance of the \\
// lightnings. Change them as suits to you and your map. \\
// NOTE: the variable 'LightningString' is to choose the \\
// lightning type, which are as follows: \\
// LSA[1] = "CLPB" // Chain Lightning Primary \\
// LSA[2] = "CLSB" // Chain Lightning Secondary \\
// LSA[3] = "DRAB" // Drain \\
// LSA[4] = "DRAL" // Drain Life \\
// LSA[5] = "DRAM" // Drain Mana \\
// LSA[6] = "AFOD" // Finger of Death \\
// LSA[7] = "FORK" // Forked Lightning \\
// LSA[8] = "HWPB" // Healing Wave Primary \\
// LSA[9] = "HWSB" // Healing Wave Secondary \\
// LSA[10] = "CHIM" // Lightning Attack \\
// LSA[11] = "LEAS" // Magic Leash \\
// LSA[12] = "MBUR" // Mana Burn \\
// LSA[13] = "MFPB" // Mana Flare \\
// LSA[14] = "SPLK" // Spirit Link \\
// NOTE: The special effects used in this spell are chosen \\
// to fit with lightning type '1'. The effects are \\
// declared in the first globals block, also to be \\
// easily edited. \\
// \\
// * Variables: - AID: The rawcode of the ability \\
// - INT: The interval of the Timers \\
// - DeltaZ: The height difference between source and point \\
// of the Lightnings \\
// - DeltaDist: The distance difference between source and \\
// point of the Lightnings \\
// - LightningString: The array of the string variable \\
// - MaxLights: This must be calculated as follows: \\
// with the function 'AmountF', use as parameter \\
// the maximum levels of the spell, by default 3 \\
// - SFX1: The effect string on ground under the lightnings \\
// - SFX2: The effect string when the spell stops \\
// \\
// * Functions: - DamageF: Calculates the Damage done every interval. \\
// - RadiusF: Calculates the Radius of the damage done \\
// - AmountF: Calculates the amount of lightnings made \\
// - TimeF: Calculates the time to fuse the lightnings \\
// - DistanceF: Calculates the main distance of the lightnings \\
// - LoadTimeF: Calculates time to spawn the lightnings \\
// \\
//==========================================================================\\
//============================ End Documentation ===========================\\
//==========================================================================\\
//==========================================================================\\
//================================== Setup =================================\\
//==========================================================================\\
globals
private constant integer AID = 'A000'
private constant integer LightningString = 1
private constant integer MaxLights = 5
private constant real INT = 0.035
private constant real DeltaZ = 1000
private constant real DeltaDist = 50
private constant string SFX1 = "Objects\\Spawnmodels\\NightElf\\NEDeathMedium\\NEDeath.mdl"
private constant string SFX2 = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
private constant string SFX3 = "Abilities\\Spells\\NightElf\\TrueshotAura\\TrueshotAura.mdl"
endglobals
//==========================================================================\\
private constant function DamageF takes integer level returns real
return 0.4 * level + 0.3
endfunction
//==========================================================================\\
private constant function RadiusF takes integer level returns real
return 10. * level + 50.
endfunction
//==========================================================================\\
private constant function AmountF takes integer level returns integer
return 2 + 1 * level
endfunction
//==========================================================================\\
private constant function TimeF takes integer level returns real
return 2.5 + 1.25 * level
endfunction
//==========================================================================\\
private constant function DistanceF takes integer level returns real
return 150. + 50. * level
endfunction
//==========================================================================\\
private function LoadTimeF takes integer level returns real
return 7.00 - 1.48 * SquareRoot(level)
endfunction
//==========================================================================\\
private function DropTimeF takes integer level returns real
return 1.3 - ((Pow(level/1.5,1.5))/level*2.)
endfunction
//==========================================================================\\
//================================ End Setup ===============================\\
//========= Do NOT edit below unless you know what you are doing! ==========\\
//==========================================================================\\
globals
private constant integer MaxArray = MaxLights - 1
private location TempLoc = Location(0,0)
private group g = CreateGroup()
private unit TempCaster
private string DLS
private string array LSA
private boolexpr AbilityFilter = null
private boolexpr GroupFilter = null
endglobals
//==========================================================================\\
private function GetTerrainZ takes real x, real y returns real
call MoveLocation(TempLoc,x,y)
return GetLocationZ(TempLoc)
endfunction
//==========================================================================\\
private struct DATA
//==========================================================================\\
unit Caster
lightning array Light [MaxArray]
lightning MainLight
effect Indication
real x
real y
real z
real Distance
real Damage
real Radius
real DistIncrease
real ZIncrease
real LoadTime
real DropTime
integer Amount
integer SFXSpam
timer t
//==========================================================================\\
static method Loop takes nothing returns nothing
local DATA dat = DATA(GetTimerData(GetExpiredTimer()))
local integer i = 0
local real a
local real x1
local real y1
local real x2
local real y2
local real z2
local real z1
local unit temp = null
if dat.LoadTime <= 0 then
if dat.DropTime > 0 then
set dat.DropTime = dat.DropTime - INT
set dat.z = dat.z - dat.ZIncrease
call MoveLightningEx(dat.MainLight, false,dat.x,dat.y,dat.z,dat.x,dat.y,GetTerrainZ(dat.x,dat.y) + DeltaZ)
loop
exitwhen i > dat.Amount - 1
set a = ((360/dat.Amount) * (i+1)) * bj_DEGTORAD
set x1 = dat.x + dat.Distance * Cos(a)
set y1 = dat.y + dat.Distance * Sin(a)
set x2 = x1 + DeltaDist * Cos(a)
set y2 = y1 + DeltaDist * Sin(a)
set z1 = GetTerrainZ(x1,y1) + dat.z
set z2 = GetTerrainZ(x1,y1) + DeltaZ
call MoveLightningEx(dat.Light [i], false, x1,y1,z1,x2,y2,z2)
set i = i + 1
endloop
else
set dat.Distance = dat.Distance - dat.DistIncrease
if dat.Distance <= 0 then
call DestroyEffect(AddSpecialEffect(SFX1,dat.x,dat.y))
call dat.remove()
else
loop
exitwhen i > dat.Amount - 1
set a = ((360/dat.Amount) * (i+1)) * bj_DEGTORAD
set x1 = dat.x + dat.Distance * Cos(a)
set y1 = dat.y + dat.Distance * Sin(a)
set x2 = x1 + DeltaDist * Cos(a)
set y2 = y1 + DeltaDist * Sin(a)
set z1 = GetTerrainZ(x1,y1)
set z2 = z1 + DeltaZ
call MoveLightningEx(dat.Light [i], false, x1,y1,z1,x2,y2,z2)
set TempCaster = dat.Caster
call GroupEnumUnitsInRange(g,x1,y1,dat.Radius,GroupFilter)
loop
set temp = FirstOfGroup(g)
exitwhen temp == null
call UnitDamageTarget(dat.Caster, temp,dat.Damage,true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_LIGHTNING, WEAPON_TYPE_WHOKNOWS)
call GroupRemoveUnit(g, temp)
endloop
if dat.SFXSpam >= 3 then
call DestroyEffect(AddSpecialEffect(SFX2, x1,y1))
endif
set i = i + 1
endloop
call GroupEnumUnitsInRange(g,dat.x,dat.y,dat.Radius,GroupFilter)
loop
set temp = FirstOfGroup(g)
exitwhen temp == null
call UnitDamageTarget(dat.Caster, temp,dat.Damage,true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_LIGHTNING, WEAPON_TYPE_WHOKNOWS)
call GroupRemoveUnit(g,temp)
endloop
if dat.SFXSpam >= 3 then
call DestroyEffect(AddSpecialEffect(SFX2, dat.x,dat.y))
set dat.SFXSpam = 0
endif
set dat.SFXSpam = dat.SFXSpam + 1
endif
endif
else
set dat.LoadTime = dat.LoadTime - INT
if dat.LoadTime <= 0 then
set i = 0
set dat.MainLight = AddLightningEx(DLS, false, dat.x,dat.y,dat.z, dat.x,dat.y,dat.z)
loop
exitwhen i > dat.Amount - 1
set a = ((360/dat.Amount) * (i+1)) * bj_DEGTORAD
set x1 = dat.x + dat.Distance * Cos(a)
set y1 = dat.y + dat.Distance * Sin(a)
set x2 = x1 + DeltaDist * Cos(a)
set y2 = y1 + DeltaDist * Sin(a)
set z1 = dat.z
set z2 = dat.z
set dat.Light [i] = AddLightningEx(DLS,false, x1,y1,z1,x2,y2,z2)
set i = i + 1
endloop
call DestroyEffect(dat.Indication)
endif
endif
set temp = null
endmethod
//==========================================================================\\
static method Create takes nothing returns boolean
local thistype this
local integer lvl
if GetSpellAbilityId() == AID then
set this = thistype.allocate()
set lvl = GetUnitAbilityLevel(GetTriggerUnit(), AID)
set .Caster = GetTriggerUnit()
set .x = GetSpellTargetX()
set .y = GetSpellTargetY()
set .z = GetTerrainZ(.x,.y) + DeltaZ
set .Distance = DistanceF(lvl)
set .Damage = DamageF(lvl)
set .Radius = RadiusF(lvl)
set .Amount = AmountF(lvl)
set .LoadTime = LoadTimeF(lvl)
set .DropTime = DropTimeF(lvl)
set .DistIncrease = .Distance/R2I(TimeF(lvl)/INT)
set .ZIncrease = DeltaZ/R2I(DropTimeF(lvl)/INT)
set .SFXSpam = 5
set .t = NewTimer()
set .Indication = AddSpecialEffect(SFX3,.x,.y)
call SetTimerData(.t, integer(this))
call TimerStart(.t, INT, true, function thistype.Loop)
endif
return false
endmethod
//==========================================================================\\
private method remove takes nothing returns nothing
local integer i = 0
set .Caster = null
loop
exitwhen i > .Amount - 1
call DestroyLightning(.Light [i])
set .Light [i] = null
set i = i + 1
endloop
call DestroyLightning(.MainLight)
set .MainLight = null
call ReleaseTimer(.t)
call .destroy()
endmethod
//==========================================================================\\
private static method groupfilter takes nothing returns boolean
return IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(TempCaster))
endmethod
//==========================================================================\\
static method StringSettings takes nothing returns nothing
set LSA[1] = "CLPB" // Chain Lightning Primary
set LSA[2] = "CLSB" // Chain Lightning Secondary
set LSA[3] = "DRAB" // Drain
set LSA[4] = "DRAL" // Drain Life
set LSA[5] = "DRAM" // Drain Mana
set LSA[6] = "AFOD" // Finger of Death
set LSA[7] = "FORK" // Forked Lightning
set LSA[8] = "HWPB" // Healing Wave Primary
set LSA[9] = "HWSB" // Healing Wave Secondary
set LSA[10] = "CHIM" // Lightning Attack
set LSA[11] = "LEAS" // Magic Leash
set LSA[12] = "MBUR" // Mana Burn
set LSA[13] = "MFPB" // Mana Flare
set LSA[14] = "SPLK" // Spirit Link
endmethod
//==========================================================================\\
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
call .StringSettings()
set DLS = LSA [LightningString]
set GroupFilter = Condition(function thistype.groupfilter)
set AbilityFilter = Condition(function thistype.Create)
loop
exitwhen i >= bj_MAX_PLAYER_SLOTS
call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
set i = i + 1
endloop
call TriggerAddCondition(t,AbilityFilter)
set t = null
endmethod
//==========================================================================\\
endstruct
//==========================================================================\\
//========================== End of the Spell ==============================\\
//==========================================================================\\
endscope
```