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

[Trigger] Fatal Error upon player leaving

Status
Not open for further replies.
Level 20
Joined
Jul 10, 2009
Messages
477
Hey guys,
I recognized a Fatal Error while testing my tower wars map, and I couldn't yet find its reason at all.

It occurs sometimes (or probably always) upon a player leaving the game, while he is still alive in-game and while the current round is still running (the tower wars map is round-based).
It does not occur, when the leaving player is either already defeated, or when he leaves between two rounds, when there is no current creep- or tower-action.

First of all, I would like to give you the only trigger running on the "Player Leaves Game" event:

(notice that I tried to translate the code into english, so it may differ from what you are used to read ;) )
  • PlayerLeavesGame
    • Events
      • Player - Player 1 (Rot) leaves the game
      • Player - Player 2 (Blau) leaves the game
      • Player - Player 3 (Blaugrau) leaves the game
      • Player - Player 4 (Lila) leaves the game
      • Player - Player 5 (Gelb) leaves the game
      • Player - Player 6 (Orange) leaves the game
      • Player - Player 7 (Grün) leaves the game
      • Player - Player 8 (Rosa) leaves the game
      • Player - Player 9 (Grau) leaves the game
      • Player - Player 10 (Hellblau) leaves the game
      • Player - Player 11 (Dunkelgrün) leaves the game
      • Player - Player 12 (Braun) leaves the game
    • Conditions
    • Actions
      • Custom script: local integer udg_TempInteger
      • Set TempInteger = (Player number of (Triggering player))
      • Set BossesDefeated[TempInteger] = MaxNumberOfBosses
      • Game - Display to (All players) for 15.00 seconds the text: (((|cff + PlayerColors[TempInteger]) + (Name of (Player(TempInteger)))) + |r |cffff1100 has left the game.|r)
      • Multiboard - Set the text for Multiboard item in column 1, row PlayerMultiboardIndex[TempInteger] to ((|cff + PlayerColors[13]) + ((Name of (Player(TempInteger))) + |r))
      • Multiboard - Set the text for Multiboard item in column 4, row PlayerMultiboardIndex[TempInteger] to ((|cff + PlayerColors[13]) + Left the Game|r)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • PlayerDefeated[(Player number of (Triggering player))] Equal to True
        • 'THEN'-Actions
          • Skip remaining actions
        • 'ELSE'-Actions
      • Unit - Kill PortalAnimation[TempInteger]
      • Multiboard - Set the text for Multiboard item in column 2, row PlayerMultiboardIndex[TempInteger] to ((|cff + PlayerColors[13]) + ((String(Income[TempInteger])) + |r))
      • Multiboard - Set the text for Multiboard item in column 3, row PlayerMultiboardIndex[TempInteger] to ((|cff + PlayerColors[13]) + ((String(PlayerLifes[TempInteger])) + |r))
      • Playergroup - Remove (Player(TempInteger)) from PlayersPlaying
      • Set PlayerDefeated[TempInteger] = True
      • Set NumberOfPlayers = (NumberOfPlayers - 1)
      • Unit - Kill TowerGuys[TempInteger]
      • Set TempUnitgroup = (Units owned by (Player(TempInteger)) matching (((Matching unit) is A Building) Equal to True))
      • Unitgroup - Pick every unit in TempUnitgroup and do (Actions)
        • Loop - Actions
          • Unit - Pause (Picked unit)
      • Custom script: call DestroyGroup (udg_TempUnitgroup)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • (Remaining time for RoundTimer) Bigger than 0.00
        • 'THEN'-Actions
          • Set TempInteger4 = (((Player(TempInteger)) Verbrauchte Nahrung) + TowersBlownUpThisRound[TempInteger])
          • Set TempUnitgroup = (Units in PlayerMazeAreas[TempInteger] matching ((((Matching unit) is Suicidal) Equal to True) and ((((Matching unit) is alive) Equal to True) and (((Level of IsAlchemist (Editor Info) for (Matching unit)) Equal to 0) and (0 Equal to 0)))))
          • Unitgroup - Pick every unit in TempUnitgroup and do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • 'IF'-Conditions
                  • TempInteger4 Bigger than 0
                • 'THEN'-Actions
                  • Set TempPoint = (Position of (Picked unit))
                  • Unit - Kill (Picked unit)
                  • Set TempInteger4 = (TempInteger4 - 1)
                  • Unit - Create 1 Totenerweckung (Dummy) for (Player(TempInteger)) at TempPoint facing default for building-orientation degrees
                  • Unit - Add a 3.00 second Standard expiration timer to (Last created unit)
                  • Custom script: call RemoveLocation(udg_TempPoint)
                • 'ELSE'-Actions
          • Custom script: call DestroyGroup (udg_TempUnitgroup)
        • 'ELSE'-Actions
      • Trigger - Run PlayerWinsProof <gen> (checking conditions)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • BetweenRounds Equal to True
        • 'THEN'-Actions
          • Trigger - Run CheckPlayersChoosed <gen> (checking conditions)
        • 'ELSE'-Actions
  • PlayerWinsProof
    • Events
    • Conditions
    • Actions
      • Set TempInteger2 = 0
      • Set TempInteger3 = 0
      • For each (Integer A) from 1 to 12, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • 'IF'-Conditions
              • PlayerDefeated[(Integer A)] Equal to False
            • 'THEN'-Actions
              • Set TempInteger2 = (TempInteger2 + 1)
              • Set TempInteger3 = (Integer A)
            • 'ELSE'-Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • TempInteger2 Smaller or Equal to 1
        • 'THEN'-Actions
          • Set GameOver = True
        • 'ELSE'-Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • TempInteger2 Smaller or Equal to 1
          • TempInteger3 Not Equal to 0
        • 'THEN'-Actions
          • Game - Display to (All players) for 100.00 seconds the text: ((|cff + PlayerColors[TempInteger3]) + ((Name of (Player(TempInteger3))) + |r|cffffcc00 has won this game. Congratulations!|r))
        • 'ELSE'-Actions
When the Player Leaves Trigger is not responsible itself, it could be another trigger that is running very often, so that the Fatal Error seems to occur upon player leaving, but does indeed occur shortly after.
The trigger that is running the most is the unit revive trigger:
  • Unit Revive
    • Events
      • Unit - A unit dies
    • Conditions
      • ((Triggering unit) is Suicidal) Equal to True
      • Or - Any (Conditions) are true
        • Conditions
          • ((Killing unit) is A Building) Equal to True
          • (Unit-type of (Killing unit)) Equal to Dummy (Boulder Tower, Missile size 3x )
          • (Unit-type of (Killing unit)) Equal to Dummy (Boulder Tower L2, Missile size 3x )
      • (Level of JailUnit (Editor Info) for (Dying unit)) Equal to 0
      • (Remaining time for RoundTimer) Bigger or Equal to 10.00
      • (Level of NoTower (Editor Info) for (Killing unit)) Equal to 0
    • Actions
      • Custom script: local location udg_TempPoint
      • Custom script: local location udg_TempPoint2
      • Custom script: local integer udg_TempInteger
      • Custom script: local integer udg_TempInteger2
      • Custom script: local integer udg_TempInteger3
      • Custom script: local integer udg_TempInteger6
      • Custom script: local unit udg_TempUnit
      • Set TempPoint = (Position of (Dying unit))
      • Set TempPoint2 = (Position of (Killing unit))
      • Set TempInteger = (Custom value of (Dying unit))
      • Set TempInteger2 = (Player number of (Owner of (Killing unit)))
      • Set TempInteger3 = (Point-value of (Killing unit))
      • Set TempInteger6 = 0
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • (Level of PaperType (Editor Info) for (Killing unit)) Equal to 1
        • 'THEN'-Actions
          • Set TempInteger6 = 1
        • 'ELSE'-Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • (Level of ScissorsType (Editor Info) for (Killing unit)) Equal to 1
        • 'THEN'-Actions
          • Set TempInteger6 = 2
        • 'ELSE'-Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • (Level of StoneType (Editor Info) for (Killing unit)) Equal to 1
        • 'THEN'-Actions
          • Set TempInteger6 = 3
        • 'ELSE'-Actions
      • Wait 0.50 game-time seconds
      • -------- Only animation and dummy stuff here --------
      • Unit - Create 1 Lightningeffect Geistverbindung (CasterDummy) for Neutral hostile at TempPoint2 facing TempPoint
      • Set TempUnit = (Last created unit)
      • Custom script: call SetUnitPathing(udg_TempUnit, false)
      • Unit - Move TempUnit instantly to TempPoint2
      • Unit - Add a 1.50 second Standard expiration timer to (Last created unit)
      • Unit - Create 1 Lightningeffect (VictimDummy) for Neutral hostile at TempPoint facing TempPoint2
      • Unit - Add a 1.50 second Standard expiration timer to (Last created unit)
      • Unit - Order TempUnit to Angreifen (Last created unit)
      • Wait 0.50 game-time seconds
      • Unit - Create 1 AuferstehungAnimation (Dummy) for Neutral hostile at TempPoint facing TempPoint
      • Unit - Add a 1.50 second Standard expiration timer to (Last created unit)
      • Wait 1.00 game-time seconds
      • -------- uses global variable TempInteger5 here, because the shadowed locals can't be used in if-conditions --------
      • Set TempInteger5 = TempInteger3
      • -------- creates a new unit for the killing player --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • TempInteger5 Bigger or Equal to NumberOfStandardTowers
        • 'THEN'-Actions
          • Set TempInteger5 = TempInteger6
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • 'IF'-Conditions
              • TempInteger5 Equal to 1
            • 'THEN'-Actions
              • Unit - Create 1 UnitsfromTowersPaper[TempInteger3] for (Player(TempInteger2)) at TempPoint facing AllWayPoints[TempInteger]
            • 'ELSE'-Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • 'IF'-Conditions
              • TempInteger5 Equal to 2
            • 'THEN'-Actions
              • Unit - Create 1 UnitsfromTowersScissors[TempInteger3] for (Player(TempInteger2)) at TempPoint facing AllWayPoints[TempInteger]
            • 'ELSE'-Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • 'IF'-Conditions
              • TempInteger5 Equal to 3
            • 'THEN'-Actions
              • Unit - Create 1 UnitsfromTowersStone[TempInteger3] for (Player(TempInteger2)) at TempPoint facing AllWayPoints[TempInteger]
            • 'ELSE'-Actions
        • 'ELSE'-Actions
          • Unit - Create 1 UnitsfromTowersStone[TempInteger3] for (Player(TempInteger2)) at TempPoint facing AllWayPoints[TempInteger]
      • Set TempUnit = (Last created unit)
      • Unit - Set the custom value of (Last created unit) to TempInteger
      • -------- applies buffs and upgrades to the created unit --------
      • Set ModifyTempUnit = (Last created unit)
      • Set ModifyTempUnit2 = (Killing unit)
      • Trigger - Run Modify Unit <gen> (checking conditions)
      • Trigger - Run Give RoundBonus <gen> (checking conditions)
      • -------- order the new unit to run through the maze --------
      • Trigger - Turn off Order Deactivation <gen>
      • Unit - Order TempUnit to Bewegen nach AllWayPoints[TempInteger]
      • Trigger - Turn on Order Deactivation <gen>
      • Custom script: call RemoveLocation (udg_TempPoint)
      • Custom script: call RemoveLocation (udg_TempPoint2)
  • Modify Unit
    • Events
    • Conditions
    • Actions
      • -------- Evolution Tower --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • (Point-value of ModifyTempUnit) Equal to 17
        • 'THEN'-Actions
          • Set GiveBonusTempIntegers[0] = (10 x ((Level of State of Evolution (Info-Text, Evolution Tower) for ModifyTempUnit2) - 1))
          • Trigger - Run Add Health To Unit <gen> (checking conditions)
        • 'ELSE'-Actions
      • -------- Evolution Tower, Level 2 --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • (Point-value of ModifyTempUnit) Equal to 27
        • 'THEN'-Actions
          • Set GiveBonusTempIntegers[0] = (30 x ((Level of State of Evolution (Info-Text, Evolution Tower) for ModifyTempUnit2) - 1))
          • Trigger - Run Add Health To Unit <gen> (checking conditions)
        • 'ELSE'-Actions
      • -------- Evolution Tower, Level 3 --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • (Point-value of ModifyTempUnit) Equal to 28
        • 'THEN'-Actions
          • Set GiveBonusTempIntegers[0] = (50 x ((Level of State of Evolution (Info-Text, Evolution Tower) for ModifyTempUnit2) - 1))
          • Trigger - Run Add Health To Unit <gen> (checking conditions)
        • 'ELSE'-Actions
      • -------- Anti-Sniper Roundbonus --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • (Point-value of ModifyTempUnit) Equal to 21
        • 'THEN'-Actions
          • Set GiveBonusTempIntegers[0] = Roundnumber
          • Trigger - Run Add Health To Unit <gen> (checking conditions)
        • 'ELSE'-Actions
      • -------- Healthy Defense --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • (Current research level of Healthy Defense for (Owner of ModifyTempUnit)) Bigger or Equal to 3
          • (Point-value of ModifyTempUnit) Not Equal to 21
        • 'THEN'-Actions
          • Set GiveBonusTempIntegers[0] = (Integer((Leben of ModifyTempUnit)))
          • Trigger - Run Add Health To Unit <gen> (checking conditions)
        • 'ELSE'-Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • (Current research level of Healthy Defense for (Owner of ModifyTempUnit)) Bigger or Equal to 2
          • (Point-value of ModifyTempUnit) Not Equal to 21
        • 'THEN'-Actions
          • Set GiveBonusTempIntegers[0] = HealthyDefenseLifeBonus[2]
          • Trigger - Run Add Health To Unit <gen> (checking conditions)
        • 'ELSE'-Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • (Current research level of Healthy Defense for (Owner of ModifyTempUnit)) Bigger or Equal to 1
          • (Point-value of ModifyTempUnit) Not Equal to 21
        • 'THEN'-Actions
          • Set GiveBonusTempIntegers[0] = HealthyDefenseLifeBonus[1]
          • Trigger - Run Add Health To Unit <gen> (checking conditions)
        • 'ELSE'-Actions
      • -------- Skip remaining actions, if the killing tower does not exist --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • ModifyTempUnit2 Equal to Keine Unit
              • (ModifyTempUnit2 is alive) Equal to False
        • 'THEN'-Actions
          • Skip remaining actions
        • 'ELSE'-Actions
      • -------- Pegasus Shoes --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • (ModifyTempUnit2 has an item of type Pegasus Shoes) Equal to True
        • 'THEN'-Actions
          • Unit - Add Movementspeed Increase (Pegasus Shoes) to ModifyTempUnit
        • 'ELSE'-Actions
      • -------- Heart Container --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • (ModifyTempUnit2 has an item of type Heart Container) Equal to True
        • 'THEN'-Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • 'IF'-Conditions
              • (Point-value of ModifyTempUnit) Not Equal to 21
            • 'THEN'-Actions
              • Trigger - Run Give RoundBonus <gen> (checking conditions)
            • 'ELSE'-Actions
              • Set GiveBonusTempIntegers[0] = Roundnumber
              • Trigger - Run Add Health To Unit <gen> (checking conditions)
        • 'ELSE'-Actions
  • Add Health To Unit
    • Events
    • Conditions
    • Actions
      • Set GiveBonusTempIntegers[2] = ((GiveBonusTempIntegers[0] / 100) + 1)
      • Set GiveBonusTempIntegers[3] = ((Integer((Leben of ModifyTempUnit))) + GiveBonusTempIntegers[0])
      • For each (Integer GiveBonusTempIntegers[1]) from 1 to GiveBonusTempIntegers[2], do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • 'IF'-Conditions
              • GiveBonusTempIntegers[0] Smaller or Equal to 100
            • 'THEN'-Actions
              • Unit - Add GetLife (+All) to ModifyTempUnit
              • Unit - Set level of GetLife (+All) for ModifyTempUnit to ((GiveBonusTempIntegers[0] / 10) + 1)
              • Unit - Remove GetLife (+All) from ModifyTempUnit
              • Set GiveBonusTempIntegers[0] = (GiveBonusTempIntegers[0] mod 10)
              • Unit - Add GetLife1to10 (+All) to ModifyTempUnit
              • Unit - Set level of GetLife1to10 (+All) for ModifyTempUnit to (GiveBonusTempIntegers[0] + 1)
              • Unit - Remove GetLife1to10 (+All) from ModifyTempUnit
              • Set GiveBonusTempIntegers[0] = 0
              • Unit - Set life of ModifyTempUnit to (Real(GiveBonusTempIntegers[3]))
            • 'ELSE'-Actions
              • Unit - Add GetLife (+All) to ModifyTempUnit
              • Unit - Set level of GetLife (+All) for ModifyTempUnit to 11
              • Unit - Remove GetLife (+All) from ModifyTempUnit
              • Set GiveBonusTempIntegers[0] = (GiveBonusTempIntegers[0] - 100)
              • Unit - Set life of ModifyTempUnit to (Real(GiveBonusTempIntegers[3]))
The trigger "GiveRoundBonus" is basically the same as "AddHealthToUnit", so there is no need to review it :)


If you think that these triggers can't be responsible for the Fatal Error, I can post further ones for you. Just don't want to flood you with triggers for now ;)

For these of you who prefer to take a direct look at the map, I uploaded it for you :)
Furthermore I attached the Error.txt and dmp. files of the crash.

I hope so much that you can help me with that.

Best regards!
Eikonium
 

Attachments

  • StoneScPTowerWars_v1.1.w3x
    636.5 KB · Views: 25
  • 2015-04-26 18.22.48 Crash.txt
    13.8 KB · Views: 53
  • 2015-04-26 18.22.48 Crash.dmp.txt
    353.9 KB · Views: 33
Level 13
Joined
Jul 16, 2012
Messages
679
  • Custom script: local location udg_TempPoint
  • Custom script: local location udg_TempPoint2
  • Custom script: local integer udg_TempInteger
  • Custom script: local integer udg_TempInteger2
  • Custom script: local integer udg_TempInteger3
  • Custom script: local integer udg_TempInteger6
  • Custom script: local unit udg_TempUnit
this part of your code will give you an error

EDIT:
Btw, dont use wait bro...
 
Level 20
Joined
Jul 10, 2009
Messages
477
In the Unit Revive trigger, TempInteger2 might be lost in the if/thens after the wait, and if it gains a value outside the range 1-16, it will cause a crash. As you did with tempint3, use a temp global variable.
TempInteger2 is already local, like TempInt3 :) So that should not be the problem (thanks for looking through the trigger though!).

GywGod133 said:
  • Custom script: local location udg_TempPoint
  • Custom script: local location udg_TempPoint2
  • Custom script: local integer udg_TempInteger
  • Custom script: local integer udg_TempInteger2
  • Custom script: local integer udg_TempInteger3
  • Custom script: local integer udg_TempInteger6
  • Custom script: local unit udg_TempUnit
this part of your code will give you an error
EDIT:
Btw, dont use wait bro...

Actually, it does not give me an error^^ Shadowing of multiple globals works since patch 1.24 afaik. This trigger runs around once every second in late-game, and it did never produce any bugs.
I use game-time waits here, so desyncs should not occur (and +-0,25 accuracy doesn't matter).

As said, the crash occurs upon a player leaving the game. Otherwise, the game is running stable! A bad correlation between the PlayerLeaves trigger and the UnitRevive trigger could be a problem, and that's why I posted both :) Thanks for looking through it though :)

Edit:
Custom script: local integer udg_TempInteger
Set TempInteger = (Player number of (Triggering player))

Does this work? :eek:
Yeah, it works ;) It's called Shadowing of global variables.

Edit 2:
Only for clarification: problem is still unsolved :)
 
Last edited:
Level 20
Joined
Jul 10, 2009
Messages
477
Even with both triggers activated, I was not yet able to reproduce the crash.
It happend twice in the past - and in both cases, we played with 5+ people, and a player left the game, while it was under heavy load.
Sadly, that's all I know.

I guess the triggers themselves are clean, because otherwise someone would have found a bad part in them.
Maybe I should wait until the next crashs occurance and try to obtain some information out there^^
 
Level 19
Joined
Jul 14, 2011
Messages
875
As far as I remember, GUI conditions are in separate functions which means that shadowing the globals might not have the desired effect.

Ill check if Im right when I have the time, in case I am remembering wrong.

E: I was talking about the conditions in the If statements. Also, they are indeed in separate functions.
 
Last edited:
Level 20
Joined
Jul 10, 2009
Messages
477
Yeah, that's an important fact :) Indeed, the triggers above are not affected by that, because I write the shadowed globals into not-shadowed globals before using them in if-conditions.
E.g. in the first trigger that I posted, TempInt3 and TempInt6 are shadowed, and are written to TempInt5 (not shadowed) to be used in the If-conditions.
 
Status
Not open for further replies.
Top