HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Strange error in Editor: Expected a Name?

03-13-2008, 03:03 AM#1
Salbrismind
Here is my code: It is a modified version of some very messy Gui code I recently converted. It had alot of boolean functions at the top so I replaced most with one line of code in the ifs. After set a few locals to my needs to make it Mui I got the error "Expected a Name" at the first line in the second function from the top. (Local real x = ....)

This trigger is meant to check for all units in an area in front of a unit to damage them if they are within a certain angle near the caster.


Collapse JASS:
function Trig_Basic_Attack_UnitGroupIf takes nothing returns boolean
    return ( IsPlayerEnemy(GetOwningPlayer(GetFilterUnit()), GetOwningPlayer(GetSpellAbilityUnit())) == true )
endfunction

function Trig_Basic_Attack_Func004A takes nothing returns nothing
    local real x = ( GetLocationX(GetUnitLoc(GetEnumUnit())) - GetLocationX(GetUnitLoc(udg_Heroes[index])) )
    local real y = ( GetLocationY(GetUnitLoc(GetEnumUnit())) - GetLocationY(GetUnitLoc(udg_Heroes[index])) )
    set udg_AtkAng[index] = AtanBJ(( y / x ))
    if ( x > 0.00 ) then
        if ( y > 0.00 ) then
        else
            set udg_AtkAng[index] = ( 360.00 + udg_AtkAng[index] )
        endif
    else
        set udg_AtkAng[index] = ( 180.00 + udg_AtkAng[index] )
    endif
    if ( And( udg_AtkAng[index] < ( GetUnitFacing(udg_Heroes[index]) + 22.50 ) , udg_AtkAng[index] > ( GetUnitFacing(udg_Heroes[index]) - 22.50 ) ) then
        call AddSpecialEffectLocBJ( GetUnitLoc(GetEnumUnit()), "Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl" )
        call UnitDamageTargetBJ( udg_Heroes[index], GetEnumUnit(), 80.00, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL )
        set udg_num = GetRandomInt(1, 6)
        call PlaySoundOnUnitBJ( udg_sounds[udg_num], 100, udg_Heroes[index] )
    else
    endif
endfunction

function Trig_Basic_Attack_Actions takes nothing returns nothing
local integer index = GetOwningPlayer(GetSpellAbilityUnit()) - 1
    call PlaySoundOnUnitBJ( gg_snd_BristleBackMissileLaunch3, 100, udg_Heroes[index] )
    call StartTimerBJ( udg_AtkTimer[index], false, 0.90 )
    if ( udg_upcheck[index] == true ) then
        set udg_upcheck[index] = false
        set udg_uptemp[index] = true
    else
        if ( udg_downcheck[index] == true ) then
            call SetUnitTimeScalePercent(udg_Heroes[index], 100 )
            call SetUnitAnimationByIndex(udg_Heroes[index], 1)
            set udg_downcheck[index] = false
            set udg_downtemp[index] = true
        else
        endif
    endif
    call ForGroupBJ( GetUnitsInRangeOfLocMatching(250.00, GetUnitLoc(udg_Heroes[index]), Condition(function Trig_Basic_Attack_UnitGroupIf)), function Trig_Basic_Attack_Func004A )
endfunction

//===========================================================================
function InitTrig_Basic_Attack takes nothing returns nothing
    set gg_trg_Basic_Attack = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Basic_Attack, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddCondition( gg_trg_Basic_Attack, Condition( GetSpellAbilityId() == 'A001' ) )
    call TriggerAddAction( gg_trg_Basic_Attack, function Trig_Basic_Attack_Actions )
endfunction

This is giving me quite a headache so any assistance would be greatly appreciated. Also because I am learning any comments on style, neatness and leaks would be welcomed.
03-13-2008, 03:10 AM#2
Pyrogasm
You forgot a ")" in this line:
if ( And( udg_AtkAng[index] < ( GetUnitFacing(udg_Heroes[index]) + 22.50 ) , udg_AtkAng[index] > ( GetUnitFacing(udg_Heroes[index]) - 22.50 ) ) ) then
You also have an undefined variable: index
03-13-2008, 04:10 AM#3
Salbrismind
Quote:
Originally Posted by Pyrogasm
You forgot a ")" in this line:
if ( And( udg_AtkAng[index] < ( GetUnitFacing(udg_Heroes[index]) + 22.50 ) , udg_AtkAng[index] > ( GetUnitFacing(udg_Heroes[index]) - 22.50 ) ) ) then
You also have an undefined variable: index

OH wow, I'm tired that must be why... And no index is defined in the first part of the trigger. Thanks though for that simple fix.
03-13-2008, 05:13 PM#4
Rising_Dusk
Quote:
And no index is defined in the first part of the trigger.
No, it isn't. Locals are not intrinsically passed to called functions in jass. Your function named "Trig_Basic_Attack_Func004A" does not have an index variable defined for it and therefore will not compile.
03-13-2008, 05:59 PM#5
Salbrismind
Quote:
Originally Posted by Rising_Dusk
No, it isn't. Locals are not intrinsically passed to called functions in jass. Your function named "Trig_Basic_Attack_Func004A" does not have an index variable defined for it and therefore will not compile.

That presents a problem... But to fix it need to make it take an integer variable that I can pass to it? :

"function Trig_Basic_Attack_Func004A takes integer index returns nothing"

Sry, I'm new to this so, what would the other line look like? :

"call Trig_Basic_Attack_Func004A (index)" Is that right?


It seemed to work, but that line with the brackets you fixed before is now giving me another problem. It says "Invalid Argument Type (Boolean)" Could you please help with this as well?

The line I am referring to: "if ( And( udg_AtkAng[index] < ( GetUnitFacing(udg_Heroes[index]) + 22.50 ) , udg_AtkAng[index] > ( GetUnitFacing(udg_Heroes[index]) - 22.50 ) ) ) then"
03-13-2008, 06:38 PM#6
Rising_Dusk
You could do it that way, but man, your BJ function littered code is really hard to follow. Invest in some better function naming, for starters. (Oh, also, your inittrig declaration won't compile) Actually, you have LOADS of compilation errors.
Collapse JASS:
local integer index = GetOwningPlayer(GetSpellAbilityUnit()) - 1
That won't even compile, you can't set a player to an integer variable. Let me help you out here, it's too impossible to figure out now. :x
Expand JASS:
This should do the same thing yours did except for running that timer. You never specified the callback for the timer, so I have no idea what it should do or why it's even there. I commented a few confusing parts for me, but it should be okay.
03-13-2008, 06:58 PM#7
Salbrismind
Quote:
Originally Posted by Rising_Dusk
You could do it that way, but man, your BJ function littered code is really hard to follow. Invest in some better function naming, for starters. (Oh, also, your inittrig declaration won't compile) Actually, you have LOADS of compilation errors.
Collapse JASS:
local integer index = GetOwningPlayer(GetSpellAbilityUnit()) - 1
That won't even compile, you can't set a player to an integer variable. Let me help you out here, it's too impossible to figure out now. :x
Expand JASS:
This should do the same thing yours did except for running that timer. You never specified the callback for the timer, so I have no idea what it should do or why it's even there. I commented a few confusing parts for me, but it should be okay.


Im gui this trigger worked perfectly to my needs with the exception that I changed certain things from the gui converted code.

1. The "GetConvertedPlayerId" was there first and I misread the function and thought all it did was subtract one from the "GetownedPlayer" but I'll change it to the proper code.

2. Do I have to have the triggers conditions in another function? Even though it is only one condition?

3. Is it faster to set all those locals first? or is it just neater and easier to edit?

4. The callback of the timer (I'm not sure what callback means but I assume it means what it does when it's done) is set in another trigger that sets a few variables to reset all the movement booleans (upcheck,downcheck etc) and resets the animation to walk when the attack animation is done.
Could I do this all in one trigger, if so how?

5. The angle is to check for units in about a 45 degree arc in front of the caster. 22.5 degrees on one side 22.5 on the other. Because it is arctangent I have to check for the x and y being
in a special spot, otherwise I would get incorrect data when the caster is facing certain directions.

Okay, thanks again. As you can see i need more experience in jass but this helps, Thank you.
03-13-2008, 07:03 PM#8
Rising_Dusk
Quote:
2. Do I have to have the triggers conditions in another function? Even though it is only one condition?
Yes, the Condition(..) native takes a function as its argument.
Quote:
3. Is it faster to set all those locals first? or is it just neater and easier to edit?
Both; locals are as fast as they come and so much more sensible than your previous code. They exist to make life easier and to add logic to your code. Notice how much easier and cleaner mine is. The BJ function calls you used were terribly inefficient and leaked locations and groups all over the place. Mine are all clean and optimized.
Quote:
The callback of the timer (I'm not sure what callback means but I assume it means what it does when it's done) is set in another trigger that sets a few variables to reset all the movement booleans (upcheck,downcheck etc) and resets the animation to walk when the attack animation is done.
Could I do this all in one trigger, if so how?
You could. Just uncomment the timer line I had, convert the other one to GUI, add it above as a new function, and have the timer run that function. Voillah.
03-13-2008, 07:28 PM#9
Salbrismind
Quote:
Originally Posted by Rising_Dusk
Yes, the Condition(..) native takes a function as its argument.

Both; locals are as fast as they come and so much more sensible than your previous code. They exist to make life easier and to add logic to your code. Notice how much easier and cleaner mine is. The BJ function calls you used were terribly inefficient and leaked locations and groups all over the place. Mine are all clean and optimized.

You could. Just uncomment the timer line I had, convert the other one to GUI, add it above as a new function, and have the timer run that function. Voillah.

Wow, excellent thank you, there are also a few things I tried to add quickly but you missed.


Also can I create a local timer in place of that global? Likely it will only be used within this function. How does the "code handlerFunc" work? , in Jass craft this is what it refers to as the last part of the TimerStart function.


Trigger:
End Attack
Collapse Events
Time - AtkTimer[1] expires
Conditions
Collapse Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
uptemp[1] Equal to True
Collapse Then - Actions
Custom script: call SetUnitAnimationByIndex(udg_Heroes[1], 6)
Set upcheck[1] = True
Set uptemp[1] = False
Collapse Else - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
downtemp[1] Equal to True
Collapse Then - Actions
Custom script: call SetUnitTimeScalePercent( udg_Heroes[1], -100)
Custom script: call SetUnitAnimationByIndex(udg_Heroes[1], 6)
Set downcheck[1] = True
Set downtemp[1] = False
Else - Actions
Set uptemp[1] = False
Set downtemp[1] = False

This is the trigger I was talking about, how do I apply that to a local timer using the TimerStart? Thanks again.
03-13-2008, 08:09 PM#10
Rising_Dusk
Quote:
Also can I create a local timer in place of that global?
You can, but you need to make sure in your timer callback (The function it runs on expiration) you destroy the timer, otherwise it will continue to run and leak and take up cpu power.
Quote:
This is the trigger I was talking about, how do I apply that to a local timer using the TimerStart? Thanks again.
If you want to use a local timer, you'll have to convert it to jass and direct your timerstart call to point to your function that was converted.
Quote:
How does the "code handlerFunc" work? , in Jass craft this is what it refers to as the last part of the TimerStart function.
A function reference. Example: function MyFunction
I recommend my tutorial on timers for further reference into how timers work and should be used.
03-13-2008, 09:17 PM#11
Salbrismind
Quote:
Originally Posted by Rising_Dusk
You can, but you need to make sure in your timer callback (The function it runs on expiration) you destroy the timer, otherwise it will continue to run and leak and take up cpu power.

If you want to use a local timer, you'll have to convert it to jass and direct your timerstart call to point to your function that was converted.

A function reference. Example: function MyFunction
I recommend my tutorial on timers for further reference into how timers work and should be used.

Awsome thank you again. Jeez I've said that alot, but truly thank you! :p

It's all well and good but In your tutorial it seems like adding my index variable to the callback function is going to be trouble. But couldn't I just make it part of the function:

"function End_Attack takes integer index returns nothing" or is the only method using cache and such?
03-13-2008, 09:58 PM#12
Rising_Dusk
Quote:
"function End_Attack takes integer index returns nothing" or is the only method using cache and such?
Timer callbacks cannot take arguments, therefore what you propose there would not compile. There must be another method of attachment or conveyance of the value to the callback if you want MUI to be possible.
Quote:
Awsome thank you again. Jeez I've said that alot, but truly thank you! :p
It's a pleasure, it's what I do. :)
03-13-2008, 11:32 PM#13
Salbrismind
Quote:
Originally Posted by Rising_Dusk
Timer callbacks cannot take arguments, therefore what you propose there would not compile. There must be another method of attachment or conveyance of the value to the callback if you want MUI to be possible.

It's a pleasure, it's what I do. :)

I want to do it your method (tutorial) but what are the dangers? Is there anything special I need to know about game cache or handles to do this? If so where could I find a tutorial for this? Thanks.
03-13-2008, 11:48 PM#14
Rising_Dusk
Quote:
I want to do it your method (tutorial) but what are the dangers? Is there anything special I need to know about game cache or handles to do this? If so where could I find a tutorial for this? Thanks.
Cache is a generally slow system with the massive H2I(I2S()) conversion count and is generally unsafe considering the necesity of I2H() to return values to original types. Cache gains some type safety back if you store only integers (Structs) and use those struct references to retrieve data from parallel arrays, but that requires knowledge of vJass and so forth. I would highly recommend moving to a more efficient and recently designed system of data handling, such as those I linked to in a previous post. Cohadar has sufficient examples of their use in the linked data handling systems, your best bets for timer attaching being in ABCT or TT. (PUI is used for unit indexing via UnitUserData)

If for whatever reason you still want the game cache handle functions, you can find them all here.
03-15-2008, 09:23 AM#15
Pyrogasm
You don't necessarily have to use a converted function as long as you still use the NewGen editor. The following will compile (but only if the first trigger is above the second in the editor):
Trigger:
Collapse Callback Trigger
Events
Conditions
Collapse Actions
Custom script: set udg_MyTimer = GetExpiredTimer()
----- Do something -----
Countdown Timer - Destroy MyTimer
Collapse Start Trigger
Collapse Events
----- Whatever -----
Conditions
Collapse Actions
----- Something -----
Custom script: call TimerStart(CreateTimer(), 1.00, false, function Trig_Callback_Trigger_Actions)