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

It seems to me like some leaks are automatically cleaned up

Status
Not open for further replies.
Level 2
Joined
Sep 9, 2008
Messages
24
EDIT: Mystery solved. Leaks were not being auto-cleaned. Read the whole thread for details. Don't stop in the middle to talk shit to the people who actually put effort into helping, kthx.

I had some issues with triggers after I added code to clean up locations... So I posted asking for help. The responses were completely useless as people put no effort into solving my problem.

What I ended up figuring out was that under certain conditions, a location I had set in a variable would cease to exist. I had units which failed to spawn because they had no location to spawn to, because at some point the location object was being removed before I told it to.

I fixed my triggers by either using a different location that wasn't being destroyed before I told it, or for some triggers I had to create a new location from scratch... But anyway, I don't know the conditions needed to get this auto-cleanup thing. Anyone have any idea what's going on?

I will post the trigger I asked for help with before and point out what I changed:

  • Savage Leap Move
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Unit-type of (Dying unit)) Equal to Savage Leap Timer
    • Actions
      • Set TempPoint = (Position of Hero[(Player number of (Owner of (Dying unit)))])
      • Set TempPoint2 = (TempPoint offset by 48.00 towards PusherAngle[(Player number of (Owner of (Dying unit)))] degrees)
      • Unit - Move Hero[(Player number of (Owner of (Dying unit)))] instantly to TempPoint2
      • Unit - Move SavageLeapUnit[(Player number of (Owner of (Dying unit)))] instantly to TempPoint2
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (SavageLeapUnit[(Player number of (Owner of (Dying unit)))] is alive) Equal to True
        • Then - Actions
          • -------- The following action was not working. The unit would not spawn. I changed it to spawn at TempPoint2 rather than TempPoint and it worked after that. --------
          • Unit - Create 1 Savage Leap Timer for (Owner of (Dying unit)) at TempPoint2 facing 0.00 degrees
          • Unit - Add a 0.03 second Generic expiration timer to (Last created unit)
        • Else - Actions
      • Custom script: call RemoveLocation(udg_TempPoint)
      • Custom script: call RemoveLocation(udg_TempPoint2)
      • Unit - Remove (Dying unit) from the game
What I thought after making this change was that TempPoint got destroyed after I used it to create TempPoint2. I applied this to other triggers that had similar problems, and it worked.

Is it really cleaning up TempPoint, or is it somehow losing track of it and leaking it anyway?
 
Last edited:
Level 3
Joined
Aug 19, 2007
Messages
24
I see no rational reason, from this trigger, that it would do that. The polar projection does not destroy TempPoint.

I suggest that you go through the rest of your map and take a look at other places where you use TempPoint.
Specifically:
1. You are moving your hero. Check for some EnterRegion event
2. You are moving the savage leap unit. See (1)

You could try using a local variable instead of TempPoint. that would tell you right away whether or not it is something messing with your global variable that is the problem.

That's all I really have for you there. Sorry I couldn't be more help.
 
Level 4
Joined
Sep 18, 2007
Messages
104
Just some questions:
-Where is PusherAngle at?
-Your moving SavageLeapUnit, is this the unit that died?

You said "What I ended up figuring out was that under certain conditions, a location I had set in a variable would cease to exist."
-What were those conditions?

Otherwise your trigger looks fine, to me at least.
 
Level 7
Joined
Jul 20, 2008
Messages
377
Leaks are never automatically cleaned up. That's why they're called leaks, you can't even clean them up manually.

I am indeed curious as to whether you use TempPoint in any of your other triggers.
 
Level 2
Joined
Sep 9, 2008
Messages
24
I am indeed using TempPoint for dozens of triggers, but none of them will necessarily run in the middle of eachother. In 100% of tests, I'd lose the TempPoint location, not sometimes, every time. I will check the object manager in case I forgot about something that would somehow mess with it.

But can multiple triggers run at the same time?
 
Level 16
Joined
Jul 21, 2008
Messages
1,121
I think I know why sometime your TempPoint variables loose their value. GUI is slow and when multiple triggers are executed and all use global TempPoint they loose their locations because one trigger destroys variable before seconds finishes execution.

I would advise you to start learning JASS or use local variables within GUI (declared in custom script)
 
Level 2
Joined
Sep 9, 2008
Messages
24
I think I know why sometime your TempPoint variables loose their value. GUI is slow and when multiple triggers are executed and all use global TempPoint they loose their locations because one trigger destroys variable before seconds finishes execution.

I would advise you to start learning JASS or use local variables within GUI (declared in custom script)

How do you explain the fact that I am losing the variable 100% of the time? I don't have any triggers that fire when these triggers move units, only other triggers that could possibly coincide, but don't necessarily do so.

Again, it happens 100% of the time.
 
Level 16
Joined
Jul 21, 2008
Messages
1,121
When I started triggering in GUI I had same problems like you. I fixed them this way: Every time I use Temporary Variable, I set its value right before function it was needed for, and right after I clear it. That means that sometimes have setting of same variable multiple times. It may look strange, but it helps.

  • Savage Leap Move
  • Events
    • Unit - A unit Dies
  • Conditions
    • (Unit-type of (Dying unit)) Equal to Savage Leap Timer
  • Actions
    • Set TempPoint = (Position of Hero[(Player number of (Owner of (Dying unit)))])
    • Set TempPoint2 = (TempPoint offset by 48.00 towards PusherAngle[(Player number of (Owner of (Dying unit)))] degrees)
    • Custom script: call RemoveLocation(udg_TempPoint)
    • Unit - Move Hero[(Player number of (Owner of (Dying unit)))] instantly to TempPoint2
    • Unit - Move SavageLeapUnit[(Player number of (Owner of (Dying unit)))] instantly to TempPoint2
    • Custom script: call RemoveLocation(udg_TempPoint2)
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • (SavageLeapUnit[(Player number of (Owner of (Dying unit)))] is alive) Equal to True
      • Then - Actions
        • Set TempPoint = (Position of Hero[(Player number of (Owner of (Dying unit)))])
        • Unit - Create 1 Savage Leap Timer for (Owner of (Dying unit)) at TempPoint facing 0.00 degrees
        • Custom script: call RemoveLocation(udg_TempPoint)
        • Unit - Add a 0.03 second Generic expiration timer to (Last created unit)
      • Else - Actions
    • Unit - Remove (Dying unit) from the game
 
Level 2
Joined
Sep 9, 2008
Messages
24
When I started triggering in GUI I had same problems like you. I fixed them this way: Every time I use Temporary Variable, I set its value right before function it was needed for, and right after I clear it. That means that sometimes have setting of same variable multiple times. It may look strange, but it helps.

Yeah, I started doing that for the places where it appears that I'm losing the location...

But I still don't understand it. Why is the location being lost? Is it being destroyed, or is it leaking?
 
Level 2
Joined
Sep 9, 2008
Messages
24
Example: You have 2 triggers. Both use TempPoint. One uses loop and fires second in the middle of the loop.

Second trigger will change value of TempPoint and destroy it before first loop executes.

I've already said this a million times. It happens every single time. It's definetly not another trigger.

It's not an occassional fluke, it happens EVERY TIME.

Have I made myself clear?
 
Level 2
Joined
Sep 9, 2008
Messages
24
That shouldn't happen because jass runs in a single thread...

I'll look into it maybe tomorrow when I've got time...

Is it possible that some stuff changed in the latest version of WC3 (was pretty recent) and no one noticed something like this yet?
 
Level 3
Joined
Aug 19, 2007
Messages
24
A few things.

1. I strongly recommend you try what I said above and use a local variable instead. This will tell you definitively whether or not it's a problem with your global or one of your function calls in the function. You can debate all you want, but it's an awful lot better to perform a test that will rule out one of your possibilities (in this case, interference by another trigger)

2. Triggers can and do interrupt each other. For example: you have a trigger that triggers when a unit enters the map. You have another trigger that creates a unit. Your second trigger will create the unit, run the first trigger in its entirety, and then finish running the first trigger. It's essentially the same as using call (function). For this reason, if you have any trigger that is set up to trigger off of any of the events in this trigger then you will have to resolve them first. This is why locals are so useful - they are not at risk of being "damaged" by interrupting triggers or anything else

3. I notice that you are using 'set position instantly'. This function actually moves your unit using SetUnitPosition, which changes its location and then issues a stop order. If you have a trigger that triggers when a unit is issued that order, it may kill your TempPoint. You can test for this by temporarily disabling the two movement functions and seeing if your units still spawn with TempPoint instead of TempPoint2

4. GUI may make it look like all your code is in one function, but it is not. Your if statement, for example, is an entirely different and the condition itself is created as a condition function instead of writing if x then y. If you convert your function to JASS and post that we may be able to help you more so we can see what's actually going on (use edit -> convert to custom text).
 
Level 2
Joined
Sep 9, 2008
Messages
24
Xarian, You're right. I had a trigger that went off when a unit was issued an order and used TempPoint.

I've changed that one to use it's own global because that's easy.

If I were to use locals, wouldn't I have to use JASS for the whole trigger that used locals? Or is there some way to use locals that I've set with the Custom Script action in GUI?
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
You can have 1 local variable in GUI by making a custom script as the first action of your trigger. The syntax is something like:

  • Custom script: local location udg_TempPoint
You can only have 1 local in GUI and it won't work when used in an if/then/else statement because of the way GUI is converted to jass.
 
Level 2
Joined
Sep 9, 2008
Messages
24
Heh. Screw that. Maybe someday I'll learn JASS, but it's hard to get motivation when GUI works fine, especially now that I've worked out most of the issues that will come up.
 
Level 6
Joined
Sep 5, 2007
Messages
264
The reason that this was occuring was...
EG:
trigger 1 has a loop... when GUI converts to JASS, the "actions" inside the loop are put into a seperate function, which the loop then calls.
trigger 2 comes along... wants to execute, but waits its turn (which may be during trigger one's loop, because when the function that gets called each loop, it can be intervened upon... as functions are queued up)

@HarblMan: I would strongly recommend that you start learning JASS. The sooner you start, the sooner you get to clean up triggers that GUI makes a mess of. It's pretty easy to learn, just get hold of JassCraft, it lists all your Wc3 functions. JASS can greatly increase the speed of your map, allowing you to get away with running more complex triggers, more often.
EG:
  • Example Trigger
  • Events
  • Conditions
  • Actions
    • If (All conditions are true) then do (Then actions) else do (Else actions)
      • If - Conditions
        • ((Triggering Unit) is A Hero) equal to True
      • Then
        • Unit - Kill (Triggering Unit)
      • Else
This trigger when converted to JASS...
JASS:
function Trig_Example_Trigger_Func001C takes nothing returns boolean
    if ( not ( IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true ) ) then
        return false
    endif
    return true
endfunction

function Trig_Example_Trigger_Actions takes nothing returns nothing
    if ( Trig_Example_Trigger_Func001C() ) then
        call KillUnit( GetTriggerUnit() )
    else
    endif
endfunction

//===========================================================================
function InitTrig_Example_Trigger takes nothing returns nothing
    set gg_trg_Example_Trigger = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Example_Trigger, function Trig_Example_Trigger_Actions )
endfunction

Now, imagine what your GUI trigger, that may contain 20+ "actions", would look like when converted to JASS... Each additional function call, takes more CPU & memory away, that could be used more productively for other triggers.

This trigger could be greatly simplified. And, it can run only the "actions" function, not this other bullcrap Trig_Example_Trigger_Func001C function that just does the condition for the if statement:
JASS:
function Trig_Example_Trigger_Actions takes nothing returns nothing
    local unit trig = GetTriggerUnit()
    // Putting the value into a variable, means that you don't call the
    // GetTriggerUnit() function more times than necessary.

    if (IsUnitType(trig, UNIT_TYPE_HERO) == true) then
        call KillUnit(trig)
    endif

    set trig = null
    // You don't have to "null" units, but I do, just to be sure.
endfunction

//===========================================================================
function InitTrig_Example_Trigger takes nothing returns nothing
    set gg_trg_Example_Trigger = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Example_Trigger, function Trig_Example_Trigger_Actions )
endfunction

PM me if you need any help. :thumbs_up:
 
Level 3
Joined
Aug 19, 2007
Messages
24
What you can do is declare your local as your first line (not going to use GUI tag here, Im sure you can figure it out)

Custom text: local location templocation
then set your global to whatever you want it to be (polar projection, etc)
then set your local equal to your global:
Custom text: set templocation = udg_TempLocation
then do whatever stuff causes your location to break (but the local is still intact)
then re-set your global to your local
Custom text: set udg_TempLocation = templocation
then do stuff with your global (if/then statements, spawn units, etc) as long as they don't break it

It's tedious but it works.

Also, you will want to learn JASS once you realize how much easier it is to deal with text than it is to deal with GUI. What happens if you want to change PlayerId(Triggering player) to PlayerId(Triggering player) + 1?

GUI: you have to change it to 'arithmetic' then add in the original value that you had and add a 1.
JASS: type + 1

Also, your problem:
GUI: jump through a bunch of hoops or use separate globals (what happens if multiple players use the same ability?)
JASS: use local the entire time, no problems

Large maps:
GUI: extreme slowdown since every trigger has 80 lines of code
JASS: faster since every trigger has 7 lines of code

Once you actually start learning JASS you will not look back, trust me
 
Level 2
Joined
Sep 9, 2008
Messages
24
Also, your problem:
GUI: jump through a bunch of hoops or use separate globals (what happens if multiple players use the same ability?)
JASS: use local the entire time, no problems

I use a lot of arrays and dummy units, and jump through a lot of hoops yes. I've gotten used to the hoops and it's pretty easy now! lol

Large maps:
GUI: extreme slowdown since every trigger has 80 lines of code
JASS: faster since every trigger has 7 lines of code

Once you actually start learning JASS you will not look back, trust me

But but but, I have a dual core!


OK, but seriously, I'll get on it... So much pressure!

What do the different 3rd party things offer that make it better? Is there anything where I can have a list of all functions, events, etc... with what they take, like how Neverwinter Nights has?
 
Level 2
Joined
Sep 9, 2008
Messages
24
This thread is SO full of bullshit. Please, anyone reading this, do not listen to any of the random shit written here. If you want more info, ask me or GhostWolf because we actually know what we're talking about.

Actually I learned some things from this thread, thank you very much. I was able to fix my triggers because of this thread.

I hereby declare this thread win.

PS. If you don't save your variable over time (ie waits/otherwise), nothing else can interrupt it.

No, not true. What was happening was a trigger was firing whenever a unit was issued an order, and it was using my variable.

This trigger interrupted my triggers every time I instantly moved a unit because the game issues a stop command when you use the instant move action.

That's why 100% of the time, I was losing my variable.

As someone else explained, the way it converts GUI triggers into JASS allows triggers to interrupt eachother like that because it uses a function queue and GUI triggers produce multiple functions.

Thanks to everyone who helped me and didn't talk shit.


PS: Also, what about my previous question? Is there a 3rd party program with a built in list of JASS functions for easy reference while coding?
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
common.j, the jass native list.

Pulling up JassCraft is nice if you want a searcher and such - you can find it on wc3c.

No, not true. What was happening was a trigger was firing whenever a unit was issued an order, and it was using my variable.
Yes true. Another trigger is not "interrupting" your trigger if your trigger is calling that trigger. You are calling that trigger.
 
Level 20
Joined
Apr 22, 2007
Messages
1,960
Suit yourself but you're wrong. And yes there are tons of third party programs for Jass function listing and highlighting and such. JassCraft is one of them.

But I'd suggest for you to get JassNewGenPack (somewhere off Welcome to Wc3Campaigns) because it includes a world editor with integrated syntax highlighting, a function list and a neat addition to Jass which you shouldn't be learning now anyway but nonetheless awesome. Oh and also a new syntax checker. It wins.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
common.j, the jass native list.

Pulling up JassCraft is nice if you want a searcher and such - you can find it on wc3c.

Yes true. Another trigger is not "interrupting" your trigger if your trigger is calling that trigger. You are calling that trigger.

It's not completely correct... What happened here is an uncontrolled consequence of the trigger causing another trigger to interrupt it. It's not the same as explicitly calling the other trigger because that would be a controlled call...
 
Level 3
Joined
Aug 19, 2007
Messages
24
Suit yourself but you're wrong.

Which part of what he said was wrong? The part where he said he learned stuff, or the part where he said he fixed his triggers? Please provide supporting evidence before you start insulting peoples' work.

Is there a 3rd party program with a built in list of JASS functions for easy reference while coding?

I use JassCraft to quickly search for types/functions because it's easy and gives me a space where I can type, but I preferred JassShopPro (its predecessor) because it loaded more quickly and the focus of the search function didn't default to a checkbox.

JASS Manual
There's Vexorian's JASS manual, it's a good reference and has some tips on typecasting

The JassNewGen pack, as Hindy said above, is extremely useful. Showing syntax is nice, but the biggest improvement for me was that it fixes the vast majority of issues that will crash your world editor (and cause you to lose text). You don't really need a 3rd party editor because of that. If you aren't using it, I recommend that you write all your scripts in a 3rd party editor (notepad if you have to) due to crashes. Also, it will show syntax for the functions that you've created, which makes things much faster.

NewGen also includes vJASS, but I would stay away from it until you are comfortable with the basics of normal JASS.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
It's not completely correct... What happened here is an uncontrolled consequence of the trigger causing another trigger to interrupt it. It's not the same as explicitly calling the other trigger because that would be a controlled call...
Whether intentional or not, the point is that he is calling it. It isn't being fired by some external circumstance.

--

HINDY was referring to instant triggers not being able to be interrupted by external causes.
 
Level 20
Joined
Apr 22, 2007
Messages
1,960
Yeah. Your trigger can't magically be interrupted, and the globals it's using can't just magically be modified (unless a sleep or something) to screw up your whole script. And most importantly, script size will NOT increase the chance for this to happen... because this never happens.

Bug cause -> 99% user, 1% machine.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
Whether intentional or not, the point is that he is calling it. It isn't being fired by some external circumstance.

Nowhere in his script he says: run trigger 2. Which is why I say "he" isn't calling it :p. That's also why I DO consider trigger 2 to be fired by an external circumstance which is indirectly caused by trigger 1.

To be more precise: he used SetUnitPositionLoc() and never ordered the unit to stop. Warcraft 3 did that for him, which in turn caused a 2nd trigger to run before continuing the first trigger. I call that an external circumstance, even though it will occur 100% of the time.

(by the way, I'm not disagreeing on anything else you've said... I guess the only thing we disagree on is the meaning of "external causes" :p)
 
Level 3
Joined
Aug 19, 2007
Messages
24
script size will NOT increase the chance for this to happen... because this never happens

It is not the script size that causes unintentional side-effects to be more frequent, but rather the lack of the knowledge of the workings of the script in question. Example: the 'pick every unit in unit group and do X' GUI command calls a function external to the primary trigger to run the enumeration. This breaks locals. At first glance, a GUI user would not think it does that because it does not appear that way in the GUI. It is, however, quite obvious when you look at the equivalent JASS.

Anyway, to Harbl: I use SetUnitX and SetUnitY instead of SetUnitPosition because it doesn't issue stop orders, runs much faster, and lets you move through terrain, and allows the unit's controller to continue moving the unit. I do not know if there is a GUI equivalent for that or not. If you don't want your units to be able to move during an ability like leap (or something similar), you can either set up a trigger to cancel orders or just pause the unit until the leap is over.

Thinking about it again, I really dislike maps that use SetUnitPosition for things like knockbacks and leap abilities. The vast majority of them don't realize (or don't care) that it breaks your queued orders. Think Spirit Breaker's Greater Bash (if you play DotA, that is). It can be a serious problem if you have too many knockbacks of that type - take a look at Age of Myths, for example.
 
Level 2
Joined
Sep 9, 2008
Messages
24
Anyway, to Harbl: I use SetUnitX and SetUnitY instead of SetUnitPosition because it doesn't issue stop orders, runs much faster, and lets you move through terrain, and allows the unit's controller to continue moving the unit. I do not know if there is a GUI equivalent for that or not. If you don't want your units to be able to move during an ability like leap (or something similar), you can either set up a trigger to cancel orders or just pause the unit until the leap is over.

There's no GUI version, but that's ok. I'm supposed to learn JASS, so thanks. :D


Anyway, reguarding the technicality of triggers being able to interrupt eachother: My point was that it would be incorrect to say that a trigger being fired as consequence in the middle of a trigger will not wait for the first one to finish. A few people were saying that can't happen, but it can and did.
 
Status
Not open for further replies.
Top