Tom_Kazansky
--- wraith it ! ---
- Reaction score
- 157
Tom_Kazansky presents
A spellpack contains:
- Scatter Lightning
- Aerial Strike
- Earth Boulder
- Thunder Break
MUI/MPI - Both
GUI/Jass - vJass
Leakless - yeah, I... think
Original - nope but I think they have good visual effects.
Scatter Lightning
- Description:
Spreads out bolts of electrical power that damages enemy units within the area of effect. Each bolt deals 30 damage.
- Screenshot:
- Code:
Aerial Strike
- Description:
Jumps off the group and throws explosive matter towards the target area, dealing damage to nearby enemy units.
(I need a more compatible name, can anyone suggest it ? )
- Screenshot: not available
- Code:
Earth Boulder
- Description:
Throws a solid bounder towards a target location, the boulder knocks and deals damage to enemy units whom it collides with. The boulder also explodes at the end of its path.
- Screenshot: not available
- Code:
Thunder Break
- Description:
Calls down powerful lightning bolts from the sky, dealing damage to enemy units in a line.
- Screenshot:
- Code:
Credit:
- Thanks Cohadar for TT system
- Thanks Tinki3 for the test map template
- and does the "dummy.mdx" belong to Vexorian ?
If someone find any leaks or bugs, please tell me, I will apperciate very much
A spellpack contains:
- Scatter Lightning
- Aerial Strike
- Earth Boulder
- Thunder Break
MUI/MPI - Both
GUI/Jass - vJass
Leakless - yeah, I... think
Original - nope but I think they have good visual effects.
Scatter Lightning
- Description:
Spreads out bolts of electrical power that damages enemy units within the area of effect. Each bolt deals 30 damage.
- Screenshot:
- Code:
JASS:
scope ScatterLightning initializer Init
globals
private integer AbilID = 039;A001039; //Raw Id of the Scatter Lightning ability
private integer DummyId = 039;n000039; //Raw Id of the dummy unit (requires dummy.mdx )
private real LightnigHeight = 600.0 //the height of the lightning
private string LightningCode = "CHIM" //lightning code of the lightning effect
private string MissileSFX = "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl" //the missile art of the bolt of lightning
private real MissileSpeed = 1000. //speed of the missile
private string AreaSFX = "Abilities\\Spells\\Other\\ForkedLightning\\ForkedLightningTarget.mdl" //effect where the lightning strikes the ground
private string TargetSFX = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl" //dealing damage sfx
private string TargetSFX_A = "origin" //attachment point of the dealing damage sfx
private real ScatterRadius = 400. //area of effect for scattering
private real ExplodeRadius = 200. //area of effect for dealing damage.
private attacktype ATKTYPE = ATTACK_TYPE_NORMAL //attack type, currently: Spell
private damagetype DMGTYPE = DAMAGE_TYPE_FIRE //damage type, currently: "Magical"
endglobals
//================================
private function GetDamage takes integer lvl returns real
return 30. //Get Damage Deal
endfunction
private function GetBoltCount takes integer lvl returns integer
return (5 + 3*lvl) //Get number of bolts <- this number shouldn't be too high :|
endfunction
//================================
//---- Utility Functions -----
private function GetPPX takes real x, real dist, real angle returns real
return x + dist * Cos(angle * bj_DEGTORAD)
endfunction
private function GetPPY takes real y, real dist, real angle returns real
return y + dist * Sin(angle * bj_DEGTORAD)
endfunction
private function AngleLocXY takes real x1, real y1, real x2, real y2 returns real
return bj_RADTODEG * Atan2(y2 - y1, x2 - x1)
endfunction
private function DistanceLocXY takes real x1, real y1, real x2, real y2 returns real
return SquareRoot( (x2-x1) * (x2-x1) + (y2-y1) * (y2-y1))
endfunction
private function SetUnitZ takes unit c, real z returns nothing
call UnitAddAbility(c,039;Amrf039;)
call UnitRemoveAbility(c,039;Amrf039;)
call SetUnitFlyHeight(c,z,0.)
endfunction
//================================
private struct data
unit c
unit d
effect e
lightning b
real x
real y
real dmg
real angle
real vel
integer tick
boolean strike = false
endstruct
private function ScatterLightningSingleF takes nothing returns boolean
local data d = TT_GetData()
local unit f = GetFilterUnit()
local boolean ok = false
if IsUnitInRangeXY(f,d.x,d.y,ExplodeRadius) then
if GetWidgetLife(f) > 0.405 then
if IsUnitEnemy(f,GetOwningPlayer(d.c)) then
if not IsUnitType(f,UNIT_TYPE_STRUCTURE) and not IsUnitType(f,UNIT_TYPE_MAGIC_IMMUNE) then
set ok = true
endif
endif
endif
endif
set f = null
return ok
endfunction
function ScatterLightningSingleE takes nothing returns boolean
local data d = TT_GetData()
local real dis
local real x
local real y
local group g
local unit p
local boolexpr bx
if d.strike then
if d.tick == 0 then
call ShowUnit(d.d,false)
call DestroyEffect(d.e)
call KillUnit(d.d)
call DestroyLightning(d.b)
call d.destroy()
return true
endif
call SetUnitVertexColor( d.d, 255, 255, 255, R2I( 255 * (d.tick / 10.) ) )
call SetLightningColor(d.b, 1. , 1., 1., d.tick / 10. )
set d.tick = d.tick - 1
else
if d.tick == 0 then
set d.b = AddLightningEx( LightningCode ,true,d.x,d.y,700.,d.x,d.y,0)
if AreaSFX != "" then
call DestroyEffect( AddSpecialEffect(AreaSFX,d.x,d.y) )
endif
set g = CreateGroup()
set bx = Condition( function ScatterLightningSingleF )
call GroupEnumUnitsInRange(g , d.x, d.y, ExplodeRadius + 100. , bx)
call DestroyBoolExpr(bx)
set bx = null
loop
set p = FirstOfGroup(g)
exitwhen p == null
call GroupRemoveUnit(g,p)
call UnitDamageTarget( d.c, p , d.dmg, false, true, ATKTYPE, DMGTYPE, null )
if TargetSFX != "" then
call DestroyEffect( AddSpecialEffectTarget(TargetSFX,p,TargetSFX_A) )
endif
endloop
call DestroyGroup(g)
set g = null
set d.tick = 10
set d.strike = true
else
set x = GetUnitX(d.d)
set y = GetUnitY(d.d)
set dis = DistanceLocXY( x, y, d.x, d.y )
if dis > MissileSpeed /25. then
set dis = MissileSpeed /25.
endif
call SetUnitX( d.d , GetPPX( x, dis, d.angle ) )
call SetUnitY( d.d , GetPPY( y, dis, d.angle ) )
call SetUnitZ( d.d, GetUnitFlyHeight(d.d) + d.vel )
set d.tick = d.tick - 1
endif
endif
return false
endfunction
function ScatterLightningSingle takes unit c, real cx, real cy, real x, real y, real dmg returns nothing
local data d = data.create()
local real dist = DistanceLocXY( cx, cy, x, y )
set d.c = c
set d.angle = AngleLocXY( cx, cy, x, y )
set d.d = CreateUnit(GetOwningPlayer(c), DummyId , cx, cy, d.angle )
call SetUnitZ( d.d, 60. )
set d.e = AddSpecialEffectTarget( MissileSFX , d.d, "origin" )
set d.x = x
set d.y = y
set d.dmg = dmg
set d.tick = R2I( dist /(MissileSpeed /25.))
if d.tick * (MissileSpeed /25.) != dist then
set d.tick = d.tick + 1
endif
set d.vel = LightnigHeight / d.tick
call TT_Start( function ScatterLightningSingleE, d )
endfunction
//================================
private function Cond takes nothing returns boolean
return (GetSpellAbilityId() == AbilID)
endfunction
private function Act takes nothing returns nothing
local unit c = GetSpellAbilityUnit()
local integer lvl = GetUnitAbilityLevel(c,AbilID)
local location loc = GetSpellTargetLoc()
local real x = GetLocationX(loc)
local real y = GetLocationY(loc)
local real cx = GetUnitX(c)
local real cy = GetUnitY(c)
local real dist
local real ang
local real tx
local real ty
local integer i = 1
local integer im = GetBoltCount(lvl)
local real dmg = GetDamage(lvl)
loop
exitwhen i > im
set dist = GetRandomReal(50. , ScatterRadius - 50. )
set ang = GetRandomReal( 0, 359. )
set tx = GetPPX(x, dist, ang )
set ty = GetPPY(y, dist, ang )
call ScatterLightningSingle( c,cx,cy, tx, ty, dmg )
set i = i + 1
endloop
call RemoveLocation(loc)
set loc = null
set c = null
endfunction
//=================================
public function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction( t, function Act )
call TriggerAddCondition( t, Condition( function Cond ) )
set t = null
endfunction
endscope
Aerial Strike
- Description:
Jumps off the group and throws explosive matter towards the target area, dealing damage to nearby enemy units.
(I need a more compatible name, can anyone suggest it ? )
- Screenshot: not available
- Code:
JASS:
scope AerialStrike initializer Init
globals
private integer AbilID = 039;A000039; //Raw Id of the Aerial Strike ability
private integer DummyId = 039;n000039; //Raw Id of the dummy unit (requires dummy.mdx )
private real JumpHeight = 400.0 //the jump height
private string ThrowAnimation = "Spell Slam" //animation which is played when the hero throws explosive matter
private string MissileSFX = "Abilities\\Weapons\\BoatMissile\\BoatMissile.mdl" //the missile art of the "explosive matter" <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin :D" loading="lazy" data-shortname=":D" />
private real MissileSpeed = 1000. //speed of the missile
private string AreaSFX = "" //special effect when the missile hits the ground,
//used for some missile models which do not have "explosive effect" when it is destroyed
//for example: the BoatMissile is the missile of Human Battle Ship, so it has "explosive effect" when it is destroyed (the Death animation)
// but if the missile art is the missile of "Death Coil",
//it doesn't have "explosive effect" when it is destroyed, so you should have an AreaSFX
private string TargetSFX = "Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl" //dealing damage sfx
private string TargetSFX_A = "origin" //attachment point of the dealing damage sfx
private real ExplodeRadius = 200. //area of effect for explode
private attacktype ATKTYPE = ATTACK_TYPE_NORMAL //attack type, currently: Spell
private damagetype DMGTYPE = DAMAGE_TYPE_FIRE //damage type, currently: "Magical"
endglobals
//================================
private function GetDamage takes integer lvl returns real
return 25. + 75*lvl //Get Damage Deal
endfunction
private function GetPPX takes real x, real dist, real angle returns real
return x + dist * Cos(angle * bj_DEGTORAD)
endfunction
private function GetPPY takes real y, real dist, real angle returns real
return y + dist * Sin(angle * bj_DEGTORAD)
endfunction
private function AngleLocXY takes real x1, real y1, real x2, real y2 returns real
return bj_RADTODEG * Atan2(y2 - y1, x2 - x1)
endfunction
private function DistanceLocXY takes real x1, real y1, real x2, real y2 returns real
return SquareRoot( (x2-x1) * (x2-x1) + (y2-y1) * (y2-y1))
endfunction
//================================
private struct data
unit c
unit d
effect dfx
real tx
real ty
real angle
real dmg
integer tick = 20
real sin
endstruct
private function ExplosiveMatterF takes nothing returns boolean
local data d = TT_GetData()
local unit f = GetFilterUnit()
local boolean ok = false
if IsUnitInRangeXY(f,d.tx,d.ty,ExplodeRadius) then
if GetWidgetLife(f) > 0.405 then
if IsUnitEnemy(f,GetOwningPlayer(d.c)) then
if not IsUnitType(f,UNIT_TYPE_STRUCTURE) and not IsUnitType(f,UNIT_TYPE_MAGIC_IMMUNE) then
set ok = true
endif
endif
endif
endif
set f = null
return ok
endfunction
private function ExplosiveMatterE takes nothing returns boolean
local data d = TT_GetData()
local group g
local unit p
local boolexpr bx
set d.tick = d.tick - 1
if d.tick == 0 then
call DestroyEffect(d.dfx)
call KillUnit(d.d)
if AreaSFX != "" then
call DestroyEffect( AddSpecialEffect(AreaSFX,d.tx,d.ty) )
endif
set g = CreateGroup()
set bx = Condition( function ExplosiveMatterF )
call GroupEnumUnitsInRange( g, d.tx, d.ty, ExplodeRadius + 100. , bx )
call DestroyBoolExpr(bx)
set bx = null
loop
set p = FirstOfGroup(g)
exitwhen p == null
call GroupRemoveUnit(g,p)
if TargetSFX != "" then
call DestroyEffect( AddSpecialEffectTarget(TargetSFX,p,TargetSFX_A) )
endif
call UnitDamageTarget(d.c,p,d.dmg, false, true, ATKTYPE, DMGTYPE, null )
endloop
call DestroyGroup(g)
set g = null
call d.destroy()
return true
endif
call SetUnitFlyHeight(d.d, d.sin * d.tick , 0. )
call SetUnitX( d.d , GetPPX( GetUnitX(d.d), MissileSpeed / 25. , d.angle ) )
call SetUnitY( d.d , GetPPY( GetUnitY(d.d), MissileSpeed / 25. , d.angle ) )
return false
endfunction
private function ExplosiveMatter takes unit c, real x, real y, real dmg returns nothing
local data d = data.create()
local real cx = GetUnitX(c)
local real cy = GetUnitY(c)
local real dist = DistanceLocXY( cx, cy, x, y )
set d.c = c
set d.tx = x
set d.ty = y
set d.dmg = dmg
set d.angle = AngleLocXY(cx,cy,x,y)
set d.d = CreateUnit(GetOwningPlayer(c), DummyId , cx, cy, d.angle )
call UnitAddAbility(d.d,039;Amrf039;)
call UnitRemoveAbility(d.d,039;Amrf039;)
call SetUnitFlyHeight(d.d, JumpHeight , 0. )
call SetUnitAnimationByIndex(d.d, 90 - R2I( AtanBJ( JumpHeight / dist ) ) )
set d.dfx = AddSpecialEffectTarget( MissileSFX , d.d, "origin")
set d.tick = R2I( dist / MissileSpeed / 0.04 )
set d.sin = JumpHeight / d.tick
call TT_Start( function ExplosiveMatterE , d )
endfunction
private struct data2
unit c
real tx
real ty
real angle
real dmg
real sin
integer tick = 0
boolean paused = false
endstruct
private function AerialStrikeE takes nothing returns boolean
local data2 d = TT_GetData()
local real x
local real y
if not d.paused then
call IssueImmediateOrder(d.c,"stop")
call PauseUnit(d.c,true)
call SetUnitInvulnerable(d.c,true)
call SetUnitPathing(d.c,false)
call SetUnitAnimation(d.c,"Ready")
set d.paused = true
endif
if d.tick == 25 then
call PauseUnit(d.c,false)
call SetUnitInvulnerable(d.c,false)
call SetUnitPathing(d.c,true)
call d.destroy()
return true
endif
set d.tick = d.tick + 1
call UnitAddAbility(d.c,039;Amrf039;)
call UnitRemoveAbility(d.c,039;Amrf039;)
call SetUnitFlyHeight(d.c, (JumpHeight-60.) * Sin( d.sin * d.tick * bj_DEGTORAD ) , 0. )
if d.tick == 9 then
call SetUnitTimeScale(d.c,1.5)
call SetUnitAnimation(d.c,ThrowAnimation )
endif
if d.tick == 13 then
set x = GetPPX( d.tx, 300. , d.angle - 90. )
set y = GetPPY( d.ty, 300. , d.angle - 90. )
call ExplosiveMatter( d.c, x, y , d.dmg)
set x = GetPPX( d.tx, 300. , d.angle + 90. )
set y = GetPPY( d.ty, 300. , d.angle + 90. )
call ExplosiveMatter( d.c, x, y , d.dmg)
set x = GetPPX( d.tx, 200. , d.angle - 45. )
set y = GetPPY( d.ty, 200. , d.angle - 45. )
call ExplosiveMatter( d.c, x, y , d.dmg)
set x = GetPPX( d.tx, 200. , d.angle + 45. )
set y = GetPPY( d.ty, 200. , d.angle + 45. )
call ExplosiveMatter( d.c, x, y , d.dmg)
endif
if d.tick == 16 then
call SetUnitTimeScale(d.c,1.)
call SetUnitAnimation(d.c,"Ready")
endif
return false
endfunction
//================================
private function Cond takes nothing returns boolean
return (GetSpellAbilityId() == AbilID)
endfunction
private function Act takes nothing returns nothing
local data2 d = data2.create()
local location l = GetSpellTargetLoc()
local real cx
local real cy
set d.c = GetSpellAbilityUnit()
set d.dmg = GetDamage(GetUnitAbilityLevel(d.c,AbilID))
set d.sin = 180. / 25
set d.tx = GetLocationX(l)
set d.ty = GetLocationY(l)
set cx = GetUnitX(d.c)
set cy = GetUnitY(d.c)
if cx == d.tx and cy == d.ty then
set d.angle = GetUnitFacing(d.c)
else
set d.angle = AngleLocXY( cx, cy, d.tx, d.ty )
endif
call TT_Start( function AerialStrikeE, d )
call RemoveLocation(l)
set l = null
endfunction
//=================================
public function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction( t, function Act )
call TriggerAddCondition( t, Condition( function Cond ) )
set t = null
endfunction
endscope
Earth Boulder
- Description:
Throws a solid bounder towards a target location, the boulder knocks and deals damage to enemy units whom it collides with. The boulder also explodes at the end of its path.
- Screenshot: not available
- Code:
JASS:
scope EarthBoulder initializer Init
globals
private integer AbilID = 039;A002039; //Raw Id of the Earth Boulder ability
private integer DummyId = 039;n000039; //Raw Id of the dummy unit (requires dummy.mdx )
private string MissileSFX = "abilities\\weapons\\catapult\\catapultmissile.mdl" //the missile art of the boulder
private real MissileSpeed = 500. //speed of the boulder
private string AreaSFX = "Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissile.mdl" //effect when the boulder moves
//private string TargetSFX = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl" //dealing damage sfx
//private string TargetSFX_A = "origin" //attachment point of the dealing damage sfx
private real MinimumRange = 300.0 //minimum throw range
private real KnockRadius = 100. //area of effect for scattering
private real ExplodeRadius = 350. //area of effect for dealing damage when explode.
private attacktype ATKTYPE = ATTACK_TYPE_NORMAL //attack type, currently: Spell
private damagetype DMGTYPE = DAMAGE_TYPE_NORMAL //damage type, currently: "Physical"
//----
private real TEMPREAL = 0.0
endglobals
//================================
private function GetDamagePS takes integer lvl returns real
return (100.+20*lvl) //Get Damage per second
endfunction
private function GetDamageEx takes integer lvl returns real
return (75.+75*lvl) //Get Explode damage
endfunction
//================================
//---- Utility Functions -----
private function GetPPX takes real x, real dist, real angle returns real
return x + dist * Cos(angle * bj_DEGTORAD)
endfunction
private function GetPPY takes real y, real dist, real angle returns real
return y + dist * Sin(angle * bj_DEGTORAD)
endfunction
private function AngleLocXY takes real x1, real y1, real x2, real y2 returns real
return bj_RADTODEG * Atan2(y2 - y1, x2 - x1)
endfunction
private function DistanceLocXY takes real x1, real y1, real x2, real y2 returns real
return SquareRoot( (x2-x1) * (x2-x1) + (y2-y1) * (y2-y1))
endfunction
private function SetUnitZ takes unit c, real z returns nothing
call UnitAddAbility(c,039;Amrf039;)
call UnitRemoveAbility(c,039;Amrf039;)
call SetUnitFlyHeight(c,z,0.)
endfunction
private function DestroyTreesE takes nothing returns nothing
local destructable d = GetEnumDestructable()
if GetDestructableMaxLife(d) == 50. then
call KillDestructable( d )
endif
set d = null
endfunction
private function DestroyTreesInCircle takes real x, real y, real rng returns nothing
local rect r = Rect(x - rng, y - rng, x + rng, y + rng)
set bj_enumDestructableCenter = Location(x,y)
set bj_enumDestructableRadius = rng
call EnumDestructablesInRect(r, null, function DestroyTreesE )
call RemoveLocation(bj_enumDestructableCenter)
set bj_enumDestructableCenter = null
call RemoveRect(r)
set r = null
endfunction
//====================================================================
private struct data
unit c
unit d
effect e
group g = CreateGroup()
integer tick
real angle
real dmgEx
real dmgPs
real dx
real dy
endstruct
function EarthBoulderFilter takes nothing returns boolean
local data d = TT_GetData()
local unit f = GetFilterUnit()
local boolean ok = false
if IsUnitInRangeXY(f,d.dx,d.dy,TEMPREAL ) then
if GetWidgetLife(f) > 0.405 then
if IsUnitEnemy(f,GetOwningPlayer(d.c)) then
if not IsUnitType(f,UNIT_TYPE_STRUCTURE) and not IsUnitType(f,UNIT_TYPE_MAGIC_IMMUNE) then
set ok = true
endif
endif
endif
endif
set f = null
return ok
endfunction
function EarthBoulderE takes nothing returns boolean
local data d = TT_GetData()
local unit p
local real x
local real y
local real a
local real dt
local boolexpr bx
set d.dx = GetUnitX(d.d)
set d.dy = GetUnitY(d.d)
if d.tick == 0 then
call SetUnitScale(d.d, 2., 2., 2. )
call SetUnitZ(d.d,0.)
call DestroyEffect(d.e)
call KillUnit(d.d)
call DestroyTreesInCircle( d.dx, d.dy, 350. )
set TEMPREAL = ExplodeRadius
set bx = Condition( function EarthBoulderFilter )
call GroupEnumUnitsInRange(d.g, d.dx,d.dy, ExplodeRadius + 100.,bx )
call DestroyBoolExpr(bx)
set bx = null
loop
set p = FirstOfGroup(d.g)
exitwhen p == null
call GroupRemoveUnit(d.g,p)
call UnitDamageTarget(d.c, p , d.dmgEx , false, true, null, DAMAGE_TYPE_NORMAL, null )
endloop
call DestroyGroup(d.g)
call d.destroy()
return true
endif
set d.dx = GetPPX( d.dx, 20. , d.angle )
set d.dy = GetPPY( d.dy, 20. , d.angle )
call SetUnitPosition( d.d, d.dx, d.dy )
if AreaSFX != "" then
call DestroyEffect( AddSpecialEffect(AreaSFX,d.dx,d.dy) )
endif
call DestroyTreesInCircle( d.dx, d.dy, 200. )
set TEMPREAL = KnockRadius
set bx = Condition( function EarthBoulderFilter )
call GroupEnumUnitsInRange(d.g, d.dx,d.dy, KnockRadius + 100.,bx )
call DestroyBoolExpr(bx)
set bx = null
loop
set p = FirstOfGroup(d.g)
exitwhen p == null
call GroupRemoveUnit(d.g,p)
set x = GetUnitX(p)
set y = GetUnitY(p)
set dt = DistanceLocXY( d.dx, d.dy, x, y )
set a = AngleLocXY( d.dx, d.dy, x, y )
call SetUnitPosition( p , GetPPX( x, KnockRadius + 50. - dt, a ), GetPPY( y, KnockRadius + 50. - dt, a ) )
call UnitDamageTarget(d.c, p , d.dmgPs , false, true, ATKTYPE, DMGTYPE, null )
endloop
set d.tick = d.tick - 1
return false
endfunction
//================================
private function Cond takes nothing returns boolean
return (GetSpellAbilityId() == AbilID)
endfunction
private function Act takes nothing returns nothing
local unit c = GetSpellAbilityUnit()
local integer lvl = GetUnitAbilityLevel(c,AbilID)
local location loc = GetSpellTargetLoc()
local real x = GetLocationX(loc)
local real y = GetLocationY(loc)
local real cx = GetUnitX(c)
local real cy = GetUnitY(c)
local data d = data.create()
local real dist = DistanceLocXY( cx, cy, x, y )
if dist < MinimumRange then
set dist = MinimumRange
endif
set d.c = c
set d.dmgEx = GetDamageEx(lvl)
set d.dmgPs = GetDamagePS(lvl) / 25.
set d.tick = R2I( dist / 20. )
set d.angle = AngleLocXY( cx,cy,x,y)
set d.d = CreateUnit(GetOwningPlayer(c), DummyId , cx, cy, d.angle )
set d.e = AddSpecialEffectTarget( MissileSFX , d.d, "origin" )
call SetUnitScale(d.d,4.,4.,4.)
call SetUnitZ(d.d,80.)
call TT_Start( function EarthBoulderE, d )
endfunction
//=================================
public function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction( t, function Act )
call TriggerAddCondition( t, Condition( function Cond ) )
set t = null
endfunction
endscope
Thunder Break
- Description:
Calls down powerful lightning bolts from the sky, dealing damage to enemy units in a line.
- Screenshot:
- Code:
JASS:
scope ThunderBreak initializer Init
globals
private integer AbilID = 039;A003039; //Raw Id of the Thunder Break ability
private string LightningCode = "CHIM" //lightning code of the lightning effect
private string AreaSFX = "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl" //effect at the "current" area ( I don't know how to explain this :|)
private string AreaSoundSFX = "Abilities\\Spells\\Orc\\LightningBolt\\LightningBoltMissile.mdl" //I only use this effect for its sound <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite1" alt=":)" title="Smile :)" loading="lazy" data-shortname=":)" />
private string LightningHitSFX = "Abilities\\Spells\\Other\\ForkedLightning\\ForkedLightningTarget.mdl" //effect where the lightning bolt hits the ground
private string TargetSFX = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl" //dealing damage sfx
private string TargetSFX_A = "origin" //attachment point of the dealing damage sfx
private real MaximumRange = 1400.0 //how long is this line of lightning
private real DamageRadius = 250. //area of effect for dealing damage.
private attacktype ATKTYPE = ATTACK_TYPE_NORMAL //attack type, currently: Spell
private damagetype DMGTYPE = DAMAGE_TYPE_LIGHTNING //damage type, currently: "Magical"
//----
private real TEMPREAL = 0.0
endglobals
//================================
private function GetDamage takes integer lvl returns real
return (150.*lvl) //Get Damage dealt
endfunction
private function GetDistance takes integer lvl returns real
return 1500. //the Distance
endfunction
//================================
//---- Utility Functions -----
private function GetPPX takes real x, real dist, real angle returns real
return x + dist * Cos(angle * bj_DEGTORAD)
endfunction
private function GetPPY takes real y, real dist, real angle returns real
return y + dist * Sin(angle * bj_DEGTORAD)
endfunction
//====================================================================
private struct data
unit c
real cx
real cy
real cf
real dmg
group hit = CreateGroup()
integer tick
integer tickdmg = 0
endstruct
private struct sdata
real color = 1.
lightning array b [5]
endstruct
private function ThunderBreakD takes nothing returns boolean
local sdata d = TT_GetData()
local integer i = 0
set d.color = d.color - 0.1
loop
exitwhen i > 4
if d.color <= 0 then
call DestroyLightning( d.b<i> )
else
call SetLightningColor( d.b<i>, 1, 1, 1 , d.color )
endif
set i = i + 1
endloop
if d.color <= 0 then
call d.destroy()
return true
endif
return false
endfunction
function ThunderBreakFilter takes nothing returns boolean
local data d = TT_GetData()
local unit f = GetFilterUnit()
local boolean ok = false
if IsUnitInRangeXY(f,d.cx,d.cy, DamageRadius ) then
if GetWidgetLife(f) > 0.405 then
if IsUnitEnemy(f,GetOwningPlayer(d.c)) then
if not IsUnitType(f,UNIT_TYPE_STRUCTURE) and not IsUnitType(f,UNIT_TYPE_MAGIC_IMMUNE) then
if not IsUnitInGroup(f,d.hit) then
set ok = true
endif
endif
endif
endif
endif
set f = null
return ok
endfunction
function ThunderBreakE takes nothing returns boolean
local data d = TT_GetData()
local sdata sd
local real cx
local real cy
local unit p
local group g
local boolexpr bx
if d.tick == 0 then
call DestroyGroup(d.hit)
call d.destroy()
return true
endif
if d.tickdmg == 0 then
//---
if AreaSFX != "" then
call DestroyEffect( AddSpecialEffect(AreaSFX,d.cx,d.cy) )
endif
if AreaSoundSFX != "" then
call DestroyEffect( AddSpecialEffect(AreaSoundSFX,d.cx,d.cy) )
endif
set sd = sdata.create()
set sd.b[0] = AddLightningEx( LightningCode ,true,d.cx,d.cy,2000.,d.cx,d.cy,-0)
//call DestroyEffect( AddSpecialEffect("Abilities\\Spells\\Other\\ForkedLightning\\ForkedLightningTarget.mdl",d.cx,d.cy) )
set cx = GetPPX( d.cx , 150., d.cf - 45 )
set cy = GetPPY( d.cy , 150., d.cf - 45 )
set sd.b[1] = AddLightningEx( LightningCode,true,cx,cy,2000. ,cx,cy,0)
call DestroyEffect( AddSpecialEffect(LightningHitSFX,cx,cy) )
set cx = GetPPX( d.cx , 150., d.cf + 45 )
set cy = GetPPY( d.cy , 150., d.cf + 45 )
set sd.b[2] = AddLightningEx( LightningCode,true,cx,cy,2000. ,cx,cy,0)
call DestroyEffect( AddSpecialEffect(LightningHitSFX,cx,cy) )
set cx = GetPPX( d.cx , 150., d.cf + 135 )
set cy = GetPPY( d.cy , 150., d.cf + 135 )
set sd.b[3] = AddLightningEx( LightningCode,true,cx,cy,2000. ,cx,cy,0)
call DestroyEffect( AddSpecialEffect(LightningHitSFX,cx,cy) )
set cx = GetPPX( d.cx , 150., d.cf - 135 )
set cy = GetPPY( d.cy , 150., d.cf - 135 )
set sd.b[4] = AddLightningEx( LightningCode,true,cx,cy,2000. ,cx,cy,0)
call DestroyEffect( AddSpecialEffect(LightningHitSFX,cx,cy) )
call TT_Start( function ThunderBreakD , sd )
set g = CreateGroup()
set bx = Condition( function ThunderBreakFilter )
call GroupEnumUnitsInRange(g,d.cx,d.cy, DamageRadius + 100., bx )
call DestroyBoolExpr(bx)
set bx = null
loop
set p = FirstOfGroup(g)
exitwhen p == null
call GroupRemoveUnit(g,p)
if TargetSFX != "" then
call DestroyEffect( AddSpecialEffectTarget(TargetSFX,p,TargetSFX_A) )
endif
call UnitDamageTarget(d.c, p , d.dmg , false, true, ATKTYPE, DMGTYPE, null )
call GroupAddUnit(d.hit,p)
endloop
call DestroyGroup(g)
set g = null
set d.cx = GetPPX( d.cx, 300., d.cf )
set d.cy = GetPPY( d.cy, 300., d.cf )
set d.tickdmg = 3
//---
endif
set d.tick = d.tick - 1
set d.tickdmg = d.tickdmg - 1
return false
endfunction
//=============================================
private function Cond takes nothing returns boolean
return (GetSpellAbilityId() == AbilID)
endfunction
private function Act takes nothing returns nothing
local unit c = GetSpellAbilityUnit()
local integer lvl = GetUnitAbilityLevel(c,AbilID)
local data d = data.create()
set d.c = c
set d.cf = GetUnitFacing(c)
set d.cx = GetPPX( GetUnitX(c), 200., d.cf )
set d.cy = GetPPY( GetUnitY(c), 200., d.cf )
set d.dmg = GetDamage( lvl )
set d.tick = R2I( (GetDistance(lvl) - 200. ) / 300. ) * 3
call TT_Start( function ThunderBreakE, d )
endfunction
//=================================
public function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction( t, function Act )
call TriggerAddCondition( t, Condition( function Cond ) )
set t = null
endfunction
endscope</i></i>
Credit:
- Thanks Cohadar for TT system
- Thanks Tinki3 for the test map template
- and does the "dummy.mdx" belong to Vexorian ?
If someone find any leaks or bugs, please tell me, I will apperciate very much