Interkarma / daggerfall-unity

Open source recreation of Daggerfall in the Unity engine
http://www.dfworkshop.net
MIT License
2.75k stars 333 forks source link

Saves in buildings within custom RMBs cannot be loaded #2703

Open drcarademono opened 1 month ago

drcarademono commented 1 month ago

Mods like Fixed Desert Architecture and Beautiful Cities of Daggerfall add completely new RMBs using unique filenames (TEMPLEBA00.RMB.json or FARMBA04.RMB.json), and then insert these RMBs into the game by modifying the BlockNames array in location files. These custom RMBs work correctly, however, if the player saves inside a building in one of these custom blocks, the save will be unloadable. If a player restarts DFU and attempts to load the save, they'll get a black screen and the following error in the log:

Exception: Could not load RMB block index 1439 DaggerfallWorkshop.DaggerfallInterior.AssignBlockData (DaggerfallWorkshop.StaticDoor door) (at Assets/Scripts/Internal/DaggerfallInterior.cs:384) DaggerfallWorkshop.DaggerfallInterior.DoLayout (UnityEngine.Transform doorOwner, DaggerfallWorkshop.StaticDoor door, DaggerfallWorkshop.ClimateBases climateBase, DaggerfallWorkshop.PlayerGPS+DiscoveredBuilding buildingData) (at Assets/Scripts/Internal/DaggerfallInterior.cs:152) DaggerfallWorkshop.Game.PlayerEnterExit.TransitionInterior (UnityEngine.Transform doorOwner, DaggerfallWorkshop.StaticDoor door, System.Boolean doFade, System.Boolean start) (at Assets/Scripts/Game/PlayerEnterExit.cs:721) UnityEngine.Debug:LogException(Exception) DaggerfallWorkshop.Game.PlayerEnterExit:TransitionInterior(Transform, StaticDoor, Boolean, Boolean) (at Assets/Scripts/Game/PlayerEnterExit.cs:726) DaggerfallWorkshop.Game.PlayerEnterExit:StartBuildingInterior(DFLocation, StaticDoor, Boolean) (at Assets/Scripts/Game/PlayerEnterExit.cs:1034) DaggerfallWorkshop.Game.<Respawner>d__105:MoveNext() (at Assets/Scripts/Game/PlayerEnterExit.cs:545) UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr) (at /home/bokken/buildslave/unity/build/Modules/IMGUI/GUIUtility.cs:197)

I looked into this a bit and believe I partially understand the bug. Vanilla RMBs are assigned a blockIndex number based on their order in BLOCKS.BSA. Custom RMBs are assigned a blockIndex number dynamically based on the order in which they're loaded in-game. This doesn't cause any problems unless you save inside a building in a custom RMB. In that case, the blockIndex assigned to each StaticDoor is written into the save file (see attached image). If you restart the game and try to load that save, it will fail to find that blockIndex since the number was assigned dynamically and no longer exists.

image

Ralzar81 commented 1 day ago

Obviously not a "fix", but an easy way to solve the issue for the moment when it happens:

1: turn off your terrain mod 2: load the savegame 3: save the game and exit 4: turn the terrain mod back on 5: load the save game

This triggers the terrain change repositioning.

drcarademono commented 3 hours ago

Just to clarify Ralzar's comment: This bug occurs when the game is unable to match buildingKeys because they are generated dynamically from RMB indices, and those are not constant for modded RMBs. This problem is very difficult to fix properly, but an easy bandaid would be to simply "reposition" the player if the buildingKey in the save isn't found. That would prevent saves from getting corrupted, and it's already how DFU handles changed terrain shaders so there's a precedent.