Difference between revisions of "Modding: Versioning"
m (→First golden rule) |
(→Dialogs: Added extra remarks) |
||
(3 intermediate revisions by the same user not shown) | |||
Line 70: | Line 70: | ||
= Changes that are never safe = | = Changes that are never safe = | ||
− | * Anything that makes previously accessible AI-grid non-accessible (a player may have been standing in that place) | + | * Regenerating the AI-grid: this might change the size of AI-grid, which will break savegames. |
+ | ** Anything that makes previously accessible AI-grid non-accessible (a player may have been standing in that place) | ||
* Changing a root template of an object from a dynamic item (orange cube icon) to a static item (blue cube item) | * Changing a root template of an object from a dynamic item (orange cube icon) to a static item (blue cube item) | ||
* Do not turn off: CanBeMoved (player may have put this item in a way that now blocks a passage, or have it in their inventory) | * Do not turn off: CanBeMoved (player may have put this item in a way that now blocks a passage, or have it in their inventory) | ||
Line 76: | Line 77: | ||
* Do not change: Local/Global property. | * Do not change: Local/Global property. | ||
* Do not remove: Scripts and script vars that have already been assigned | * Do not remove: Scripts and script vars that have already been assigned | ||
+ | * Do not delete Osiris/story files: story patching does not support removing files. You can however remove all rules from an existing story file by keeping it, but removing all of its contents. See also [[#Story/Osiris|Story Patching]]. | ||
= Issues related to specific resources = | = Issues related to specific resources = | ||
Line 90: | Line 92: | ||
== Dialogs == | == Dialogs == | ||
− | + | Safe changes | |
+ | * Adding new nodes | ||
+ | * Adding new node connections | ||
+ | * Setting extra flags | ||
+ | |||
+ | Changes that are never safe: | ||
+ | * Removing nodes (a player could have saved while they were in this node) | ||
+ | |||
+ | Other things to be careful about: | ||
+ | * Changing flag checks on nodes. A player could have saved right before the node(s) you're changing and might not have valid nodes anymore after your changes (because the checked flags are set in earlier nodes only in the new version of the dialog). This will force close the dialog for the player in such cases. | ||
+ | * Changing dialog structure (remove/change existing node connections). Always make sure that a user that saved during the dialog has a way out. | ||
== Behaviour scripts == | == Behaviour scripts == | ||
Line 160: | Line 172: | ||
==== Second version of your mod ==== | ==== Second version of your mod ==== | ||
− | You realise that the skeleton is currently allied to all players, and you would rather have it neutral. So you change the alignment in the sidebar to ''Neutral NPC''. Unfortunately, that won't change its alignment in existing | + | You realise that the skeleton is currently allied to all players, and you would rather have it neutral. So you change the alignment in the sidebar to ''Neutral NPC''. Unfortunately, that won't change its alignment in existing savegames. Additionally, you forgot to add the dialog for a second skeleton that was also already in the game. Similarly as with the alignment, defining another [[Osiris/Shared/DB_Dialogs|DB_Dialogs]] in the init section of the goal will only define that dialog for new games. |
Luckily, you can take advantage of story patching to ensure your changes also become available to existing savegames: | Luckily, you can take advantage of story patching to ensure your changes also become available to existing savegames: |
Latest revision as of 13:50, 23 April 2018
Contents
- 1 Overview
- 2 First golden rule
- 3 Second golden rule
- 4 Third golden rule
- 5 Changes visible in existing savegames
- 6 Changes only visible in new games
- 7 Changes that are never safe
- 8 Issues related to specific resources
Overview
It is possible to release new versions of a mod that work both for existing savegames, that use an older version of the mod, and for new games. However, keeping savegame compatibility requires that you are careful regarding what and how you change things.
First golden rule
Never remove anything from your mod: root template, material, script, locals, lsb files, entries in lsb files, stats, etc. You can only add or modify certain things.
You can, however, use tricks to "remove" objects: set items/characters off-stage, or move them to inaccessible locations. Keep in mind that if the items can be be picked up, they may already be in a player's inventory and they most likely will not appreciate suddenly losing them.
Second golden rule
Only change things explicitly mentioned here as changeable.
Third golden rule
Test your changes with old savegames, to at least verify your change doesn't crash. Think about how your change can affect a play-through or savegame, and let someone think along with you.
Changes visible in existing savegames
- Stat properties. Take into account that properties will change for existing objects as well.
- Treasure tables
- SkillData
- Root template/item OnUse/OnDeath actions
- You can change Tags of roots and objects. Be careful when removing existing Tags from them.
- Materials
- Textures
- GR2s
- Effects
- Animations / Action templates
- Physics
- AI grid
- Minimaps
- Atmospheres (take into account that Osiris can change the atmosphere though)
- Icons
- Sound files
- Voice types
- Instances (grass etc...)
- Terrain
- Item combinations
- Camera triggers
- Walls
- Decals
- Lights
- Lightprobes
- Camera splines
- Vision Grid
- AllSpark effects
- Objects which are tagged as “Scenery” can change all their properties
- Create new levels
- Crime reactions can be changed or modified, but not the properties of the crime itself.
- You can add a new tag in the tag editor, but you cannot remove tags there
- Newly defined alignments and alignment entities in the alignment editor (never delete any!)
Changes only visible in new games
Everything that is stored in the savegames can of course not be changed for existing games (for characters / items / triggers). In short these are things like:
- Position, rotation, scale
- IsBoss
- DefaultDialog
- IsTrader
- AnimationOverride
- Root template
- Alignment
- Stats object
- Inventory
- Skillset
- Character / item variables
- IsKey
- Key
- LockLevel
- Dynamic Tags of objects
- Most crime properties (lifetime, continuous, audible, etc)
- You can add/remove a skill to a creature and change the conditions on it.
- Changes to alignment relations in the alignment editor
Changes that are never safe
- Regenerating the AI-grid: this might change the size of AI-grid, which will break savegames.
- Anything that makes previously accessible AI-grid non-accessible (a player may have been standing in that place)
- Changing a root template of an object from a dynamic item (orange cube icon) to a static item (blue cube item)
- Do not turn off: CanBeMoved (player may have put this item in a way that now blocks a passage, or have it in their inventory)
- Do not turn off: CanBePickedUp (idem)
- Do not change: Local/Global property.
- Do not remove: Scripts and script vars that have already been assigned
- Do not delete Osiris/story files: story patching does not support removing files. You can however remove all rules from an existing story file by keeping it, but removing all of its contents. See also Story Patching.
Stats
- Never delete a stat.
- Never delete a delta-modifier.
- Never delete a skill.
- You can change stats.
- Runes, however, are already applied and have been saved to the item.
Objects/root template instances
The root template rules are also valid for LOCAL characters, items and triggers (except for atmosphere triggers), since these objects are stored in a special savegame (the levelcache) as soon as a player enters a certain region. For scenery all properties can still be changed, since these are not saved. However, never change an object from scenery to non-scenery or vice-versa.
Dialogs
Safe changes
- Adding new nodes
- Adding new node connections
- Setting extra flags
Changes that are never safe:
- Removing nodes (a player could have saved while they were in this node)
Other things to be careful about:
- Changing flag checks on nodes. A player could have saved right before the node(s) you're changing and might not have valid nodes anymore after your changes (because the checked flags are set in earlier nodes only in the new version of the dialog). This will force close the dialog for the player in such cases.
- Changing dialog structure (remove/change existing node connections). Always make sure that a user that saved during the dialog has a way out.
Behaviour scripts
Behaviour scripts are loaded from their textual form whenever the game starts. This means that any changes to behaviour scripts will automatically apply to savegames that were started with older versions of those scripts. There are, however, a number of things to take into account.
Variables
The following holds both for global and local variables:
- New variables added to an existing behaviour script are added to existing characters that had this script assigned, and will get the default (null/0/empty value).
- Removing a variable merely makes this variable no longer accessible in existing savegames; it does not remove it. It will not be present in new games though.
- Do not change the type of a variable.
Reactions
Whenever a reaction is interrupted (such as when saving the game), the game will store the instruction pointer (~ line) in that reaction. This pointer is relative to the start of the reaction. The next time this reaction resumes, it will resume from this saved instruction pointer location.
If you add or remove lines to/from a reaction, the instruction pointer stored in a savegame may now point to a different instruction. If it now points past the last line of the reaction, it will be reset to point to the start of the reaction again.
Do not completely remove reactions. If a savegame was in the middle of a reaction that was removed from the game, the result is undefined behaviour (including possibly crashes, depending on the game version).
Events
Events are executed entirely in one gameplay tick. This means that a savegame can never be in the middle of an event, and changing, removing and adding events can be done at will.
Story/Osiris
It is impossible to save while in the middle of an Osiris rule/condition/action. In this sense, story code behaves like events in behaviour scripts: in principle, it is safe to change anything. However, unlike behaviour scripts, the compiled story is stored in a savegame. This means that upon loading the savegame again, potential changes to the story code in the used mods will not be picked up by default.
That said, Osiris has a feature called "story patching". This feature can be used to update the savegame's compiled story to a new version.
What is story patching
Story patching replaces the existing story rules with new rules while keeping the current story state:
- All database facts in the savegame are extracted/dumped
- The story rules of the savegame story are replaced with the story rules of the new version of the mod(s)
- The previously dumped database fact are reimported (without triggering any rules that depend on them)
- All goals that were active/initialised in the savegame story, are again marked as active (based on goal name, regardless of their location in the hierarchy). Similarly, completed goals are again marked as completed.
- If new goals were added to the mod and these new goals are either top-level goals or subgoals of goals that were completed in the savegame, then these new goals will be initialised at this point.
- Other newly added goals will not be initialised unless their (potentially also new) parent goal completes
When does story patching activate
Every mod has a version. You can set this version in the Project menu -> Project Settings... -> General tab in the editor while your mod is loaded. When the version of the installed mod is higher than the version of the mod in the savegame, the game performs story patching.
Hooking into story patching
In most cases, you will also want to manually fix up certain things in savegames apart from what gets done automatically by the story patching. The most common one is if you change the INIT section of a goal: since that INIT section will not be executed again if the goal was already active in a savegame, you need a way to perform those actions for existing savegames. Another common case is setting certain flags that should have been set under certain conditions, but were not for one reason or another.
In order to perform such changes, you need two things:
- an event to catch at which point you perform your changes
- a way to check the version of the savegame, to know which changes you have to perform at that point
The event to use is SavegameLoaded. It gets thrown whenever a savegame gets loaded. Unfortunately, the version number it gets passed is the version of the game binary and unrelated to your mod. As a result, you cannot use this to determine the version of your mod that was used in that savegame.
Therefore, to perform savegame versioning, you should define a unique version database fact that you check in the SavegameLoaded event to determine whether or not anything needs to be patched.
Example
First version of your mod
You have a skeleton with the Good NPC alignment. Additionally, you also have a story goal with the following contents:
INIT { DB_Dialogs(CHARACTERGUID_MyPrefix_Skeleton1_UUID,"SkellyDialog"); // Version that we will use to check what changes we need to apply to savegames DB_MyPrefix_ModVersion(1); } KB { } EXIT { }
Second version of your mod
You realise that the skeleton is currently allied to all players, and you would rather have it neutral. So you change the alignment in the sidebar to Neutral NPC. Unfortunately, that won't change its alignment in existing savegames. Additionally, you forgot to add the dialog for a second skeleton that was also already in the game. Similarly as with the alignment, defining another DB_Dialogs in the init section of the goal will only define that dialog for new games.
Luckily, you can take advantage of story patching to ensure your changes also become available to existing savegames:
- increase the version number of your mod so story patching gets activated for existing savegames
- modify your story goal as follows:
INIT { DB_Dialogs(CHARACTERGUID_MyPrefix_Skeleton1_UUID, "SkellyDialog"); // Only gets added for new games DB_Dialogs(CHARACTERGUID_MyPrefix_Skeleton2_UUID, "SecondSkellyDialog"); // Only new games will get this version DB_MyPrefix_ModVersion(2); } KB { // We don't care about the game binary's version number IF SavegameLoaded(_,_,_,_) AND DB_MyPrefix_ModVersion(_Version) AND _Version < 2 THEN // Update version number so this patching does not happen every time NOT DB_MyPrefix_ModVersion(_Version); DB_MyPrefix_ModVersion(2); // Add the extra DB_Dialogs entry DB_Dialogs(CHARACTERGUID_MyPrefix_Skeleton2_UUID, "SecondSkellyDialog"); } // Fix the alignment of the skeleton SetFaction(CHARACTERGUID_MyPrefix_Skeleton1_UUID, "Neutral NPC"); EXIT { }