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

[Crash] I seem to have destroyed a player!

Status
Not open for further replies.
Level 14
Joined
Aug 30, 2004
Messages
909
I have a complicated map based on a missile system that lets you fly Star Wars ships about and duel.

About fifteen minutes into the map, things started to break in strange ways. I don't even begin to know where to look for the bug because it's unlike anything I've seen before. Here's one problem that just makes no sense to me:

I have a trigger called "test Copy" which gives me information to help debug. In short, it lists all the ships in the game and who their current AI target is (who are they going after). That's not important though because the bug is really strange. The trigger below fired; I know because the "environment" action was called and the screen did look differently after it. But nothing showed up on the screen, i.e. the "Game - Display to (All players) the text: (((Name of Fliers[test]) + (String(test))) + (Name of AiTargets[test]))" action didn't print anything. It should have printed a list about 75 names long. But nothing was printed. It's as if being player 1 wasn't included in "all players".

  • test Copy
    • Events
      • Player - Player 1 (Red) types a chat message containing test as An exact match
      • Player - Player 2 (Blue) types a chat message containing test as An exact match
      • Player - Player 3 (Teal) types a chat message containing test as An exact match
    • Conditions
    • Actions
      • Hero - Set Hero[(Player number of (Triggering player))] Hero-level to 9, Show level-up graphics
      • For each (Integer test) from 1 to 75, do (Actions)
        • Loop - Actions
          • Game - Display to (All players) the text: (((Name of Fliers[test]) + (String(test))) + (Name of AiTargets[test]))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Fliers[test] is in IonizedShips) Equal to True
            • Then - Actions
              • Game - Display to (All players) the text: (ion: + (Name of Fliers[test]))
            • Else - Actions
      • Unit Group - Pick every unit in FliersUG and do (Actions)
        • Loop - Actions
          • Game - Display to (All players) the text: (Name of (Picked unit))
      • Cinematic - Ping minimap for (All players) at ((Position of ATAT) offset by 1000.00 towards 135.00 degrees) for 5.00 seconds
        • Environment - Set fog to style Linear, z-start 1000000000.00, z-end 1000000000.00, density 0.00 and color (100.00%, 100.00%, 100.00%)
The hero that was meant to be made level 9 was level 10 already... but other than that the trigger should have worked fine. I'm very confused by it.

The same thing happened a moment later when the Star Destroyer was blown up and the ending trigger fired:

  • Rebels Wins
    • Events
      • Unit - Imperial Star Destroyer 0002 <gen> Dies
    • Conditions
    • Actions
      • Sound - Play Heroic Victory
      • Trigger - Run Ending Trigger cancel <gen> (ignoring conditions)
      • Cinematic - Turn cinematic mode On for (All players)
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • Camera - Apply Star Destroyer End <gen> for (Picked player) over 0.00 seconds
          • Camera - Apply Star Destroyer End 3 <gen> for (Picked player) over 9.50 seconds
      • Animation - Change (Dying unit)'s animation speed to 5.00% of its original speed
      • Unit - Pause all units
      • Set BUSY = True
      • Unit Group - Pick every unit in (Units of type Laser Port empire) and do (Actions)
        • Loop - Actions
          • Unit - Unpause (Picked unit)
          • Unit - Kill (Picked unit)
      • Set tempPlayerGroup = (All allies of Player 11 (Dark Green))
      • Game - Display to tempPlayerGroup the text: |c0066ff66VICTORY|r...
      • Custom script: call DestroyForce(udg_tempPlayerGroup)
      • Set tempPlayerGroup = (All allies of Player 12 (Brown))
      • Game - Display to tempPlayerGroup the text: |c00FF0000FAILURE|r...
      • Custom script: call DestroyForce(udg_tempPlayerGroup)
      • Wait 2.00 game-time seconds
      • Animation - Change (Dying unit)'s animation speed to 30.00% of its original speed
      • Wait 5.00 game-time seconds
      • Animation - Change (Triggering unit) flying height to 800.00 at 50.00
      • Animation - Change (Dying unit)'s animation speed to 80.00% of its original speed
      • Wait 2.00 game-time seconds
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked player) is an ally of Player 11 (Dark Green)) Equal to True
            • Then - Actions
              • Game - Victory (Picked player) (Show dialogs, Show scores)
            • Else - Actions
              • Game - Defeat (Picked player) with the message: Defeat!
I know this trigger fired as well because the Star Destroyers death animation was slowed, and its flying height was increased (I lift it up as it dies so the nose of the ship doesn't go in the ground).

But there were no messages played to allies of player 11 (which would include me, as player 1). Cinematic mode was not turned on even though the trigger has "Cinematic - Turn cinematic mode On for (all players). Camera "Star Destroyer End" was not played for me even though it's in a loop for "all players."

I think the units were paused but I'm not sure because most of the movement is disabled when the game is working normally.

Finally, even though the trigger ends by picking all players and giving them either victory or defeat, nothing happened to me. I didn't get the victory screen or the defeat screen.

It looks as if somehow player 1 was no longer a player... That would account for some of the errors, though not all.

Does anyone know what could even cause a bug like this? I'm new to removing leaks and such, so maybe I destroyed a force when I shouldn't or something like that.
 
Level 14
Joined
Aug 30, 2004
Messages
909
bug identification:

I believe the problem is that at one point I DestroyForce(udg_tempPlayerGroup) when tempPlayerGroup is set to All players. The result is, apparently, to destroy "all players" in the mind of the computer so that future commands to do something with "all players" are not fired. This is illustrated by the trigger below which, if put into a map as the only trigger, results in the following feedback:

Disappearing text
test
test
test
test
test...

  • Untitled Trigger 001
    • Events
      • Time - Every 2.00 seconds of game time
    • Conditions
    • Actions
      • Set tempPlayerGroup = (All players)
      • Game - Display to (All players) the text: Disappearing text
      • Custom script: call DestroyForce(udg_tempPlayerGroup)
      • Game - Display to Player Group - Player 1 (Red) the text: test
Clearing up these memory leaks are kind of dangerous. Any other things I should keep my eye out for?
 
Level 28
Joined
Jan 26, 2007
Messages
4,789
You should never delete "all players".
The group "All players" does NOT leak: it is a variable set to all players currently in the game.

You were doing right to try and remove leaks, but All Players is an exception here, removing it may have catastrophic results (as you probably noticed).
As far as I know, it's also the only exception. All other leaks must be removed :)
 
Level 14
Joined
Aug 30, 2004
Messages
909
You should never delete "all players".
The group "All players" does NOT leak: it is a variable set to all players currently in the game.

You were doing right to try and remove leaks, but All Players is an exception here, removing it may have catastrophic results (as you probably noticed).
As far as I know, it's also the only exception. All other leaks must be removed :)

It's good to know I'm not the only one who noticed this, thank you.

I do have a question as long as you're here... would this leak:

  • Set tempPlayerGroup = (All allies of Player 11 (Dark Green))
  • Game - Display to tempPlayerGroup the text: |c0066ff66MISSION S...
  • Set tempPlayerGroup = (All allies of Player 12 (Brown))
  • Game - Display to tempPlayerGroup the text: |c00FF0000MISSION F...
  • Custom script: call DestroyForce(udg_tempPlayerGroup)
...or should I use:

  • Set tempPlayerGroup = (All allies of Player 11 (Dark Green))
  • Game - Display to tempPlayerGroup the text: |c0066ff66MISSION S...
  • Custom script: call DestroyForce(udg_tempPlayerGroup)
  • Set tempPlayerGroup = (All allies of Player 12 (Brown))
  • Game - Display to tempPlayerGroup the text: |c00FF0000MISSION F...
  • Custom script: call DestroyForce(udg_tempPlayerGroup)
 
Level 14
Joined
Aug 30, 2004
Messages
909
The first one will have 1 leak: All Allies of Player 11 (Dark Green).
I think it's fairly obvious why it leaks: you never remove that specific player group (you can't remove it anymore since you already set the variable to something else).

So you should use the second method

Excellent thank you. I'm still new to this, so I really don't understand leaks really. I'm just following the guides. I didn't know if you just have to clear a variable at the end of the trigger, or clear it every time you change it from one value to another...

Anyway, you answered my question so thank you very much.
 
By the way, you don't need to make a whole player group, in order to refer to the allies of a specific player. You can use:
  • Actions
  • Player Group - Pick every player in (All players) and do (Actions)
    • Loop - Actions
      • If (All conditions are true) then do (Actions) else do (Actions)
        • If - Conditions
          • ((Picked player) is an ally of Player 11 (Dark Green)) Equal to True
        • Then - Actions
          • //Actions here
        • Else - Actions
This way, you save yourself from variables that are unnecessary.
Alternative:
  • Actions
    • For each (Integer A) from 1 to 12, do (Actions)
      • Loop - Actions
        • If (All conditions are true) then do (Actions) else do (Actions)
          • If - Conditions
            • ((Player(IntegerA) is an ally of Player 11 (Dark Green)) Equal to True
          • Then - Actions
            • //Actions here
          • Else - Actions
Instead of "Integer A", you may want to use a custom integer variable, so as to prevent possible conflicts.
 
Level 14
Joined
Aug 30, 2004
Messages
909
Thanks Pharaoh, I'll consider those.

I use a variable called tempPlayerGroup, and every time I have a message to give I set whoever gets the message to it, send the message, then destroy the tempPlayerGroup.

Is that an inefficient way to go about it? Would it be better to set two global variables: Rebels and Empire, or something at Initialization and then just never remove the leak because the variable really doesn't change?

I'm at that point where I'm trying to optimize the code so slower computers don't lag with the game.

Thanks again for all the help. I've been off the boards for about 6 months now (moved to Australia); it's nice to see the same familiar helpful faces about.

+rep to both of you, in case that wasn't obvious
 
Level 4
Joined
Apr 15, 2011
Messages
108
Solution: Change to StarCraft II.
Memory leaks make panda sad.
Garbage collector makes panda happy =]

like we need garbage collection
it may have gc, but we is better
also game is from 2003, few leaks are fine, and IF map is small, simple map, you can even make all triggers leak. they are triggers after all, you cant lag game very much in small games.

also, we can collect our own garbages. we dont need someone else to do it :ogre_hurrhurr:
 
Level 14
Joined
Aug 30, 2004
Messages
909
I have SC2 but haven't dived into the editor yet. I'm planning to for my next map; but I want to at least finish and post one map for all my effort!

As long as you're all here, I don't know much JASS but I've gotten some help here. I have a question:

  • Frag Repeated Nest
    • Events
    • Conditions
    • Actions
      • Custom script: set udg_x2 = GetUnitX(udg_fragUnit)
      • Custom script: set udg_y2 = GetUnitY(udg_fragUnit)
      • Set aoe2 = 400.00
      • Custom script: call GroupEnumUnitsInRange(udg_tempDamageUnits2, udg_x2, udg_y2, udg_aoe2, null)
      • Unit Group - Pick every unit in tempDamageUnits2 and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is Undead) Equal to True
            • Then - Actions
              • Unit - Kill (Picked unit)
            • Else - Actions
      • Custom script: call DestroyGroup(udg_tempDamageUnits2)
Do I need that last Custom script or can I get rid of it? Does the "call GroupEnumUnitsInRange" script cause a leak?
 
Status
Not open for further replies.
Top