• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

*Effectline* To improve your linear spells

Level 8
Joined
Feb 15, 2009
Messages
463
Effectline System v 1.0.avJass
Hey Guys,

1. Introduction

A. What you are giving us Saia?
I'm proud to present you a system which aids you creating (straight) lines
compared with several effects and mehods you can call on/with/in/at them.
All this runs via a struct ,which is nearly unlimited configurable
B. What can we do with it Saia?
This allows you to create linespells pared with effects more easy e.g you can easily trigger a stunning shockwave or a manaburning line etc. with this system

BUT
i would only use if u have at least (2 - indefinite) spells which should behave linear otherwise its not necessary to have this System

2.Facts / Requirements / etc.

-JNGP
-uses vJass
- The Effectline script which you have to include in your map

3.Manual
Here is the (current , more will come in next vers.) list which explains how to use the single methods , how to create a line ...


JASS:
So this is a System which aids you creating Lines ( which can be used to create linespells , eyecandy 
or just because you like lines )
Also there are following  examples ( Just Spells ) included in this Map:( more will come )

 - Magical Line
 - Firestorm
 - Arctic Wave
 
 
THIS IS THE MANUAL I THINK U SHOULD READ BEFORE USING
=======================================================================================
 
There are some defaults use by the System which you should change in the Effectline trigger
but i list them up here to explain them :

    integer          DUMMY_ID = 'u000'      //Set this to the Dummypath used by your Map(should be flying and use the dummy model of vexorian (look the import section of this map))
    
    real                EFFECT_DISTANCE  = 35. // How far a effect is created from the previous one. This is the MIN VALUE which a step could minimal be set to  
    
    integer          MAX_INSTANCES = 90 // The MAX counter of effects created ,higher values allow longer lines, but a bit less performace 
    
    real                EFFECTLINE_UNITRANGE = 150. //(default )How far from the Line  the Units are catched from the GetUnitsOnLine Method

======================================================================================= 


 The first method is just the Create method used like this :
 
 
 ( LINENAME can be what you want it to be [ just to tell you ] )
 
1st :  local    Effectline      LINENAME  (nothing more or it will not work correct if created at beginning )
2nd : set LINENAME  =   Effectline.Create( player owner , real sourceX , real sourceY , real targetX , real targetY , string look , string attach , real linestep )

//********************************************************************************************************

        player          owner                   The Owner of the Effectline
        real              sourceX               The X Coordinate of the start point 
        real              sourceY               The Y Coordinate of the start point
        real              targetX                The X Coordinate of the end point
        real              targetY                The Y Coordinate of the end point
        string           look                     The string name of the model which should be used       ( e.g. "Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl" )
        string           attach                  The string name of the attachmentpoint                          ( e.g. "origin" )
        real              linestep               The real value of the distance between each line object ( just use 0. to use the default one or your own like 75. just do what u want here)

//********************************************************************************************************

        so it will look like this then :
        
        local Effectline LINENAME
        
        // DO what u want with your code
        
        set LINENAME = Effectline.Create( Player(0) , 0. , 0. , 500. , 500. , "Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl" , "origin" , 0. ) // we used a linestep of 0 here to use the default one just experiment which step fits best with which model
        
        
 The next thing to know is just to know how to destroy the Effectline
 
 You just can do this with
        
        call LINENAME + . + destroy + ( )
        
        so it will look like this then :
        
        call LINENAME.destroy()

        the rest will be cleaned by itself
    
    Now your Effectline is there where u created it ( haha ) and you can destroy it , but you want more or not ?

=======================================================================================
    
    
First of all i show you the method model which allows you to change the model of a existing line

method operator model= takes string newPath returns nothing
 
//********************************************************************************************************
 
        newPath is the just the string used by the new model

//********************************************************************************************************

This time we do this with the set LINENAME + . + model = newPath
 
To take up the last example we have this :

    local Effectline LINENAME

    set LINENAME = Effectline.Create( Player(0) , 0. , 0. , 500. , 500. , "Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl" , "origin" , 0. )
 
    Now we just use a wait or a timer to wait the time till we change the model
    
    call PolledWait(1.5) // we wait 1.5 seconds and then :
    
    set LINENAME.model = "Abilities\\Spells\\Orc\\LiquidFire\\Liquidfire.mdl"
    
    Now we changed the Effectline look-a-like to a burning fire (know it doesn't fit with the drain model )
    
    You can also call this multiple times maybe used for mutating lines etc.
    
=======================================================================================

The next method is the :

method GetUnitsOnLine takes  real radius ,boolexpr match, unit caster returns nothing

This method just catches the units which are within a changeable radius of the Effectline and adds them
to the struct´s own group STRUCTNAME + . + affect

to do this just call

call STRUCTNAME + . + GetUnitsOnLine ( real radius ,boolexpr match, unit caster )
    
//********************************************************************************************************

        real                radius               The MaxDistance from units to the line to be catched ( use 0. if you want the default one )
        boolexpr        match               The Condition for Units to be catched 
        unit                caster               The Spellcaster is needed to be not catched himself in the group
        
//********************************************************************************************************

Now you can loop through your group like you want ( e.g. ForGroup(group g, code c) , or with FirstOfGroup(group g)
    
____________________IMPORTANT_____________________________________________________________    

Before you use the .affect group you must have called .GetUnitsOnLine or the group will not exist already

______________________________________________________________________________________________     

The STRUCTNAME.affect group can also be changed to a local group  with following code :

 1st :  local group g = CreateGroup()
 
 2nd : call STRUCTNAME + . + GetUnitsOnLine( 0. , boolexpr , caster )
 
 3rd : call GroupAddGroup( STRUCTNAME.affect , g )
 
 Now you have the Units in your local group g and can do whatever you want to do with them

 
=======================================================================================

The in this version last included method is the Color method ( more methods will come )

method Color takes integer red , integer green , integer blue , integer alpha returns nothing

This method just allows you to change the visual attributes of a line because we change the
Effectline`s base units colors and alphas  to which the effects are attached which has visual
changings to the effects attached ( Doesnt work for everything , but for most buffs it will work ( like the Icecube from the Frostwyrms chilling attack)  )

You can call this method like this:

call STRUCTNAME + . + Color(integer red , integer green , integer blue , integer alpha) to change its color .


e.g

call STRUCTNAME.Color ( 255 , 255, 255 ,0 ) now nothing will be shown coz we reduced the alpha value to min 
( or max min this case ) and the models will be invisible so also the effect attached to it













Fine we read us in next version with some new methods and if neccessary some fixes.


Regards Saia_Djinn


4.System Code
JASS:
//******************************************************************************************
//                                  Line System by Saia_Djinn 
//                                               v. 1.0
//
//Credits go to:
//Vexorian,  for his work for the Community(and Introducing vJass) and the DummyModel
//         
//          
//
//SlyRabbit for writing a NewType tutorial , which the Line System is mainly based on
//******************************************************************************************

library Effectline

//Config*************************************************************************************

globals
    private constant integer DUMMY_ID = 'u000'      //Set this to the Dummypath used by your Map(should be flying) can also be the one from e.g. xe system etc.
    private constant real EFFECT_DISTANCE  = 35. // How far a effect is created from the previous One (MIN VALUE) max can be set on the create method
    private constant integer MAX_INSTANCES = 60 // The MAX counter of effects created ,higher values allow longer lines, but a bit less performace 
    private constant real EFFECTLINE_UNITRANGE = 150. //How far from the Line  the Units are catched from the UnitsOnLine Method
endglobals

//End***************************************************************************************

private struct Data
    real sX
    real sY
    real tX
    real tY
    real facing
    
    real cX
    real cY
endstruct

struct Effectline
    
    real distance
    group effectcounter
    effect array fxremove[MAX_INSTANCES]
    group affect

static method Create takes player owner ,real sourceX ,real sourceY ,real targetX ,real targetY,string look, string attach , real linestep returns Effectline
    local unit dummy
    local Data value = Data.create()
    local Effectline line = Effectline.create()
    local integer count
    local integer a = 0
    local real step
    
    if ( linestep == 0. ) then 
        set step = EFFECT_DISTANCE
    else
        set step = linestep
    endif
    
    set value.sX = sourceX
    set value.sY = sourceY
    set value.tX = targetX
    set value.tY = targetY
    set value.facing =  Atan2( value.tY - value.sY, value.tX - value.sX )
    
    set line.effectcounter = CreateGroup()
    set line.distance = SquareRoot( (value.tX - value.sX ) * (value.tX - value.sX ) + (value.tY - value.sY ) * (value.tY - value.sY ) )
    
    set count = R2I( line.distance / step )
    
    loop
        set a = a+1
        exitwhen a > count
            set value.cX = value.sX + I2R(a) * step * Cos(value.facing )
            set value.cY = value.sY + I2R(a) * step * Sin(value.facing )
            
            set dummy = CreateUnit(owner ,DUMMY_ID ,value.cX ,value.cY ,0. )
            call SetUnitPathing(dummy ,false )
            call SetUnitFlyHeight(dummy ,0. ,0 )
            
            set line.fxremove[a] = AddSpecialEffectTarget( look , dummy , attach )
            call GroupAddUnit(line.effectcounter,dummy )
            set dummy = null
    endloop
    
    call Data.destroy(value)
    
    return line
endmethod

method operator model= takes string newPath returns nothing
    local integer a = 0
    local unit v
    local group g = CreateGroup()

    call GroupAddGroup(this.effectcounter , g)
    
    loop
        set a = a+1
        exitwhen a > MAX_INSTANCES
            call DestroyEffect( this.fxremove[a] )
            set this.fxremove[a] = null
    endloop

    set a = 0
    
    loop
        set v = FirstOfGroup(g)
        set a = a+1
        exitwhen v == null
            set this.fxremove[a] = AddSpecialEffectTarget( newPath , v , "origin" )
            call GroupRemoveUnit(g, v)
    endloop
    
    call DestroyGroup(g)
    set g= null
endmethod

method Color takes integer red , integer green , integer blue , integer alpha returns nothing
    local group g = CreateGroup()
    local unit v
    
    call GroupAddGroup(this.effectcounter , g)
    
    loop
        set v = FirstOfGroup(g)
        exitwhen v == null
        call SetUnitVertexColor(v ,red , green, blue ,alpha )
        call GroupRemoveUnit(g, v)
    endloop
    
    call DestroyGroup(g)
    set g = null
endmethod

method GetUnitsOnLine takes  real radius ,boolexpr match, unit caster returns nothing
    local group g = CreateGroup()
    local real x
    local real y
    local unit v
    local group Temp = CreateGroup()
    
    set this.affect = CreateGroup()
    
    if radius == 0. then
        set radius = EFFECTLINE_UNITRANGE
    endif
    
    call GroupAddGroup(this.effectcounter, Temp)
    
    loop
        set v = FirstOfGroup(Temp)
        set x = GetUnitX(v)
        set y = GetUnitY(v)
        exitwhen v == null
            call GroupRemoveUnit(Temp , v )
            call GroupEnumUnitsInRange(g , x, y , radius , match )
            
            loop
                set v = FirstOfGroup(g)
                exitwhen v == null
                    if IsUnitInGroup(v , this.affect ) or IsUnit(v , caster ) then
                        call GroupRemoveUnit(g , v )
                    else
                        call GroupAddUnit(this.affect,v)
                        call GroupRemoveUnit(g , v )
                    endif
            endloop
            
            call GroupClear(g)
    endloop
    
    
    call DestroyBoolExpr(match)
    call DestroyGroup(Temp)
    call DestroyGroup(g)
    set match = null
    set Temp = null
    set g = null

endmethod

method onDestroy takes nothing returns nothing
    local unit d
    local integer a = 0
    
    if this.affect != null then
        call DestroyGroup(this.affect)
        set this.affect = null
    endif
        
    loop
        set d = FirstOfGroup( this.effectcounter)
        exitwhen d == null
            call RemoveUnit(d)
            call GroupRemoveUnit( this.effectcounter, d)
            set d = null
    endloop

    loop
        set a = a+1
        exitwhen a > MAX_INSTANCES
            call DestroyEffect( this.fxremove[a] )
            set this.fxremove[a] = null
    endloop 
    
endmethod

endstruct

endlibrary


5.News
-More methods will appear when i find some time to add new code , for bugfixes i have always time.

-A guide (comments) in the examples will come 2

6.Screens
1. Arctic Wave


arcticwave.jpg



2. Firestorm
firestorm.jpg


E:
-Fixed Images
-Reworked Presentation a bit
 

Attachments

  • Effectline v.1.0.w3x
    62.9 KB · Views: 49
Last edited:
Level 11
Joined
Nov 4, 2007
Messages
337
if ( linestep == 0. ) then

==>

if linestep == 0. then


static method Create takes player owner ,real sourceX ,real sourceY ,real targetX ,real targetY,string look, string attach , real linestep returns Effectline

==> Better to have two possibilities:
A: Create X effects between the points.
B: Create as much effects as fit between the points with distance d.


Simple, but nice system.
 
Level 8
Joined
Feb 15, 2009
Messages
463
It is a struct so i can call things like model and GetUnitsOnLine more easily and faster then with functions( think its also not possible to attach then the different groups etc. to the function )

What else then enums ? plz gimme examples

and for that :
if ( linestep == 0. ) then

==>

if linestep == 0. then

thx for that Taktiker

but 2 your second point :

A: Create X effects between the points.
Coz of i added the linestep argument so you can easily get it: e.g max range = 600 and linestep = 60 then u can have max 10 instances
B: Create as much effects as fit between the points with distance d.
then use a step of 0.01 which will be very imperformant(is this a word ?) and the MAX_INSTANCES global has to be very high 2 to get this working
 
Level 11
Joined
Nov 4, 2007
Messages
337
JASS:
static method Create takes player owner ,real sourceX ,real sourceY ,real targetX ,real targetY,string look, string attach , real linestep returns Effectline
    local unit dummy
    local Data value = Data.create()


===>

JASS:
static method create takes player owner ,real sourceX ,real sourceY ,real targetX ,real targetY,string look, string attach , real linestep returns Effectline
    local unit dummy
    local Data value = Data.allocate()

JASS:
method Color takes integer red , integer green , integer blue , integer alpha returns nothing
    local group g = CreateGroup()
    local unit v

    call GroupAddGroup(this.effectcounter , g)

    loop
        set v = FirstOfGroup(g)
        exitwhen v == null
        call SetUnitVertexColor(v ,red , green, blue ,alpha )
        call GroupRemoveUnit(g, v)
    endloop

    call DestroyGroup(g)
    set g = null
endmethod
Wow, this method is so bad..
You push the handle ID and use GroupAddGroup!

JASS:
call GroupAddGroup(this.effectcounter, Temp)
    call DestroyBoolExpr(match)
    call DestroyGroup(Temp)
    call DestroyGroup(g)

Err.. Ok.
I tell everybody: Don't use this! It's unperformant and pushes the handle ID.
Recycle/Clear groups better!

And: Don't use groups! Use unit arrays!
 
Level 11
Joined
Feb 22, 2006
Messages
752
Don't use groups! Use unit arrays!

Sometimes groups are necessary, like when using the unit enum functions (there's no way to do that other than groups). And sometimes wut you're doing dictates that using group is smarter than using an array. For example, if you're going to be doing a lot of searching, IsUnitInGroup() is more or less a constant time operation while searching through a unit array is linear time. So don't say groups suck, never use them. Groups have their uses; you just need to know when it's good to use them.
 
Top