• 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] Function isn't working

Status
Not open for further replies.
Level 11
Joined
Mar 31, 2009
Messages
732
Okay I'm stumped.

I have one trigger that adds the events to a second trigger at map initialization.

JASS:
function Trig_Initialization_Actions takes nothing returns nothing
    local integer  index
    local player   indexPlayer
    local location indexStartLoc
    local real     copX
    local real     copY
    // enec = nightelf runner
    // ncop = circle of power


    set index = 0
    loop
       set indexPlayer = Player(index)
       if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
            set indexStartLoc = GetStartLocationLoc(GetPlayerStartLocation(indexPlayer))

            // Create initial CTF starting units
            set copX = GetLocationX(indexStartLoc)
            set copY = GetLocationY(indexStartLoc) - 400.00

            call CreateUnit(indexPlayer, 'ncop', copX, copY, bj_UNIT_FACING)
            set udg_cops[index] = GetLastCreatedUnit()
            set udg_copArea[index] = RectFromCenterSizeBJ( GetUnitLoc(GetLastCreatedUnit()), 100.00, 100.00 )
            call TriggerRegisterEnterRectSimple( gg_trg_Taken, udg_copArea[index] )
            call TriggerRegisterEnterRectSimple( gg_trg_Capture, udg_copArea[index] )

            call CreateUnit(indexPlayer, 'enec', copX, copY, bj_UNIT_FACING)
       endif

       set index = index + 1
       exitwhen index == bj_MAX_PLAYERS
    endloop
endfunction

However the second trigger is never firing like I want it to.
The conditions arent even being checked.

JASS:
//===========================================================================
function InitTrig_Taken takes nothing returns nothing
    set gg_trg_Taken = CreateTrigger(  )
    call TriggerAddCondition( gg_trg_Taken, Condition( function Trig_Taken_Conditions ) )
    call TriggerAddAction( gg_trg_Taken, function Trig_Taken_Actions )
endfunction

Uploaded the whole map too, if you need to see the rest of the triggers.
 

Attachments

  • (4)RuinsCTF.w3x
    336.8 KB · Views: 42
Last edited:
Level 14
Joined
Nov 23, 2008
Messages
187
First of all, use
JASS:
 tag, not [trigger].

Well, the problem is clear. You have [b]GetLastCreatedUnit()[/b] function, which returns value of [b]bj_lastCreatedUnit[/b] variable. But you used [b]CreateUnit[/b] native function, which is not connected with any bj's.

[code=jass]function Trig_Initialization_Actions takes nothing returns nothing
    local integer  index
    local player   indexPlayer
    local location indexStartLoc
    local real     copX
    local real     copY
    // enec = nightelf runner
    // ncop = circle of power


    set index = 0
    loop
       set indexPlayer = Player(index)
       if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
            set indexStartLoc = GetStartLocationLoc(GetPlayerStartLocation(indexPlayer))

            // Create initial CTF starting units
            set copX = GetLocationX(indexStartLoc)
            set copY = GetLocationY(indexStartLoc) - 400.00

            // >> the problem is here, natives doesn't use bj_*** variables
            // call CreateUnit(indexPlayer, 'ncop', copX, copY, bj_UNIT_FACING)
            // set udg_cops[index] = GetLastCreatedUnit()
            // set udg_copArea[index] = RectFromCenterSizeBJ( GetUnitLoc(GetLastCreatedUnit()), 100.00, 100.00 )

            // I think, you would have to use this instead:
            set udg_cops[index] = CreateUnit(indexPlayer, 'ncop', copX, copY, bj_UNIT_FACING)
            set udg_copArea[index] = RectFromCenterSizeBJ( GetUnitLoc(udg_cops[index]), 100.00, 100.00 )

            call TriggerRegisterEnterRectSimple( gg_trg_Taken, udg_copArea[index] )
            call TriggerRegisterEnterRectSimple( gg_trg_Capture, udg_copArea[index] )

            call CreateUnit(indexPlayer, 'enec', copX, copY, bj_UNIT_FACING)
       endif

       set index = index + 1
       exitwhen index == bj_MAX_PLAYERS
    endloop
endfunction
 
Level 11
Joined
Mar 31, 2009
Messages
732
Hmm, okay thanks. I'll give it a try when I'm back home tonight.

I don't understand it though, that part of the code is just converted from the GUI triggers: CreateUnit() and GetLastCreatedUnit(). If GetLastCreatedUnit() doesn't work for units created by the Create Unit action, then... what is it used for :bored:

And I realised after posting that I should have used the jass tag, but didn't have time then to change it, heh.

Edit: Okay I see what I've done now. I copied from the MeleeStartingUnits function in the blizzard.j file. The function I should have used was:
3027 function CreateUnitAtLocSaveLast takes player id, integer unitid, location loc, real face returns unit
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
If GetLastCreatedUnit() doesn't work for units created by the Create Unit action, then... what is it used for
GUI uses a function that goes something like this (writing it by hand since I don't have common.j at hand):

JASS:
function CreateUnitAtLocSaveLast takes player p, integer id, location loc, real facing returns unit
    set bj_lastCreatedUnit = CreateUnitAtLoc(p,id,loc,facing)
    return bj_lastCreatedUnit
endfunction

(Note: CreateNUnitsAtLoc calls this if I recall correctly)

IE: It's set manually.
 
Level 6
Joined
Nov 10, 2006
Messages
181
Use locals and you won't need to refer them by GetLastCreatedUnit() and just refer them through their variable name.

Change all ur GUI variables to locals and it will be fine.
 
Level 23
Joined
Nov 29, 2006
Messages
2,482
First of all, use
JASS:
 tag, not [trigger].

Well, the problem is clear. You have [b]GetLastCreatedUnit()[/b] function, which returns value of [b]bj_lastCreatedUnit[/b] variable. But you used [b]CreateUnit[/b] native function, which is not connected with any bj's.

[code=jass]function Trig_Initialization_Actions takes nothing returns nothing
    local integer  index
    local player   indexPlayer
    local location indexStartLoc
    local real     copX
    local real     copY
    // enec = nightelf runner
    // ncop = circle of power
[...]

JASS:
    local player   indexPlayer
    local location indexStartLoc
needs to be nulled at the end. Dont forget that.
 
Level 23
Joined
Nov 29, 2006
Messages
2,482
Oh you're right. They shouldnt. But then again, think about multiboardgetitem. You may think they are static, but they are not. I was just thinking just in case, or not thinking about it at all:p
 
Level 14
Joined
Nov 18, 2007
Messages
816
@Teelo: No simply declaring a local does not leak, but creating a new location and not destroying it leaks the object.
To fully recycle that object you also have to set the local variable to null because WC3 only recycles indexes with a reference count of 0. And the ref. counter increase caused by locals is not reverted when that local is destroyed (the function ends)
 
Level 11
Joined
Mar 31, 2009
Messages
732
Okay, so just so I properly understand this, why does Blizzard get away with doing this in Blizzard.j? Or am I missing something:

JASS:
	function MeleeStartingUnits takes nothing returns nothing
    local integer  index
    local player   indexPlayer
    local location indexStartLoc
    local race     indexRace

    call Preloader( "scripts\\SharedMelee.pld" )

    set index = 0
    loop
        set indexPlayer = Player(index)
        if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
            set indexStartLoc = GetStartLocationLoc(GetPlayerStartLocation(indexPlayer))
            set indexRace = GetPlayerRace(indexPlayer)

            // Create initial race-specific starting units
            if (indexRace == RACE_HUMAN) then
                call MeleeStartingUnitsHuman(indexPlayer, indexStartLoc, true, true, true)
            elseif (indexRace == RACE_ORC) then
                call MeleeStartingUnitsOrc(indexPlayer, indexStartLoc, true, true, true)
            elseif (indexRace == RACE_UNDEAD) then
                call MeleeStartingUnitsUndead(indexPlayer, indexStartLoc, true, true, true)
            elseif (indexRace == RACE_NIGHTELF) then
                call MeleeStartingUnitsNightElf(indexPlayer, indexStartLoc, true, true, true)
            else
                call MeleeStartingUnitsUnknownRace(indexPlayer, indexStartLoc, true, true, true)
            endif
        endif

        set index = index + 1
        exitwhen index == bj_MAX_PLAYERS
    endloop
    
endfunction

Well, I did made the changes you all suggested, but theres still something wrong =(

JASS:
function Trig_Initialization_Actions takes nothing returns nothing
    local integer  index
    local player   indexPlayer
    local location indexStartLoc
    local real     copX
    local real     copY
    // enec = nightelf runner
    // ncop = circle of power

    set index = 0
    loop
       set indexPlayer = Player(index)
       if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
            set indexStartLoc = GetStartLocationLoc(GetPlayerStartLocation(indexPlayer))

            set copX = GetLocationX(indexStartLoc)
            set copY = GetLocationY(indexStartLoc) - 400.00

            set udg_cops[index] = CreateUnit(indexPlayer, 'ncop', copX, copY, bj_UNIT_FACING)
            set udg_copArea[index] = RectFromCenterSizeBJ( GetUnitLoc(udg_cops[index] ), 200.00, 200.00 )
            call TriggerRegisterEnterRectSimple( gg_trg_Taken, udg_copArea[index] )
            call TriggerRegisterEnterRectSimple( gg_trg_Capture, udg_copArea[index] )

            call CreateUnit(indexPlayer, 'enec', copX, copY, bj_UNIT_FACING)
       endif

       set index = index + 1
       exitwhen index == bj_MAX_PLAYERS
    endloop
    set indexStartLoc = null
endfunction
 
Last edited:
Level 23
Joined
Nov 29, 2006
Messages
2,482
The reason why Blizzard has gone away with it, is not really certain, but they probably didn't know it themselves.
Also, Single player is handling leaks "better" in the way that it doesnt lag as much as when you play something multiplayer.
 
Level 11
Joined
Mar 31, 2009
Messages
732
Well I don't know. I still can't get this to work.

JASS:
function Trig_Initialization_Actions takes nothing returns nothing
    local integer  index
    local player   indexPlayer
    local location indexStartLoc
    local unit     nearestMine
    local location copLoc
    // enec = nightelf runner
    // ncop = circle of power

    set index = 0
    loop
       set indexPlayer = Player(index)
       if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
            set indexStartLoc = GetStartLocationLoc(GetPlayerStartLocation(indexPlayer))

            set nearestMine = MeleeFindNearestMine(indexStartLoc, bj_MELEE_MINE_SEARCH_RADIUS)
            if (nearestMine != null) then
                set copLoc = MeleeGetProjectedLoc(indexStartLoc, GetUnitLoc(nearestMine), -400, 0)
            else
                set copLoc = Location(GetLocationX(indexStartLoc), GetLocationY(indexStartLoc) - 400.00)
            endif

            set udg_cops[index] = CreateUnitAtLocSaveLast(indexPlayer, 'ncop', copLoc, bj_UNIT_FACING)
            set udg_copArea[index] = RectFromCenterSizeBJ(GetUnitLoc(udg_cops[index]), 200.00, 200.00)
            call TriggerRegisterEnterRectSimple( gg_trg_Taken, udg_copArea[index] )
            call TriggerRegisterEnterRectSimple( gg_trg_Capture, udg_copArea[index] )
            call CreateUnitAtLocSaveLast(indexPlayer, 'enec', copLoc, bj_UNIT_FACING)
       endif
       set index = index + 1
       exitwhen index == bj_MAX_PLAYERS
    endloop

    set indexStartLoc = null
endfunction
 
Level 11
Joined
Mar 31, 2009
Messages
732
1.) Use static triggers
2.) Use coordinates, locations are significantly slower

1. I've searched and can't find any information on "static triggers".
2. MeleeFindNearestMine, MeleeGetProjectedLoc both have to work with locations, so why not just use locations when I'd only have to convert coords to locations for those functions anyway?
3. Changing the structure of my function won't change the fact that its not working anyway.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
1. I've searched and can't find any information on "static triggers".
Not destroyed or changed after map init.
2. MeleeFindNearestMine, MeleeGetProjectedLoc both have to work with locations, so why not just use locations when I'd only have to convert coords to locations for those functions anyway?
Or code better funcs.
3. Changing the structure of my function won't change the fact that its not working anyway.
But it will improve your code.
 
Level 14
Joined
Nov 18, 2007
Messages
816
3. Changing the structure of my function won't change the fact that its not working anyway.
Well, it might just happen that a rewrite cleans out the bug. I dont know.

2. MeleeFindNearestMine, MeleeGetProjectedLoc both have to work with locations, so why not just use locations when I'd only have to convert coords to locations for those functions anyway?
Guess what comes next: Dont use those functions. There are only a select few natives that DONT work with coordinates. And your code is not using one of them.

I don't want those events bound to regions placed on my map, so I can rip the triggers right out and place them on another map without much effort.
Learn to use (and love) vJass. Thats exactly the reason why vJass was created in the first place.
 
Level 11
Joined
Mar 31, 2009
Messages
732
Well, I've opened and saved my map using that "newgen jasspack" WE (which saves it as an old version of wc3), and now I can't save it under the normal world editor anymore.

Needless to say, that trigger action still isn't working. Siiigh.



My latest attempt.

JASS:
function Trig_Initialization_Actions takes nothing returns nothing
    local integer  index
    local player   indexPlayer
    local location indexStartLoc
    local unit     nearestMine
    local location copLoc
    local real copX
    local real copY
    // enec = nightelf runner
    // ncop = circle of power

    set index = 0
    loop
       set indexPlayer = Player(index)
       if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
            set indexStartLoc = GetStartLocationLoc(GetPlayerStartLocation(indexPlayer))

            set nearestMine = MeleeFindNearestMine(indexStartLoc, bj_MELEE_MINE_SEARCH_RADIUS)
            if (nearestMine != null) then
                set copLoc = MeleeGetProjectedLoc(indexStartLoc, GetUnitLoc(nearestMine), -400, 0)
            else
                set copLoc = Location(GetLocationX(indexStartLoc), GetLocationY(indexStartLoc) - 400.00)
            endif
            set copX = GetLocationX(copLoc)
            set copY = GetLocationY(copLoc)
            set udg_cops[index] = CreateUnit(indexPlayer, 'ncop', copX, copY, bj_UNIT_FACING)
            set udg_copArea[index] = CreateRegion()
            call RegionAddCell( udg_copArea[index], copX, copY)
            call TriggerRegisterEnterRegion( gg_trg_Untitled_Trigger_001, udg_copArea[index], null )
            call CreateUnit(indexPlayer, 'enec', copX, copY, bj_UNIT_FACING)
       endif
       set index = index + 1
       exitwhen index == bj_MAX_PLAYERS
    endloop

    set nearestMine = null
    set copLoc = null
    set indexStartLoc = null
endfunction

MeleeFindNearestMine and MeleeGetProjectedLoc are not causing any problems at the moment, so I will fix them when I get the rest of this function working.
gg_trg_Untitled_Trigger_001 has one action: display "DEBUG".

When I test my map with two players, it says the message twice right at game start, but not when a unit enters the region (the point where the cop was made). :cry:
 
Last edited:
Level 14
Joined
Nov 23, 2008
Messages
187
Hmm, I found the problem (in trigger Capture):

JASS:
function InitTrig_Capture takes nothing returns nothing
    // what the ...?
    set gg_trg_Taken = CreateTrigger(  )
    call TriggerAddCondition( gg_trg_Capture, Condition( function Trig_Capture_Conditions ) )
    call TriggerAddAction( gg_trg_Capture, function Trig_Capture_Actions )
endfunction

Should be:

JASS:
function InitTrig_Capture takes nothing returns nothing
    set gg_trg_Capture = CreateTrigger(  )
    call TriggerAddCondition( gg_trg_Capture, Condition( function Trig_Capture_Conditions ) )
    call TriggerAddAction( gg_trg_Capture, function Trig_Capture_Actions )
endfunction

It seems that you register actions and conditions on gg_trg_Taken, then rewrite variable by creating new trigger, and then registering events.
The trigger gg_trg_Capture was not even created.
 
Level 11
Joined
Mar 31, 2009
Messages
732
Ahhh hah ha. Okay thank you. That was the problem.
Yay for carelessness I guess.
I've merged those two triggers to prevent similar errors, and now at least its firing properly when I want it to.

Having three problems though:
1. How can I make my map open-able in the regular world editor again? (Well, it opens, but crashes if I try to save it).
2. The triggers firing, but I don't think its finding the circle of power. Any suggestions on a better way to detect which circle of power my runner walked into?
3. Multiboard / player index woes. Bah, are they zero based or one based??! There seems to be some inconsistency floating around.
 

Attachments

  • (4)RuinsCTF.w3x
    337.1 KB · Views: 29
Status
Not open for further replies.
Top