Line Spell Template v4
Allows you to cast projectiles in a line, which cast abilities on enemies in their path.
This template is really made for GUIers. If you desire more options, such as neat geometric movements, a generic projectile system is more what you are looking for. This is simple, easy to use, and gets the job done efficiently, though is does offer some various advanced functionality.
You may ask, but why just casting spells? Where are the other options? If you think about it, basically anything you would want to do, baring advanced triggered effects, can be done simply using a base blizzard spell cast on an enemy. Stuns, slows, damage, etc. Whatever.
Read Me:
Line Spell Template v4
Importing:
*Copy the LineSpellTemplate trigger to your map.
*Save. If it saves, everything is ready to go, if not, try again.
*Copy the Line Spell Template Dummy to your map, and the model it uses, unless you already have a comparable type of unit
*Configure the options and enjoy!
*Optionally requires the GroupUtils library.
Usage:
All you need to do is call the function LST_Cast()
This can be done in JASS as normal, or in GUI through the "Custom Script" Action
function LST_Cast takes unit cast, string sfx, real range, real angle, real speed, real dist, integer abil, integer lvl, string order returns unit
cast is the caster of your ability
sfx is the effect you want used as your missiles model - remember to use \\ as opposed to just \ as in GUI
range is the range of the effect of the spell around the unit created, or, how close an enemy has to be to get hit
angle is the angle to launch the projectile, in radians
speed is the movement rate the projectile will move at per timer interval
dist is the total distance the projectile moves
abil is the ability to be cast on affected units
lvl is the level of the ability you want casted
string is the string order used to cast said ability
returns the missile unit created
for example:
call LST_Cast( GetTriggerUnit(),"Abilities\\Weapons\\LichMissile\\LichMissile.mdl",200,90.,15.,1000.,'A023',3,"innerfire")
This will, for the caster of the ability, create a missile with the lichs attack as its model, and move it at 15 speed, a total of 1000 distance. Enemies within 200 range will have your caster dummy cast the ability with rawcode 'A023', of level 3, with the string "innerfire", so that an innerfire ability will be cast on effected units.
Extra:
Using an ability rawcode of 0 as the argument abil will cast nothing. This is incase you just want a projectile, and nothing else.
Function returns the created unit, so the user can edit all aspects of it as they so choose.
See the System's comments for advanced JASS use, including interfaces and struct members.
Importing:
*Copy the LineSpellTemplate trigger to your map.
*Save. If it saves, everything is ready to go, if not, try again.
*Copy the Line Spell Template Dummy to your map, and the model it uses, unless you already have a comparable type of unit
*Configure the options and enjoy!
*Optionally requires the GroupUtils library.
Usage:
All you need to do is call the function LST_Cast()
This can be done in JASS as normal, or in GUI through the "Custom Script" Action
function LST_Cast takes unit cast, string sfx, real range, real angle, real speed, real dist, integer abil, integer lvl, string order returns unit
cast is the caster of your ability
sfx is the effect you want used as your missiles model - remember to use \\ as opposed to just \ as in GUI
range is the range of the effect of the spell around the unit created, or, how close an enemy has to be to get hit
angle is the angle to launch the projectile, in radians
speed is the movement rate the projectile will move at per timer interval
dist is the total distance the projectile moves
abil is the ability to be cast on affected units
lvl is the level of the ability you want casted
string is the string order used to cast said ability
returns the missile unit created
for example:
call LST_Cast( GetTriggerUnit(),"Abilities\\Weapons\\LichMissile\\LichMissile.mdl",200,90.,15.,1000.,'A023',3,"innerfire")
This will, for the caster of the ability, create a missile with the lichs attack as its model, and move it at 15 speed, a total of 1000 distance. Enemies within 200 range will have your caster dummy cast the ability with rawcode 'A023', of level 3, with the string "innerfire", so that an innerfire ability will be cast on effected units.
Extra:
Using an ability rawcode of 0 as the argument abil will cast nothing. This is incase you just want a projectile, and nothing else.
Function returns the created unit, so the user can edit all aspects of it as they so choose.
See the System's comments for advanced JASS use, including interfaces and struct members.
System Code:
JASS:
library LST needs optional GroupUtils
//=====Line Spell Template v4=====\\
globals
public constant real TIMEOUT = .04 // Periodic timer interval, lower=looks better but less efficient, higher=looks worse but more efficient
private constant integer CASTERID = 039;n000039; // Rawcode of your map's dummy caster
private constant integer MISSILEID = 039;n004039; // Rawcode of your map's Line Spell Template Dummy, or comparable dummy unit
endglobals
private function Filt takes unit caster, unit target returns boolean
return true // Custom targeting filter
endfunction
//=====DON'T TOUCH PAST THIS POINT!!!=====\\
globals
private timer T=CreateTimer()
private integer I=0
private linespell TEMPD
private linespell array D
private unit TARG=null
private boolexpr B
private group G=CreateGroup()
endglobals
private interface face
// Every periodic interval
method onPeriodic takes nothing returns nothing defaults nothing
// When the line spell is over
method onEnd takes nothing returns nothing defaults nothing
// When a unit is collided with
method onCollision takes unit target returns nothing defaults nothing
endinterface
struct linespell extends face
unit caster // Caster of the spell
unit dummy // Projectile dummy unit
group g=null // Units that have been struck
player p // Owner of the projectile
effect sfx // Effect created on dummy
integer abil=0 // Ability to be cast
integer lvl // Level of ability to be cast
integer ticks // Number of iterations until the spell is over
string order // Order for ability to be case
real cos // X vector component of movement
real sin // Y vector component of movement
real angle // Angle of movement in Radians
real range // Collision radius around projectile
method destroy takes nothing returns nothing
call .onEnd()
// Clean up
call DestroyEffect(.sfx)
call KillUnit(.dummy)
if .abil>0 then
static if LIBRARY_GroupUtils then
call ReleaseGroup(.g)
else
call DestroyGroup(.g)
endif
set .abil=0
endif
endmethod
private static method filter takes nothing returns boolean
local unit dum
local linespell this=TEMPD
set TARG=GetFilterUnit()
if Filt(.caster,TARG) and not IsUnitInGroup(TARG,.g) and IsUnitEnemy(TARG,.p) and UnitAlive(TARG) then // Target unit is valid
// Cast ability on target
set dum=CreateUnit(.p,CASTERID,GetUnitX(TARG),GetUnitY(TARG),0.)
call UnitApplyTimedLife(dum,039;BTLF039;,1.)
call UnitAddAbility(dum,.abil)
call SetUnitAbilityLevel(dum,.abil,.lvl)
call IssueTargetOrder(dum,.order,TARG)
set dum=null
// Store unit to eliminate future targeting
call GroupAddUnit(.g,TARG)
call .onCollision(TARG)
endif
return false
endmethod
private static method movement takes nothing returns nothing
local integer i=1
local real x
local real y
local linespell this
loop
exitwhen i>I
set this=D<i>
if .ticks==0 then // Max distance reached
call .destroy()
set D<i>=D<i>
set I=I-1
set i=i-1
else // Update position of missile, deal targeting effects
set .ticks=.ticks-1
set x=GetUnitX(.dummy)+.cos
set y=GetUnitY(.dummy)+.sin
call SetUnitX(.dummy,x)
call SetUnitY(.dummy,y)
// Filter through available targets
set TEMPD=this
call GroupEnumUnitsInRange(G,x,y,.range,B)
call .onPeriodic()
endif
set i=i+1
endloop
if I==0 then // No more instances currently running
call PauseTimer(T)
endif
endmethod
static method create takes unit cast, string sfx, real range, real angle, real speed, real dist, integer abil, integer lvl, string order returns linespell
local linespell this=linespell.allocate()
set .angle=angle
set .caster=cast
set .p=GetOwningPlayer(cast)
set .cos=speed*Cos(angle)
set .sin=speed*Sin(angle)
set .dummy=CreateUnit(.p,MISSILEID,GetUnitX(cast)+.cos,GetUnitY(cast)+.sin,.angle*bj_RADTODEG)
set .sfx=AddSpecialEffectTarget(sfx,.dummy,"origin")
// Store total timeouts needed for this instance
set .ticks=R2I(dist/(speed))
set .range=range
if abil>0 then // User wants an ability cast
static if LIBRARY_GroupUtils then
set .g=NewGroup()
else
set .g=CreateGroup()
endif
set .abil=abil
set .lvl=lvl
set .order=order
endif
set I=I+1
// First instance
if I==1 then
call TimerStart(T,TIMEOUT,true,function linespell.movement)
endif
set D<i>=this
return this
endmethod
//==INITIALIZATION==\\
private static method onInit takes nothing returns nothing
set B=Condition(function linespell.filter)
endmethod
endstruct
//==USER FUNCTIONS==\\
public function Cast takes unit cast, string sfx, real range, real angle, real speed, real dist, integer abil, integer lvl, string order returns unit
local linespell d=linespell.create(cast,sfx,range,angle,speed,dist,abil,lvl,order)
return d.dummy
endfunction
endlibrary</i></i></i></i>
Release Info.
Version 4:
Version 3:
Version 2:
Version 1:
- Removed CSData requirement, added GroupUtils optional requirement, and requirement for the UnitAlive native
- No longer uses dynamic triggers for collision detection
- Now features interfaces for onEnd, onPeriodic and onCollision
- Various optimizations
- Replaced location with angle in base wrapper function
- Changed the way effects were removed to improve visuals
- Added a JASS use demonstration featuring interface implementation
Version 3:
- Now uses CSData to store and retrieve data from dynamic triggers
- No longer uses the bj_ variable
- Now uses a dummy missile unit with Vexs model, requiring the syntax to be slightly changed, taking now the effect string wanted as opposed to the dummy unit, and returning the created unit
- Read Me updated to reflect changes
Version 2:
- Ported to vJASS
- System now uses a different execution syntax, read the Read Me for more info.
- Added a new test spell: Nova
Version 1:
- Initial release