Difference between revisions of "Targets not preserved in saved games"

From DoomWiki.org

[unchecked revision][checked revision]
(I added more. The source cause of the error is needed though.)
(Technical: Added note explaining how it' s possible to reconstruct infighting targets by analyzing pointers.)
(18 intermediate revisions by 10 users not shown)
Line 1: Line 1:
{{template:stub}}
+
When the game is saved in any [[Doom engine]] game, [[monster]] and [[projectile|missile]] targets are not registered in the save game file, so any monsters which were active at the time of saving the game become dormant upon loading the game again. However, their location and angle when the game was saved is preserved.
  
In any DOOM game, when you save, soundtargets are not kept in the savegame, so any monsters that saw you and was active is dormant again. Their location and angle when you saved is however preserved.
+
== Demonstrating the effect ==
  
 
Here is one way to see the anomalous behavior:
 
Here is one way to see the anomalous behavior:
  
 
#Start a new game of [[Doom II]] ([[MAP01: Entryway|MAP01]]) on [[I'm too young to die]].
 
#Start a new game of [[Doom II]] ([[MAP01: Entryway|MAP01]]) on [[I'm too young to die]].
#When the program loads, you will be looking at two troopers whose backs are toward you. Ignore them for now; instead, walk west along the short corridor until you reach the balcony.
+
#When the program loads, you will be looking at two [[trooper]]s with their backs to you. Ignore them for now; instead, walk west along the short corridor until you reach the balcony.
#Fire a bullet. Two grunting sounds will now inform you that you have gotten the troopers' attention.
+
#Fire a bullet. Two grunting sounds will now indicate that you have attracted the troopers' attention.
#Save your game.
+
#Save the game.
 
#Load the game you just saved.
 
#Load the game you just saved.
#(Optional) Stand still for a minute or two and listen. One would expect to hear the breathing noise made by zombies as they walk around, but all is quiet.
+
#(Optional) Stand still for a minute or two and listen. One would expect to hear the breathing noise made by zombies as they walk around, but all is quiet.
#Carefully inch your way back along the corridor to the starting point, keeping your eye on the opening to the north. As you get into each trooper's line of sight, one of two things will happen:
+
#Carefully move back along the corridor to the starting point, keeping your eye on the opening to the north. As you move into each trooper's line of sight, one of two things will happen:
#*If he is facing you, he will become aroused and start moving.
+
#*If he is facing you, he will become active and start moving again.
 
#*If he is not facing you, you will see him standing still.
 
#*If he is not facing you, you will see him standing still.
  
So, even though the troopers became aroused in step 3, they "fell asleep" during step 5.
+
So, even though the troopers woke up in step 3, they "fell asleep" during step 5.
  
[[Category: Errors and bugs]]
+
== Specific effects ==
 +
 
 +
Some distinguishable effects become evident because of the bug. The target of an incomplete [[arch-vile]] attack, for example, is not preserved in a saved game because of the bug. This means loading a saved game that includes such a situation will render the arch-vile attack harmless apart from the flame animation on the arch-vile's ex-target, which is displayed all the way through (as the corresponding flame [[thing]] had been spawned there as an effect of the attack). Similarly, the target of a [[revenant]]'s [[projectile|missile]] is not stored in the save game data. Therefore, the missiles will no longer follow anything after it is restored.
 +
 
 +
== Technical ==
 +
 
 +
The cause of this effect can be found in the Doom source code in [[Doom source code files|p_saveg.c]], in the functions ''P_ArchiveThinkers'' and ''P_UnarchiveThinkers''.
 +
 
 +
In the Doom source code, the ''mobj_t'' structure is used to represent game objects such as monsters.  Monster targets are stored in these structures as a field named ''target'', which is a pointer to another ''mobj_t'' that the monster is currently targeting.
 +
 
 +
The Doom engine saves games by directly writing the raw structures used in memory to disk.  When reloading saved games, pointers such as the ''target'' field are no longer valid (as the layout of structures within memory is different).  When loading a game, the ''P_UnarchiveThinkers'' function deliberately sets ''target'' on all map objects to NULL in order to avoid crashes due to accessing invalid areas of memory.  A null target indicates that a monster has no current target, causing active monsters to return to sleep.
 +
 
 +
A number of [[source ports]] have fixed the save game exploit, producing save game files with monsters that will continue to hound their previous target upon reloading the saved game. It is also possible to reconstruct infighting targets from standard Doom savegames by treating the stored mobj_t pointers as unique identifiers and analyzing their mutual relationships to determine which monster used to be which thinker. [[Mocha Doom]] uses this approach to reconstruct full target relationships from standard Doom savegames.
 +
 
 +
== See also ==
 +
 
 +
*[[Spawn spots not preserved in saved games]]
 +
 
 +
[[Category:Errors and bugs]]
 +
[[Category:Monsters]]

Revision as of 10:51, 3 October 2011

When the game is saved in any Doom engine game, monster and missile targets are not registered in the save game file, so any monsters which were active at the time of saving the game become dormant upon loading the game again. However, their location and angle when the game was saved is preserved.

Demonstrating the effect

Here is one way to see the anomalous behavior:

  1. Start a new game of Doom II (MAP01) on I'm too young to die.
  2. When the program loads, you will be looking at two troopers with their backs to you. Ignore them for now; instead, walk west along the short corridor until you reach the balcony.
  3. Fire a bullet. Two grunting sounds will now indicate that you have attracted the troopers' attention.
  4. Save the game.
  5. Load the game you just saved.
  6. (Optional) Stand still for a minute or two and listen. One would expect to hear the breathing noise made by zombies as they walk around, but all is quiet.
  7. Carefully move back along the corridor to the starting point, keeping your eye on the opening to the north. As you move into each trooper's line of sight, one of two things will happen:
    • If he is facing you, he will become active and start moving again.
    • If he is not facing you, you will see him standing still.

So, even though the troopers woke up in step 3, they "fell asleep" during step 5.

Specific effects

Some distinguishable effects become evident because of the bug. The target of an incomplete arch-vile attack, for example, is not preserved in a saved game because of the bug. This means loading a saved game that includes such a situation will render the arch-vile attack harmless apart from the flame animation on the arch-vile's ex-target, which is displayed all the way through (as the corresponding flame thing had been spawned there as an effect of the attack). Similarly, the target of a revenant's missile is not stored in the save game data. Therefore, the missiles will no longer follow anything after it is restored.

Technical

The cause of this effect can be found in the Doom source code in p_saveg.c, in the functions P_ArchiveThinkers and P_UnarchiveThinkers.

In the Doom source code, the mobj_t structure is used to represent game objects such as monsters. Monster targets are stored in these structures as a field named target, which is a pointer to another mobj_t that the monster is currently targeting.

The Doom engine saves games by directly writing the raw structures used in memory to disk. When reloading saved games, pointers such as the target field are no longer valid (as the layout of structures within memory is different). When loading a game, the P_UnarchiveThinkers function deliberately sets target on all map objects to NULL in order to avoid crashes due to accessing invalid areas of memory. A null target indicates that a monster has no current target, causing active monsters to return to sleep.

A number of source ports have fixed the save game exploit, producing save game files with monsters that will continue to hound their previous target upon reloading the saved game. It is also possible to reconstruct infighting targets from standard Doom savegames by treating the stored mobj_t pointers as unique identifiers and analyzing their mutual relationships to determine which monster used to be which thinker. Mocha Doom uses this approach to reconstruct full target relationships from standard Doom savegames.

See also