1. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  2. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still haven't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. Ride into the sunset with the 32nd Modeling Contest.
    Dismiss Notice
  4. This adventure has come to an end. Congratulate our heroes in the 16th Mini Mapping Contest Results.
    Dismiss Notice
  5. From the gates of hell, the 5th Special Effect Contest Results have emerged.
    Dismiss Notice
  6. Race against the odds and Reforge, Don't Refund. The 14th Techtree Contest has begun!
    Dismiss Notice
  7. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[JASS] JASS Troubles

Discussion in 'Triggers & Scripts' started by chaoslord301, Mar 13, 2009.

  1. chaoslord301

    chaoslord301

    Joined:
    Sep 18, 2007
    Messages:
    105
    Resources:
    0
    Resources:
    0
    Well I opened up an old clan project and decided to recode it all in JASS for practice, and I ran into some problems. The following to triggers aren't working...

    This trigger is supposed to display the message "*Hero Name*'s forces have been obliterated") to all players. Nothing happens, not even the debug.

    Death Message
    Code (vJASS):
    function DeathMessageActions takes nothing returns nothing
        call DisplayTextToForce( GetPlayersAll(), ( "|cff32cd32" + ( GetHeroProperName(GetTriggerUnit()) + " Forces have been Obliterated|r" ) ) )
        debug call BJDebugMsg("Debug1")
    endfunction

    //===========================================================================
    function InitTrig_DeathMessage takes nothing returns nothing
        local trigger DeathMessage = CreateTrigger()
        call TriggerRegisterUnitEvent( DeathMessage, gg_unit_H00A_0025, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( DeathMessage, gg_unit_H003_0022, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( DeathMessage, gg_unit_H006_0023, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( DeathMessage, gg_unit_H002_0016, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( DeathMessage, gg_unit_H009_0019, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( DeathMessage, gg_unit_O001_0020, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( DeathMessage, gg_unit_H001_0018, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( DeathMessage, gg_unit_E000_0017, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( DeathMessage, gg_unit_H008_0024, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( DeathMessage, gg_unit_H004_0423, EVENT_UNIT_DEATH )
        call TriggerAddAction( DeathMessage, function DeathMessageActions )
        set DeathMessage = null
    endfunction


    This trigger is supposed to spawn units at the location of the Gate Captain. The debug message comes up, but no units spawn. Also gate captains do not die, they switch owners before that. I have already wrote that script though.

    Spawns
    Code (vJASS):
    globals
       constant group captains = GetUnitsOfTypeIdAll('h00B')
    endglobals

    function Spawns takes nothing returns nothing
        local location loc = GetUnitLoc(GetEnumUnit())
        call CreateNUnitsAtLoc( 2, 'h005', GetOwningPlayer(GetEnumUnit()), loc, bj_UNIT_FACING )
        call CreateNUnitsAtLoc( 3, 'hfoo', GetOwningPlayer(GetEnumUnit()), loc, bj_UNIT_FACING )
        call CreateNUnitsAtLoc( 4, 'nhea', GetOwningPlayer(GetEnumUnit()), loc, bj_UNIT_FACING )
        set loc = null
    endfunction

    function Trig_Gate_Spawn_Actions takes nothing returns nothing
        call ForGroup( captains, function Spawns )
        debug call BJDebugMsg("Debug2")
    endfunction

    //===========================================================================
    function InitTrig_Gate_Spawn takes nothing returns nothing
        local trigger GateSpawn = CreateTrigger()
        call TriggerRegisterTimerEventPeriodic( GateSpawn, 120.00 )
        call TriggerAddAction( GateSpawn, function Trig_Gate_Spawn_Actions )
        set GateSpawn = null
    endfunction
     
    Last edited: Mar 16, 2009
  2. chaoslord301

    chaoslord301

    Joined:
    Sep 18, 2007
    Messages:
    105
    Resources:
    0
    Resources:
    0
  3. Ciebron

    Ciebron

    Joined:
    Apr 6, 2008
    Messages:
    760
    Resources:
    2
    Spells:
    2
    Resources:
    2
    Code (vJASS):
    globals
        group captains = CreateGroup() //must create a group
    endglobals

    function Spawns takes nothing returns nothing
        local location loc = GetUnitLoc(GetEnumUnit())
    call CreateNUnitsAtLoc( 2, 'h005', GetOwningPlayer(GetEnumUnit()), loc, bj_UNIT_FACING )
        call CreateNUnitsAtLoc( 3, 'hfoo', GetOwningPlayer(GetEnumUnit()), loc, bj_UNIT_FACING )
        call CreateNUnitsAtLoc( 4, 'nhea', GetOwningPlayer(GetEnumUnit()), loc, bj_UNIT_FACING )
        set loc = null
    endfunction

    function Trig_Gate_Spawn_Actions takes nothing returns nothing
        call ForGroup( captains, function Spawns )
        debug call BJDebugMsg("Debug2")
    endfunction

    //===========================================================================
    function InitTrig_Gate_Spawn takes nothing returns nothing
        local trigger GateSpawn = CreateTrigger()
        call TriggerRegisterTimerEventPeriodic( GateSpawn, 120.00 )
        call TriggerAddAction( GateSpawn, function Trig_Gate_Spawn_Actions )

        call GetUnitsOfTypeIdAll('h00B') //get the units here
       
        set GateSpawn = null
    endfunction


    petty inefficent code, get rid of those locations
     
  4. chaoslord301

    chaoslord301

    Joined:
    Sep 18, 2007
    Messages:
    105
    Resources:
    0
    Resources:
    0
    Thank you. But I am new to JASS, and may I ask what you suggest to optimize the code?

    And I may as well ask, what's the difference between nulling a location and removing it.

    Code (vJASS):
    local location loc
    set loc = null
    call RemoveLocation(loc)
     
    Last edited: Mar 15, 2009
  5. Ciebron

    Ciebron

    Joined:
    Apr 6, 2008
    Messages:
    760
    Resources:
    2
    Spells:
    2
    Resources:
    2
    if u null a location Var the location is still there and will take up size, if u remove it the location gets removed and wont take any size. all i can tell you.

    but dont use locations much better to use X/Y

    and i dont think call ForGroup is that good either since u need to call a new function

    ill rewrite the code to a efficent tomorrow so u can learn from it gotta sleep now
     
  6. chaoslord301

    chaoslord301

    Joined:
    Sep 18, 2007
    Messages:
    105
    Resources:
    0
    Resources:
    0
    Alright thanks, and I totally spaced on the x/y coordinates :/ I usually remember.

    Anyways thanks, wish I could rep you more :/
     
  7. Shadow Daemon

    Shadow Daemon

    Joined:
    Nov 23, 2008
    Messages:
    184
    Resources:
    3
    Tools:
    3
    Resources:
    3
    You forgot something:

    Code (vJASS):
    globals
        group captains = null
        // it should be null, because GetUnitsOfTypeIdAll() creates resulting group.
    endglobals

    function InitTrig_Gate_Spawn takes nothing returns nothing
        local trigger GateSpawn = CreateTrigger()
        call TriggerRegisterTimerEventPeriodic( GateSpawn, 120.00 )
        call TriggerAddAction( GateSpawn, function Trig_Gate_Spawn_Actions )
        // --->>
        set captains = GetUnitsOfTypeIdAll('h00B') //get the units here
        // <<---
        set GateSpawn = null
    endfunction


    And I think, that picking should be periodical (for that case, if Gate Captain was killed). My variant:

    Code (vJASS):
    globals
      group captains = CreateGroup()
      boolexpr conditions = null
    endglobals

    function Spawns takes nothing returns boolean
      local unit u = GetFilterUnit()
      local real x = 0.
      local real y = 0.
      local real f = 0.
      local player p = null
      if GetUnitTypeId(u) == 'h00B' then
        set x = GetUnitX(u)
        set y = GetUnitY(u)
        set f = GetUnitFacing(u)
        set p = GetOwningPlayer(u)
        // -----
        // >> Creating units
        call CreateUnit(p, 'h005', x, y, f)
        // . . .
        // . . .
        call CreateUnit(p, 'nhea', x, y, f)
      endif
      set u = null
      return false
    endfunction

    function Trig_Gate_Spawn_Actions takes nothing returns nothing
      local integer i = 0
      loop
        call GroupEnumUnitsOfPlayer(captains, Player(i), conditions)
        exitwhen i > 15
      endloop
    endfunction

    function InitTrig_Gate_Spawn takes nothing returns nothing
      call TimerStart(CreateTimer(), 120.0, true, function Trig_Gate_Spawn_Actions)
      set conditions = Condition(function Spawns)
    endfunction


    About the first issue - ensure, that your unit variables are not equal to null.
     
  8. chaoslord301

    chaoslord301

    Joined:
    Sep 18, 2007
    Messages:
    105
    Resources:
    0
    Resources:
    0
    I should of probably stated that the gate captains do not get killed, I will update first post. Should I use TimerUtils then since you recommend a timer?
     
  9. maskedpoptart

    maskedpoptart

    Joined:
    Aug 4, 2006
    Messages:
    351
    Resources:
    1
    Spells:
    1
    Resources:
    1
    i think the problem is that your triggers are local. when function InitTrig_DeathMessage is run at map intialization, it creates a local trigger DeathMessage that only exists within that function. it registers events and actions for DeathMessage. at the end of the function, the trigger DeathMessage no longer exists. so, the trigger actions don't get set off. try changing your InitTrig functions to the following:

    Death Message
    Code (vJASS):
    function InitTrig_DeathMessage takes nothing returns nothing
        set gg_trg_DeathMessage = CreateTrigger()
        call TriggerRegisterUnitEvent( gg_trg_DeathMessage, gg_unit_H00A_0025, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( gg_trg_DeathMessage, gg_unit_H003_0022, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( gg_trg_DeathMessage, gg_unit_H006_0023, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( gg_trg_DeathMessage, gg_unit_H002_0016, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( gg_trg_DeathMessage, gg_unit_H009_0019, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( gg_trg_DeathMessage, gg_unit_O001_0020, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( gg_trg_DeathMessage, gg_unit_H001_0018, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( gg_trg_DeathMessage, gg_unit_E000_0017, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( gg_trg_DeathMessage, gg_unit_H008_0024, EVENT_UNIT_DEATH )
        call TriggerRegisterUnitEvent( gg_trg_DeathMessage, gg_unit_H004_0423, EVENT_UNIT_DEATH )
        call TriggerAddAction( gg_trg_DeathMessage, function DeathMessageActions )
    endfunction



    Spawns
    Code (vJASS):
    function InitTrig_Gate_Spawn takes nothing returns nothing
        set gg_trg_GateSpawn = CreateTrigger()
        call TriggerRegisterTimerEventPeriodic( gg_trg_GateSpawn, 120.00 )
        call TriggerAddAction( gg_trg_GateSpawn, function Trig_Gate_Spawn_Actions )
    endfunction


    after you make these changes, export your map script, view it in JassCraft, and make sure all your triggers are being initialized at the top (e.g. "trigger gg_trg_DeathMessage = null")


    a location variable "points" to a certain location. removing the location that the variable points to frees up the memory that the location was occupying. This keeps the game from slowing down over time since every location that is created is also removed. Setting a variable = null makes the variable no longer reference anything, so you should RemoveLocation(loc) before you set loc = null.
     
    Last edited: Mar 16, 2009
  10. Shadow Daemon

    Shadow Daemon

    Joined:
    Nov 23, 2008
    Messages:
    184
    Resources:
    3
    Tools:
    3
    Resources:
    3
    There's no such need, because timer would stay all the game.

    Ok, the second variant with single unit pick:

    Code (vJASS):
    globals
      group captains = CreateGroup()
    endglobals

    function Conditions takes nothing returns boolean
      if GetUnitTypeId(GetFilterUnit()) == 'h00B' then
        call GroupAddUnit(captains, GetFilterUnit())
      endif
      return false
    endfunction

    function Spawns takes nothing returns nothing
      local unit u = GetEnumUnit()
      local real x = GetUnitX(u)
      local real y = GetUnitY(u)
      local real f = GetUnitFacing(u)
      local player p = GetOwningPlayer(u)

      // >> Creating units
      call CreateUnit(p, 'h005', x, y, f)
      // . . .
      call CreateUnit(p, 'nhea', x, y, f)

      set u = null
    endfunction

    function OnTimer takes nothing returns nothing
      call ForGroup(captains, function Spawns)
    endfunction

    function InitTrig_Gate_Spawn takes nothing returns nothing
      local integer i = 0
      local group gr = CreateGroup()
      loop
        call GroupEnumUnitsOfPlayer(gr, Player(i), Condition(function Conditions))
        exitwhen i > 15
      endloop
      call DestroyGroup(gr)
      set gr = null

      call TimerStart(CreateTimer(), 120.0, true, function OnTimer)
    endfunction


    (Almost the same, that Ciebron wrote. Almost ;) )

    By the way, ForGroup is better than a FirstOfGroup loop.

    >> ADDED <<
    No sir, you're wrong, there is absolutely no matter, global or local variable the trigger is. You can check it by yourself:

    Code (vJASS):
    function TestFunc takes nothing returns nothing
      call BJDebugMsg("zomg")
    endfunction

    function InitTrig_Test takes nothing returns nothing
      local trigger tr = CreateTrigger()
      call TriggerAddAction(tr, function TestFunc)
      call TriggerRegisterTimerEvent(tr, 1.0, false)
    endfunction


    is identical to:

    Code (vJASS):
    function TestFunc takes nothing returns nothing
      call BJDebugMsg("zomg")
    endfunction

    function InitTrig_Test takes nothing returns nothing
      set gg_trg_Test = CreateTrigger()
      call TriggerAddAction(gg_trg_Test, function TestFunc)
      call TriggerRegisterTimerEvent(gg_trg_Test, 1.0, false)
    endfunction


    Both variants would work.
     
  11. maskedpoptart

    maskedpoptart

    Joined:
    Aug 4, 2006
    Messages:
    351
    Resources:
    1
    Spells:
    1
    Resources:
    1
    hmm... both variants may work but i don't understand why. could you explain how the local trigger can exist outside the init function? does it have something to do with the hidden native code of CreateTrigger or TriggerRegisterEvent or TriggerAddAction? :confused: bleh... sorry if make this thread go off on a tangent.
     
  12. Eleandor

    Eleandor

    Joined:
    Aug 21, 2005
    Messages:
    3,681
    Resources:
    2
    Models:
    1
    Tutorials:
    1
    Resources:
    2
    any handle, this includes units, locations, triggers, are nothing more than pointers.

    If you create a local unit or location and the function ends, the pointer to this unit is removed, but the actual unit or location is still in-game. Especially in the case of locations this usually results in memory leaks. The location is still in-game and consumes memory but you've lost reference to it because your location pointer was local.

    The same is true for triggers: the actual trigger behind the trigger pointer variable is still there and will still run. You simply lost reference to the trigger var but it's still there.
     
  13. chaoslord301

    chaoslord301

    Joined:
    Sep 18, 2007
    Messages:
    105
    Resources:
    0
    Resources:
    0
    I have another question, I just recoded my Spawn trigger and wanted some feedback. Just wondering if I should call the CreateUnit actions X amount of times or loop it like this:
    Spawn
    Code (vJASS):
    globals
        group Captains = CreateGroup()
        constant integer ID1 = 'h005'
        constant integer ID2 = 'hfoo'
        constant integer ID3 = 'nhea'
    endglobals

    function Reinforcements takes nothing returns nothing
        local integer i = 0
        local unit u = GetEnumUnit()
        local player p = GetOwningPlayer(u)
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        local real f = GetUnitFacing(u)
        loop
            exitwhen i == 2
            call CreateUnit(p, ID1, x, y, f)
            set i = i + 1
        endloop
        loop
            exitwhen i == 5  
            call CreateUnit(p, ID2, x, y, f)
            set i = i + 1
        endloop
        loop
            exitwhen i == 9
            call CreateUnit(p, ID3, x, y, f)
            set i = i + 1
        endloop  
        set u = null
        set p = null
        set i = 0
        set x = 0
        set y = 0
        set f = 0
    endfunction

    function SpawnActions takes nothing returns nothing
        call ForGroup( Captains, function Reinforcements )
    endfunction

    //===========================================================================
    function InitTrig_Gate_Spawn takes nothing returns nothing
        local trigger trig = CreateTrigger()
        call TriggerRegisterTimerEventPeriodic( trig, 120.00 )
        call TriggerAddAction( trig, function SpawnActions )
        set Captains = GetUnitsOfTypeIdAll('h00B')
    endfunction
     
     
  14. Shadow Daemon

    Shadow Daemon

    Joined:
    Nov 23, 2008
    Messages:
    184
    Resources:
    3
    Tools:
    3
    Resources:
    3
    If the X is a constant and not too big number, it would be better to write CreateUnit() X times. If X is dependant to another variable, or changes with time, make a loop.

    Also, you don't need to null reals, integers and strings:

    Code (vJASS):
    //    set i = 0
    //    set x = 0
    //    set y = 0
    //    set f = 0
     
  15. chaoslord301

    chaoslord301

    Joined:
    Sep 18, 2007
    Messages:
    105
    Resources:
    0
    Resources:
    0
    Alright, thanks, they are constant throughout the entire game, and I didn't think I needed to null reals or integers, just wasn't sure and wanted to be safe. Wish I could rep you again, you've been a great help.