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

My map leaks and I don't know where.

Status
Not open for further replies.
Level 6
Joined
Jul 12, 2017
Messages
139
I have tried to search for it but no clue. It's like something is glitching every 2 or 3 seconds but I have tried turning off the suspected triggers which don't help at all.

I don't think my triggers leak but it's like the framerate drop every 2 seconds or so, I wonder if anyone can help me find it?

The map is not big and triggers are sorted neatly (at least for me) so I don't think it will be difficult to navigate through my triggers.

I have attached the map below.

Thanks in advance and I hope to learn something new as well.
 

Attachments

  • Zombie Supply Survival Test 16.w3m
    2.5 MB · Views: 11
Level 38
Joined
Feb 27, 2007
Messages
4,951
Whatever you're doing with a unit indexer is probably bad news. You used GetWorldBounds() as the rect for a 'unit enters map' event, and in that event you enum over every unit owned by the owning player to find previously-allocated indices that can be recycled. Every time any unit enters the map anywhere. Why write this indexing yourself instead of using an already established indexer that will not have an issue like this?

I didn't look at much more but it's my guess as to what's happening. You should look for periodic triggers, those that activate in/use regions, or when looping over large quantities of data. What you're describing sounds like a runaway loop with no exit condition that just crashes the thread that ran it; such behavior would produce a freeze while it tries to execute 30,000 sequential operations before it hits the op limit and crashes out.

Depending on what's actually happening during normal gameplay, it's possible that some of your item-effect triggers could be getting bogged down with a large number of units or spellcasts or damage events.

Another example of a suspect trigger is Chopper Check Victory. Whenever it's running (off by default) every 6 seconds it loops over every unit on the entire map and checks 4 conditions against that unit. If your map has a lot of units active at once this could cause a regular hang. The condition is this: (All units of (Units in (Playable map area) matching ((((Matching unit) belongs to an enemy of Player 21 (Coal).) Equal to True) and ((((Matching unit) is A Hero) Equal to True) and ((((Matching unit) is alive) Equal to True) and ((Unit-type of (Matching unit... Equal to True, and it also leaks a unit group every time it runs.
 
Last edited:
Level 6
Joined
Jul 12, 2017
Messages
139
Whatever you're doing with a unit indexer is probably bad news. You used GetWorldBounds() as the rect for a 'unit enters map' event, and in that event you enum over every unit owned by the owning player to find previously-allocated indices that can be recycled. Every time any unit enters the map anywhere. Why write this indexing yourself instead of using an already established indexer that will not have an issue like this?

No, I didn't write that trigger. I just copied it directly from whoever made this trigger in this site first hand.
Another example of a suspect trigger is Chopper Check Victory. Whenever it's running (off by default) every 6 seconds it loops over every unit on the entire map and checks 4 conditions against that unit. If your map has a lot of units active at once this could cause a regular hang. The condition is this: (All units of (Units in (Playable map area) matching ((((Matching unit) belongs to an enemy of Player 21 (Coal).) Equal to True) and ((((Matching unit) is A Hero) Equal to True) and ((((Matching unit) is alive) Equal to True) and ((Unit-type of (Matching unit... Equal to True, and it also leaks a unit group every time it runs.

I have changed the trigger to this one instead. Is this still leaking?

  • Chopper Check Victory
    • Events
      • Time - Every 6.00 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet UnitGroup1 = (Units in (Entire map) matching ((((Matching unit) is A Hero) Equal to True) and ((((Matching unit) belongs to an ally of Player 10 (Light Blue).) Equal to True) and (((Matching unit) is A sapper) Equal to False))))
      • Unit Group - Pick every unit in UnitGroup1 and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) belongs to an enemy of Player 21 (Coal).) Equal to True
              • ((Picked unit) is alive) Equal to True
              • ((Picked unit) is A Hero) Equal to True
              • (Unit-type of (Picked unit)) Not equal to Villager Chief
            • Then - Actions
              • Trigger - Run Victory <gen> (checking conditions)
            • Else - Actions
      • Custom script: call DestroyGroup(udg_UnitGroup1)
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,457
What exactly is the goal of that victory trigger? It looks like you're looking for a single living Hero, in which case can't you just detect that using any of these events?
  • Unit - A unit enters playable map area
  • Unit - A unit finishes training
Also, Victory will run multiple times if it finds multiple units that match those conditions.
 
Level 6
Joined
Jul 12, 2017
Messages
139
What exactly is the goal of that victory trigger? It looks like you're looking for a single living Hero, in which case can't you just detect that using any of these events?
  • Unit - A unit enters playable map area
  • Unit - A unit finishes training
Also, Victory will run multiple times if it finds multiple units that match those conditions.
You mean make it like this instead?

  • Chopper Check Victory
    • Events
      • Unit - A unit enters Region 166 <gen>
    • Conditions
      • ((Entering unit) belongs to an enemy of Player 21 (Coal).) Equal to True
      • ((Entering unit) is A Hero) Equal to True
    • Actions
      • Trigger - Run Victory <gen> (checking conditions)
Also, I have tried to change my trigger to be like this but it seems to leak harder than before, it looks like this,

  • Wisp Nature Buff 1
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet UnitGroup1 = (Units in (Playable map area))
      • Unit Group - Pick every unit in UnitGroup1 and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) has buff (Wisp) Nature Buff 1 ) Equal to True
            • Then - Actions
              • Unit - Set life of (Picked unit) to ((Percentage life of (Picked unit)) + 1.00)%
            • Else - Actions
      • Custom script: call DestroyGroup(udg_UnitGroup1)
I have copied it from the trigger below to adjust it, what's the difference? Maybe cuz I need to add more match to unitgroup1 and not just unit in playable map area?

  • Divine shield revival effect
    • Events
      • Time - Every 0.30 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet UnitGroup1 = (Units in (Entire map) matching ((((Matching unit) is A Hero) Equal to True) and ((((Matching unit) belongs to an ally of Player 10 (Light Blue).) Equal to True) and (((Matching unit) is A sapper) Equal to False))))
      • Unit Group - Pick every unit in UnitGroup1 and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) has buff (Item) Resurrection Shield ) Equal to True
            • Then - Actions
              • Unit - Make (Picked unit) Invulnerable
            • Else - Actions
              • Unit - Make (Picked unit) Vulnerable
      • Custom script: call DestroyGroup(udg_UnitGroup1)
 
Level 6
Joined
Jul 12, 2017
Messages
139
I can't tell you if that's correct if I don't know what you're trying to accomplish.
Basically if the all "alive" players get close to the chopper, it will take them to safe spot and if all of alive players are presented in that area, the alive player will get victory screen while dead player will get defeat screen.

And the main topic is to get rid of mysterious leak that lies somewhere in my triggers which is very likely to be a time trigger that run every some second, that's why I show you if that trigger is correct or not.
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,457
I see, well I don't think your changes would make it leak harder, if anything the triggers look more efficient and seem to have all of their memory leaks handled properly.

For the Chopper trigger, if the Chopper doesn't move you could use a Enters/Leaves Region trigger along with a Unit Group to track just the units near the Chopper. This way you aren't checking if EVERY unit in the playable map area fit some Conditions. Or better yet just track the player's Heroes in a Unit Group from the start. Then it really simplifies things:
  • Unit Group - Pick every unit in PlayerHeroes and do...
Now any Conditions that you have will be for strictly for those X units in the PlayerHeroes unit group rather than filtering through potentially thousands of units on the map ALL at once. This method of efficient design can improve performance greatly.
 
Last edited:
Level 6
Joined
Jul 12, 2017
Messages
139
I see, well I don't think your changes would make it leak harder, if anything the triggers look more efficient and seem to have all of their memory leaks handled properly.

For the Chopper trigger, if the Chopper doesn't move you could use a Enters/Leaves Region trigger along with a Unit Group to track just the units near the Chopper. This way you aren't checking if EVERY unit in the playable map area fit some Conditions. Or better yet just track the player's Heroes in a Unit Group from the start. Then it really simplifies things:
  • Unit Group - Pick every unit in PlayerHeroes and do...
Now any Conditions that you have will be for strictly for those X units in the PlayerHeroes unit group rather than filtering through potentially thousands of units on the map ALL at once. This method of efficient design can improve performance greatly.
I will be sure to try that, thanks a lot. I think I have already reduce quite some leaks.


On a side note, I saw you upload a save/load system file here so I tried to add it to my map but it got an error like this,




image_2022-09-21_193829896.png


In the red circle, as the editor said, it doesn't allow it so I'm confused.
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,457
I've only ever uploaded slightly edited versions of TriggerHappy's Codeless save/load system to help people understand how to use it. I can't promise that my edits will work or that his system works, especially on the latest patch since that broke many things.

You should try enabling JassHelper and see if that error goes away.
 
Level 6
Joined
Jul 12, 2017
Messages
139
I've only ever uploaded slightly edited versions of TriggerHappy's Codeless save/load system to help people understand how to use it. I can't promise that my edits will work or that his system works, especially on the latest patch since that broke many things.

You should try enabling JassHelper and see if that error goes away.
I've already enabled it and like above, it said that line in red circle is not the type that allow syntax something.
 
Level 38
Joined
Feb 27, 2007
Messages
4,951
Then you forgot to copy over a trigger or part of a trigger that includes the Savecode object. Everything recently in this site's Resources section works and can compile without problems; its your map that has the issue. If you really do have both of those settings enabled for your map then remove it all and try reimporting it from scratch.

If your map is in Lua mode instead of JASS mode then you likely won't be able to use that resource at all unless you can transpile it. JASS -> Lua is not hard but Lua -> JASS is a tall order.
 
Last edited:
Level 6
Joined
Jul 12, 2017
Messages
139
Then you forgot to copy over a trigger or part of a trigger that includes the Savecode object. Everything recently in this site's Resources section works and can compile without problems; its your map that has the issue. If you really do have both of those settings enabled for your map then remove it all and try reimporting it from scratch.

If your map is in Lua mode instead of JASS mode then you likely won't be able to use that resource at all unless you can transpile it. JASS -> Lua is not hard but Lua -> JASS is a tall order.
ah yes, now it works, thank you.

Now, I don't know if it's proper to ask it here or need to create a new topic but what I want from this system is very simple. To save stack of item and food (as experience point) for player.

Basically, if you finish the game, you get food (exp point) as a progress to unlock stuffs, but there is no example on how to store resources. May I ask how to do that?
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,457
ah yes, now it works, thank you.

Now, I don't know if it's proper to ask it here or need to create a new topic but what I want from this system is very simple. To save stack of item and food (as experience point) for player.

Basically, if you finish the game, you get food (exp point) as a progress to unlock stuffs, but there is no example on how to store resources. May I ask how to do that?
I've posted a lot about this over the years, for example:

Note that all this save/load system does is save Integers, but an Integer can be made to represent anything.

If your player's have a custom resource called Food which is stored as an Integer:
  • Set Variable Food[Player number of (Some player)] = 100
It'd be pretty simple to save it:
  • Set VariableSet SaveCount = (SaveCount + 1)
  • Set VariableSet SaveValue[SaveCount] = Food[(Player number of SaveLoadEvent_Player)]
  • Set VariableSet SaveMaxValue[SaveCount] = 99999
So what you're doing is filling an Integer array with all of the things that you want to save. You're also providing a Max Value to each of these things which acts like a limit. So in this case I said that Food can Save a value up to 99,999. SaveCount is there to simplify the process by increasing the [index] for each new Integer added to the array.
 
Last edited:
Level 6
Joined
Jul 12, 2017
Messages
139
I've posted a lot about this over the years, for example:

Note that all this save/load system does is save Integers, but an Integer can be made to represent anything.

If your player's have a custom resource called Food which is stored as an Integer:
  • Set Variable Food[Player number of (Some player)] = 100
It'd be pretty simple to save it:
  • Set VariableSet SaveCount = (SaveCount + 1)
  • Set VariableSet SaveValue[SaveCount] = Food[(Player number of SaveLoadEvent_Player)]
  • Set VariableSet SaveMaxValue[SaveCount] = 99999
So what you're doing is filling an Integer array with all of the things that you want to save. You're also providing a Max Value to each of these things which acts like a limit. So in this case I said that Food can Save a value up to 99,999. SaveCount is there to simplify the process by increasing the [index] for each new Integer added to the array.
Yes, that will work, thank you. Now I only got one problem which is how to enable local files which doesn't work at all ;l.
 
Status
Not open for further replies.
Top