Modding:General Best Practices
![]() |
This page is about modding. See the modding overview for an abstract on modding. |
![]() |
This article may need cleanup to meet quality standards.
Please help improve this page by editing it. Reason: "This article should be merged into Modding:Overview as well as the main articles for each section." |
Please help improve this page by editing it.
Reason: "This article should be merged into Modding:Overview as well as the main articles for each section."
Please help improve this page by editing it.
Reason: "This article should be merged into Modding:Overview as well as the main articles for each section."
Prefixing
Prefix your object and table names with some unique ID.
For instance, alphabeardmods_{id}
. This will prevent namespace conflicts with official content and other mods in the future.
<?xml version="1.0" encoding="utf-8"?>
<objects>
<object Name="ALPHABEARDMODS_CoolNewSword" Load="Merge">
...
</object>
</objects>
Merging
Only include your content and the minimum changeset via Load="Merge"
in tables and object definitions.
Don't copy the whole contents of the game xml. You only need to include new content.
For objects and population tables, if you're editing an existing item you can use Load="Merge"
in it's tag and only specify new items. For example, if I wanted my mod to give chain mail a 2DV:
<?xml version="1.0" encoding="utf-8"?>
<objects>
<object Name="Chain Mail" Load="Merge">
<part Name="Armor" DV="2" />
</object>
</objects>
ObjectBlueprint Definitions
In general, unless you're defining a unique object, make sure you add the xml attribute Load="Merge"
(and avoid including the Inherits
attribute) to prevent breaking behavior.
Random Functions
To avoid conflicts and to keep consistency between seeds, Stat.Random() and Stat.Rnd() should not be called. The ideal is to use GetSeededRandomGenerator() for your mod's randomness. The next best is calling RandomCosmetic() or Rnd2().
Stats
Prefer using value
over sValue
, unless you're creating a unique creature. When loading ObjectBlueprints, the code loads both sValue
and value
into a stat, then if sValue
is set, prefers using that to set a stat over value
.
Named arguments
Save migration
When writing scripting mods, you should prefer using IScribedPart
, IScribedEffect
, and IScribedSystem
over IPart
, Effect
, and IGameSystem
, respectively. These will allow you to migrate between saves more easily when you need to add or remove fields from a class.
In cases where you can't directly inherit from one of these classes (e.g. when you need to use IActivePart
for its functionality), you can turn a component into a "scribed" version by implementing its Read
and Write
methods as follows:
public override void Write(GameObject Basis, SerializationWriter Writer)
{
Writer.WriteNamedFields(this, GetType());
}
public override void Read(GameObject Basis, SerializationReader Reader)
{
Reader.ReadNamedFields(this, GetType());
}
The IScribed*
have some performance implications you should be aware of that are relevant to certain mods; see the serialization article for more details.
Harmony Patches
Harmony Patches are an advanced technique for code injection/modification. It allows modding parts of the game that are not normally accessible via the normal part and event systems exposed to modders. Harmony patching is recommended only for modders with advanced coding experience. For some advice about when and when not to use Harmony, see Harmony Modding.
|