• 🏆 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!

Looking for help with leaks and crashes

Status
Not open for further replies.
Level 6
Joined
Feb 18, 2018
Messages
42
Hello all! I'm looking for help with my map and triggers if someone has the time. Basically, this is the first time I've ever really run into memory leaks or crashes, so I've never bothered to look into map optimization and leak clearing. However I'm now running into crashes much more frequently than ever before and I can only assume it's down to leaks - so I figured now is the time to learn about this stuff properly so I'm better prepared to avoid these issues in the future.

For this map particularly, I'm encountering semi-frequent crashes with the two bosses of the level (triggers can be found in the Trigger Categories "Nitrixx" and "Bog Lord", but I imagine there is also a lot of cleaning up to do through the rest of the triggers too.

For now, I was hoping someone who knows what they're doing could take a look at my map and the triggers within and check it for leaks and any other potential crash-causers. From there I should be able to learn for future maps and be able to deal with this stuff myself. Please let me know if there's any additional information I can provide. Thanks in advance to anyone who takes a look!
 

Attachments

  • 02-Wrath of the Dragon 2.w3x
    39.1 MB · Views: 25

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,538
A crash is usually the result of an infinite loop like:
When a unit dies -> Create a unit -> Kill last created unit.

But I'm sure leaks can cause crashes as well. I edited your map and put Comments anywhere I found a Leak or at least the first Leak I found in a trigger (you have a lot of reoccurring Point leaks).

Regarding the crashes, I think the culprits are these two triggers: Nitrixx Trample Stop, Bog Lord Stomps.
I believe it has to do with how you're periodically adding the same Events to the triggers over and over again. That's definitely not good, you only need to add the Events to them once. But do you even need to Add the Events through triggers? Can't you just put the Events in the standard way? I think your approach to whatever you're trying to do with these triggers is incorrect.

Otherwise, most of your triggers appeared to look fine.

So what leaks exactly?
A leak is something that you've lost the ability to interact with and is no longer needed. Think of it like a piece of garbage that you can't throw away because you can't pick it up. It's there taking up space and making your room messy, but you just can't get it.

Points (aka Locations) are a big culprit for memory leaks. Here's what's going on "under the hood" when you Set a Point variable:
  • Set Variable TempPoint = Center of (Playable map area)
Understand that the game code is actually generating a new Location when you do this. A Location is a game object which contains a pair of x/y coordinates of wherever you directed your Point variable. In this case I directed the Point variable to the Center of playable map area (coordinates: 0x, 0y).

This isn't actually a problem yet, but it becomes a problem if I were to Set TempPoint a second time:
  • Set Variable TempPoint = Center of (Playable map area)
  • Set Variable TempPoint = Somewhere else

Now we have two Location objects that exist in the game's memory. The problem here is that the first Location is now considered a memory leak. Why? Because we can no longer reference it. We can't remove the first Location that we created at the Center of the map because our TempPoint variable is now referencing "Somewhere else". A Point variable can only act as a reference to one Location at a time. If we were to use the function that one uses to remove a Location:
  • Custom script: call RemoveLocation (udg_TempPoint)
It would remove the Location created at "Somewhere else" but it has no idea about the Location at the Center of the map.

The solution to avoid the memory leak here is to Remove the first Location before Setting the second one:
  • Set Variable TempPoint = Center of (Playable map area)
  • Custom script: call RemoveLocation (udg_TempPoint)
  • Set Variable TempPoint = Somewhere else
And that's generally how you have to go about memory leaks. Before Setting something that has the potential to leak (Points, Unit Groups, Player Groups, Special Effects) you must remove (oftenreferred to as destroy) any previous instance of said thing.


With that being said, anything that you create only once and intend to reference throughout the rest of the game, for example:
  • Events
  • Map initialization
  • Actions
  • Set Variable CenterPoint = Center of (Playable map area)
Will NOT leak as long as you stay true to your intent of setting it only once. It becomes a problem when you decide to Set CenterPoint AGAIN before Removing it's previous Location.
 

Attachments

  • 02-Wrath of the Dragon 2.w3x
    39.1 MB · Views: 16
Last edited:
Level 6
Joined
Feb 18, 2018
Messages
42
A crash is usually the result of an infinite loop like:
When a unit dies -> Create a unit -> Kill last created unit.

But I'm sure leaks can cause crashes as well. I edited your map and put Comments anywhere I found a Leak or at least the first Leak I found in a trigger (you have a lot of reoccurring Point leaks).

Regarding the crashes, I think the culprits are these two triggers: Nitrixx Trample Stop, Bog Lord Stomps.
I believe it has to do with how you're periodically adding the same Events to the triggers over and over again. That's definitely not good, you only need to add the Events to them once. But do you even need to Add the Events through triggers? Can't you just put the Events in the standard way? I think your approach to whatever you're trying to do with these triggers is incorrect.

Otherwise, most of your triggers appeared to look fine.

So what leaks exactly?
A leak is something that you've lost the ability to interact with and is no longer needed. Think of it like a piece of garbage that you can't throw away because you can't pick it up. It's there taking up space and making your room messy, but you just can't get it.

Points (aka Locations) are a big culprit for memory leaks. Here's what's going on "under the hood" when you Set a Point variable:
  • Set Variable TempPoint = Center of (Playable map area)
Understand that the game code is actually generating a new Location when you do this. A Location is a game object which contains a pair of x/y coordinates of wherever you directed your Point variable. In this case I directed the Point variable to the Center of playable map area (coordinates: 0x, 0y).

This isn't actually a problem yet, but it becomes a problem if I were to Set TempPoint a second time:
  • Set Variable TempPoint = Center of (Playable map area)
  • Set Variable TempPoint = Somewhere else

Now we have two Location objects that exist in the game's memory. The problem here is that the first Location is now considered a memory leak. Why? Because we can no longer reference it. We can't remove the first Location that we created at the Center of the map because our TempPoint variable is now referencing "Somewhere else". A Point variable can only act as a reference to one Location at a time. If we were to use the function that one uses to remove a Location:
  • Custom script: call RemoveLocation (udg_TempPoint)
It would remove the Location created at "Somewhere else" but it has no idea about the Location at the Center of the map.

The solution to avoid the memory leak here is to Remove the first Location before Setting the second one:
  • Set Variable TempPoint = Center of (Playable map area)
  • Custom script: call RemoveLocation (udg_TempPoint)
  • Set Variable TempPoint = Somewhere else
And that's generally how you have to go about memory leaks. Before Setting something that has the potential to leak (Points, Unit Groups, Player Groups, Special Effects) you must remove (oftenreferred to as destroy) any previous instance of said thing.


With that being said, anything that you create only once and intend to reference throughout the rest of the game, for example:
  • Events
  • Map initialization
  • Actions
  • Set Variable CenterPoint = Center of (Playable map area)
Will NOT leak as long as you stay true to your intent of setting it only once. It becomes a problem when you decide to Set CenterPoint AGAIN before Removing it's previous Location.
Thank you so much, this is super helpful I really appreciate it! As for those two culprit triggers, that’s pretty much what I suspected. Since you can’t refer to a specific unit as a range check at the initial event of a trigger I had to add it as an extra one after the initial event. Would the trigger still function the same if it wasn’t a periodic event? I might be misunderstanding the logic, but I assumed with the way I’d done the trigger the game is essentially checking every 0.5 second whether or not the unit is within the required range of the units in question. I thought without it being repeating that it would just check once, then stop checking. How would you go about re-doing this trigger yourself? Thanks again!

Edit: I've only just got the chance to actually download the map and take a look at your comments, thanks so much again for this, it helps a lot! I will try to get all the issues sorted soon and will update the thread again if I have any more questions :)
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
A crash is usually the result of an infinite loop like:
Or if playing a legacy version of Warcraft III it can be as simple as passing nonsense values to native functions such as Player(16), or nonsense dependency equivelants for a unit in the object editor, or nonsense values for many spell ability fields.

Warcraft III has no shortage of ways to crash, especially with legacy versions.
 
Level 6
Joined
Feb 18, 2018
Messages
42
Or if playing a legacy version of Warcraft III it can be as simple as passing nonsense values to native functions such as Player(16), or nonsense dependency equivelants for a unit in the object editor, or nonsense values for many spell ability fields.

Warcraft III has no shortage of ways to crash, especially with legacy versions.
Ah, suppose I should have mentioned the version I'm running on in the OP. I'm currently on 1.32 myself - should I still be worried about those things?
 
Level 6
Joined
Feb 18, 2018
Messages
42
Still encountering crashes with these after they trigger for the third or fourth time. Any suggestions on how I should change them? Not sure what's causing the crashes at all since they're no longer infinite-loops (I don't think?)
 

Attachments

  • Bog Lord Charge.PNG
    Bog Lord Charge.PNG
    22.4 KB · Views: 22
  • Bog Lord Stomps.PNG
    Bog Lord Stomps.PNG
    38.3 KB · Views: 25
Level 20
Joined
Feb 23, 2014
Messages
1,264
I believe it has to do with how you're periodically adding the same Events to the triggers over and over again.
If I were to guess, your issue is that you haven't fixed the problem Uncle pointed out in the quote above.

Looking at the "Bog Lord Stomps" trigger - every time the unit is ordered to move, you're adding events to it. As moving is a very frequent action, you will very quickly end up with a situation where you add too many events and the game tries to run this trigger too many times. It might be what's causing your crash.

I'm not sure why you don't just add the events to that trigger normally, but if for some reason you really want to add them via triggers, put the two add event to a trigger actions in a following condition block to ensure that they are only added once, upon the first successful execution of the trigger:

  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • (Execution count of (This trigger)) Equal to 1 -- Integer Comparison; Trigger - Trigger Execution Count function
    • Then - Actions
      • -- Move your "Add event" actions here
    • Else - Actions
 
Last edited:
Level 6
Joined
Feb 18, 2018
Messages
42
If I were to guess, your issue is that you haven't fixed the problem Uncle pointed out in the quote above.

Looking at the "Bog Lord Stomps" trigger - every time the unit is ordered to move, you're adding events to it. As moving is a very frequent action, you will very quickly end up with a situation where you add too many events and the game tries to run this trigger too many times. It might be what's causing your crash.

I'm not sure why you don't just add the events to that trigger normally, but if for some reason you really want to add them via triggers, put the two add event to a trigger actions in a following condition block to ensure that they are only added once, upon the first successful execution of the trigger:

  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • (Execution count of (This trigger)) Equal to 1 -- Integer Comparison; Trigger - Trigger Execution Count function
    • Then - Actions
      • -- Move your "Add event" actions here
    • Else - Actions
I don’t know if just having the actions of the second trigger as a simple follow-up would have the desired effect, I will give a little overview of the design concept of the triggers!

Trigger one (bog lord charge): the boss casts an ability (death stare) on one of the heroes, briefly pauses, then charges to their location (moving a dummy to the position of the target then attempting to move to said dummy)

Trigger two (bog lord stomps): whilst charging, the boss checks whether he’s in range of either the dummy or one of the heroes, then stops and does a combo of spells (the stomps - thunder clapx2, war stomp). After the war stomp the boss resumes normal behaviour.

The problem I have is that since the distance the boss charges would be different every time the triggers are triggered, I don’t think having the stomps as a simple follow up in the charge trigger would work as they would frequently activate either too early or too late.

I will try out the triggers you mentioned and see how it goes, I did simply try adding the extra events of the second trigger to the first trigger to save having them separate, but that caused the trigger to stop functioning completely for some reason, so I rolled back to the triggers in the attached screenshot.

Edit: also afaik with the way I’ve done the triggers the only command the boss should be given between the first and second trigger is it being told to move to the position of the dummy? Since it’s acquisition range is set to 0 it shouldn’t be giving itself any commands therefore disrupting the trigger?

Edit2: Here's a video showing the triggers in progress including the crash (happened on the 6th cycle through the triggers this time):
 
Last edited:
Level 6
Joined
Feb 18, 2018
Messages
42
If I were to guess, your issue is that you haven't fixed the problem Uncle pointed out in the quote above.

Looking at the "Bog Lord Stomps" trigger - every time the unit is ordered to move, you're adding events to it. As moving is a very frequent action, you will very quickly end up with a situation where you add too many events and the game tries to run this trigger too many times. It might be what's causing your crash.

I'm not sure why you don't just add the events to that trigger normally, but if for some reason you really want to add them via triggers, put the two add event to a trigger actions in a following condition block to ensure that they are only added once, upon the first successful execution of the trigger:

  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • (Execution count of (This trigger)) Equal to 1 -- Integer Comparison; Trigger - Trigger Execution Count function
    • Then - Actions
      • -- Move your "Add event" actions here
    • Else - Actions
Sorry, I feel like I'm being dense here, thanks for being patient :xxd:
I've tried what you said and it's just caused the trigger to stop functioning completely. The boss charges to the spot but does not continue with the second trigger.
  • Bog Lord Stomps
    • Events
      • Unit - Svaegrumm the Bog Lord 0024 <gen> Is issued an order targeting a point
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Execution count of (This trigger)) Equal to 1
        • Then - Actions
          • Trigger - Add to (This trigger) the event (Unit - A unit comes within 100.00 of Lucian)
          • Trigger - Add to (This trigger) the event (Unit - A unit comes within 100.00 of Dummy 0191 <gen>)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Entering unit) Equal to BogLord
            • Then - Actions
              • Trigger - Turn off (This trigger)
              • Animation - Change BogLord's animation speed to 100.00% of its original speed
              • Unit - Turn collision for BogLord On.
              • Unit - Set BogLord movement speed to 0.00
              • Unit - Make BogLord Vulnerable
              • Unit - Order BogLord to Stop.
              • Unit - Add Bog Lord Slam to BogLord
              • Wait 0.50 seconds
              • Unit - Order BogLord to Human Mountain King - Thunder Clap.
              • Wait 1.50 seconds
              • Unit - Order BogLord to Human Mountain King - Thunder Clap.
              • Wait 1.00 seconds
              • Unit - Remove Bog Lord Slam from BogLord
              • Unit - Add Bog Lord Slam 2 (Neutral Hostile 1) to BogLord
              • Unit - Order BogLord to Orc Tauren Chieftain - War Stomp.
              • Wait 2.00 seconds
              • Unit - Remove Bog Lord Slam 2 (Neutral Hostile 1) from BogLord
              • Unit - Set BogLord acquisition range to 1000.00
              • Unit - Set BogLord movement speed to 300.00
              • Wait 5.00 seconds
              • Trigger - Turn on Bog Lord Mushrooms <gen>
            • Else - Actions
              • Do nothing
        • Else - Actions
          • Do nothing
 
Level 6
Joined
Feb 18, 2018
Messages
42
I don't know why we're even bothering with this. I still don't see any reason why these Events need to be added through Actions. What's wrong with the normal way?
Because they need to be added through actions. They aren't available in the events list for some reason. Or if they are, I haven't been able to find them.

Edit: Ignore the above. Me being a dense, blind fool. :)
 
Last edited:
Level 6
Joined
Feb 18, 2018
Messages
42
Yeah, the events will only be added once during the first time the trigger runs.
This has solved the crashing issue, thank you very much! Posting the trigger below in case anyone else can make use of it and avoid the headaches I had:

  • Bog Lord Stomps
    • Events
      • Unit - Svaegrumm the Bog Lord 0024 <gen> Is issued an order targeting a point
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Execution count of (This trigger)) Equal to 1
        • Then - Actions
          • Trigger - Add to (This trigger) the event (Unit - A unit comes within 100.00 of Lucian)
          • Trigger - Add to (This trigger) the event (Unit - A unit comes within 100.00 of Dummy 0191 <gen>)
        • Else - Actions
          • Do nothing
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Entering unit) Equal to BogLord
        • Then - Actions
          • Trigger - Turn off (This trigger)
          • Animation - Change BogLord's animation speed to 100.00% of its original speed
          • Unit - Turn collision for BogLord On.
          • Unit - Set BogLord movement speed to 0.00
          • Unit - Make BogLord Vulnerable
          • Unit - Order BogLord to Stop.
          • Unit - Add Bog Lord Slam to BogLord
          • Wait 0.50 seconds
          • Unit - Order BogLord to Human Mountain King - Thunder Clap.
          • Wait 1.50 seconds
          • Unit - Order BogLord to Human Mountain King - Thunder Clap.
          • Wait 1.00 seconds
          • Unit - Remove Bog Lord Slam from BogLord
          • Unit - Add Bog Lord Slam 2 (Neutral Hostile 1) to BogLord
          • Unit - Order BogLord to Orc Tauren Chieftain - War Stomp.
          • Wait 2.00 seconds
          • Unit - Remove Bog Lord Slam 2 (Neutral Hostile 1) from BogLord
          • Unit - Set BogLord acquisition range to 1000.00
          • Unit - Set BogLord movement speed to 300.00
          • Wait 5.00 seconds
          • Trigger - Turn on Bog Lord Mushrooms <gen>
        • Else - Actions
          • Do nothing
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,538
Oh I see Lucian is a unit variable. The Dummy unit can be added to the Events though, since it's a preplaced unit.

But what you should do in this situation is Add Lucian to the Events upon Setting the Lucian variable:
  • Set Variable Lucian = some unit
  • Trigger - Add to Bog Lord Stomps the event (Unit - A unit comes within 100.00 of Lucian)
This way it's a one time addition and you don't need to constantly ask the same question over and over again -> Is Execution count Equal to 1?

Also, the Do nothing action serves no purpose. It's no different from a Comment. Might as well just not use it at all.
 
Level 6
Joined
Feb 18, 2018
Messages
42
Oh I see Lucian is a unit variable. The Dummy unit can be added to the Events though, since it's a preplaced unit.

But what you should do in this situation is Add Lucian to the Events upon Setting the Lucian variable:
  • Set Variable Lucian = some unit
  • Trigger - Add to Bog Lord Stomps the event (Unit - A unit comes within 100.00 of Lucian)
This way it's a one time addition and you don't need to constantly ask the same question over and over again -> Is Execution count Equal to 1?

Also, the Do nothing action serves no purpose. It's no different from a Comment. Might as well just not use it at all.
Omfg, I really am dense :xxd:
I was looking under the Generic/Specific unit events category... I didn't even realise "Unit within range" was an event I could choose... :ugly:
Right, I will try and simplify my trigger using that as the starting event. Hopefully, I don't start running into crashes again.

Thank you all very much for your patience with me :cute:
 
Last edited:
Level 20
Joined
Feb 23, 2014
Messages
1,264
The problem I have is that since the distance the boss charges would be different every time the triggers are triggered, I don’t think having the stomps as a simple follow up in the charge trigger would work as they would frequently activate either too early or too late.
I don't really understand how this is relevant. Nobody suggested that you put "stomps" in the "charge" trigger - the approach you've taken to separate these two actions (i.e. charging and stomping) is correct, given that the second (i.e. stomping) trigger uses an event that checks the range between the boss and its targets, thus making the distance covered while charging irrelevant. I don't see any problems here.

The problem was that you were adding the same event to the same trigger over and over again, which made no sense and caused the crash.

Thank you both very much for your patience with me :cute:
No worries, mate - everyone has to learn at some point and making even the most silly mistakes is a part of the process :)
 
Status
Not open for further replies.
Top