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

Major Problem with Loop in first Jass-Trigger

Status
Not open for further replies.
Level 4
Joined
Dec 3, 2014
Messages
64
Hello i need some help for the following idea: a unit attacks if it has an specific item it has a chance of 1 to (10 - customvalue of the item) to create a unit on a point with polar offset random range from x-y and random degree. the point should be walkable so a needed a while-loop (while the created point is not walkable keep creating new points) i decide to quickly learn Jass former i learnd C# (does it help?). I had all i needed for my trigger except the loop. i took my if's and call's from the GUI trigger and tried to set them into the right places etc. but it doesn't work and worldeditor says that pretty much everything is an error. Here is my code:

JASS:
function Tentacle_Spawn takes nothing level returns nothing
    local integer RND = GetRandomInt(1, ( 10 - GetItemUserData(GetItemOfTypeFromUnitBJ(GetAttacker(), 'oflg')) ))//'item'
    if RND == 1 then
        local location pt // TentaklePunkt Variable
        local boolean begehbar = true //Check ob pt brauchbar ist
        loop
            // Erzeuge zufälligen Polaren Punkt
            set pt = PolarProjectionBJ(GetUnitLoc(GetTriggerUnit()), GetRandomReal(50.00, 350.00), GetRandomDirectionDeg())
            if ( not ( IsTerrainPathableBJ(pt, PATHING_TYPE_WALKABILITY) == false ) ) then
            set bgehbar = false
            endif
            exitwhen begehbar = false
        endloop
        // Debug: Richtige Unit?
        call CreateNUnitsAtLocFacingLocBJ( 1, 'o004', GetOwningPlayer(GetAttacker()), pt, GetUnitLoc(GetAttackedUnitBJ()) ) 
    else
    call SetItemUserData( UnitItemInSlotBJ(GetAttacker(), 1), ( GetItemUserData(GetItemOfTypeFromUnitBJ(GetAttacker(), 'oflg')) + 1 ) )
endfunction
 
Level 7
Joined
Oct 19, 2015
Messages
286
In JASS, you must declare all your local variables at the start of the function.

Also, the number of brackets on your first line does not match.

Also also, you are missing an endif at the end of the function.

Also also also, your function must either take "nothing" or take "integer level", it can't take "nothing level".

Here is a fixed and optimized version of the function:

JASS:
function Tentacle_Spawn takes nothing returns nothing
    local item it
    local integer i = 0
    local unit u = GetAttacker()
    local real ux = GetUnitX( u )
    local real uy = GetUnitY( u )
    local real a
    local real d
    local real x
    local real y

    loop
        set it = UnitItemInSlot(u, i)
        exitwhen (it != null) and (GetItemTypeId(it) == 'oflg')
        set i = i + 1
        if i >= bj_MAX_INVENTORY then
            // do nothing if unit does not have the item
            set it = null
            set u = null
            return
        endif
    endloop
    
    set i =GetRandomInt(1, ( 10 - GetItemUserData( it ) ) )
    if i == 1 then
        loop
            set a = GetRandomReal(0.0, bj_PI*2.0 )
            set d = GetRandomReal(50.00, 350.00)
            set x = ux + Cos(a)*d
            set y = uy + Sin(a)*d
            exitwhen IsTerrainPathable( x, y, PATHING_TYPE_WALKABILITY )
        endloop
        set a = Atan2( GetUnitY(GetTriggerUnit())-y, GetUnitX(GetTriggerUnit())-x )
        set u = CreateUnit( GetOwningPlayer(u), 'o004', x, y, a * bj_RADTODEG )
        call UnitApplyTimedLife( u, 'BTLF', 12.0 )
        // I am guessing you want to reset once a unit is spawned so I added this line:
        call SetItemUserData( it, ( 0 ) )
    else
        call SetItemUserData( it, ( GetItemUserData(it) + 1 ) )
    endif

    set u = null
    set it = null
endfunction
 
Last edited:
Level 4
Joined
Dec 3, 2014
Messages
64
First thanks for the quick answer. :)
its my fault that i copy'n'pasted "takes nothing level".
what does the line do?:

JASS:
set a = Atan2( GetUnitY(GetTriggerUnit())-y, GetUnitY(GetTriggerUnit())-ux )

and will it be enough to add the following line to get an 12 sec experation timer ( i copied from the GUI into JASS (own text -methode).

JASS:
call UnitApplyTimedLifeBJ( 12.00, 'BTLF', GetLastCreatedUnit() )

Is this an Attacktrigger to cause your code to work?

JASS:
function TS_Trigger takes nothing returns nothing
    set TS_Trigger = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( TS_Trigger , EVENT_PLAYER_UNIT_ATTACKED )
    call TriggerAddAction( TS_Trigger, function Trig_TS_Trigger )
endfunction

i got two more qustions while comprehending your code

JASS:
local item it
// the variable i has a value before the first loop
local integer i = GetRandomInt(1, ( 10 - GetItemUserData(it) ))//'item'
local unit u = GetAttacker()
//... the real variables
loop
        set it = UnitItemInSlot(u, i)
        exitwhen (it != null) and (GetItemTypeId(it) == 'oflg')
        set i = i + 1 // <-  ! ! ! ! ! 
//on the first round it has the value  (GetRandomInt(1, ( 10 - GetItemUserData(it) ))) i think?
        if i >= bj_MAX_INVENTORY then
            // do nothing if unit does not have the item
            set it = null
            set u = null
            return
        endif
    endloop
// does the loop end if the item isn't carried?
 
Last edited:
Level 7
Joined
Oct 19, 2015
Messages
286
what does the line do?:
That's for calculating the angle between the spawn coordinates and the attacked unit, so that the spawned unit can be created facing the attacked unit.

and will it be enough to add the following line to get an 12 sec experation timer ( i copied from the GUI into JASS (own text -methode).
That won't work because I used the native CreateUnit, which does not set the bj_lastCreatedUnit variable that is used by GetLastCreatedUnit. However, you can set it yourself: set bj_lastCreatedUnit = CreateUnit( GetOwningPlayer(u), 'o004', x, y, a * bj_RADTODEG ). Alternatively, you can just reuse the local variable u instead of bj_lastCreatedUnit. Then, you could apply the timed life with call UnitApplyTimedLife( u, 'BTLF', 12.0 ).

Is this an Attacktrigger to cause your code to work?
If you're using regular JASS you need to use the correct names for your function and trigger variable or it won't compile/work:
JASS:
function InitTrig_TRIGGERNAME takes nothing returns nothing
    set gg_trg_TRIGGERNAME = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_TRIGGERNAME , EVENT_PLAYER_UNIT_ATTACKED )
    call TriggerAddAction( gg_trg_TRIGGERNAME, function Tentacle_Spawn )
endfunction

i got two more qustions while comprehending your code
That was my mistake, the initial value of i should be 0 but I forgot to change it. I'll edit my first post now to fix it.

If the item isn't carried, then the whole function ends (at the return statement). I changed this from your code since I assumed you only wanted to spawn the tentacles if the attacker has the item.
 
Level 4
Joined
Dec 3, 2014
Messages
64
Ok i mostly understand this line except that y has no "u" for prefix but ux has it and my instinct is that x comes before y.
JASS:
set a = Atan2( GetUnitY(GetTriggerUnit())-y, GetUnitY(GetTriggerUnit())-ux )

Do i have to change the value for u from the attack to the created unit to get the exp timer on the tentacle?

JASS:
call UnitApplyTimedLife( u, 'BTLF', 12.0 )
 
Level 7
Joined
Oct 19, 2015
Messages
286
Ah, my mistake, that line should read:
set a = Atan2( GetUnitY(GetTriggerUnit())-y, GetUnitX(GetTriggerUnit())-x )
That's just how Atan2 works, it takes y first.

Yes, you should set the created tentacle to the variable like I mentioned:
set u = CreateUnit( GetOwningPlayer(u), 'o004', x, y, a * bj_RADTODEG )
I edited my first post with these corrections.
 
Level 4
Joined
Dec 3, 2014
Messages
64
Hi again, while trying the triggers i got errormassages for lines 70;71;72;202;203;208;208

JASS:
function Tentacle_Spawn takes nothing returns nothing
    local item it
    local integer i = 0
    local unit u = GetAttacker()
    local real ux = GetUnitX( u )
    local real uy = GetUnitY( u )
    local real a
    local real d
    local real x
    local real y

    loop
        set it = UnitItemInSlot(u, i)
        exitwhen (it != null) and (GetItemTypeId(it) == 'oflg')
        set i = i + 1
        if i >= bj_MAX_INVENTORY then
            // do nothing if unit does not have the item
            set it = null
            set u = null
            return
        endif
    endloop
   
    set i =GetRandomInt(1, ( 10 - GetItemUserData( it ) ) )
    if i == 1 then
        loop
            set a = GetRandomReal(0.0, bj_PI*2.0 )
            set d = GetRandomReal(50.00, 350.00)
            set x = ux + Cos(a)*d
            set y = uy + Sin(a)*d
            exitwhen IsTerrainPathable( x, y, PATHING_TYPE_WALKABILITY )
        endloop
        set a = Atan2( GetUnitY(GetTriggerUnit())-y, GetUnitX(GetTriggerUnit())-x )
        set u = CreateUnit( GetOwningPlayer(u), 'o004', x, y, a * bj_RADTODEG )
        call UnitApplyTimedLife( u, 'BTLF', 12.0 )
        // I am guessing you want to reset once a unit is spawned so I added this line:
        call SetItemUserData( it, ( 0 ) )
    else
        call SetItemUserData( it, ( GetItemUserData(it) + 1 ) )
    endif

    set u = null
    set it = null
endfunction

//----------

function InitTrig_TRIGGERNAME takes nothing returns nothing
    set gg_trg_TRIGGERNAME = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_TRIGGERNAME , EVENT_PLAYER_UNIT_ATTACKED )
    call TriggerAddAction( gg_trg_TRIGGERNAME, function Tentacle_Spawn )
endfunction

Sorry if its a super easyfixed mistake.
 
Hi again, while trying the triggers i got errormassages for lines 70;71;72;202;203;208;208
Lines 70 and 208? The code you posted probably doesn't even have 50. As you can probably tell, we don't actually see what line is what. You have to show what line is causing you the error.

You should also tell us what the error messages actually say.
 
Level 7
Joined
Oct 19, 2015
Messages
286
You need to replace "TRIGGERNAME" with the name of your trigger, I'm sorry I thought that was obvious so I didn't say it explicitly.
 
Status
Not open for further replies.
Top