• 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.

[JASS] First Jass

Status
Not open for further replies.
Ok... I got some troubles, I read a big long tut on JASS got the jist of it, but it was wrong... I got like 18 errors in my custom code for a spell I thought up, I think its all just basic errors someone more familliar with JASS could fix, so if you would look through this and find the errors it would help me out.
JASS:
function Condo takes nothing returns boolean
  if ( not ( GetSpellAbilityId() == 'Awrs' ) ) then
    return false
  endif
  return true
endfunction

function Lightning takes nothing returns nothing
  local location p
  local group g
  local unit u
  set p = PolarProjectionBJ(GetUnitLoc(udg_cast), (udg_tim)*1.5+100, GetUnitAngle(udg_cast)+(udg_tim))
  set g = GetUnitsInRangeOfLocAll(100,p)
  call AddSpecialEffectLocBJ( p, "Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl" )
  loop
    set u=FirstOfGroup(g)
    exitwhen u==null
    call GroupRemoveUnit(g,u)
    if  IsUnitEnemy(u, GetOwningPlayer(udg_cast))==true then
      call KillUnit(u)
    endif
  endloop
  set udg_tim=(udg_tim)+10
  set p=null
  set g=null
  set u=null
endfunciton

function Main takes nothing returns nothing
  local timer t
  set udg_tim=10
  set udg_cast=GetTriggerUnit()
  set t = CreateTimer()
  call TimerStart(t,0.03,true,function Lightning)
  call TriggerSleepAction(1.00)
  call DestroyTimer(t)
  set udg_cast=null
  set t=null
endfunction
  
function InitTrig_SSS takes nothing returns nothing
  local trigger t
  set t=CreateTrigger()
  call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
  call TriggerAddCondition(t, Condition(function Condo))
  call TriggerAddAction(t, function Main)
  set t=null
endfunction

//===========================================================================
function InitTrig_SSS takes nothing returns nothing
    set gg_trg_SSS = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_SSS, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_SSS, Condition( function Condo ) )
    call TriggerAddAction( gg_trg_SSS, function Main )
endfunction
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Why do you have two init blocks ? remove the lower one.
Also, DO NOT NULL THE TRIGGER.

Now, why do you use globals at all ? you can simply use locals for everything.

Every time the time actions start, you leak a... timer reference ?
Create a local timer that will be set to "GetExpiredTimer()" and null it.

JASS:
function Condo takes nothing returns boolean
  if ( not ( GetSpellAbilityId() == 'Awrs' ) ) then
    return false
  endif
  return true
endfunction
Can be
JASS:
function Condo takes nothing returns boolean
   return GetSpellAbilityId() == 'Awrs'
endfunction
 
Level 5
Joined
Oct 27, 2007
Messages
158
It isn't leaking a timer reference. The way it's done is unusual and prone to errors. This can cause problems when there are multiple instances. The lightning callback will run 33 times before the timer is destroyed and nulled. The actions function and the callback function both use udg_cast and udg_tim. This can cause a problem with multiple instances. You also have to lose the udg_cast and udg_tim global and attach those to the timer instance. You can also attach a callback count which holds the number of times the callback needs to run. After that pause the timer and destroy the timer in the callback function lightning.
 
It isn't leaking a timer reference. The way it's done is unusual and prone to errors. This can cause problems when there are multiple instances. The lightning callback will run 33 times before the timer is destroyed and nulled. The actions function and the callback function both use udg_cast and udg_tim. This can cause a problem with multiple instances. You also have to lose the udg_cast and udg_tim global and attach those to the timer instance. You can also attach a callback count which holds the number of times the callback needs to run. After that pause the timer and destroy the timer in the callback function lightning.


So..... Im getting something like...
JASS:
function Lightning takes interger tim, unit cast returns nothing
but wouldnt that ruin the looping effect and make tim not grow by 10each timer? I honestly dont know much of what your saying in the above, please post an example.
 
Ok Idk what VJASS is, until I look into it I would like to know JASS so if you would please help me with the basics first it would be helpful.

Also:
Can be
JASS:
function Condo takes nothing returns boolean
   return GetSpellAbilityId() == 'Awrs'
endfunction
What does this do, it checks if id == awrs and returns T/F?
... Yea thats more efficient then other way. Ok ty.

EDIT

Ok I got JassCraft and got this code
JASS:
function Condo takes nothing returns boolean
  return GetSpellAbilityId() == 'Awrs'
endfunction

function Buffer takes nothing returns nothing
  set udg_tim=10
endfunction
// Above is line 7, I beleive the error is actually for line 6 but it says line 7
  
function Lightning takes nothing returns nothing
  local location p
  local group g
  local unit u
  call Buffer
  set p = PolarProjectionBJ(GetUnitLoc(GetTriggerUnit()), real ((udg_tim)*1.5+100), (GetUnitFacing(unit GetTriggerUnit()+(udg_tim)))
// Above is line 14
  set g = GetUnitsInRangeOfLocAll(100,p)
  call AddSpecialEffectLocBJ( p, "Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl" )
  loop  
    set u=FirstOfGroup(g)    
    exitwhen u==null    
    call GroupRemoveUnit(g,u)    
    if  IsUnitEnemy(u, GetOwningPlayer(GetTriggerUnit()))==true then      
      call KillUnit(u)    
    endif
  endloop
  set udg_tim = (udg_tim)+10  
// Above is line 25
  set p=null  
  set g=null  
  set u=null
endfunction

function Main takes nothing returns nothing  
  local timer t    
  set t = CreateTimer()  
  call Buffer
  call TimerStart(t,0.03,true,function Lightning) 
// Above is line 35 
  call TriggerSleepAction(1.00)  
  call DestroyTimer(t)    
  set t=null
endfunction

function InitTrig_SSS takes nothing returns nothing 
  local trigger t  
  set t=CreateTrigger()  
  call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)  
  call TriggerAddCondition(t, Condition(function Condo))  
  call TriggerAddAction(t, function Main)  
  set t=null
endfunction
I still have errors,
Line 7: Undeclared Variable: udg_tim
Line 14: Syntax error
Line 14: Syntax error
Line 25: Undeclared Variable: udg_tim
Line 35: Syntax error
 
Last edited:
Level 29
Joined
Jul 29, 2007
Messages
5,174
Ok Idk what VJASS is, until I look into it I would like to know JASS so if you would please help me with the basics first it would be helpful.

As I said, you need a attachment system.
What attachment systems basically do, is using a bug (one of the thousands >.<) that allows us to use H2I (Handle to Integer) and by that we can later on get the value in a different function.
So, we can create a local, attach it to the timer, and retrieve it in the timer call back.

If no one will give you links until tomorrow I will, I must go now though.

Also:

What does this do, it checks if id == awrs and returns T/F?
... Yea thats more efficient then other way. Ok ty.

It simply checks if that statement is true and then returns the answer (true or false).
Instead of that, blizzard in their awesome lazy coding, made it to check if the statement is NOT true, if its not true - return false, if its true, return true.
There is simply no need for this.
 
Level 4
Joined
May 25, 2007
Messages
55
Well, let me see if I can help you with what I know.
JASS:
function Condo takes nothing returns boolean
  return GetSpellAbilityId() == 'Awrs'
endfunction

function Buffer takes nothing returns nothing
  set udg_tim=10
//Is this all your gonna have this do?  Set a global to 10?
//If thats the case you don't even need to make this function, you could just
//hard code it in it's place
endfunction
// Above is line 7, I beleive the error is actually for line 6 but it says line 7
  
function Lightning takes nothing returns nothing
  local location p = PolarProjectionBJ(GetUnitLoc(GetTriggerUnit()), ((udg_tim)*1.5+100), (GetUnitFacing(unit GetTriggerUnit()+(udg_tim)))
//also you had real in your polarprojection function, thats a declaration term.
//so that would be one of your syntax errors.
  local group g = GetUnitsInRangeOfLocAll(100,p)
  local unit u

//Zack: you can set your variables the moment you declare them like this.
//Also, you might want to use more local variable to make the code easier to ready.  Such as 

//local unit tu = GetTriggerUnit()
//local location up = GetUnitLoc(tu)
//local real r = ((udg_tim) * 1.5 + 100)
//local real angle = GetUnitFacing(tu + udg_tim)
//local location p = PolarProjectionBJ(up,r,angle)
//call RemoveLocation(up)   //If you don't use GetUnitLoc(tu) anymore

//Zack: this alot easier to read, I Have it commented out so you can read it first
//Also, are you using NewGen world editor?  Cause it really helps for reading
//and fixing up Jass

  call Buffer()

//Zack: You forgot to put () after buffer, even if a function doesn't take a value,
//it needs an open and close parenthesis

// Above is line 14


  call AddSpecialEffectLocBJ( p, "Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl" )
//Zack: Your creating a special effect here but not getting rid of it, you might 
//want to store this in an effect variable, and destroy it when you need too.
//if you want to destroy it the moment its created, do this
call DestroyEffect(AddSpecialEffectLocBJ(p, "Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl" )

  loop  
    set u=FirstOfGroup(g)    
    exitwhen u==null    
    call GroupRemoveUnit(g,u)    
    if  IsUnitEnemy(u, GetOwningPlayer(GetTriggerUnit()))==true then      
      call KillUnit(u)    
    endif
  endloop
  set udg_tim = (udg_tim)+10  
// Above is line 25
call RemoveLocation(p)
//You need to remove locations when your done with them, or the cause
//a memory leak, which could lag/crash your game.
  set p=null  
  set g=null  
  set u=null
endfunction

function Main takes nothing returns nothing  
  local timer t = CreateTimer()  
//Zack: once again, they can be set when declared
  call Buffer()
//Zack: Another syntax error because you didn't have the () after buffer
  call TimerStart(t,0.03,true,function Lightning) 
// Above is line 35 
  call TriggerSleepAction(1.00)  
  call DestroyTimer(t)    
  set t=null
endfunction

function InitTrig_SSS takes nothing returns nothing 
  local trigger t = CreateTrigger()
//Zack: once again, can be set once declared, saves you a line.
  call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)  
  call TriggerAddCondition(t, Condition(function Condo))  
  call TriggerAddAction(t, function Main)  
  set t=null
//Zack: Ghostwolf, what happens if you null the local triggers?  
//They are locally declared, does something bad happen if you do?  
//Does it leak?  
//Cause my triggers all work fine even after the local trigger is nulled out.
endfunction

That could fix the error's you may have.

On another personal note, its better to use locations as minimal as possible. They consume more processing power and require you to remove them after they are used. Instead its better to use x and y coordinates.

It's actually alot easier, it only requires an extra declaration.

Instead of
JASS:
function LocationsSuck takes nothing returns nothing
    local unit tu = GetTriggerUnit()
    local location p = GetUnitLoc(tu)
    call RemoveLocation(p)
    set tu = null
    set p = null
endfunction

use

JASS:
function CoordinatesYay takes nothing returns nothing
    local unit tu = GetTriggerUnit()
    local real x = GetUnitX(tu)
    local real y = GetUnitY(tu)

    set tu = null
endfunction

Coordinates are reals so they don't need to be nulled out or removed, also they take less processing power so the game runs them faster.

Practically every useful function in jass uses x and y coordinates, so you should always use them over locations everytime you can. It's a good habit to start off on.
 
JASS:
function Condo takes nothing returns boolean  
  if ( not ( GetSpellAbilityId() == 'Awrs' ) ) then    
  return false  
  endif  
  return true
endfunction

function Buffer takes nothing returns nothing
  set udg_tim=10
endfunction
  
function Lightning takes nothing returns nothing
  call Buffer()
  local unit tu = GetTriggerUnit()
  local location up = GetUnitLoc(tu)
  local real r = ((udg_tim) * 1.5 + 100)
  local real angle = GetUnitFacing(tu + udg_tim)
  local location p = PolarProjectionBJ(up,r,angle)
  local group g = GetUnitsInRangeOfLocAll(100,p)
  call DestroyEffect(AddSpecialEffectLocBJ(p, "Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl" ))
  loop  
    local unit u = FirstOfGroup(g)    
    exitwhen u==null    
    call GroupRemoveUnit(g,u)    
    if  IsUnitEnemy(u, GetOwningPlayer(GetTriggerUnit()))==true then      
      call KillUnit(u)    
    endif
  endloop
  set tu=null
  set udg_tim = ((udg_tim)+10)
  call RemoveLocation(p)
  set r=null
  set angle=null  
  set g=null  
  call RemoveLocation(up)
endfunction

function Main takes nothing returns nothing      
  local timer t = CreateTimer()  
  call Buffer()
  call TimerStart(t,0.03,true,function Lightning)  
  call TriggerSleepAction(1.00)  
  call DestroyTimer(t)    
  set t=null
endfunction

function InitTrig_SSS takes nothing returns nothing 
  local trigger t  
  set t=CreateTrigger()  
  call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)  
  call TriggerAddCondition(t, Condition(function Condo))  
  call TriggerAddAction(t, function Main)  
  set t=null
endfunction

Still has alot of errors, sayin it wont let me declare variables at same time as giving them a value.
 
Level 4
Joined
May 25, 2007
Messages
55
JASS:
function Condo takes nothing returns boolean  
  return GetSpellAbilityId() == 'Awrs' 
//This is the raw code for Neutral Unit ability Warstomp,
// what are you trying to do, maybe I can help you do it?
endfunction

function Buffer takes nothing returns nothing
  set udg_tim=10
endfunction

function RunBuffer takes nothing returns integer
  call Buffer()
  return 0
//see this function is called when you declare your i integer,
//its purpose is just to return the integer 0, 
//but at the same time, this function runs buffer,
//so you can set your global to 10... for whatever reason you have
endfunction
  
function Lightning takes nothing returns nothing
//  call Buffer()
//Buffer cant be called here!!! you cannot use the call function
//before any local declarations.  
//But if you want, you can trick 
//the code into running it first anyway
//create a function that returns a value,
// and have it call buffer during that function.
//  local integer i = RunBuffer()
//But if your going to change udg_tim during the timer function
//this isnt necessary at all, as all buffer will do is undo your
//set udg_tim = udg_tim + 10 back to 10
  local unit tu = GetTriggerUnit()
//Also, this is a timer function, I'm not sure if timer's are capable of reading GetTriggerUnit(), so it might
//always be null, if thats the case you'll have to set a global variable or use a gamecache.
//I could show you if your interested.
  local location up = GetUnitLoc(tu)
  local real r = ((udg_tim) * 1.5 + 100)
  local real angle = GetUnitFacing(tu + udg_tim)
  local location p = PolarProjectionBJ(up,r,angle)
  local group g = GetUnitsInRangeOfLocAll(100,p)
  local unit u
  call DestroyEffect(AddSpecialEffectLocBJ(p, "Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl" ))
  loop  
//    local unit u = FirstOfGroup(g)
//once you use anything other than local, you cant declare locals anymore
    set u = FirstOfGroup(g)
    exitwhen u==null    
    call GroupRemoveUnit(g,u)    
    if  IsUnitEnemy(u, GetOwningPlayer(GetTriggerUnit()))==true then      
      call KillUnit(u)    
    endif
  endloop
  set tu=null
  set udg_tim = ((udg_tim)+10)
//if this is what your intending to do with the Buffer function, you dont want to run it during this code.
//also, why do you have so many parenthesis over this?  you can just put 
  set udg_tim = udg_tim + 10
  call RemoveLocation(p)
  set p = null
//make sure every locally declared variable 
//is nulled out when the function is finished
//the only variables that cant be nulled 
//are reals, integers, and booleans.
  set r=null
  set angle=null  
  set g=null  
  call RemoveLocation(up)
  //as a habit, Remove your locations 
//before you null out all your variables
  //this way you don't accidently null out
// a location before you remove it
  //because if you null the location out first,
// remove location cant remove it
  //and it ends up removing a location that doesn't exist
  set up = null
endfunction

function Main takes nothing returns nothing      
  local timer t = CreateTimer()  
  call Buffer()
  call TimerStart(t,0.03,true,function Lightning)  
  call TriggerSleepAction(1.00)  
  call DestroyTimer(t)    
  set t=null
endfunction

function InitTrig_SSS takes nothing returns nothing 
  local trigger t  
  set t=CreateTrigger()  
  call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)  
  call TriggerAddCondition(t, Condition(function Condo))  
  call TriggerAddAction(t, function Main)  
  set t=null
endfunction

It won't let you set a value when you declare it? Are you sure? You should be able too.

Edit: Actually I think that error is from you declaring a local after the local declaration. If you try to declare another local variable after using a call or set, it will give an error, because your not aloud to do that.
Declaring locals can only be done at the very beginning of the code.


Anyway, if you want to get it working, tell me what your trying to make warstomp do and I'll help you.

Edit2: Nevermind, i figured it out, your trying to making the caster do a warstomp, then have lightning explode in a spiral outward from the casters position. Am I correct?
 
Last edited:
Level 11
Joined
Feb 18, 2004
Messages
394
Problem 1: The function "Condo":
JASS:
function Condo takes nothing returns boolean
  if ( not ( GetSpellAbilityId() == 'Awrs' ) ) then
  return false
  endif
  return true
endfunction

Thats one hell of a mess, and its the same as:
JASS:
function Conditions takes nothing returns boolean
  return GetSpellAbilityId() == 'Awrs'
endfunction

Also, its suggested you prefix all function names with a codename so that there will be no conflicts, eg: MySpellName_Conditions()

Problem 2:
JASS:
function Lightning takes nothing returns nothing
  call Buffer()
  local unit tu = GetTriggerUnit()
  local location up = GetUnitLoc(tu)
  local real r = ((udg_tim) * 1.5 + 100)
  local real angle = GetUnitFacing(tu + udg_tim)
  local location p = PolarProjectionBJ(up,r,angle)
  local group g = GetUnitsInRangeOfLocAll(100,p)

You can only declare locals at the top of a function, BEFORE doing anything else. Calling the Buffer() function before declaring locals results in a syntax error.

Problem 3: The Buffer() function itself is useless. Removing it, and using 4 space indents (Which is the established norm):
JASS:
function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'Awrs'
endfunction

function Lightning takes nothing returns nothing
    local unit tu = GetTriggerUnit()
    local location up = GetUnitLoc(tu)
    local real r
    local real angle
    local location p = PolarProjectionBJ(up,r,angle)
    local group g = GetUnitsInRangeOfLocAll(100,p)
    
    set udg_tim = 10
    
    set r = ((udg_tim) * 1.5 + 100)
    set angle = GetUnitFacing(tu + udg_tim)
    
    call DestroyEffect(AddSpecialEffectLocBJ(p, "Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl" ))
    
    loop
        local unit u = FirstOfGroup(g)
        exitwhen u==null
        call GroupRemoveUnit(g,u)
        if IsUnitEnemy(u, GetOwningPlayer(GetTriggerUnit()))==true then
            call KillUnit(u)
        endif
    endloop
    
    set tu=null
    set udg_tim = ((udg_tim)+10)
    call RemoveLocation(p)
    set r=null
    set angle=null
    set g=null
    call RemoveLocation(up)
endfunction

function Main takes nothing returns nothing
    local timer t = CreateTimer()
    set udg_tim = 10
    call TimerStart(t,0.03,true,function Lightning)
    call TriggerSleepAction(1.00)
    call DestroyTimer(t)
    set t=null
endfunction

function InitTrig_SSS takes nothing returns nothing
    local trigger t
    set t=CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition(function Condo))
    call TriggerAddAction(t, function Main)
    set t=null
endfunction

Problem 4:
JASS:
    loop
        local unit u = FirstOfGroup(g)
Another local declared not at the top of the function. Fixing that yeilds:
JASS:
function Lightning takes nothing returns nothing
    local unit tu = GetTriggerUnit()
    local location up = GetUnitLoc(tu)
    local real r
    local real angle
    local location p = PolarProjectionBJ(up,r,angle)
    local group g = GetUnitsInRangeOfLocAll(100,p)
    local unit enum
    
    set udg_tim = 10
    
    set r = ((udg_tim) * 1.5 + 100)
    set angle = GetUnitFacing(tu + udg_tim)
    
    call DestroyEffect(AddSpecialEffectLocBJ(p, "Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl" ))
    
    loop
        set enum = FirstOfGroup(g)
        exitwhen enum == null
        call GroupRemoveUnit(g, enum)
        if IsUnitEnemy(enum, GetOwningPlayer(GetTriggerUnit())) == true then
            call KillUnit(enum)
        endif
    endloop
    
    set tu=null
    set udg_tim = ((udg_tim)+10)
    call RemoveLocation(p)
    set r=null
    set angle=null
    set g=null
    call RemoveLocation(up)
endfunction

Problem 5: the line set angle = GetUnitFacing(tu + udg_tim). You can not add a number to a unit >.> i must presume you meant: set angle = GetUnitFacing(tu) + udg_tim

Problem 6: the lines:
JASS:
    set tu=null
    set udg_tim = ((udg_tim)+10)
    call RemoveLocation(p)
    set r=null
    set angle=null
    set g=null
    call RemoveLocation(up)

Firstly, you only have to set variables which are a sub-type of handle and will at some point contain a handle that will be destroyed to null. Examples of what you need to null: unit group location destructable item widget. The types that do not descend from handle and should never even be given a null value, let alone nulled at the end of a function: boolean integer real string code

Secondly, you destroy two locations without nulling them.

Fixing all that (and ignoring the "enum" local, as it will be set to null before the loop even exits):
JASS:
    call RemoveLocation(p)
    call RemoveLocation(up)
    set p = null
    set up = null
    set tu = null
    set g = null

Problem 7: You use a few Blizzard.j functions. Functions from Blizzard.j are coded in JASS and are mainly made for the GUI. They are generally poorly coded and generally useless. Instead, use the "natives" from common.j which BJ (Blizzard.J) functions call. (Natives are functions internal within the game, which are only defined in JASS and not implemented in JASS. Eg, this native from common.j: native KillUnit takes unit whichUnit returns nothing)

The first BJ you use is:
JASS:
function GetUnitsInRangeOfLocAll takes real radius, location whichLocation returns group
    return GetUnitsInRangeOfLocMatching(radius, whichLocation, null)
endfunction

But GetUnitsInRangeOfLocMatching is also a BJ:
JASS:
function GetUnitsInRangeOfLocMatching takes real radius, location whichLocation, boolexpr filter returns group
    local group g = CreateGroup()
    call GroupEnumUnitsInRangeOfLoc(g, whichLocation, radius, filter)
    call DestroyBoolExpr(filter)
    return g
endfunction

This is an example of a horrible blizzard.j function for two reasons: Its useless, you can just use the natives; and it destroys a boolexpr. (Because of an optimization, Condition() will return the same output for the same input, thus boolexprs never need to be destroyed anyway, and destroying them can cause some weird problems.)

Inlining it, we end up with:
JASS:
function Lightning takes nothing returns nothing
    local unit tu = GetTriggerUnit()
    
    local location up = GetUnitLoc(tu)
    local location p = PolarProjectionBJ(up,r,angle)
    
    local real r
    local real angle
    
    local unit enum
    local group g = CreateGroup()
    
    call GroupEnumUnitsInRangeOfLoc(g, p, 100, null)
    
    set udg_tim = 10
    
    set r = ((udg_tim) * 1.5 + 100)
    set angle = GetUnitFacing(tu) + udg_tim
    
    call DestroyEffect(AddSpecialEffectLocBJ(p, "Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl" ))
    
    loop
        set enum = FirstOfGroup(g)
        exitwhen enum == null
        call GroupRemoveUnit(g, enum)
        if IsUnitEnemy(enum, GetOwningPlayer(GetTriggerUnit())) == true then
            call KillUnit(enum)
        endif
    endloop
    
    set udg_tim = ((udg_tim)+10)
    
    call RemoveLocation(p)
    call RemoveLocation(up)
    set p = null
    set up = null
    set tu = null
    set g = null
endfunction

Another BJ you use is:
JASS:
function AddSpecialEffectLocBJ takes location where, string modelName returns effect
    set bj_lastCreatedEffect = AddSpecialEffectLoc(modelName, where)
    return bj_lastCreatedEffect
endfunction

Truly useless. Inlining it yeilds:
JASS:
call DestroyEffect(AddSpecialEffectLoc("Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl", p))

Another one which we will inline later is:
JASS:
function PolarProjectionBJ takes location source, real dist, real angle returns location
    local real x = GetLocationX(source) + dist * Cos(angle * bj_DEGTORAD)
    local real y = GetLocationY(source) + dist * Sin(angle * bj_DEGTORAD)
    return Location(x, y)
endfunction

And one more, which you don't need to inline, as its a half-well written function:
JASS:
function TriggerRegisterAnyUnitEventBJ takes trigger trig, playerunitevent whichEvent returns nothing
    local integer index

    set index = 0
    loop
        call TriggerRegisterPlayerUnitEvent(trig, Player(index), whichEvent, null)

        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
endfunction
Let me say again: Its OK to use THAT BJ, as it actually does something useful: It compresses a lot of code you will likely use a lot in to a single line, and it does it without also doing something stupid.

Problem 8: You use locations. When you use locations, you have to destroy locations. For every native function that uses locations, there is a native(s) that use real x and y coordinates, which you don't have to destroy. (There are two important exceptions: GetLocationZ() and GetSpellTargetLoc())

Switching to X/Y coordinates starts here:
JASS:
    local location up = GetUnitLoc(tu)
    local location p = PolarProjectionBJ(up,r,angle)
Using X/Y and inlining PolarProjectionBJ(), we end up with:
JASS:
    local real x = GetUnitX(tu) + r * Cos(angle * bj_DEGTORAD)
    local real y = GetUnitY(tu) + r * Sin(angle * bj_DEGTORAD)
(There is a small ordering issue I'll address in the summary of this section.)

Now for the functions which use the old location:
JASS:
call GroupEnumUnitsInRangeOfLoc(g, p, 100, null)
We can also use:
JASS:
call GroupEnumUnitsInRange(g, x, y, 100, null)

And its used again at:
JASS:
call DestroyEffect(AddSpecialEffectLoc("Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl", p))
We can use:
JASS:
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl", x, y))

Finally, these lines can just be removed:
JASS:
    call RemoveLocation(p)
    call RemoveLocation(up)
    set p = null
    set up = null

This makes us end up with this: (Accounting for changing the order things are declared / set so it all works out:)
JASS:
function Lightning takes nothing returns nothing
    local unit tu = GetTriggerUnit()
    
    local real x
    local real y
    
    local real r
    local real angle
    
    local unit enum
    local group g = CreateGroup()
    
    call GroupEnumUnitsInRange(g, x, y, 100, null)
    
    set udg_tim = 10
    
    set r = ((udg_tim) * 1.5 + 100)
    set angle = GetUnitFacing(tu) + udg_tim
    
    set x = GetUnitX(tu) + r * Cos(angle * bj_DEGTORAD)
    set y = GetUnitY(tu) + r * Sin(angle * bj_DEGTORAD)
    
    call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl", x, y))
    
    loop
        set enum = FirstOfGroup(g)
        exitwhen enum == null
        call GroupRemoveUnit(g, enum)
        
        if IsUnitEnemy(enum, GetOwningPlayer(GetTriggerUnit())) == true then
            call KillUnit(enum)
        endif
    endloop
    
    set udg_tim = ((udg_tim)+10)
    
    set tu = null
    set g = null
endfunction

Problem 9: The function Main, and all it contains:
JASS:
function Main takes nothing returns nothing
    local timer t = CreateTimer()
    set udg_tim = 10
    call TimerStart(t,0.03,true,function Lightning)
    call TriggerSleepAction(1.00)
    call DestroyTimer(t)
    set t=null
endfunction

Firstly, using TriggerSleepAction to destroy the timer after a certain time is just horrible. Secondly, using the global udg_tim removes the ability to have the spell cast more than once at a time. (Commonly reffed to as "MUI")

You also use GetTriggerUnit() in the Lightning() function. GetTriggerUnit() will return null, as its called in the timer callback, not a triggers callback.

Its 1:34 AM, so I'm way too tired to continue right now. With a few minor fixups, heres what we have so far:

JASS:
function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'Awrs'
endfunction

function Lightning takes nothing returns nothing
    local unit tu = GetTriggerUnit()
    
    local real x
    local real y
    
    local real r
    local real angle
    
    local unit enum
    local group g

    set udg_tim = 10
    
    set r = udg_tim * 1.5 + 100
    set angle = GetUnitFacing(tu) + udg_tim
    
    set x = GetUnitX(tu) + r * Cos(angle * bj_DEGTORAD)
    set y = GetUnitY(tu) + r * Sin(angle * bj_DEGTORAD)
    
    call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl", x, y))
    
    set g = CreateGroup()
    call GroupEnumUnitsInRange(g, x, y, 100, null)
    
    loop
        set enum = FirstOfGroup(g)
        exitwhen enum == null
        call GroupRemoveUnit(g, enum)
        
        if IsUnitEnemy(enum, GetOwningPlayer(GetTriggerUnit())) == true then
            call KillUnit(enum)
        endif
    endloop
    
    set udg_tim = udg_tim + 10
    
    set tu = null
    set g = null
endfunction

function Main takes nothing returns nothing
    local timer t = CreateTimer()
    set udg_tim = 10
    call TimerStart(t, 0.03, true, function Lightning)
    call TriggerSleepAction(1.00)
    call DestroyTimer(t)
    set t = null
endfunction

function InitTrig_SSS takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition(function Conditions))
    call TriggerAddAction(t, function Main)
endfunction

If you want to do things properly with timers, the easyest way will be with vJASS structs. to use vJASS, you need the JASS NewGen World Editor hack: http://wc3campaigns.net/showthread.php?t=90999 The NewGen editor will also add syntax highlighting, fix the crashes on syntax error, add vJASS, and comes with a bunch of useful utilities that do anything from importing files to editing the tileset you are using to include more tiles than the WorldEditor will allow you to select normally.

The vJASS manual can be found here: http://wc3campaigns.net/vexorian/jasshelpermanual.html
 
Ok I think I need to clarify,

Basically the spell warstomp is a dummy spell, Ive made it do nothing but the effect.
The JASS then finds his position and like Zach said, it spirals out lightning, which kills anything in melee range from caster.
I didnt know about the naming locals after doing something else, that fixed most my errors.
You guys were also right about the Buffer function it is completely useless, but now after fixing it up I still have 1 error, it doesnt know what udg_tim is.
I need to name the variable before but not in Lightning function.

Something was said about Hardwiring it. What can I do.
[/code]The huge jass you dun need to see[/code]

EDIT

I fixed it!

For anyone who wants to know, I looked it up online and found this
JASS:
globals
    real udg_tim = 10
endglobals
Hooray!

Ok new problem...
JASS:
globals
real udg_tim = 10
endglobals

function Condo takes nothing returns boolean 
    return GetSpellAbilityId() == 'Awrs'
endfunction
  
function Lightning takes nothing returns nothing
    local unit tu = GetTriggerUnit()
    local location up = GetUnitLoc(tu)
    local real r = ((udg_tim) * 1.5 + 100)
    local real angle = GetUnitFacing(tu)+udg_tim
    local location p = PolarProjectionBJ(up,r,angle)
    local group g = GetUnitsInRangeOfLocAll(100,p)
    local unit u
    call DestroyEffect(AddSpecialEffectLocBJ(p, "Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl" ))
    loop  
        set u = FirstOfGroup(g)    
        exitwhen u==null    
        call GroupRemoveUnit(g,u)    
        if  IsUnitEnemy(u, GetOwningPlayer(GetTriggerUnit()))==true then      
            call KillUnit(u)    
        endif
    endloop
    set tu=null
    set udg_tim = ((udg_tim)+10) 
    set g=null  
    call RemoveLocation(up)
    call RemoveLocation(p)
    set up=null
    set p=null
endfunction

function Main takes nothing returns nothing      
    local timer t = CreateTimer()
    call TimerStart(t,0.03,true,function Lightning)  
    call TriggerSleepAction(1.00)  
    call DestroyTimer(t)    
    set t=null
endfunction

function InitTrig_SSS takes nothing returns nothing 
    local trigger t  
    set t=CreateTrigger()  
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)  
    call TriggerAddCondition(t, Condition(function Condo))  
    call TriggerAddAction(t, function Main)  
    set t=null
endfunction

The syntax checker finds NOTHING wrong but when I load it into game it finds all sorts.
Why isnt it working?
 
Last edited:
Level 4
Joined
May 25, 2007
Messages
55
Look above for text

Excellent work on the aid Earth-Fury, +rep for the tutorial.
I'm kinda surprised I missed a couple things like nulling the reals, very nice tips.
but can you not make the lines stretch out so far? it's making the browser
very high in width.
Can you cut it down a little bit with some new lines?
In other words |n you post please.

If you don't mind though I'm going to reference your post here while helping out the OP.

Back to the OP

Ok allow me to explain, the globals, end globals text that you found is part
of vJass, this feature is NOT available in the standard warcraft 3 frozen throne world editor.

This feature is a part of vJass which is included in NewGen World editor, Which
I Highly suggest you download, it's really easy, you just download it into your warcraft 3 folder
and place all the contents into a folder name NewGen. The download will have an
executable that runs both Warcraft 3 and its own modded version of World Editor.

Like I said earlier, its really suggested that you get this program, it will make
your jassing experience much more enjoyable.

Also, JassCraft was Designed to read vJass, so it doesn't produce any syntax error's for your code as it is,
but the regular World Editor doesn't have vJass,
so they display as syntax errors.

Here is basically what vJass does to your code in Newgen,
when you type Globals then end globals, whatever variables or data you input
into those fields will be moved up to the top of the code of your map where your
udg_ global variables are declared, the "globals" and "endglobals" text aren't
recognized by the standard world editor, so when NewGen saves, it moves
the variables then hides the "globals" and "endglobals" from the world editor.
Also, when you declare a global using vJass, you dont need the udg_
you can declare udg_tim, as simply tim, or if you want to prevent conflict
call it TestReal or something thats easier to type.

So finally, if the syntax checker is stating there is nothing wrong with your code
then all you have to do, is download, and run NewGen world editor, and save
your code using NewGen world editor, after that your code should work how you want it.

PS. after you try the code again using NewGen, try fixing up the code like how Earth-Fury explained.
It's good habit to use optimal code and to stay away from BJ's.
 
Honestly, I only understood half of what earth-fury said. Its obious that he is a very expieranced, zzz, user when it comes to Jass.
I have no idea what he was talking about when he was saying that the blizzard BJ arent good and to use other native stuff.

Ok I got NewGen world editor.
I loaded the map/code into it.
Its syntax checker didnt find anything wrong.
I tested the map.
Paladin sittin on his little island.
I used the spell.
The paladin opened his book...
and made the game crash >.<
Why isnt it working. I get this big ol error every time.
I kinda like WC bein in a window though...
 
Last edited:
Status
Not open for further replies.
Top