• 🏆 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] [Solved] Local trigger

Status
Not open for further replies.
Level 12
Joined
Jan 10, 2023
Messages
191
I recently began learning JASS via converting GUI and reading tutorials and I have a question about local triggers

I think it's easiest if I post my example:

SG_Init makes a local trigger and after the other actions it queues SG_InitPlayer
SG_InitPlayer loops to make a 5184 images per player for later use in making various grids for the players
- these triggers were separated because the world editor didn't seem to want to do 5184*12 loops in one trigger

I'm guessing there are many things I can improve, and that's what I'm currently trying to do, but my real question is can I make the SG_InitPlayer a local trigger? It seems like between the two of them, it would be better to have SG_InitPlayer be local because it is much larger

The reason I elected to add the trigger to the queue and didn't just run the trigger is because it seemed to perform better this way, and to my mind it was safer, rather than having the trigger call itself within itself many times, testing which worked better, run or add to queue, they seemed to perform the same, but I think its better to have breaks in the trigger.
(correct me if I'm wrong, but it also seemed to help on another project that makes a much larger loop)

When I change SG_InitPlayer to use 'local trigger t = CreateTrigger()' (and the rest of the InitTrig_SG_InitPlayer function to match), I lose my handle on the trigger it seems and I can't add it to the queue, or maybe it can't be added because it isn't a global trigger... I can't figure it out.

If I were to simply merge the two triggers, the trigger fails because it is too large..

It runs fine if I just don't make it a local trigger, but I thought at the very least this would be a good opportunity for me to learn something about local triggers
(I can't seem to find this specific question anywhere)

To formalize the question:
Can I write this so that SG_InitPlayer is a local trigger that can still be accessed by SG_Init?

I have a feeling that I can't do that (sounds like the word local would imply I can't) so my follow up question would be:
Is there a way I can make SG_InitPlayer a local function of SG_Init without making the trigger too large to work?

JASS:
function Trig_SG_Init_Actions takes nothing returns nothing
    local integer i = 1
    set udg_SG_MaxPlayer = 12
    set udg_SG_MaxSize = 72
    set udg_SG_MaxRect = ( udg_SG_MaxSize * udg_SG_MaxSize )
    call InitHashtableBJ(  )
    set udg_SG_CycleHash = GetLastCreatedHashtableBJ()
    call InitHashtableBJ(  )
    set udg_SG_ImagesHash = GetLastCreatedHashtableBJ()
    set udg_SG_Pos = Location(0, 0)
    loop
        exitwhen i > udg_SG_MaxPlayer
        set udg_SG_PathingRadius[i] = ( udg_SG_MaxSize * 32 )
        set i = i + 1
    endloop
    call TriggerExecute( gg_trg_SG_ColorValues )
    call TriggerExecute( gg_trg_SG_ColorNames )
    set udg_SG_PlayerIndex = 1
    call QueuedTriggerAddBJ( gg_trg_SG_InitPlayer, false )
endfunction

//===========================================================================
function InitTrig_SG_Init takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterTimerEventSingle( t, 0.05 )
    call TriggerAddAction( t, function Trig_SG_Init_Actions )
    set t = null
endfunction
JASS:
function Trig_SG_InitPlayer_Actions takes nothing returns nothing
    local integer i = 0
    local integer j = udg_SG_MaxSize
    local integer k = udg_SG_MaxRect
    local integer l = udg_SG_PlayerIndex
    local integer x
    local integer y
    loop
        exitwhen i > k
        set x = ( ModuloInteger(i, j) - ( j / 2 ) )
        set y = ( ( ( i - ModuloInteger(i, j) ) / j ) - ( j / 2 ) )
        call CreateImageBJ( "war3mapImported\\Grid64.blp", 64.00, udg_SG_Pos, 0, 3 )
        call SaveImageHandleBJ( GetLastCreatedImage(), i, l, udg_SG_ImagesHash )
        call SetImageRenderAlways( LoadImageHandleBJ(i, l, udg_SG_ImagesHash), true )
        call ShowImageBJ( false, LoadImageHandleBJ(i, l, udg_SG_ImagesHash) )
        set i = i + 1
    endloop
    set udg_SG_isCycleOn[l] = true
    set udg_SG_PlayerIndex = ( udg_SG_PlayerIndex + 1 )
    if ( udg_SG_PlayerIndex > udg_SG_MaxPlayer ) then
        call RemoveLocation(udg_SG_Pos)
        call QueuedTriggerRemoveBJ( GetTriggeringTrigger() )
        call StartTimerBJ( udg_SG_PostInializationTimer, false, 0.10 )
    else
        call QueuedTriggerAddBJ( GetTriggeringTrigger(), false )
        call QueuedTriggerRemoveBJ( GetTriggeringTrigger() )
    endif
endfunction

//===========================================================================
function InitTrig_SG_InitPlayer takes nothing returns nothing
    set gg_trg_SG_InitPlayer = CreateTrigger(  )
    call TriggerAddAction( gg_trg_SG_InitPlayer, function Trig_SG_InitPlayer_Actions )
endfunction
 
Level 39
Joined
Feb 27, 2007
Messages
5,013
the world editor didn't seem to want to do 5184*12 loops in one trigger
The operations limit (op limit) is 32768. It used to be 8192. Any operation (any line that starts with call, set, and maybe keywords like if?) past this limit will cause a thread crash and nothing further will execute in that thread. This is to prevent a game freeze from an infinite loop or some other extremely inefficient process. Triggers that run other triggers and functions that call other functions are all part of the same thread, so you cannot circumvent the op limit that way. You can get around this in a few ways:
  • Any wait action will end the thread allowing the op count to reset.
  • A periodic trigger with a low timeout that runs one big chunk of the process each execution.
  • Run multiple threads by using ExecuteFunc (dangerous, will cause a map crash if the function name string doesn't correspond to any function in the map script, cannot be used on functions with arguments) or .execute() (see functions as objects in the JASSHelper documentation)
However... I think whatever you're doing is far too much a brute force approach. There should be an easier/simpler solution that does not require 62k unique image objects.
  • Images can safely be manipulated (but not created or destroyed) locally, as they have no effect on anything in-game that would result in a gamestate desync. You could use the same set of image objects for all players, with them locally moved/shaded/scaled as needed. At the very least you would only want to create images for players that are actually in the game (though of course you'd want it to still work with a full house).

  • Are there really 5184 unique images you need that couldn't be easily represented by simpler subset of images repeated in different ways?

  • There's no way you're showing 5184 images per player simultaneously. Is it not possible just to move the images around to the correct positions as they are needed?
 
Level 12
Joined
Jan 10, 2023
Messages
191
The operations limit (op limit) is 32768. It used to be 8192. Any operation (any line that starts with call, set, and maybe keywords like if?) past this limit will cause a thread crash and nothing further will execute in that thread. This is to prevent a game freeze from an infinite loop or some other extremely inefficient process. Triggers that run other triggers and functions that call other functions are all part of the same thread, so you cannot circumvent the op limit that way. You can get around this in a few ways:
  • Any wait action will end the thread allowing the op count to reset.
  • A periodic trigger with a low timeout that runs one big chunk of the process each execution.
  • Run multiple threads by using ExecuteFunc (dangerous, will cause a map crash if the function name string doesn't correspond to any function in the map script, cannot be used on functions with arguments) or .execute() (see functions as objects in the JASSHelper documentation)

Thank you, that link is about to become a bible to me!! lol
Feel free to ignore the rest of my reply, it is lengthy, this link should solve my problem I think (or tell me if their is a better solution)
The rest is just explanation
However... I think whatever you're doing is far too much a brute force approach. There should be an easier/simpler solution that does not require 62k unique image objects.

So, along with what you said about being a brute force method, this method (adding to queue) does work for me and only occurs at initialization
(well, 0.05 game time) so I wrote a few of the reasons why I did this..
Some key points that justified it to me were:
  • The images are used in a grid system that makes block-circles (like a circle of pixels) to represent a range
    • 5184 'tiles' sized at 64x64 per tile means the max range that can be displayed this way is a range of 2304.00, any lower seems too low
    • The range is of course circular, but the loop will still require that I use 72x72 in order to draw every row of the block-circle

  • Everyone can show their grid simultaneously without any lag (tested with twelve players each displaying max range grids) so they need their own images.

  • At maximum range, not all images fit on the screen, but again it doesn't bother me to show it because if the camera isn't locked, they can still pan and see their whole grid/ other players could see their grid
    • I'm not certain if I will hide the grids of other players yet, I might just restrict where a player can place their grid... I had this vision of players grid bombing another player they didn't like... it didn't lag much when I grid bombed myself, but it could still be a distraction or a nuisance...

  • Images can safely be manipulated (but not created or destroyed) locally, as they have no effect on anything in-game that would result in a gamestate desync. You could use the same set of image objects for all players, with them locally moved/shaded/scaled as needed. At the very least you would only want to create images for players that are actually in the game (though of course you'd want it to still work with a full house).

For the potential of making grids invisible except to the player who the grid belongs to, I was intending (if I choose to go that way) to make the 'show image' action to be the local manipulation, as in I would create them, enable rendering, but only 'show' locally, if that didn't work I planned to make the enable rendering action a local thing too.

  • Are there really 5184 unique images you need that couldn't be easily represented by simpler subset of images repeated in different ways?

It seemed like that would be more difficult, but I suppose that's only more difficult to write, and not by much and would otherwise be more efficient except for one thing:
  • If the bottom-left corner of an image is off screen (what I think of now as the origin of the image), then that whole image will be hidden, so if I make larger images to fill larger sections of the interior of the circle, then the player will see a void in the grid if they pan too far upward or right-ward for that image.
  • Having many small images avoids this and makes the writing as simple as 'if y^2 + x^2 <= r then show' (well that's an over simplification, but you see my point) to check if the tile is within the circular range.

  • There's no way you're showing 5184 images per player simultaneously. Is it not possible just to move the images around to the correct positions as they are needed?

They don't all fit on screen, so that's definitely a point for you, but lets say I cast this on a unit and want to know the attack range, if the range can target something off-screen, the player might pan over to that edge of the range and still want to see the edge of the grid to so how far is in range.

Similarly, you may want to be able to see another player's grid if it is an ally or has some other relevance to you in-game.

Regardless of whether you can see another player's grid, the point about being able to pan the game-cam to see the full range is a big one, and I don't want player 1's grid to be stolen when player 12 wants to use it.

Each player's grid does recycle itself, players each only have 5184 tiles that get re-used/ moved around as needed.

Pyrogasm, seriously, thanks for the help you continually give! Always appreciated!!
 
Level 39
Joined
Feb 27, 2007
Messages
5,013
Things running through the Trigger Queue are probably all be their own thread, but I don't know for certain. Seems your approach to iterate works fine enough. I generally agree with your logic because of the image origin determining if the whole thing is shown or not. I don't think you understand my point about not needing a set for each player. Since they can be locally moved, colored, hidden, and shown... a single set of 5k images could be shared among all players with each player seeing the images in different locations.

Consider your argument that the range is big enough to extend off the screen for any given player: since that's true, then in what situation is a player likely to need to see more than one grid simultaneously? I should see a grid around my unit when my unit is selected, and if i want to see the grid around another player's unit I should just have to select that unit and the images should reorganize around it. If I can see the grids from multiple units simultaneously, how can I know which parts of which grids correspond to which units, anyway? Again I don't know exactly why you're doing this (I did see the build grid thread), so maybe there is a good reason but I just don't see it. When the edge of two grids is near each other and you pan your camera to that intersection then yeah you might reasonably be able to see them both, but what purpose does that serve? Isn't knowing what units/locations are inside each grid the critical information, rather than how the grids overlap? In any case being able to toggle between them should provide that same information.

Even if you disagree entirely with the above paragraph, in what universe does a player need to see more than two grids simultaneously? You could definitely get away with having primary grid and a secondary grid so two can be shown at once and nobody would ever need more than that. Player 1 shouldn't care about whatever grids are being shown to Player 3. If they want to see grids for player 3's units they can activate them manually.



If the grids are not being colored in some way to differentiate different properties of each square of the grid, then why do you need a full grid at all? It would be far simpler to make a giant circle with effects (or lightning objects or an upscaled image) around the relevant origin point, and then along the edge place just those edge-grid pieces so it's explicitly clear to the player which cells are 'in' vs 'out' of the bigass circle. Like this:

Basic_circular_tower_layouts.png
 
Level 19
Joined
Aug 16, 2007
Messages
881
The operations limit (op limit) is 32768. It used to be 8192. Any operation (any line that starts with call, set, and maybe keywords like if?) past this limit will cause a thread crash and nothing further will execute in that thread. This is to prevent a game freeze from an infinite loop or some other extremely inefficient process.
I believe you mixed up op limit with array size.

Testing the op limit with the following code:
JASS:
scope OPLimitTest initializer Init
    globals
        private integer i = 0
    endglobals

    private function DisplayResult takes nothing returns nothing
        call BJDebugMsg("OP Limit: " + I2S(i))
    endfunction

    private function RunTest takes nothing returns boolean
        loop
            set i = i + 1
        endloop
        return false
    endfunction

    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterPlayerEvent(t, Player(0), EVENT_PLAYER_END_CINEMATIC)
        call TriggerAddCondition(t, Condition(function RunTest))
        set t = null
        
        call TimerStart(CreateTimer(), 1.0, true, function DisplayResult)
    endfunction
endscope

Gives a result of ATLEAST 428571 operations. I'm not sure if "loop" or "endloop" costs multiple operations.

oplimit.png
 
Level 12
Joined
Jan 10, 2023
Messages
191
Replies:
I believe you mixed up op limit with array size.

Testing the op limit with the following code:
JASS:
scope OPLimitTest initializer Init
    globals
        private integer i = 0
    endglobals

    private function DisplayResult takes nothing returns nothing
        call BJDebugMsg("OP Limit: " + I2S(i))
    endfunction

    private function RunTest takes nothing returns boolean
        loop
            set i = i + 1
        endloop
        return false
    endfunction

    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterPlayerEvent(t, Player(0), EVENT_PLAYER_END_CINEMATIC)
        call TriggerAddCondition(t, Condition(function RunTest))
        set t = null
     
        call TimerStart(CreateTimer(), 1.0, true, function DisplayResult)
    endfunction
endscope

Gives a result of ATLEAST 428571 operations. I'm not sure if "loop" or "endloop" costs multiple operations.

View attachment 425579
I think if we put another integer in the loop with 'i' we could find the value of 'n' and 'i', compare it to the 428571 found with 'i', do a little math, and find out if those loops and endloops are counting toward our limit.

for example, if 'n' and 'i' reach somewhere near 214285 (half), then loops are not contributing, if we get something like 321429 (three quarters), then the loops are contributing.


Things running through the Trigger Queue are probably all be their own thread, but I don't know for certain. Seems your approach to iterate works fine enough. I generally agree with your logic because of the image origin determining if the whole thing is shown or not.
This is nearest to the real question, and I do appreciate the help, thank to it I intend to have them all share the images and have them move/ change color locally, but the real question is still being missed, the rest are design suggestions (which are cool, but you don't need to know what it's for, the question is):
Can I write this so that SG_InitPlayer is a local trigger that can still be accessed by SG_Init?
I think I am lacking understanding here, my intention for making SG_InitPlayer was to make it a local trigger in the hopes that it would be better for memory. I thought that using local triggers meant they would not be held in the games memory but instead are removed as soon as they are done, or can be removed more easily... (I feel another link coming lol)

Consider your argument that the range is big enough to extend off the screen for any given player: since that's true, then in what situation is a player likely to need to see more than one grid simultaneously? I should see a grid around my unit when my unit is selected, and if i want to see the grid around another player's unit I should just have to select that unit and the images should reorganize around it. If I can see the grids from multiple units simultaneously, how can I know which parts of which grids correspond to which units, anyway? Again I don't know exactly why you're doing this (I did see the build grid thread), so maybe there is a good reason but I just don't see it. When the edge of two grids is near each other and you pan your camera to that intersection then yeah you might reasonably be able to see them both, but what purpose does that serve? Isn't knowing what units/locations are inside each grid the critical information, rather than how the grids overlap? In any case being able to toggle between them should provide that same information.
In hindsight, this one has sunk a lot over the last few days. It would become (I think) a weapon of spam if everyone could see the other's grids.
"GRID-BOMB THE n00b!!!!" could be a thing if anyone ever used it lol.

Overlapping wouldn't be useless, if for some reason I decided to allow one player to have multiple grids, because they are different colors and pastel colors so they blend when on top of another grid to make a blocky Easter-Venn-diagram... and would then be showing maybe the range of a unit's ability and the range some other units attack, or whatever ranges they have (it cycles through all applicable ranges for the target unit by default), could be useful to visually compare who will have an advantage.

If it is critical information to know who is in what grid, then isn't it only more critical that we know if a unit is in two grids.
It's like wanting to know if there is one gun to your head but not being concerned about two... I mean sure one might be enough, but you should get away from both.

Even if you disagree entirely with the above paragraph, in what universe does a player need to see more than two grids simultaneously? You could definitely get away with having primary grid and a secondary grid so two can be shown at once and nobody would ever need more than that. Player 1 shouldn't care about whatever grids are being shown to Player 3. If they want to see grids for player 3's units they can activate them manually.
Ironically, after all of this, I'm debating keeping 60k tiles and making it so that each player shares 60k tiles and can each have like 50 grids...
Hear me out, imagine I want to see the range of all my towers at the same time..

I think we have slightly different mentalities here, it just causes so little drag on the game (seemingly) to have 60k+ images that I wonder why not.
The only annoyance of the system as I have it is a tiny lag spike at the start of the map, lasting only a moment on my 3 year old basic laptop, so I think if my laptop can handle it, it has been made efficient enough.

I do agree that players shouldn't see other player's ranges. I was kind of stretching when I made that point, and if I want to see the range of one of another player's units, I can just use my grid like you said. I can even then add functionality to make it so that maybe you can't see all ranges of an enemy, maybe only certain ones like attack ranges and auras but leave some hidden.

If the grids are not being colored in some way to differentiate different properties of each square of the grid, then why do you need a full grid at all? It would be far simpler to make a giant circle with effects (or lightning objects or an upscaled image) around the relevant origin point, and then along the edge place just those edge-grid pieces so it's explicitly clear to the player which cells are 'in' vs 'out' of the bigass circle.
They are being colored tile by tile at times. I know it is unfocused, I'm trying to hold off on design decisions in part because I am trying to make something with broad applicability and don't have a specific project in mind to apply it to atm, but as it is now the grid serves the purpose of revealing the pathability of terrain when targeting the ground (this colors each tile differently), and it cycles through the ranges of a unit's attacks and abilities when applied to a unit, cycling through them and applying a pre-defined color to distinguish each ability/ attack from the other abilities of that unit (these are solid colors).

HOWEVER, all this talk on image semantics gave me an idea to work with a simple circle image when it comes to the solid-color ranges, or at least to make an option:
  • If I make the origin the middle of the unit using CreateImage and setting the origin there, I wonder if the images are only disappearing because the origin is off-screen, seems likely, in which case I might make this a toggle that can be used for non-pathing ranges.
Frankly, I like the look of tiles in a grid as opposed to a solid filled circle, but I can understand the want for a circle for a few reasons.

Honestly, to explain the strange nature of my system here being unapplied - I began work on this in GUI a little while ago, and it seemed to me that optimizing it and converting it to JASS would be a good first lesson in JASS since I have some small experience with object-oriented code, so despite not having an application for it, I find it helpful to me. Hopefully that explains the system with no specific purpose aspect that keeps popping up.

In the meantime, I'm brain-storming ideas and also have a few friends that are less about code and more about game-storming to key off of.



Here's what I came up with to make the triggers all local:

JASS:
//
// tmpSetOwner is exclusively used by SG_PostInit for the sake of debugging
// it is meant only to give 12 players a base with various units that are pre-placed on the map
// and in the map's force properties I have players 1-12 on one force with full shared control
// This is so that I can test that all grids are all functioning correctly simultaneously
//
function tmpSetOwner takes nothing returns nothing
    call SetUnitOwner( GetEnumUnit(), ConvertedPlayer(udg_SG_PlayerIndex), true )
endfunction

//
// Currently SG_PostInit just sets the terrain visibility and then sets the unit ownership for the sake of debugging
// Theoretically this would be the stage of initiation for anything that should happen after the grid is made.
// This has little use at the moment but serves as my 'Map Initialization - Event' trigger.
//
function SG_PostInit takes nothing returns nothing
    local integer i = 1
    local group g
    call BlzShowTerrain( true )
    loop
        exitwhen i > udg_SG_MaxPlayer
        set udg_SG_PlayerIndex = i
        set g = GetUnitsInRangeOfLocAll(1600.00, GetPlayerStartLocationLoc(ConvertedPlayer(i)))
        call ForGroup( g, function tmpSetOwner )
        call DestroyGroup( g )
        call BJDebugMsg("Ownership changed for units near Player " + I2S(i) + "'s start location")
        set i = i + 1
    endloop
endfunction

//
// SG_PlayerInit is executed by SG_Init once per player.
// It creates the images and stores them each with a handle for later use.
//
function SG_InitPlayer takes nothing returns nothing
    local integer i = 0
    local integer j = udg_SG_MaxSize
    local integer k = udg_SG_MaxRect - 1
    local integer SG_P = udg_SG_PlayerIndex
    local integer x
    local integer y
    local image tile
    loop
        exitwhen i > k
        set x = ( ModuloInteger(i, j) - ( j / 2 ) )
        set y = ( ( ( i - ModuloInteger(i, j) ) / j ) - ( j / 2 ) )
        set tile = CreateImage( "SGrid64.blp", 64, 64, 64, 0, 0, 0, 0, 0, 0, 3 )
        call SaveImageHandle( udg_SG_ImagesHash, SG_P, i, tile )
        call SetImageRenderAlways( LoadImageHandle( udg_SG_ImagesHash, SG_P, i ), true )
        call ShowImage( LoadImageHandle( udg_SG_ImagesHash, SG_P, i ), false )
        set i = i + 1
        set tile = null
    endloop
    set udg_SG_isCycleOn[SG_P] = true
    set udg_SG_PathingRadius[SG_P] = udg_SG_MaxRect
    call BJDebugMsg("Grid made for Player " + I2S(udg_SG_PlayerIndex))
    set udg_SG_PlayerIndex = ( udg_SG_PlayerIndex + 1 )
endfunction

//
// First Trigger, does some initializing then executes SG_InitPlayer once for each player, then calls SG_PostInit
// PreInit trigger could be added here before the loop at the desired line if wanted/needed.
//
function SG_Init takes nothing returns nothing
    local integer i = 1
    local trigger t = CreateTrigger(  )
    call TriggerAddAction( t, function SG_InitPlayer )
    set udg_SG_PlayerIndex = 1
    set udg_SG_CycleHash = InitHashtable()
    set udg_SG_ImagesHash = InitHashtable()
    call TriggerExecute( gg_trg_SG_ColorValues )
    call TriggerExecute( gg_trg_SG_ColorNames )
    loop
        exitwhen i > udg_SG_MaxPlayer
        call BJDebugMsg("SG_InitPlayer added for Player " + I2S(i))
        call TriggerExecute( t )
        set i = i + 1
    endloop
    call SG_PostInit()
endfunction

//===========================================================================
function InitTrig_SG_Init takes nothing returns nothing
    local trigger T = CreateTrigger(  )
    call TriggerRegisterTimerEventSingle( T, 0.05 )
    call TriggerAddAction( T, function SG_Init )
endfunction

The issue I was having was that I couldn't access a local trigger from outside of the function it was local to so I just rearranged the triggers so that SG_Init creates SG_PlayerInit as an action, adds its action, and then calls it, rather than having SG_PlayerInit initiate itself.
I did some research to confirm that 'TriggerExecute' (the native that QueuedTriggerAddBJ relies on) does start a new context for the function it executes (hence the failure to find the local trigger, hindsight is 20-20) so this avoids the OP limit.

I figured I'd add the SG_PostInit trigger to the bunch and eliminate the need for more than one global trigger (as small of an optimization as it may be, might as well, its good practice it seems). This also eliminated my need for a global timer.

Outside of the things we have mentioned already, what do you think? I figured I might as well boil it down to use natives over function calls that simply call natives, so there are a few changes in that respect (again, I figured this is a good practice)
 
Last edited:
Level 12
Joined
Jan 10, 2023
Messages
191
I am not sure what you are trying to achieve with all those triggers. You can just call the function instead.

If I call the function the trigger fails after four loops of SG_InitPlayer

I am executing SG_InitPlayer in a new trigger context to avoid this.
If I use TriggerExecute then SG_InitPlayer instead of calling the function it runs the function in a new context and can run many times more than four.
 
Level 12
Joined
Jan 10, 2023
Messages
191
little update, I did make the images show locally and removed the player init trigger.

I put all the JASS into one long script, is that common or advised? Seemed practical to me (this isn't the whole script, all JASS for whole system in one script including several triggers and many functions)
 
Status
Not open for further replies.
Top