• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[JASS] Expected ' Error Help Please

Status
Not open for further replies.
Level 6
Joined
May 15, 2008
Messages
146
Ok I've uber-mastered GUI(see my arena game) and am sick of it's limitations, and now I'm practicing Jass, but I still lack the experience. :eekani:

What's the thing with the Expected ' :goblin_jawdrop: error I don't get that??
Here is the code it shows that the error in this line:

:fp:
JASS:
    call TimerStart(T, 0.03, true, function  Blood_Twister_Execute())

Uhm don't pay attention on the uncompletion (since it does nothing, 'xcept moving the dummy unit) of the spell I'm just practicing so I get the hang of using the timers.

Thanx in advance!!! :thumbs_up:

:fp:
JASS:
//Condition Main

function Blood_Twister_Condition takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A004' ) ) then
        return false
    endif
    return true
endfunction

//Actionez

function Blood_Twister_Execute takes nothing returns nothing
    local timer T = GetExpiredTimer()
    local unit sfx = LoadUnitHandle(udg_Hashtable, GetHandleId(GetTriggerUnit()), 2)
    local integer x = LoadIntegerBJ(1, GetHandleId(GetTriggerUnit()), udg_Hashtable)
    set x = x+1
    call SaveIntegerBJ(x, 1, GetHandleId(GetTriggerUnit()), udg_Hashtable)
    if x > 12 then
        call DisplayTextToForce( GetPlayersAll(), I2S(x) )
        call SetUnitPosition(sfx, PolarProjectionX( GetUnitX(sfx), 90, 0), PolarProjectionY( GetUnitY(sfx), 90, 0))
    else
        call PauseTimerBJ( true, T )
        call DestroyTimer(T)
        call KillUnit(sfx)
    endif
    set T = null
    set sfx = null
    call FlushChildHashtableBJ( GetHandleIdBJ(GetTriggerUnit()), udg_Hashtable ) 
endfunction


function Blood_Twister_Action takes nothing returns nothing
    local timer T = CreateTimer()
    local unit sfx
    local integer x = 0
    local real Angle = 0
    call CreateNUnitsAtLoc( 1, 'h000', GetOwningPlayer(GetTriggerUnit()), GetUnitLoc(GetTriggerUnit()), Angle )
    set sfx = GetLastCreatedUnit()
    call SetUnitAnimation(sfx, "birth")
    call QueueUnitAnimation(sfx, "stand")
    call SaveIntegerBJ(x, 1, GetHandleId(GetTriggerUnit()), udg_Hashtable)
    call SaveUnitHandleBJ(sfx, 2, GetHandleId(GetTriggerUnit()), udg_Hashtable)
    call TimerStart(T, 0.03, true, function  Blood_Twister_Execute())
    set T = null
    set sfx = null
endfunction

//////////////////////////////////////////////////////
function InitTrig_Blood_Twister takes nothing returns nothing
    local trigger T = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( T, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( T, Condition( function Blood_Twister_Condition ) )
    call TriggerAddAction( T, function Blood_Twister_Action )
    set T = null
endfunction
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
this >>> Blood_Twister_Execute() >>> remove this >>> ()

do NOT use BJ's, except for some few...

samples;
PauseTimerBJ >>> PauseUnit
SaveIntegerBJ >>> SaveInteger
and so on...

also...this...
JASS:
function Blood_Twister_Condition takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A004' ) ) then
        return false
    endif
    return true
endfunction

to this...
JASS:
function Blood_Twister_Condition takes nothing returns boolean
   return GetSpellAbilityId() == 'A004'
endfunction

Welcome to the world of jazzers!
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
^As mentioned, they are only few BJ (smaple, switch - generally 'red' functions) that are usefull, like: TriggerRegisterAnyUnitEventBJ and GetCurrentCameraSetup.

JassCraft will help you a lot with replacing those into native, plus it hold wisdom about most Jass functions.

- Conditions and Actions can be merged
- Refer to timer's id instead of units one
- Your 'Blood_Twister_Execute' function wouldn't work properly because GetTriggerUnit() will return null
- use low letters for locals
- bj_lastCreatedUnit can help you get rid of unneded local
- flush child only when instance is finished
- passing code callback funcion in TimerStart should be done without '()'
- 'Angle' and 'x' variables aren't needed
- use GetTriggerPlayer() instead of GetOwningPlayer()

JASS:
function Blood_Twister_Execute takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local integer x = LoadInteger(udg_Hashtable, id, 1) + 1
    local unit u = LoadUnitHandle(udg_Hashtable, id, 2)
    local real dx = GetUnitX(u) + 90 * Cos(0 * bj_DEGTORAD)
    local real dy = GetUnitY(u) + 90 * Sin(0 * bj_DEGTORAD)

    if x > 12 then
        if IsPlayerInForce(GetLocalPlayer(), bj_FORCE_ALL_PLAYERS) then
            call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, I2S(x))
        endif
        call SetUnitPosition(u, dx, dy)
        call SaveInteger(udg_Hashtable, id, x)
    else
        call PauseTimer(t)
        call DestroyTimer(t)
        call KillUnit(u)
        call FlushChildHashtable(udg_Hashtable, id) 
    endif

    set t = null
    set u = null
endfunction

function Blood_Twister_Condition takes nothing returns boolean
    local unit u = GetTriggerUnit()
    local timer t
    local integer id

    if GetSpellAbilityId() == 'A004' then
        set t = CreateTimer()
        set id = GetHandleId(t)
        set bj_lastCreatedUnit = CreateUnit(GetTriggerPlayer(), 'h000', GetUnitX(u), GetUnitY(u), bj_UNIT_FACING)
        call SetUnitAnimation(bj_lastCreatedUnit, "birth")
        call QueueUnitAnimation(bj_lastCreatedUnit, "stand")
        call SaveInteger(udg_Hashtable, id, 1, 0)
        call SaveUnitHandle(udg_Hashtable, id, 2, bj_lastCreatedUnit)
        call TimerStart(t, 0.03125, true, function  Blood_Twister_Execute)
        set t = null
    endif

    set u = null
    return false
endfunction

function InitTrig_Blood_Twister takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition(t, Condition( function Blood_Twister_Condition ) )
    set t = null
endfunction
 
Last edited:
Level 14
Joined
Nov 18, 2007
Messages
1,084
JASS:
function Blood_Twister_Condition takes nothing returns boolean
    local unit u = GetTriggerUnit()
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)

    if GetSpellAbilityId() == 'A004' then
        set bj_lastCreatedUnit(GetTriggerPlayer(), 'h000', GetUnitX(u), GetUnitY(u), bj_UNIT_FACING)
        call SetUnitAnimation(bj_lastCreatedUnit, "birth")
        call QueueUnitAnimation(bj_lastCreatedUnit, "stand")
        call SaveInteger(udg_Hashtable, id, 1, 0)
        call SaveUnitHandle(udg_Hashtable, id, 2, bj_lastCreatedUnit)
        call TimerStart(t, 0.03125, true, function  Blood_Twister_Execute)
    endif

    set t = null
    set u = null
    return false
endfunction
I would do things a bit differently.
JASS:
function Blood_Twister_Condition takes nothing returns boolean
    local unit u
    local timer t
    local integer id

    if GetSpellAbilityId() == 'A004' then
        set u = GetTriggerUnit()
        set t = CreateTimer()
        set id = GetHandleId(t)
        set bj_lastCreatedUnit = CreateUnit(GetTriggerPlayer(), 'h000', GetUnitX(u), GetUnitY(u), bj_UNIT_FACING)
        call SetUnitAnimation(bj_lastCreatedUnit, "birth")
        call QueueUnitAnimation(bj_lastCreatedUnit, "stand")
        call SaveInteger(udg_Hashtable, id, 1, 0)
        call SaveUnitHandle(udg_Hashtable, id, 2, bj_lastCreatedUnit)
        call TimerStart(t, 0.03125, true, function  Blood_Twister_Execute)
        set t = null
        set u = null
    endif
    
    return false
endfunction
 
Last edited:
Level 6
Joined
May 15, 2008
Messages
146
WOW guys I've just asked one question and all of you posted something and spinnaker even fixed the script, THANX +REP to all of you.

:fp: @Spinnaker Tnx for the script once more by paralleling it with my script I cane get where am I doing wrong. :thumbs_up: I am in fact using JassCraft, but was just the random trigger I'm trying to convert my GUI trigger patterns to the Jass but I lack the xp and syntax and those finesses with BJ and stuff which you get with practice. :thumbs_up: Also thanks for the list of the tips :thumbs_up:

:fp: @mckill2009 Thanks for the warm welcome and the explanation of the error ^^ I know about NOT USING BJ (one of the top 10 rules Jass) I'm just new as I said and trying to get a hang of it. :grin:

:fp: @Watermelon and Pharaoh tnx for fixing the script GJ :thumbs_up:

:fp: @Bribe actually I was using that trick of a timer and a unit group, but than started to use Time - Every _ seconds of game instead of timers, just I have a lot patterns for wave and similar spells and knockback 'n' jump sys and was making a set of variables for each of the spell's (xcept the sys) so I'm not sure if it is wise to put, let's say just pending spells into one group with some number of general variables to reduce the num of total vars, but then I think wouldn't it be slow trigger when it starts to cycle through all spells.

:fp: @Magtheridon tnx for the tips.

//==============================
OK I've got some questions also, I've read a pretty fair amount of tutorials and still don't get some stuff.

What's the difference between these two types of creating the trigger?

JASS:
function InitTrig_Blood_Twister takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition(t, Condition( function Blood_Twister_Condition ) )
    set t = null
endfunction

//and this type of creating a trigger, sry it's just a converted empty trig

function InitTrig_Blood_Twister takes nothing returns nothing
    set gg_trg_Blood_Twister = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Blood_Twister, function Trig_Blood_Twister_Actions )
endfunction

Also can I have more than one creaton of trigger function in a single script, or I need to use those CreateTrigger and TriggerExecute func ,I thinks it was a tutorial which Vexorian wrote (I'll check that out) but I didn't get all of it really?

I have some more questions but I'm in a hurry right now, I'll ask later. :thumbs_up:

Thanx again all of you :ogre_haosis:
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
the difference is mainly >>> top uses local trigger, down a global which is pretty ugly...

Also can I have more than one creaton of trigger function in a single script

you can do this...
JASS:
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ...
call AddAction...
blahhhh...

set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ...
call AddAction...
blahhh...
 
Level 6
Joined
May 15, 2008
Messages
146
Why thank you all for clearing that thingie about triggers. ^^

Q1 - So what's better using stuff like
JASS:
call TriggerRegisterTimerEventPeriodic( Some_Trigger, 2 )
or using local Timers or Timers generaly?

Q2 - Also Bribe mentioned that cycling through all spells is faster than having dozens of timers run in the same time, does this apply to the TimerPeriodicEvent also?
Cuz I cannot realy cycle through all of spells it would be one trigger where some kind of identfication would need to be applied for recognizing which spell is being done and that's num of spells x ITE functions for each but that's a pain in the ass. :grin:

Q3 - Also can unit groups be saved somehow into hashtable I've been trying to do that in GUI versions of spells for example Wave damage spells so I can save the damaged units stocked into group but it didn't worked?

Q4 - Uhm Spinnaker your code wasn't working for x > 12 so I've changed that into < and than it worked but I'm not seeing reason why is that? Also when moving a unit shouldn't you be using angle in which you want to move the unit when multiplying with sin cos to ge x,y coordinates instead of using 90 degree angle?? That wai the wave always goes to the right hehehehe ^^ :p. BTW thanks for the code it's really helpful.

Q5 - Also with this you can get id of every handle like when setting a unit into variable and than getting it's id?
JASS:
set id = GetHandleId(SomeUnit)

Q6 - and what's with this you can like set what's the last created unit?!
JASS:
set bj_lastCreatedUnit = CreateUnit(GetTriggerPlayer(), 'h000', GetUnitX(u), GetUnitY(u), bj_UNIT_FACING)
 
Last edited:
Q1: Depends on the use, really.
Q2: Adding units to a unit group and enumerating them in the periodic event usually does the trick.
Q3: You need a custom script, e.g.:
  • Custom script: call SaveGroupHandle (udg_Hash, Where, Label, Value)
Q4: "90" is not the angle; it's the offset. The script moves the unit to the east, since 0 degrees is east, 90 is north, 180 is west and 270 is south.
Q5: Not sure if that's what you ask, but yes, you can get the handle id of a variable'd unit.
Q6: It's a Blizzard global variable, instead of increasing and decreasing the handle counter all the time, you can use this globally generated one.
 
Level 6
Joined
May 15, 2008
Messages
146
Why thank you Pharaoh you rulez, I get that thingies I just needed confirmation ^^

Sry for not using right terminology with offset and angles I used to call all of that angles, the real angle is between the caster and casting point. :p

I know i need to use xustom script :p

Yup I asked cuz normaly in GUI you can't set the id of a unit unless it's that blizzard refferenced type (triggering unit, picked unit last created, again sry for terminology if I got it wrong)

About Timers and TimedEvent, I mean in GUI I use a general pattern of activation trigger and a effect trigger which has timer event, with storage of variables into hashtables. I turn off the effect trigger if unit group (for check) is empty e.g. there are no active spell effects. My question is is it better to use timer and pause them or use timer events when having multiple spells and a knockback/jump sys.
I am over exaggerating cuz I have no lag with the systems/spells and they work perfect, I'm just trying to improve them by trying to have in mind both minimum and maximum chance when they are used i mean when it's just casted one spell, and when there are 100 instances running. But that won't happen it's a Hero Arena and most of spell effects last under 0.8 sec guess that's ok.

Thank you ^^
 
For GUI, I prefer a timed event, than creating and destroying a timer (array'd variable).

I know there's no such thing in GUI to get the handle of a variable; just make an integer variable and use the custom script to GetHandleId() ;]

Jass can generally save you some lag, but it cannot eliminate it. There's always a limit that even the best script can't ignore.
 
Level 6
Joined
May 15, 2008
Messages
146
Thank you very very much Pharaoh :goblin_good_job:!!!

One more question:

Q1 - I'm makin some dynamic movement system for jumps and etc, and I need to put sfx for different terrain type and i cannot seem to get either of these 3 functions to work, i get "Expected a name" error in line for these 2

JASS:
set TempBoolean = IsPointWaterLoc(TempPoint)

set TempBoolean = IsPointWater(GetLocationX(TempPoint), GetLocationY(TempPoint))

and for this one Im using ITE funcion with message debug so it displays Terrain is land/water, just it show land weather I'm on land or in water. :eekani:

JASS:
set TempBoolean = (IsTerrainPathable(GetLocationX(TempPoint) ,GetLocationY(TempPoint) ,PATHING_TYPE_AMPHIBIOUSPATHING))

what's the prob I don't get it?

EDIT:
I've screwed a little with pathing check, replacing the cond of boolean to check if false (original it was true), but now it shows water debug msg only while I'm on the cliffs which translate from land to water(wheather it's shallow or deep), when i stand at any point of the pool it show land msg again. I was using the GetLocationZ so all values under 0 are considered water but I wanna add some pool on cliffs so i need to get this checking to work.

EDIT 2: Well I've got it to work for deep water using the dual pathability check from the IsPointWater func, but is there any way to make this work for shallow water??
 
Status
Not open for further replies.
Top