Duke3D: Loading outdated savegames and resulting problems with loadmapstate
In recent commits there was an update to the savegame system that allows old saves to be loaded, even when CON code has changed since.
It turns out that this does not mesh well with the savemapstate
/loadmapstate
system.
In the following video recorded in the mod WGRealms 2 Demon Throne, there is a Town hub that can be accessed from almost any level in the game, and which has its state saved throughout the game. Prior to what is seen in the video, I had accessed said Town map from E1L1, continued to E1L2, saved there and updated the CON files to a newer version from the development SVN. Afterwards, I access the Town again from E1L2:
https://www.youtube.com/watch?v=6RWOznRe_Ro&feature=youtu.be
Many of the sprites in the map started rapidly shooting all over the place, actors that were supposed to be dead came back to life, and several scripts stopped working entirely. From what I can gather, loadmapstate
works similarly to the save system itself. Perhaps whatever data has to be corrected when loading an outdated save is not being corrected for loading a mapstate.
Also here are some errors that were output into the console while this was going on. The console was being spammed so this is just a small sample:
Sprite 7590 tile 2329: invalid action at offset 137225
Sprite 7531 tile 2329: invalid action at offset 137225
Sprite 13198 tile 2329: invalid action at offset 137225
EDIT 07.17.2021: I have managed to isolate the problem into a small test case.
Download the following zip file:
The zip contains two maps, e1l1.map
and e1l2.map
, both copies of each other, named as such to allow quick loading with Duke3D. TILES060.ART simply contains a copy of the rotategun sprites. Then there are two CON files, rotategun_custom.con
and rotategun_custom_altered.con
, which define a new useractor that is a copy of the Duke3D turret code. The former is the original file, and the latter has the following four dummy actions added to it:
action TESTTESTEST5 4 1 1 1 4
action TESTTESTEST4 3 1 1 1 4
action TESTTESTEST1 2 1 1 1 4
action TESTTESTEST2 1 1 1 1 4
The naming of the actions was chosen arbitrarily. The actions are not used anywhere in the CON, and hence should not affect the turret when loading saves. However, these are apparently enough to trigger the problem.
The CON file also defines the ALTFIRE
event such that, if you press the altfire key, the map state is saved, and you'll be transported between e1l1 and e1l2 alternatingly.
Finally, I constructed a save file savedstate.esv
to demonstrate the problem. Follow the following steps to reproduce it:
- Launch eduke32 r9476 with the parameter
eduke32.exe -mx rotategun_custom.con
- Load the save
savedstate.esv
inside the Load Game menu. - You will be placed in E1L2 and will observe a turret actor in front of you with a number of random sprites placed on the ground. Observe how the turret actor behaves.
- Press ALTFIRE to jump to E1L1 with loadmapstate. This will load the state of the map when I left it, after picking up some of the items and destroying an object.
- Observe that the turret actor behaves the same as before.
- Close the game, and now launch
eduke32.exe -mx rotategun_custom_altered.con
. This is supposed to simulate a patch to the script file. - Again load the save file
savedstate.esv
in the Load Game menu, and observe the turret actor. It should still behave as normal. - Press ALTFIRE to load E1L1, and behold as the turret actor now appears to be stuck in one of the newly defined test actions, which are not referenced anywhere in the actor's code.
Judging from the frame that the turret displays after loading E1L1, it appears that it gets stuck in the action :
action TESTTESTEST1 2 1 1 1 4
EDIT: After further investigation, I'm now fairly sure that at the time of saving, the turret was inside action ASATWAIT_C
, which was the third action defined in sequence. After adding the above 4 actions, the turret gets stuck in action TESTTESTEST1
, which in the new CON file is now the third action in sequence.