Skip to content

Conversation

@esbudylin
Copy link
Contributor

This is my take on the idea of a modular mod system that we discussed a few months ago in Discord. The goal of this PR is to lay the foundation for a OpenCiv3 scenario format, and to allow scenario definitions to be modularized into several files.

Game generation

This PR introduces a new class, GameModeLoader, that implements the logic for loading the new scenario format. The process for loading a scenario consists of several steps:

  1. The game loads the "base" file of a scenario. This can be either a JSON file or a Lua script that returns a table. The format of the data is the same as we use for save files.

  2. The game passes the data to a pipeline of Lua functions loaded from separate scripts. Each of the functions accepts the data as a Lua table, modifies and returns it. The resulting table is passed to the next function in the pipeline.

  3. The final table is converted to JSON and deserialized as SaveGame.

As before, the final game generation is handled by GameSetup class, which generates map and places players on it if the scenario doesn't specify this data.

Basic and standalone modes

This PR uses this new system to redefine the basic and the standalone modes. Previously, these two modes were defined in two separate JSON files. The difference in the "standalone" save was that it excluded the units we didn't have graphics for and updated art names for other units.

With the new system, both modes share the same JSON save as their base, while the logic for replacing the units in standalone mode is defined procedurally in Lua! And, besides being a good example of the new system, it also removes the burden of maintaining two almost identical JSON files :)

Right now, there is no way to define new modes without changing the C# source. However, if we settle on the system, we can easily implement some config or even GUI for defining new modes by selecting a base file and its addons.

Other changes

This PR reorganizes the C7Engine classes related to Lua into a new sub-namespace: C7Engine.Lua.

There is also a new class, JsonConverter, which is used to convert data between Lua tables and JSON objects. This class was written by an LLM. Before going with it, I tried the converter built-in in the Moonsharp (it had bugs that made it unusable), and pure Lua libraries - dkjson and lunajson (they worked too slow under Moonsharp runtime).

There is also a new extension class, ScriptExtensions, for MoonSharp Script class. The goal of new extension methods is to provide logging for errors in Lua code, making debugging more straightforward.

@esbudylin esbudylin added prototype A prototype of something modding related to scenario data or mod api Lua anything relating to Lua labels Jan 5, 2026
Copy link
Contributor

@TomWerner TomWerner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I skimmed through this pretty quick and it seems reasonable to me.

@@ -0,0 +1,54 @@
local unit_replacement_art_map = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you leave a comment explaining the purpose of this, and how the new strings correspond to folders in the art directory?

["Curragh"] = "MinoanGalley",
}

return function(civ3_game_mode)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this will the example people look at when creating new versions of these Lua files, could you leave some documentation about what this function is/does/etc?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Lua anything relating to Lua modding related to scenario data or mod api prototype A prototype of something

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants