CryoFall

CryoFall

28 ratings
How to create a mod (WIP)
By Djekke
CryoFall is a game with very high modding possibility. If you brave enough - you can walk a glorious way of a mod creator and your name will shine in our hearts for eternity! Or only for few minutes... but still shine :)
2
   
Award
Favorite
Favorited
Unfavorite
Modding prerequisites
There a great article about it in the game forum written by main developer ai_enabled:
http://forums.atomictorch.com/index.php?topic=1027.0

Here will be same steps that mentioned in article above, but with screenshots and more walkthrough.

  1. Install CryoFall Editor. (optional but highly recommended)
    You can develop mods by using Client or Server, but it's highly recommended to use CryoFall Editor as it including both Client and Server in a single executable (and some other awesome developer features as well).
    You can find it in your Library -> Tools.



  2. Prepare working directory
    It's highly recommended to use other game directory than main game folder.
    Locate installed game folder: Right click on CryoFall Editor (or CryoFall game client if you don't want to use Editor) in you Steam Library and select "Properties". There go to tab "Local files" and press button "Browse local files".
    .
    Copy it content to prepared folder excluding "steam" file.
    For example I use `D:\Projects\CryoFall\ModDevelopment`
    .
    You can see at screenshot above few bat scripts that I use to automatically update my working directory whenever new game version is released.

  3. Extract core mods
    Why we need it would be told in next section.
    You can use "Extract Core and Mods.cmd" to do it for you or do it manually.
    .

  4. Install Visual Studio 2019.
    This and other few steps are not mandatory and you can use any text editor for your needs, but if you want to create something big or complicated, then I am recommending you to use Visual Studio or other IDE for do it.

    In this and other sections I will use free community edition of Visual Studio as reference.
    Visual studio download page.[visualstudio.microsoft.com]
    Before installation, please ensure that you've checked ".NET Framework 4.7.2 targeting pack".

    If you already have VS2019 installed, please ensure launch Visual Studio Installer -> Modify -> Individual components -- and ensure that ".NET Framework 4.7.2 targeting pack" is checked.
    .
    .

  5. Download and install CryoFall Modding SDK extension for VS2019.
    You can download it from site[marketplace.visualstudio.com] or find it in Visual studio online extension list:
    .
    Note, that after extension installation you need to restart Visual Studio.

  6. Configure Visual Studio (optional but highly recommended)
    A few important notes:
    • XAML Designer is not supported
      Though it can work fine in most cases, but it's recommended to disable it (Visual Studio Options, XAML designer, uncheck "Enable XAML Designer").
    • If you want to debug your code with breakpoints:
      Go to Visual Studio Options, Debugging, uncheck "Require source files to exactly match the original version" (because the game includes C# compiler which performs some code-generation and so resulting C# files do not match the original C# files - but it's not a problem for step-by-step debugging as the C# code lines kept intact).
How mods works in this game
Here I gather some info from forum[forums.atomictorch.com], wiki and my own experience as mod creator.
  • The game IS a mod for the engine
    Essentially the game IS a mod for the engine. It uses available API to create the entire game.
    The entire Core.cpk package is a VisualStudio Project with EVERYTHING. It is completely open to the players. Every single game system is 100% open-source :)

  • Mods extension
    *.cpk for Core Package and *.mpk for Mod Package
    Basically, these files are just a regular .zip archive (with no compression) and they should contain files directly, not in an extra subfolder.
    The game could work fine with both archive Core.cpk file or unpacked Core.cpk folder — it will either create a virtual file system to access the files in the archive or use the real file system

  • Live re-compiling
    The CryoFall custom game engine (called Renkei) supports live reloading of C# & XAML code (as well as all the visual and audio assets) so it's not necessary to restart the game to observe the changes!

  • Mods interaction
    When a mod file (or several mod files) is loaded it will merge with the already loaded core files into a so-called "virtual file system". Even though the contents of the core and mod packages are stored separately, the game will treat them as one file system with shared paths. Now, what does that mean?

    As an example, let's say we have a CPK with a file located at "/content/some_file.txt" and an MPK with a file "/content/some_file.txt" that has the same path and name. What happens when we start the game? Since both files in the CPK and the MPK share the same path, the file stored in the MPK will override the one in the CPK since it was loaded after the CPK. This mechanism makes it possible to override the core functionality and content easily without recompiling the whole CPK or modifying its content. The same principle works not just with content files, but with assets, scripts, and any other type of files.

  • Virtual file system concepts
    • The core and all mods are loaded into one virtual file system, with an overwrite rule (See "File precedents and overloading" section above for explanation).
    • Mods can use each other's files, so don't hesitate to use original game resources in your mods.
    • MPK files are loaded in the order listed in ModsConfig.xml. If two MPK files have the same file (path+name), the file in the later MPK will be loaded.
    • File names are NOT case-sensitive. QWER.xml and qwer.xml are considered the same file!
Mod structure
Most important file: header.xml
It contains all essential information about mod:
<?xml version="1.0" encoding="utf-8"?> <root> <id>unique_mod_id</id> <title>Name of the mod</title> <author>Author name</author> <description>Brief description for the mod.</description> <version>1.0.0</version> <!-- current mod version --> <updated>01.01.2015</updated> <!-- last updated date --> <!-- Mod type: 1 - server, 2 - client-server, 3 - client --> <!-- Please note: mods of type 1 and 2 are ignored when you're connecting to the server which is missing them --> <modtype>2</modtype> </root>
All the elements are mandatory for a mod and must be properly specified.

Modtype
It is a special parameter which defines whether a mod should be loaded by a server, client, or both.
  • client
    For example, if we want to create a mod which just replaces some icons, that would be a typical client mod. Client-side mods will be ignored by servers if listed in ModsConfig.xml.
  • server
    On the other hand, mods that contains only server-side alterations, like spawn scripts are typical server mods. If they are listed in ModsConfig.xml, a server will load them but clients won't, and the server won't demand that the player have them in order to play.
    Again, clients do not need any server-side mods to connect.
  • client-server
    Lastly there is a client-server mod, which is needed on both client and server. If a server was created with a specific client-server mod and the client doesn't have the same one, the server won't let the client connect.

Location
The header file must be placed in the root of the MPK like so:
root --> header.xml --> Content/ --> Scripts/ --> UI/
The content and data folders are also on the same level.

Version Handling
The way the game treats mod files is actually a bit trickier. This is because you may have different versions of the same mod in your mods folder and since they share the same ID how would the game know which one to load?

When a mod is loaded, the version of the mod must be specified along with its ID. The full internal ID for a mod is [id]_[version]. For instance, the unique ID of this mod from the above example would be unique_mod_id_1.0.0.

To determine which mods the game should load, there's a file ModsConfig.xml (usually located in the user documents folder). All mods that should be loaded should be listed in this file.
Creating your first mod
So, you know everything you should know about mods for CryoFall?
Than let's try to make new mod.

  1. Open Visual Studio 2019

  2. Create new CryoFall Mod Project
    If you setup CryoFall Mod SDK right, than you should find new project template for CryoFall Mod




    • Enter name of your new mod
      Project name is your mod name.
      I named it "TestModPleaseIgnore" for educational purpose.
    • Select working directory 'Data/Mods' folder
      My working directory is 'C:\Projects\CryoFall\ModDevelopment'
      So, mod would go to 'C:\Projects\CryoFall\ModDevelopment\Data\Mods\'
    • Check "Place solution and project in the same directory" checkbox.
      (In VS2017 it was inverted checkbox. In VS2019 this checkbox name is more clear of what we need to achieve.)
    If all was set up correctly then you should see something like this:

    (There is some warnings in "Dependencies" section, it's fine, let's clear them now.)

  3. Switch project platform from "Debug_LibsAsProjects" to simple "Debug".

    After that - save project, close it and open again. (This will clear dependencies problems)

  4. Link Core mod to your project (optional but highly recommended)
    File -> Add -> Existing Project
    Select `AtomicTorch.CBND.CoreMod.csproj` located in Core/Core.cpk of your working directory.

    After doing so - you can notice that CoreMod project was added in Solution Explorer:


    .
  5. Add reference to CoreMod project
    Open Reference Manager window (there is few ways of doing so)
    (This screenshot from VS2017, in VS2019 it's "Add Project Reference...")
    .
    And check checkbox for CoreMod project.

    .
    Adding CoreMod to your project is QoL addition:
    • Visual Studio IntelliSense will help you with auto-complete of core game api.
    • You can easily look to core game code while working on your mod.
    • Using breakpoints on core game code for debugging purposes.

  6. Save changes

  7. Add your mod to game
    Go to your working directory's 'Data' folder and edit ModConfig.xml file with any text editor.
    For unpacked mods there a bit different entry in ModConfig.xml:
    <?xml version="1.0" encoding="utf-8" standalone="yes"?> <mods> <unpacked_mod> <mod_id>core_1.0.0</mod_id> <is_core_mod>1</is_core_mod> <path>Core/Core.cpk</path> </unpacked_mod> <unpacked_mod> <mod_id>editor_1.0.0</mod_id> <is_core_mod>0</is_core_mod> <path>Core/Editor.mpk</path> </unpacked_mod> <unpacked_mod> <mod_id>TestModPleaseIgnore_0.0.1</mod_id> <is_core_mod>0</is_core_mod> <path>Data/Mods/TestModPleaseIgnore</path> </unpacked_mod> </mods>
  8. Run game
    Run it directly from your working directory.
    `CryoFall Editor.exe` (or `CryoFall Client.exe` If you want to test it in proper environment)
  9. Is my mod are loaded at all?
    Our new fresh mod is absolutely useless and do absolutely nothing, so how to check if it loaded at all?
    The answer is simple: check logs!
    Go to 'Data\Logs' of your working directory and open latest 'Client_CryoFall_.....log'
    In the beginning there should be few lines:
    [IMP] Mods catalog initialized. Available files: core_1.0.0, editor_1.0.0, TestModPleaseIgnore_0.0.1 [IMP] Mods config location: "D:\Projects\CryoFall\ModDevelopment\Data\ModsConfig.xml" Active core/mods list: * core - ClientServer v1.0.0 (from folder "D:/Projects/CryoFall/ModDevelopment/Core/Core.cpk") * editor - ClientServer v1.0.0 (from folder "D:/Projects/CryoFall/ModDevelopment/Core/Editor.mpk") * TestModPleaseIgnore - ClientServer v0.0.1 (from folder "D:/Projects/CryoFall/ModDevelopment/Data/Mods/TestModPleaseIgnore") [IMP] Real file system initialized successfully: Core mod: Core Mods list: * Editor * TestModPleaseIgnore
    First line: Show all available mods.
    Second line: Show result of 'ModsConfig.xml' parsing.
    Third line: Show which mods loaded successfully.

  10. Prepare mod for distribution
    After all the necessary work on your mod is done, it's time to prepare it to distribution to the world.
    We need to pack it to *.mpk as all other mods do.
    As was said previously - mpk is just an zip-archive without compression.
    You can use any suitable tool to do so, just don't forget to add all necessary things inside.
    (header.xml, license.txt and all your work)

    For WinRaR:


    For 7-Zip:


    Change format to "ZIP", compression method to "Store" and resulting file extension to ".mpk"
Making something useful
There a few different ways of modding:

  • Altering existing code
  • Expanding content
  • Making something completely new

More about it is in sections below.
- Altering existing code
If you want just to adjust some numbers or make some small changes for original code: you need to copy existed CoreMod file, put it in your mod in corresponding folder (following folder hierarchy in CoreMod) and make some changes there.
After your mod loads to the game, it replaces this file in game virtual file system and game will use it as original.
Examples:
  • To adjust the game LP rate (gained via skills activity) you need to make a copy of '/Scripts/Technologies/Base/TechConstants.cs' and altered constant SkillExperienceMultiplier. (Please note that it is server-side changes)
  • If you want to extend the lifespan of the buildings built by players (for example, if you want to play on your server rarely and don't want to see your base destroyed after the login a few days later) than you are looking for this file 'Scripts/StaticObjects/Structures/Base/StructureConstants.cs' constant StructureDecayDelaySeconds defining the duration in seconds after which the structure decay will kick-in if the player is not visiting the base longer than the defined duration. (Please note that it is server-side changes)
  • If you want to alter some icons - all you need to do is find existing item icon in Content folder of CoreMod, and create a new one with same name and path in your mod's folder. (it's a pure client mod) Also, please note, that for some icons to determine theirs attach point are used a magenta pixel.
- Expanding content
Adding new items, buildings, mobs or other game object are related to this.
(Please note, that it is client-server mod type)

For example we want to add new Ammo for sniper rifle with uranium core:

  1. Find existing object of that type in CoreMod files.
    Let's take as example an incendiary ammo for sniper rifle 'Scripts\Items\Ammo\ItemAmmo300Incendiary.cs'
  2. Copy it to your mod with new name
    Let's name it 'ItemAmmo300Uranium' and save it to our mod:
    'Scripts\Items\Ammo\ItemAmmo300Uranium.cs'
  3. Alter some parameters
    For example add radiation poisoning, slightly increase range and armor piercing:
    namespace AtomicTorch.CBND.CoreMod.Items.Ammo { using AtomicTorch.CBND.CoreMod.CharacterStatusEffects; using AtomicTorch.CBND.CoreMod.CharacterStatusEffects.Debuffs; using AtomicTorch.CBND.GameApi.Data.Characters; using AtomicTorch.CBND.GameApi.Data.Weapons; using AtomicTorch.GameEngine.Common.Helpers; public class ItemAmmo300Uranium : ProtoItemAmmo, IAmmoCaliber300 { public override string Description => "Heavy anti-material .300 round with uranium core."; public override string Name => ".300 uranium ammo"; public override void ServerOnCharacterHit(ICharacter damagedCharacter, double damage) { // 40% chance to add bleeding if (RandomHelper.RollWithProbability(0.40)) { damagedCharacter.ServerAddStatusEffect<StatusEffectBleeding>(intensity: 0.05); // 30 seconds } // Add radiation poisoning instead of heat damagedCharacter.ServerAddStatusEffect<StatusEffectRadiationPoisoning>(intensity: 0.25); } protected override void PrepareDamageDescription( out double damageValue, out double armorPiercingCoef, out double finalDamageMultiplier, out double rangeMax, DamageDistribution damageDistribution) { damageValue = 35; // very high armor piercing armorPiercingCoef = 0.8; finalDamageMultiplier = 1.5; // more range for rounds with uranium core rangeMax = 15; // only kinetic damage on impact damageDistribution.Set(DamageType.Kinetic, 1.0); } } }
    Now we have new ammo type in code, what we a missing? Right, icon.
  4. Add icon
    Add images to Content folder of your mod with corresponding folder and exact same name as new object
    For our ammo it would be 'Content\Textures\Items\Ammo\ItemAmmo300Uranium.png'

    We are successfully added new ammo to the game, but wait where it is?
    We forgot to add recipe for it.

    Btw, I suggest for your to use CNEI mod, that can show all entity in a game.
  5. Add recipe for items
    For our new ammo it should be something like this:
    'Scripts\CraftRecipes\StationCrafting\WeaponWorkbench\RecipeAmmo300Uranium.cs'
    namespace AtomicTorch.CBND.CoreMod.CraftRecipes { using System; using AtomicTorch.CBND.CoreMod.Items.Ammo; using AtomicTorch.CBND.CoreMod.Items.Generic; using AtomicTorch.CBND.CoreMod.StaticObjects.Structures.CraftingStations; using AtomicTorch.CBND.CoreMod.Systems; using AtomicTorch.CBND.CoreMod.Systems.Crafting; public class RecipeAmmo300Uranium : Recipe.RecipeForStationCrafting { protected override void SetupRecipe( StationsList stations, out TimeSpan duration, InputItems inputItems, OutputItems outputItems) { stations.Add<ObjectWeaponWorkbench>(); duration = CraftingDuration.Medium; inputItems.Add<ItemIngotSteel>(count: 5); inputItems.Add<ItemIngotCopper>(count: 5); inputItems.Add<ItemFormulatedGunpowder>(count: 30); inputItems.Add<ItemComponentsIndustrialChemicals>(count: 5); outputItems.Add<ItemAmmo300Uranium>(count: 10); } } }
    I use old recipe for incendiary ammo, as we don't add uranium yet :D (You can do it on your own, because it's just an example)


  6. Add new technology node (or alter existed one)
    Now recipe is set, but it's not shown in workbench yet, because we need to unlock it with corresponding technology.
    Let's add new technology node for our new ammo right after incendiary ammo
    'Scripts\Technologies\Tier4\Offense4\TechNodeAmmo300Uranium.cs'
    namespace AtomicTorch.CBND.CoreMod.Technologies.Tier4.Offense4 { using AtomicTorch.CBND.CoreMod.CraftRecipes; public class TechNodeAmmo300Uranium : TechNode<TechGroupOffense4> { protected override void PrepareTechNode(Config config) { config.Effects .AddRecipe<RecipeAmmo300Uranium>(); config.SetRequiredNode<TechNodeAmmo300Incendiary>(); } } }

    Congratulation to us, we made something useful (or not).
    This is resulting project tree of our work:

- Making something completely new (WIP)
This is the hardest part of modding (adding new gui, new systems or other various things).

You can look into existed mods and learn the ways of how they work or investigate CoreMod game code to figure it by yourself.

Some explanation of different script types and their usage.
  • ClientComponents, Systems and Triggers.
    This kind of scripts executes every frame (or on some small time interval).
    • ClientComponents - executes only on client.
      (Things related to gui, various helpers and other client related stuff)
    • Systems - executes on client and server, main way of client-server interaction.
      (Client tell server to run server variant of function on it's side)
    • Triggers - executes only on server.
      (Various spawn scripts and other things)
  • Bootstrappers.
    This kind of scripts are executes on game start.
    You can specify order of it using:
    [PrepareOrder(afterType: typeof(BootstrapperClientCore))]
    Also in BootstrapperClientGame there is few event callbacks that you can use on game init and reset. (it's actual game load after you choose server to connect)
  • Adding hotkeys
    There is few things you need to do to make it work:
    • Add new button enum
      Something like that:
      [NotPersistent] // Prevent this enum to be a part of network serialization. public enum MyNewButtons { [Description("Do almost nothing")] [ButtonInfo(InputKey.J, Category = "My new amazing mod")] DoNothing, }
    • Register new button enum on game startup.
      Add new bootstrapper for your mod and add lines
      public override void ClientInitialize() { ClientInputManager.RegisterButtonsEnum<MyNewButtons>(); }
      there MyNewButtons is a name of your button enum.
    • Assign actions to your new hotkeys
      Start new input context in ClientInputContext to handle button actions.
      (You can add it on game startup, game load or on some specific action)
      gameplayInputContext = ClientInputContext .Start("My amazing mod input context") .HandleButtonDown(MyNewButtons.DoNothing, MyFunctionThatDoNothing());
      If you want to disable buttons from using - just stop related input context.
      gameplayInputContext?.Stop(); gameplayInputContext = null;
  • Adding options
    Main game settings menu are made by procedural generation.
    It's assemble all categories and options based on existed scripts of ProtoOptionCategory and ProtoOption types.
  • Local settings storage
    Local settings are stored in 'Data/ClientStorage' folder.
    To load or save storage you need to use followed Api:
    settingsStorage = Api.Client.Storage.GetStorage("Mods/YourMod.Settings");
    (You can use any name you want, but to avoid conflicts I suggest using 'Mods/UnicModID' as base)
    You need to register all custom types you want to storage there
    settingsStorage.RegisterType(typeof(MyCustomType));
    After that you can try to load settings from local storage
    settingsStorage.TryLoad(out settingsInstance)
    Do not forget to create new settings if none already existed and version mismatch cases.
    To save settings use this:
    settingsStorage.Save(settingsInstance);
  • ...
Troubleshooting (WIP)
  • I'm starting Editor\Client from my dev directory, but it instantly closed and run one from steam instead.
    It happens because of steam file with no extension in your dev folder that you copy from steam game folder. Just delete this file (in your dev folder) and all should be fine.
11 Comments
ai_enabled  [developer] Jul 19, 2021 @ 5:41am 
@Revenant, you can find the primary map in Content/Maps folder after unpacking Core.cpk.
Ɽevenant Jul 18, 2021 @ 10:16am 
@ Djekke Are you still active with this? I have a question, I have the editor downloaded in my launcher and I am curious if you have done any custom maps. I would like to make my own. Is the base game map in the SDK files? I looked through The 2 Directories ie: Steam\Common and Apdata folders and can't seem to find the map file.
Yurii M. Jan 27, 2021 @ 1:47pm 
Super cool! Thank you
Djekke  [author] Dec 4, 2020 @ 7:41pm 
I updated guide for VS2019 and add screenshots for MPK packing settings.
If I missed something or there is other points that I should clarify more - I open to any suggestions.
ai_enabled  [developer] Dec 4, 2020 @ 7:25pm 
Hi @Morgus. Here is a screenshot of the MPK packing settings with 7-Zip: https://atomictorch.com/Files/Images/CryoFall_Modding_MPK_Packing.jpg (I hope @Djekke will update the guide as he is the guide owner)
Morgus Dec 3, 2020 @ 12:38pm 
Hi there AI we all miss you on the Discord server, and I think that this guide should contain some screenshots of how to make a zip-archive without compression, it might be rather confusing for newbies.
ai_enabled  [developer] Dec 2, 2020 @ 10:35am 
This step is no longer correct for VS2019:
> Uncheck "Create directory for solution" checkbox.
The correct step is:
Check "Place solution and project in the same directory"
See screenshot https://atomictorch.com/Files/Images/CryoFall_Modding_VS2019_NewProject.png
Discussion here https://forums.atomictorch.com/index.php?topic=1813.msg9206#msg9206
Kastuk Feb 9, 2020 @ 1:31am 
*Notepad++ for code highlighting.
Djekke  [author] May 28, 2019 @ 3:49am 
Sure, you can do it notepad for cases when you just adjust some numbers, but if you want to create new content - with the Visual Studio it would be much easier.
Mcloutier87 Apr 28, 2019 @ 5:34pm 
you know you can just use notepad or any word doc lol