HighFleet

HighFleet

34 ratings
The Ultimate HighFleet Modding Guide [23.11.2023]
By Dwang Zhongson
Everything you need to know before diving into modding the game.
3
3
   
Award
Favorite
Favorited
Unfavorite
Intro
Ever wanted to make this garbage gun more useful? Something seems to be too OP for you? Want to build an invulnerable meme machine? Or planning a big and serious rebalance mod? This guide is here to help you.

Do not forget to check my Total Rebalance mod (1.151):Nexus[www.nexusmods.com]


Disclaimer: the guide is not complete (and probably never will be), so sections may be either too brief or miss completely. However, it covers all the basic material and should enable you to discover new modding approaches on your own. Enjoy!

History:
01.03.2022: Initial version;
24.07.2022: Major edit, updated mod tools, updated save files section, added levels section;
25.07.2022: Updated save files section (spawning new SGs);
05.04.2023: Updated GH links in the Modding Tools section.
22.11.2023: Greatly expanded the Save Editing section (cities, inventories, tarkhans, ship perks, other additions); OL.seria and parts.seria section updates; spelling.
23.11.2023: Updated the Modding Tools section, new ModLoader section.

The game versions considered are 1.151 and 1.163.
.seria Structure
Save files, ships and part configs share the common format and are stored in .seria files. Getting familiar with their structure is the first thing you should to know before taking on modifying values or adding new entries, since it will keep you from fixing the annoying syntax errors.

A .seria consists of nodes, each of which which is enclosed by {...} parentheses. Parentheses always exclusively occupy a new line, there is nothing else on it. All nodes except the root also have a header—some attribute-value pair, where a value is typically some integer. A header value should not be unique and is meaningless on its own.

An example of a non-root node (contents replaced by "..."):

m_stats=2051 { ... }

Node contents may be a combination of the following:
  • An attribute-value pair
    m_children=15 { ... m_classname=Body ... }
  • A nested node
    m_children=15 { ... m_mesh=1073741827 { ... } }
  • (Only for mesh nodes) A sequence of floats
    { m_classname=Mesh m_size=4 -3.53553 5.32097 -3.53553 -5.32097 3.53553 -5.32097 3.53553 5.32098 }
See the Libraries/parts.seria section for more info on meshes.

Attribute-value pairs may repeat:
m_children=15 { ... m_sectors=1 m_sectors=1 m_sectors=1 m_sectors=1 m_sectors=1 m_sectors=1 #360 "m_sectors" entries in total ... }

That's how the game handles arrays. For example, the 360 "m_sectors" entries denote a firing or a sensor arc in a ship file, one for each degree.

If you want to parse/edit .seria,
DO NOT
EVER
INDENT
—this will break a file.

Armed with this knowledge, now you should be able to parse a .seria file, modify it and write it back so it remains valid. Also note that the syntax structure is quite similar to C++, so it's convenient to use C++ parsers for syntax highlighting and collapsing.
OL.seria
The Libraries/OL.seria is the first of the two config file related to parts. It stores parameters which don' require keeping their states in a save file, so you can tweak them and changes will apply immediately after relaunch, even within an ongoing campaign. It also contains the particularly interesting attribute which encodes the part category, which is discussed in details at the end of the section.

Luckily, the parameters belong to ones you are most likely to tweak—clip size, reload speed, cost, fuel amount, thrust/consumption and many more.

The structure is very simple—each part got a
m_stats=2051 { ... }
entry without nested nodes. The incomplete list of interesting entries is:

Global
m_oid
Internal module name. It's recommended to learn them for modules you want to tweak.
m_price
Price in gold. Despite being written in a save file, ship cost is being always recomputed on restart, so you're free to modify the param. (Salty Sis' 4U) Note that if you set parts cost to zero so a ship also costs nothing, it won't be displayed on the fleet pick screen.
m_repair_cost
Total repair time, units unknown.
m_icon_name
Thumbnail name. Thumbnails are registered in Media/Tex/Static*.res
m_mdl_crew
Crew requirements.
m_mdl_power_need
Power requirements in kW.
m_mdl_ammobox_need
Ammo requirements. Float values like 0.5 are also valid, though they will be displayed truncated.
m_resources
Stackable attribute indicating how many "resources" it's needed to construct a structure element (hull/deck/armor). See the ModLoader section for more details on such parts.
Guns
m_weapon_load_amount
Weapon ammo clip.
m_weapon_load_time
Clip reload time in 4/7 seconds (~0.571s).
m_weapon_rate
Clip unload speed, RPM.
m_weapon_caliber
Weapon caliber index. Shell speed, damage and special ammo used are tied to a particular value. See the ModLoader section for more details on how to modify the shell stats.
m_mdl_rotation
Turret rotation speed.
m_weapon_priority
If a ship has multiple different calibers installed, the guns with the lowest stat will be set as auxiliary. Note that ground units can fire only guns with priority 100 (AK-725) or lower.
Missiles
m_missile_explosive
Tactical/arcade missile explosive charge.
m_missile_ap
How well damage "phases" through armor.
m_launched_health
Missile health after launch.
m_launched_range
Range of an aircraft/tactical/arcade missile. For strategic assets it's measured in km.
m_launched_speed
Global map speed for aircraft/tactical/arcade(sic!) missiles in m/s.
m_launched_speed2
Arcade speed for aircraft/tactical/arcade missiles (seems to be km/h).

m_category
This subsection is based on the A220 Man, Cruiser Fodder post in the unofficial Discord[discord.com].

m_category is a 32bit integer attribute where each bit is responsible for providing the part with a particular logic. The table is given below
1-4
Unused
5
Strategic launch
6
Deck
7
APS
8
Game Engine (Rescues) (?)
9
Flares
10
Jammer
11
Bomb logic (MMB drop)
12
IR detection
13
Unknown. Enables fire arc calculations, elevation and alters it by -1 (?)
14
Unknown/unused
15
Railing deco (?)
16
ELINT/Radar (?)
17
Anti-Radiation Homing (?)
18
Arcade launch (missile)
19
Leg
20
Cargo (?)
21
Crew/generator (causes % popups) (?)
22
Aircraft
23
Destiller (? Hammerfight leftovers)
24
Engine
25
Hull
26
MDL_BLOCK (?)
27
Gun (enables elevation and alters it by +1)
28
Ammo
29
Escape pods (jettison on T)
30
FSS
31
Armor
32
Fuel
parts.seria
The Libraries/parts.seria file is another of the two part-related files. It describes:
  • Auxiliary fields such as part type and logic
  • Sprites
  • Meshes
  • State variables (current and max HP, amount, fuel (in addition to fuel entries in OL.seria)...)
  • Joints
These are being written in a ship/save file—technically, a config entry is being cloned with minor changes addressing the part usage. This implies that anything you tweak in the parts.seria will not transfer into already existing ship files and saves. Only parts freshly picked and installed in the shipworks will have new stats.

However, there is a way to update already existing ship .seria's to new values—see the Modding tools section.

The structure of the file is multi-level:
{ ... #Root node tech stuff m_children=15 #An example entry; there are lots of entries like this { attribute_one=value_one attribute_two=value_two ... m_mesh=1073741827 #Entries contain a single mesh node... { ... } attribute_three=value_three ... m_sprites=536870915 #...and one/multiple sprite nodes... { ... } m_sprites=536870915 { ... } m_sprites=536870915 { ... } m_slots=2147483651 #...and zero/one/multiple slot nodes { ... } m_slots=2147483651 { ... } opt_attr_one=value_four opt_attr_two=value_five ... } ... #Other module entries }

Along with attr=value pairs the part entry also contains additional level of nested nodes. The child node types are m_mesh (single), m_sprites (multiple) and m_slots (optional, multiple).

Potentially interesting attributes:

Param
Desc
m_id
Node id. Useless on its own, but is important to track if your game keeps crashing.
m_master_id
Parent node id. If it's wrong, your game won't load/will freeze at the shipworks.
m_oid
Same m_oid as the one from the OL.seria.
m_density
Affects module mass. More about that below.
m_mass
NOT A MODULE MASS but is a number used for GUI mass displaying.
m_burn_hp
Either a module HP against fire OR HP subtracted during fire.
m_health and m_health_max
Module HP. m_health is the current module state which makes sense only in a ship file.
m_explosive
Boom damage once this module is destroyed.
m_rescue_explosive
Whether this module will destroy another loot if not looted in the crash site mini-game.
m_floor_type
Module height along Z-axis. For example, large tanks have it set to 3. Very few modules have this value set to nonzero.
m_spasmcode
Stackable attribute at the end of an entry. The functioning is not completely clear, but seems to affect arcs required for functioning (like ones for engines or escape pods)
m_count
The attribute only makes sense in a save file, since a city or a player inventory is represented as a list of cloned part entries, where this value denotes how many of the parts there are.

Meshes
A mesh structure is fixed:
m_mesh=1073741827 { m_classname=Mesh #Common attribute for (almost) all nodes m_size=4 #How many points are there in a mesh 3.13553 #Each pair of numbers is a point X and Y coordinates -3.13553 3.13553 3.13553 -3.13553 3.13553 -3.13553 -3.13553 }
N.B.: the X/Y axes are directed right/down respectively. If you want to visualise a mesh in-game, simply select a part and its white contour will be its mesh.

Mass. The game doesn't expose any particular mass stat. Instead, it computes the mass dynamically by the following formula:

Mass = Mesh Volume x m_density
Mesh Volume = min(Mesh Width, Mesh Height) x Mesh Area

where mesh area can be computed with the Gauss formula for polygon.

So, if we change a side of a square mesh (keeping it square) the mass will grow cubic; if we extend the longer side of a rectangle mesh, then the mass will grow linearly.

Sprites
The sprite subnode doesn't have any children:
m_sprites=536870915 { m_classname=Sprite m_code=536870915 #Should be same as a header value m_animation_name=ap_07 m_position.y=-7 m_stage=-2 m_mask=0 m_animation_mode=4 m_scale.x=1.4 m_scale.y=1.4 }
The sprite attributes are not well documented yet. Here are the known ones:

m_animation_name
A sprite name which is registered in Media/Tex/Ships1.res file. An example entry from the file:
Animation ap_07 { texture = Ships1 rect = 3,3,140,140 hotspot = 70,70 zorder = 0.000000 resgroup = 0 frames = 40 }

An animation may be either a frame-by-frame animation or a single sprite.
m_position.x and m_position.y
Sprite offsets relative the the part zero point.
m_scale.x and m_scale.y
Sprite scaling factors. It's not recommended to stretch/squeeze sprites too much, since they will be too low-res/too sharp. Dithering allows smoothen the issues.
m_angle
Rotation in rads.
m_stage
Seems to be a sprite layer OR a condition under which a sprite is being drawn (on mouse hovering, on being placed, ...)

Slots
Slots are module attachments. They may be either side attachments or internal attachments (like ones provided by hull).

m_slots=2147483651 { m_classname=Slot m_code=2147483651 #Should be same as a header value m_master.id=7246492521041933693 #Should be same as a part id m_type=5 m_position.x=1.78571 m_position.y=5.4888 }

m_position
Slot position. Can be set based on a mesh contour. Note that if you place an external slot inside a mesh, it won't work.
m_type
Slot type—external, internal, internal large, ... . Not properly documented yet.
is_slave
Seems to be "false" for internal slots.
Ship Files
Ship files contain:
  • Module entries very similar to ones in the parts.seria
  • Joint entries which define connections between parts
  • Special Creature entry with ship global stats

Example:
{ m_classname=Node m_code=7 m_id=-492343618703753414 m_name=Archangel m_children=31 {...} m_children=15 {...} m_children=15 {...} ... m_children=15 {...} m_joints=8589934595 {...} m_joints=8589934595 {...} ... m_joints=8589934595 {...} }
  • m_children=15 are part nodes
  • m_joints=8589934595 are joint nodes

The list of the parts on the first nested level is not complete—these are guns, legs, gimbaled engines and dummy nodes without mass and density. The rest of the modules are the children of the m_children=31 node:
{ m_classname=Frame m_code=31 m_id=1883400248470934012 m_state=2 m_master_id=-492343618703753414 m_owner_id=-9178736643823363944 m_children=15 {...} m_children=15 {...} ... m_children=15 {...} m_center.x=0.000152588 m_center.y=18.7003 m_mass=7826850.0 m_mesh=1073741827 { m_classname=Mesh m_size=0 } }

The first m_children=15 child node there is unique—that's the bridge:
{ m_classname=Body m_code=15 m_id=481579170968876493 m_name=COMBRIDGE ... m_children=47 {...} ... m_mesh=1073741827 {...} ... m_oid=MDL_COMBRIDGE_01 ... m_sprites=536870915 {...} ... m_sprites=536870915 {...} m_slots=2147483651 {...} ... m_slots=2147483651 {...} }

And finally—the m_children=47 node, which keeps the ship global stats:
{ m_classname=Creature m_code=47 ... m_mesh=1073741827 {...} m_layer=0 m_health=10 m_health_lock=true m_ship_name=Archangel m_playable=true m_alignment=1 m_card_caption={align=2}{font=courier_28}ÀÐÕÀÍÃÅË@{font=myriad_10}ÓÄÀÐ. ËÅÃÊÈÉ ÊÐÅÉÑÅÐ m_card_main={align=0}{font=flash_large}ÒßÃÀ/ÂÅÑ: 4@ÑÊÎÐÎÑÒÜ: 190 êì/÷@ÄÀËÜÍÎÑÒÜ: 820 êì@ m_card_arma={align=0}{font=flash_large}ÂÎÎÐÓÆÅÍÈÅ:@004X CANNON 2x57mm@002X CANNON 2x180mm@002X MISSILE m_card_modules=MDL_CANNON_57_2=4,MDL_ENGINE_04=8,MDL_ENGINE_05=2,MDL_CANNON_180_2=2,MDL_MISSILE_01=2, m_bio_caption={align=2}{color=2281701376}{font=courier_28}PROFILE@¹981 m_bio_snapshot=no_photo ... creatureId=2 m_damageCounter=8360 versionCompatibility=Ñîâìåñòèì ñ âåðñèåé 1.15 }

This node contains the ship global stats, which indicate how far/fast/long it can fly/see/be seen. It's important to know that there's no sense to change them if you want to alter ship's speed, range or sensor strength; these are used mostly for spawn computations or GUI visualisations. What's really important there is the m_flagship flag which you may set to "true" is you want the ship to be recognised as a flagship:
... m_ship_name=Varyag m_playable=true m_flagship=true ...

If you want to mess with ship stats, it's better to change ship module stats and then force the game to recompute the global stats. Module entries are very similar to the ones in parts.seria, with some differences:
  • Guns, sensors, jammers, missiles—everything with an arc—gets the m_sectors repeating attribute, 360 entries per part. It's one/zero for guns/missiles, ELINT power value for ELINT (zero, full or half if obstructed) and radar range in km for radars (zero/full/half).
  • m_position.*, m_scale.* and m_angle attributes now make sense and define the module location. m_scale is being used to flip symmetric parts like legs/engines.
  • Other minor changes in tech attributes, like parent ids.

Read the Ship Replacements and Updating section about updating the ship stats after you changed module values.
Save Files
This section is relatively brief since the save editing is not well documented; however, there already are some tools to alter your campaign experience significantly. Note that editing an ongoing campaign is tied to large risks and may render your save broken beyond repair, so always make backups.

Simple tweaks

It's possible to change the amount of starting cash bonus by tweaking the m_scores root attribute:
m_scores=76886

You can also unlock ships by flipping a binary flag near a ship name:
... m_unlocks=Lancer|0 m_unlocks=Gladiator|1 m_unlocks=Paladin|0 m_unlocks=Lightning Mk3|0 m_unlocks=Jaguar PVO|0 m_unlocks=Intrepid|1 ...
Note that many ships cannot be unlocked through playing, and some of them come straight from early builds.

This timer in days is responsible for triggering the darkness event. Increase it if you want to postpone.
m_countdown=11.3644

Tweaking existing strike groups

It is possible to change or spawn new strike groups (as well as other enemy squadron) via save editing. If a ship structure wasn't changed since the spawn (no parts damaged, no missiles fired, etc.), it is being stored in a save file in a compacted form, with includes only the bridge instead of a complete part description tree. This makes it easy to remove, replace or place a new ship into an existing enemy fleet.

At the moment when a ship structure changes, it's being stored verbosely with a full description and its name changes to a generic one, making it harder to tell different enemy groups. This is an aspect one should consider if they want to write a script which will tweak enemy compositions.

Spawning new strike groups

See the Modding Tools section for the tools which automate the process. The manual algorithm is:
  1. Clone an existing SG entry (the m_escadras=327 node containing SG-specific ship subnodes);
  2. Edit its coordinates and the callsign;
  3. Change the m_intels=515 nodes to correspond to other fleet stats. The first one with the callsign and the current coordinates is the first to edit;
  4. Edit fleet composition if you want to. Note that some ship fields get added or modified when the ship entry from its .seria gets cloned into the save, so refer to the modding tool code for this.

Ship morale and promotions
These attributes are stored inside the Creature node of the player ship.
m_moral=8
Integer morale value.
m_rest=0.742202
Float rest value till the next morale point.
m_promotions=6
Repeated perk attribute with different integer values for different perks. There are 8 perks in the game.
m_xp=364.88
Either the total xp or xp to the next promotion.

Cities and their inventories
Cities also can be modified by save editing. The roads are not stored in the save, and seem to be randomly generated between non-hidden cities within a certain distance. The city node is two-level, with the m_locations=199 root node storing the main city info, the m_items=2199023255555 child nodes denoting the ammo stored in the city, and the single m_world_trade=7 child node containing several m_children=15 children nodes for parts (generic hull, generic armor, engines, guns, ...) sold in the city. Note that the m_world_trade nodes generate only after you visit a city!

Root node selected attributes:
m_codename
City codename, works similarly to fleet callsigns.
m_position.x, m_position.y
Floats for city position.
m_bonus, m_bonus_type
Boolean and integer values for city type (repair, rare items, ...)
m_repair_capacity
How much of repair bonus the city can provide.
m_discontent and m_treason_threshold
[0, 1] floats. The first one increases with your fleet staying in the city; the second one is the threshold when the city will report your location.
m_aad
Anti-air defenses. Absent (zero), 1 or 2 for vanilla.
m_discovered
2 for ordinary city, 1 for the discovered hidden ones, absent (zero) otherwise.
m_fuel, m_fuel_capacity
Self-explanatory floats. Note that the city fuel capacity is limited, albeit by default it's huge (9.99999e+08).
m_citysize, m_population, m_population_init
Float, int, int. Self-explanatory. m_population decreases after your warcrimes.

m_items attributes:
m_index
Ammo index. To find the ammo index, refer the Logdots ammo-extended mod; ammo index is its order in the config.
m_count
How many shells of the particular type are stored.

City inventories are tricky to edit by several reasons, the main one being that they lazily generate only after you visit it. Another one is that instead of a plain list of items, the city inventory structure follows basically a ship convention of cloned parts.seria entries. Note that the parts requiring "resources" to be built (hull, fuel tanks, armor) are stored as a generic part (ITEM_HULL. ITEM_ARMOR, ITEM_FUEL) instead of particular hull pieces:
m_children=15 { m_classname=Body m_code=15 ... m_mesh=1073741827 { ... } ... m_oid=ITEM_ARMOR m_count=74 is_loot=true m_sprites=536870915 { ... } }
Also note the m_count attribute, which denotes the amount of the parts in the city inventory.

Tarkhan and player stats
The save file contains multiple m_npcs entries, most of which seem to correspond to some unused/unshown/technical characters. However, some of them belong to tarkhans you can recruit, and here's their stat table:
m_name
This allows to distinguish between a tarkhan and a generic character. Tarkhans have a capitalized string name assigned, while generics have integer numbers.
m_fullname
Localized full character name.
m_joined
Self-explanatory bool.
m_loyalty
Current loyalty level, 3 points correspond to one star.
m_char_fear, m_char_gerat, m_char_romani, m_char_faith, m_char_right, m_char_force, m_char_wealth, m_char_kindness
{-2, -1, 0, 1, 2} ints for personality stats.
m_arch_fear, m_arch_gerat, ...
Similar to the above, but the difference is unknown (?).
m_ship_first
The tarkhan ship.
m_location
City where the tarkhan is at.

Player stats are the m_char_* entries located at the save root node (typically at the end of the file) and can be float. Don't confuse them with stats of the NPC named MARK!

Other stuff to experiment with

It is known that by tweaking save files it's also possible to:
  • Change intel amounts in cities
  • Reroll a mercenary roster after they spawn in a city
  • Many more

Individual entries will be expanded once a proper algorithm is established.
Localization Files
Localization files editing is not only interesting for translation and adding ship description reasons, but also because this allows to tweak dialogue trees in story or random events.

The files are located at the Data/Dialogs folder. Refer to this guide for more details:
Dialogue (and now Character) Modification

Ship entries
There are two entries you need to edit if you want to add a ship description:
#SHIP_NAME_Nomad Nomad
The SHIP_NAME_* entry is mainly needed for Russian version where it allows to add a cyrillic ship name. The * should be replaced with the ship m_name root node attribute value.

#SHIP_DESC_NOMAD Romani heavy strategic cruisers, which have been serving as a core of command groups for decades. Despite their age, they have undergone an extensive amount of upgrades and participated in field tests of the state-of-the-art AEW systems, which were planned to be installed later on the newest Sevastopol-class cruisers under construction.
SHIP_DESC_* stores the ship description visible at the campaign start. Note that a ship name substituted for * is uppercase. Also note that the tag and the value are being separated by tabulations and have no newlines.

Part entries
#MDL_CANNON_220 M-22 #MDL_CANNON_220_SDESC CANNON #MDL_CANNON_220_DESC A 180mm large-caliber cannon with an increased fire rate.
If you want to add a module entry there, you will need an entry for a name, type and description (MDL_*, MDL_*_SDESC, MDL_*_DESC where * is the module m_oid).

Events
Dialogue files also store some rewards or penalties you get from events. While some outcomes are hardcoded (like new ships, forced stays, no repairs/refueling in a city, ...), cash/rep/morale may be tweaked there.
#INTERCOM_FASIL_1 <NPC=FASIL><SIDE=0><SHADOW=1>Yes, Duke?<ANS=I’d like to ask you for a loan to supply this campaign, Prince.> #INTERCOM_FASIL_2 <NPC=FASIL>War is an expensive undertaking, is it not, my Duke? <ANS=Alas, it most certainly is. Can you lend me a hand, Prince?> <ANS=I’ve changed my mind, Prince. My apologies. That will be all.|EXIT> #INTERCOM_FASIL_3 <TRG=INTERCOM_FASIL|1><NPC=FASIL>Very well. I’ll get the money together.<SCR=STOP|GOLD=10000|FASIL=-1> #INTERCOM_FASIL_SHORT <NPC=FASIL>Very well. I’ll get the money together.<SCR=STOP|GOLD=10000|FASIL=-1>
A dialogue "direction" in terms of sprites/fade effects can also be tweaked there.
Making New Parts
Before moving on making new parts it's worth to mention what we are not able to do:
  • We cannot add new parts into an existing campaign. There is no mod yet which will spawn new parts in cities; however, parts requiring resources to build can appear in campaign, while the rest can be added via save editing.

Also note that this section got partially outdated after the release of the ShipworksExtended mod by Logdot; in particular, the mod automates the bullets 3 and 4 and simply loads new parts.seria entries into the shipworks without replacing any of the existing parts, so you only need to focus on creating proper OL.seria and parts.seria nodes. Refer to the ModLoader section to find more details on that, while I list the old approach there for educational reasons.

How to
The process is very similar to the one described in this guide, with minor differences:
Making Wheels Available in Ship Editor

The algorithm is following:
  1. Choose a vanilla module which is closest to something you're going to make.
  2. Duplicate its entry in OL.seria, tweak its m_oid and stats.
  3. Go to Libraries/constructor.seria (make a backup) and remove the
    m_children=15 { ... m_oid=ITEM_EMERGENCY ... }
    node to free some space.
  4. Go to parts.seria, pick a vanilla module entry and paste it into constructor.seria instead of a deleted node.
  5. Set m_oid, m_master_id (IMPORTANT, the value is the constructor.seria root node m_id value, otherwise your game will freeze).
  6. Tweak the stuff you want—HP, density, mass, ...
  7. Do not forget about module mesh, sprites, slots.
  8. Start the game and go to shipworks.
Now the last module category will be replaced with the module you just created. Note that you don't need an entry in parts.seria—once you install a part on a ship, it will be written in a ship file and will only refer to OL.seria.


The game got some unsused sprites, but there isn't much. OTOH, you can still create new visuals if you are creative with the sprites you already have. For example, the M-22 180mm cannon was created based on a Mk-1-180 sprite with a new barrel made of Sprint+flare and a muzzle brake made of a hull block.

Do not forget to create corresponding entries in dialogue files, otherwise the name and description will be empty.
Ship Replacements and Updating
Another potential mod you may want to develop is vanilla ship replacements. Vanilla ships are treated in a separate way and are kept in Objects/Designs folder. They cannot be deleted in the game neither overwritten in the shipworks.

Replacements
If you're going to replace a vanilla ship with your own, the pipeline is following:
  1. Open both vanilla and custom ships in text editor
  2. Change the custom ship m_name (root node attr) to the vanilla ship value
  3. Change the name in m_card_caption (global stats section) to the vanilla name
  4. Change the m_ship_name stat (global stats section) to the vanilla name
  5. (Optional) change the m_combatvalue stat, which affects how many instances of the ship will spawn in-combat and within enemy squadrons. If your replacement combat value is too high, it may not spawn at all due to the cap on the total combat value for garrisons or other enemy groups.
  6. (Optional) change the m_card_snapshot path (global stats section) to the vanilla snapshot path (which you will also need to replace)

Ship updating
You may want to update all the ships (including vanilla) after you tweak parts.seri or ship modules. There are 79 vanilla ships, so pick a vacation and start from Archa...

JK, lol, there are some mechanisms implemented which are intended to help you with that:
  • The game may update some stats by itself
  • DIY scripts may be written to update ship files

If you launch a new version of the game first time, it will update everything in the Ships folder and will place the old copies in Ships_backup. What it does recompute:
  • Weapon firing arcs
  • Sensor arcs (it may fail there, manual tweaking can be needed)
  • All global stats
  • Density/mass
  • Elevation
To force the game to do that, open Config.ini and change CORE_LAST_LOADED_VERSION=1.15 value to some older one, like 1.14 or 1.1.

However, it won't pull all the data from parts.seria by itself. If you modified the parts.seria and want a ship to get new values, before performing the step above you need to alter part entries in a ship file first. This is very tedious to do manually, so I released some Python scripts to do that, see the Modding Tools section.

In conclusion, the ship update pipeline is the following:
  1. Pick a ship file
  2. Alter by yourself/update with a script module entries there
  3. Put it into Ships folder (make a folder backup, just in case)
  4. Change the game version in Config.ini to some older one
  5. Run the game
Modding Tools
While most of changes can be technically done by hands, propagating part configuration updates or save editing is extremely tedious. While there is no dedicated mod software yet, there are some scripts and packed GUI programs to automate some portion of work.

The GUI app for modding is the ModTool v0.1:

Supports map browsing, spawning and editing enemy groups, and automated ship updates with new parts.seria stats. Note that enemy spawn function is somewhat buggy, so always backup your saves. Available on Nexus:

Nexus[www.nexusmods.com]

The raw Python scripts are published on GH:
Github[github.com]
Usage example:
Github[gist.github.com]

No docs provided, but the example is self-explanatory.

Again note, that some functionality can be missing, as well as be unstable or break something. Use at your own risk.
ModLoader
This section was intended to be the part of the previous Modding Tools one, but I decided to expand it since it deserves a particular attention.

The ModLoader by Logdot allows to perform code injections into the game to add additional functionality, which cannot be delivered otherwise:

ModLoader Github[github.com]

The usage is simple—you install the ModLoader, install the supported mods, configurate them to your taste and launch the game through the ModLoader. There are currently two mods which are supported by the loader: ShipworksExtended and ammo-extended.

ShipworksExtended

This mod allows to load custom parts.seria entries into the shipworks without replacing existing ones. The usage is straightforward and well-described on the mod Github page[github.com], so I won't cover it there. Note that unlike the orthodox way of adding new parts described in the corresponding section, this requires keeping your new entry in the parts.seria file. Also note that the mod affects only the shipworks and will not spawn new parts in cities; however, parts requiring "resources" for construction may appear as buildable in campaign too.

ammo-extended

This mod[github.com] allows to manipulate with shell parameters, including damage, speed, armor piercing capabilities and many others, as well as converting shells between different types.

The shell parameters can be configured by tweaking the ammo-extended.json config. Unlike the previous mod, this one is somewhat worse documented, so I will cover it there in more detail.
padding_cch
The value defining the shooting behavior and the number used in OL.seria to assign a weapon caliber.
shell_in, shell_out, shell_enemy, shell_far
Sound effects used in different situations.
caliber
Something related to shell behavior. "100" is default, "90" won't detonate on impact and will bounce off instead, "180" will detonate on proximity in the direction of the target, "160" is proxy.
index
Auxiliary value related to padding_cch. It's recommended to keep them identical to avoid bugs.
speed
Shell speed.
ap_drag
Setting this to nonzero will turn the shell into AP, changing the reticle and making it disappear after some distance. Can be set to negative.
explosive_power
Shell explosive damage. Note that APs have it set to 1.
penetrative_power
Shell AP strength.
incendiary_power
Shell incendiary strength. 100 by default, 300 for incendiary shells.
unknown_16ch
Shell lifetime. Only applies to non-AP.
shop_price
Self-explanatory.
unknown_174h
Chance to spawn in a city inventory.
unknown_178h
Average amount spawned.
unknown_17ch
Fire delay (?). Affects aircraft payload release rate.
Levels
N.B.: This section is incomplete and will be updated in the future.

Levels are barely moddable for now, but some things still can be tweaked. Level files are stored in the Data/Levels folder.

An example level file:
{ m_classname=LEVEL m_code=3 LVL_SCRIPT=SCR_EDITOR_EXTENDED LVL_WIND_FORCE=3 LVL_BACKGROUND=background_mid_01 LVL_HIGH.x=1000 LVL_HIGH.y=2000 LVL_LOW.x=-1000 LVL_LOW.y=-2000 m_world=7 { m_classname=Node m_code=7 m_id=1 m_state=4 m_name=LEVEL_ROOT physical_root=true } m_world_trade=7 { m_classname=Node m_code=7 m_id=2 m_state=4 m_name=LEVEL_TRADE_ROOT } }

Note the LVL_SCRIPT attribute—it defines a script attached to the level. Scripts seem to be responsible for all the level logic, including terrain generation if needed. However, some levels also contain child nodes with parts, like the City or Dungeon—probably to describe some predefined terrain.

Note that there don't seem to be separated script files in the game directory.

Primitive tweaks

Combat levels contain the LVL_HIGH.x, LVL_HIGH.y, LVL_LOW.x, LVL_LOW.y attributes which define the level size. If you want to extend/shrink combat arena, you can change them. The supposed combat levels are:
Name
Desc
Bombers
Maybe the aircraft vs landed ships scene?
Combat
Generic ship-to-ship combat? Corresponds to the shipworks test combat too.
Combat_test
Meaning unknown.
CraftsVsCraft
Aircraft combat on intercept?
CraftsVsMissile
Missile intercept scene?
Random_Combat
Meaning unknown.

Level swap
There is no known way to add new levels into the game (since transitions seem to be done with scripts, which we cannot modify yet), but we can plug level files instead of existing ones, like the shipworks or the test level—simply rename the level file to Editor.seria, for example. The list of known hidden levels (currently incomplete, filling is in progress):

Name
How to access
Desc
Dungeon
Swap City_generated and change the LVL_SCRIPT back for SCR_CITY_GENERATED
A hidden underground level with unique sprites. Seemed to serve as a flight tutorial.
EditorExtended
Swap Editor
An editor with extended capabilities, allowing to place non-part sprites as well as different ships. Ships placed on the level can enter a combat with each other.
Builder
Swap Editor
A level where a script builds three Intrepid variants one-by-one. The player cannot control anything except engine rotation of a currently built ship. This level seems to be mentioned for promotional GIF/video recording.


EditorExtended
Planned sections
Events
  • Expanding and branching existing events
  • Triggering specific ones

Textures
How to edit and add some new.
  • Existing files enumeration with some hints on content
  • .res file structure
  • Experiment on adding a new texture file for a new part
  • Implementation of swappable/side-specific camos

Cheat Engine
Allows to do things which are otherwise undoable.
  • Change weapon stats
  • Change player stats
  • Change enemy stats
  • Further fiddling with variables
41 Comments
NNINE(SETH) 18 Nov, 2024 @ 9:27am 
Hi, is there any way to change the explosion effect of kh-15_CONV to a nuclear explosion effect?
武德九 3 Nov, 2024 @ 4:57am 
Hello, is there any way to modify the time and scene of the simulated test battle that can be performed in the Ship Editor? What file controls this?
Dwang Zhongson  [author] 9 Oct, 2024 @ 5:20am 
@friedvossk
Read the ModLoader section carefully.
friedvossk 8 Oct, 2024 @ 4:42pm 
How do you add a new part? The method you showed only allowed adding one new part and it replaces the old ones, is there a way to add more than one new part without replacing existing ones?
Mouse Lover 2 Oct, 2024 @ 1:38pm 
:fhappy: Thank you for confirming my doubts.
Shame we can't change it, I guess all my men will go down with the ship.
:spg2devil::bunthumbup:
Dwang Zhongson  [author] 2 Oct, 2024 @ 11:56am 
@Mouse Lover
I have checked the config files and there doesn't seem to be the parameter which is responsible for that. Looks like KK hardcoded it like many other stuff.
Mouse Lover 2 Oct, 2024 @ 11:17am 
Is there a way to increase the amount of people that can fit in escape pods?
Most of my ship builds have little space to fit an escape pod, so I would like to increase their carry capacity.

But the problem I have is that I tried looking at the code and can't find a way to modify it, unless I am blind as a bat.
Sphyrwa 23 Sep, 2024 @ 9:35am 
@Dwang Zhongson
Oh I see, thank you very much
Dwang Zhongson  [author] 23 Sep, 2024 @ 3:33am 
@Sphyrwa
You should edit engine fuel consumption in OL.seria. IIRC power generators use a small amount of fuel as well, but all of this is like 8 parts to edit.
Sphyrwa 11 Sep, 2024 @ 8:59am 
If I wanted to make everything use less fuel, would I need to adjust the power requirement on all the parts?