Before you continue:
First of all please forgive me for anything unclear in this article because English is not my native language.
Purpose of this tutorials:
1. Is to provide a useful code to other Ability makers, which has been tested in a map that works;
2. To show some advantage of vJass.
Preparation:
Tools:
All codes are written in vJass, kindly prepare the relative tools. I recommend Jass New Gen Pack.
Knowledge:
At least you have to know how vJass & Jass works, otherwise dont waste time on this tutorials.
Please ignore all sentences start with debug, its only for debugging.
Other statement:
I will provide:
Answering of any questions followed;
Code problems fixing.
But will not provide:
Code migrating;
Take responsibility for maps destruction by code misuse or map tools.
Have you been tired of creating a set of units then remove them one by one after that, or repeat loop/ endloop million times?
Here is an example: When a unit cast Flame Strike, create a Flame line on the ground from <TriggerUnit>s location to <SpellTarget> location. What do we do in a typical way?
1, Calculate the distance between <TriggerUnit>s location & <SpellTarget> location;
2, Create a set of dummy units attached special effects(or directly special effects without units) along the path between this two locations, by loop/ endloop;
3, Wait a little bit time;
4, Delete these sets of units, by an other loop/ endloop of course.
Yes you may think of a custom function to perform it, but how do you reach each of the elements? Again you may say global variables, and if this is in a melee game, you have to use array for different players.
This is millions of works.
Now try to imagine that we have unitsline type object in the game which we can declare and use at any time, what happen if we can do this?
Read the trigger below:
DrawUnitsline() is a custom function that returns unitsline, so we can easily use a local var to save it, then Get its length or Destroy it, such as what we normally do to a lightning, or effect, or unit.
This can be completely accomplished with our new friend, vJass.
I have to say that even now I am not so clear about how vJass works, anyway here is what we need to do:
Build a struct named unitsline, inclusive a real length, group members. "length is a sub-var that save the length of line, members is actually a group that save all units we created.
Code:

JASS:
struct unitsline
real length
group members
endstruct
Then we start our work, create a custom function. You may see that its just as normal as creating a custom function, but please pay attention to that how we save data in unitsline var:
Code:

JASS:
struct linedata
real ox
real oy
real tx
real ty
real dx
real dy
real face
endstruct
function DrawUnitsline takes player who, location startPoint, location endPoint returns unitsline
local unit u
local linedata line = linedata.create()
local unitsline units_line = unitsline.create()
local integer num
local integer f = 1
//! textmacro generaldebug
debug local string message
debug local string head
debug local string mid
debug local string end
//! endtextmacro
//! runtextmacro generaldebug()
set line.ox = GetLocationX( startPoint )
set line.oy = GetLocationY( startPoint )
set line.tx = GetLocationX( endPoint )
set line.ty = GetLocationY( endPoint )
set line.face = Atan2( line.ty - line.oy, line.tx - line.ox )
set units_line.members = CreateGroup()
set units_line.length = SquareRoot(( line.tx - line.ox ) * ( line.tx - line.ox ) + ( line.ty - line.oy ) * ( line.ty - line.oy ))
set num = R2I( units_line.length ) / R2I( line_step )
debug set head = "function call: " + SetTextColor( "Drawline()", "Yellow" ) + " "
debug set mid = "by " + SetTextColor( "Player " +I2S( GetPlayerId( who ) + 1 ), "Red" ) + ", "
debug set end = SetTextColor( I2S( num ), "Yellow" ) + " units been placed."
debug set message = head + mid + end
loop
exitwhen f > num
set line.dx = line.ox + I2R(f) * line_step * Cos( line.face )
set line.dy = line.oy + I2R(f) * line_step * Sin( line.face )
set u = CreateUnit( who, Dummysetting_DummyU, line.dx, line.dy, 0.0 )
call SetUnitPathing( u, false )
call SetUnitFlyHeight( u, 0.00, 0.00 )
call AddSpecialEffectTarget( Dummysetting_FireModel, u, "origin" )
call GroupAddUnit( units_line.members, u )
set u = null
set f = f + 1
endloop
debug call BJDebugMsg( message )
call linedata.destroy( line )
return units_line
endfunction
Now we already have a function that can create and return a unitsline, we still need more functions to reach the data that contain in this type of object. Of course the most important 1 is Destroy, we cant just create something and then let it run forever without anyway to destroy. Another function I can think of is to get a unitslines length, actually its not necessary because you may use whichLine.length to get it simply, I create this function for an example purpose that how it works only.
Code:

JASS:
function DestroyUnitsline takes unitsline whichLine returns nothing
local unit u
debug local integer num = 0
//! runtextmacro generaldebug()
loop
set u = FirstOfGroup( whichLine.members )
exitwhen u == null
call RemoveUnit( u )
debug set num = num + 1
call GroupRemoveUnit( whichLine.members, u )
endloop
debug set head = "function call: " + SetTextColor( "DestroyUnitsline()", "Yellow" ) + " "
debug set mid = SetTextColor( I2S(num), "Yellow" ) + " units been destroyed."
debug set message = head + mid
debug call BJDebugMsg( message )
call whichLine.destroy()
endfunction
function GetUnitslineLength takes unitsline whichLine returns real
//! runtextmacro generaldebug()
debug local integer num = CountUnitsInGroup( whichLine.members )
debug set head = "function call: " + SetTextColor( "GetUnitslineLength()", "Yellow" ) + " "
debug set mid = "= " + SetTextColor( R2S( whichLine.length ), "Yellow" ) + "; "
debug set end = SetTextColor( I2S(num), "Yellow" ) + " x " + SetTextColor( R2S(line_step), "Yellow" ) + " = " + SetTextColor( R2S( I2R(num) * line_step ), "Yellow" )
debug set message = head + mid + end
debug call BJDebugMsg( message )
if ( whichLine.members == null ) then
return 0.0
endif
return whichLine.length
endfunction
And here is the complete code, in case you don't have interest with researching it you can just paste it to your map and use:
Code:

JASS:
library Dummysetting
globals
public constant integer DummyU = 'u000'
public constant string FireModel = "Abilities\\Spells\\Human\\FlameStrike\\FlameStrikeDamageTarget.mdl"
endglobals
struct unitsline
real length
group members
endstruct
scope Debugfunctions
function SetTextColor takes string txt, string color returns string
//! textmacro settextcolorfunction takes color, colorcode
if ( color == "$color$" ) then
set color = "$colorcode$"
endif
//! endtextmacro
//! runtextmacro settextcolorfunction ( "White", "|cFFFFFFFF" )
//! runtextmacro settextcolorfunction ( "Red", "|c00ff0000" )
//! runtextmacro settextcolorfunction ( "Blue", "|c000000ff" )
//! runtextmacro settextcolorfunction ( "Teal", "|c0000ffff" )
//! runtextmacro settextcolorfunction ( "Purple", "|c00800080" )
//! runtextmacro settextcolorfunction ( "Yellow", "|c00ffff00" )
//! runtextmacro settextcolorfunction ( "Green", "|c0000ff00" )
//! runtextmacro settextcolorfunction ( "Pink", "|c00ff00ff" )
//! runtextmacro settextcolorfunction ( "Gray", "|cFF808080" )
//! runtextmacro settextcolorfunction ( "LightBlue", "|cFFC0FFFF" )
//! runtextmacro settextcolorfunction ( "DarkGreen", "|cFF004000" )
//! runtextmacro settextcolorfunction ( "Brown", "|cFF400000" )
//! runtextmacro settextcolorfunction ( "Black", "|cFF000000" )
return color + txt + "|r"
endfunction
endscope
endlibrary
library Drawfunctions requires Dummysetting
globals
private constant real line_step = 30.0
private constant real letter_verticle = 400.0
private constant real letter_horizon = letter_verticle * 2.0
private constant real effect_lifetime = 5.00
private constant real angle_step = 3.00
endglobals
scope UnitslineFunctions
struct linedata
real ox
real oy
real tx
real ty
real dx
real dy
real face
endstruct
function DrawUnitsline takes player who, location startPoint, location endPoint returns unitsline
local unit u
local linedata line = linedata.create()
local unitsline units_line = unitsline.create()
local integer num
local integer f = 1
//! textmacro generaldebug
debug local string message
debug local string head
debug local string mid
debug local string end
//! endtextmacro
//! runtextmacro generaldebug()
set line.ox = GetLocationX( startPoint )
set line.oy = GetLocationY( startPoint )
set line.tx = GetLocationX( endPoint )
set line.ty = GetLocationY( endPoint )
set line.face = Atan2( line.ty - line.oy, line.tx - line.ox )
set units_line.members = CreateGroup()
set units_line.length = SquareRoot(( line.tx - line.ox ) * ( line.tx - line.ox ) + ( line.ty - line.oy ) * ( line.ty - line.oy ))
set num = R2I( units_line.length ) / R2I( line_step )
debug set head = "function call: " + SetTextColor( "Drawline()", "Yellow" ) + " "
debug set mid = "by " + SetTextColor( "Player " +I2S( GetPlayerId( who ) + 1 ), "Red" ) + ", "
debug set end = SetTextColor( I2S( num ), "Yellow" ) + " units been placed."
debug set message = head + mid + end
loop
exitwhen f > num
set line.dx = line.ox + I2R(f) * line_step * Cos( line.face )
set line.dy = line.oy + I2R(f) * line_step * Sin( line.face )
set u = CreateUnit( who, Dummysetting_DummyU, line.dx, line.dy, 0.0 )
call SetUnitPathing( u, false )
call SetUnitFlyHeight( u, 0.00, 0.00 )
call AddSpecialEffectTarget( Dummysetting_FireModel, u, "origin" )
call GroupAddUnit( units_line.members, u )
set u = null
set f = f + 1
endloop
debug call BJDebugMsg( message )
call linedata.destroy( line )
return units_line
endfunction
function DestroyUnitsline takes unitsline whichLine returns nothing
local unit u
debug local integer num = 0
//! runtextmacro generaldebug()
loop
set u = FirstOfGroup( whichLine.members )
exitwhen u == null
call RemoveUnit( u )
debug set num = num + 1
call GroupRemoveUnit( whichLine.members, u )
endloop
debug set head = "function call: " + SetTextColor( "DestroyUnitsline()", "Yellow" ) + " "
debug set mid = SetTextColor( I2S(num), "Yellow" ) + " units been destroyed."
debug set message = head + mid
debug call BJDebugMsg( message )
call whichLine.destroy()
endfunction
function GetUnitslineLength takes unitsline whichLine returns real
//! runtextmacro generaldebug()
debug local integer num = CountUnitsInGroup( whichLine.members )
debug set head = "function call: " + SetTextColor( "GetUnitslineLength()", "Yellow" ) + " "
debug set mid = "= " + SetTextColor( R2S( whichLine.length ), "Yellow" ) + "; "
debug set end = SetTextColor( I2S(num), "Yellow" ) + " x " + SetTextColor( R2S(line_step), "Yellow" ) + " = " + SetTextColor( R2S( I2R(num) * line_step ), "Yellow" )
debug set message = head + mid + end
debug call BJDebugMsg( message )
if ( whichLine.members == null ) then
return 0.0
endif
return whichLine.length
endfunction
endscope
endlibrary