Category System - AntonIT99/Flans-Mod-Ultimate-2.0 GitHub Wiki

Category System

The category system lets you apply content-pack settings to groups of items without editing every item .txt file. It is useful for server balancing, modpacks, and large content packs where many guns, bullets, grenades, or other items should share the same values.

For the full list of content-pack parameters that can be used in category properties, see Config Reference.

What Categories Do

A category is a named group with:

  • items: the short names of the items affected by the category.
  • properties: content-pack parameters to apply to all of those items.
  • inherits (optional): a same-type parent category to reuse. See Inheritance and Default Overrides.
  • exceptions (optional): properties that specific items of the category must not receive. See Exceptions.

When the mod loads an item, it reads the item's normal content-pack .txt file and then applies matching category properties. For simple one-value settings, category properties usually override the value from the content-pack file. For repeatable settings, category properties add extra lines.

This means categories are a good way to:

  • rebalance many weapons at once;
  • create shared behavior for ammunition groups;
  • override built-in default tuning without editing content packs;
  • keep local/server balance changes separate from downloaded content packs.

Where Category Files Are

User-editable category files are in:

config/flansmodultimate/

Built-in default examples are copied to:

config/flansmodultimate/default/

Do not put your custom edits in the default folder. Those files are owned by the mod and may be refreshed when the built-in defaults change. Put your edits in the matching file directly inside config/flansmodultimate/.

Category Files by Type

Each item type has its own category file.

Item type Category file Content-pack folder
AA guns aagun_categories.json aaguns
Armor armor_categories.json armorFiles
Armor boxes armor_box_categories.json armorBoxes
Attachments attachment_categories.json attachments
Bullets and ammunition bullet_categories.json bullets
Gloves glove_categories.json gloves
Grenades and thrown shootables grenade_categories.json grenades
Guns gun_categories.json guns
Gun boxes gun_box_categories.json boxes
Item holders item_holder_categories.json itemHolders
Parts part_categories.json parts
Tools tool_categories.json tools

If you want to edit guns, use gun_categories.json. If you want to edit bullets or ammo, use bullet_categories.json. A gun category cannot affect a bullet, and a bullet category cannot affect a gun.

Basic JSON Format

An empty category file should contain:

{}

A category file with one category looks like this:

{
  "Category Name": {
    "properties": {
      "ConfigKey": "value",
      "AnotherConfigKey": 123
    },
    "items": [
      "item_short_name_1",
      "item_short_name_2"
    ]
  }
}

The category name identifies it for inheritance and default overrides. Names are case-sensitive. Use clear names such as "Assault Rifle Tuning" or "Heavy Explosive Ammo".

Item Names

Items are matched by their content-pack ShortName, not by display name, file name, or Minecraft registry ID.

Example content-pack line:

ShortName AK47

Use this in a category:

"items": [
  "ak47"
]

Short names are sanitized by the mod, so it is best to write them in lowercase and replace spaces with underscores.

When a content-pack item is renamed, shipped/default categories should add the new sanitized short name without deleting the former one. Keeping both names preserves compatibility with older content-pack releases and external packs that still use the legacy ShortName. Remove a legacy category entry only as an explicit retirement, not as an automatic part of a rename or coverage cleanup.

Property Names

Property names are the same settings used in content-pack .txt files. For example:

  • gun properties such as RoundsPerMin, MuzzleVelocity, Dispersion, Recoil;
  • AA-gun properties such as firing-event RoundsPerMin, Dispersion, RealMassKg, and UseRealisticVehicleHealth;
  • bullet properties such as Mass, FallSpeed, ExplosiveMassTNTg, PenetrationAt100m;
  • grenade properties such as Fuse, ExplosiveMassTNTg, FragType;
  • armor properties such as Defence, DamageReduction, Durability.
  • mecha properties such as RealMassKg, RealMaxSpeedKmh, RotateSpeed, StepHeight, JumpHeight, Reach, and UseRealisticVehicleHealth.

Use Config Reference to find the exact property name, expected format, default value, and which type supports it.

Historical gun and AA-gun categories must define RoundsPerMin and Dispersion. Research the exact configuration first and use a compatible specialist or game source as a fallback. If neither establishes a value, use a gameplay-coherent value based on comparable weapons and disclose that it is invented in the category batch report.

MuzzleVelocity is resolved from ammunition when ammunition MuzzleVelocity or BulletSpeed is present; that value takes precedence over the gun's. Ordinary small arms normally define gun-category velocity as the barrel-specific source and fallback. Autocannon belts, shells, and missiles define ammunition velocity for the exact projectile/load; a matching gun or AA gun may retain a compatible fallback. Do not put different configurations on the two sides.

Property Values

Category property values may be:

  • a JSON string;
  • a JSON number;
  • an array of strings or numbers.

Examples:

"RoundsPerMin": 750
"ExplosiveMassTNTg": "85"
"AddRound": [
  "AP 1 162 0 800 45",
  "HE 2 135 16 835 0"
]

Do not use raw JSON booleans inside properties. Use strings instead:

"TranslucentRendering": "true"

or use 1 / 0 where the content-pack parameter accepts boolean-style values.

For properties that normally have several values on one line, put the whole value part in one string. Do not repeat the property name inside the value.

Content-pack line:

AddRound AP 1 162 0 800 45

Category value:

"AddRound": "AP 1 162 0 800 45"

If you need several AddRound lines, use an array.

Override and Add Behavior

The category system adds property lines after the item's normal content-pack lines. Most single-value parameters use the last value, so category values override the content-pack value.

Example:

Content-pack gun file: RoundsPerMin 600
Category property:     "RoundsPerMin": 750
Final value:           750

Repeatable parameters keep multiple lines. Category values are added to the existing lines.

Example:

Content-pack bullet file: AddRound Ball 1 147 0 850 30
Category property:      "AddRound": "Tracer 1 145 0 850 25"
Final result:           both rounds are available

Categories can select a different merge strategy for individual properties with propertyModes:

"properties": {
  "AddRound": [
    "AP 1 162 0 800 45",
    "HE 2 135 16 835 0"
  ]
},
"propertyModes": {
  "AddRound": "replace"
}

The supported modes are:

  • append: add the category values after existing values. This is the default and preserves the behavior of category files that do not declare a mode.
  • replace: discard values supplied by the content definition or earlier categories, then use the values from this category.
  • ifAbsent: apply the category values only when neither the content definition nor an earlier category supplied that property.

Property names and mode values are case-insensitive. A complete category-authored AddRound belt should normally use replace. It then remains usable as a fallback in the content definition when categories are disabled without doubling the belt when categories are enabled.

If an item belongs to several categories that set the same single-value property, the later applied category wins. Avoid putting the same item in several categories that edit the same value unless you are deliberately overriding something.

Exceptions

Sometimes almost every item in a category should share the same value, but a few variants must keep their own. Instead of splitting the category, add an optional exceptions block.

exceptions maps a property name to the list of items that must not receive that property. Those items still receive every other property of the category.

{
  "Panzerkampfwagen VI Ausf. H1 Tiger": {
    "properties": {
      "RealMassKg": 57250,
      "RealEnginePowerPS": 650,
      "RealMaxSpeedKmh": "45.4",
      "DriveType": "TRACKED",
      "RealMaxReverseSpeedKmh": "9.2"
    },
    "items": [
      "44_tiger1h",
      "tiger",
      "tiger131",
      "tigersnow"
    ],
    "exceptions": {
      "RealMaxSpeedKmh": ["tiger131", "tigersnow"]
    }
  }
}

In this example:

  • 44_tiger1h and tiger receive all six properties;
  • tiger131 and tigersnow receive everything except RealMaxSpeedKmh, so they keep the speed written in their own content-pack file (or one set by another category).

Rules:

  • exceptions is optional. Category files without it keep working unchanged.
  • Keys are property names taken from properties. A key that does not exist in properties simply does nothing.
  • Values are item short names. A single item may be written without brackets: "RealMaxSpeedKmh": "tiger131".
  • Property names and item names are matched case-insensitively.
  • An excepted item stays a member of the category. Only the listed property is skipped for it.
  • Exceptions are per category. They do not block a property applied by a different category, so if a default category also sets the same property, add the exception there or override the value in your user category.

Use exceptions for variants that differ in only one or two values, such as a snow skin with a different top speed, a captured vehicle with a different engine, or a single gun in a family with a different rate of fire.

Default Categories and User Categories

By default, the mod loads built-in categories from:

config/flansmodultimate/default/

Then it loads your user categories from:

config/flansmodultimate/

User categories apply after untouched default categories. Your user category can override default category values for the same items.

To disable all built-in default categories, edit:

config/flansmodultimate-content-loading.toml

Set:

useDefaultCategories=false

Leave this enabled if you want the mod's built-in balancing categories. Disable it if you want only your own categories applied. Explicit inheritance can still reuse built-in definitions.

Inheritance and Default Overrides

Use the optional inherits string to name one parent category from the same InfoType subtype (the same category file). Category names are case-sensitive; property names and item short names are case-insensitive.

{
  "My Ammo Base": {
    "properties": { "Mass": 12, "FallSpeed": 1 },
    "items": []
  },
  "My Heavy Ammo": {
    "inherits": "My Ammo Base",
    "properties": { "Mass": 20 },
    "items": ["my_heavy_ammo"]
  }
}

The child receives Mass = 20 and FallSpeed = 1. Parents may appear later in the file, and inheritance chains are supported. A parent with an empty items list is a useful settings template. Inheritance also carries the parent's items: if the parent lists items, the child applies to those items as well as its own.

Editing a Built-in Category

With useDefaultCategories=true, declaring the exact same category name in the user file automatically merges it with the built-in category. No inherits is needed. For example, if a built-in category named Example Ammo supplies Mass, FallSpeed, and items old_ammo_a and old_ammo_b, this user declaration:

{
  "Example Ammo": {
    "properties": { "Mass": 20 },
    "items": ["my_extra_ammo"]
  }
}

keeps the built-in FallSpeed, changes Mass to 20, and applies the resulting settings to all three items. Omitting items keeps all built-in members. The merged category is applied once, so redeclaration does not duplicate repeatable properties from the built-in declaration.

Explicitly Inheriting Built-in Settings

Use "inherits": "default:Example Ammo" to select the original built-in definition, even if a user category has the same name. Replace Example Ammo with an actual name from the corresponding default file. This works with useDefaultCategories=false, including when the child has the same name as its built-in parent. Only your child is activated; other default categories stay disabled. The child still inherits the selected parent's item membership.

An unqualified name such as "inherits": "Example Ammo" selects the active category, including user edits. When defaults are disabled, unqualified names can only select user categories; same-name declarations do not automatically keep built-in values or items. The default: prefix is reserved for built-in lookup.

Merge and Application Rules

  • Precedence is the same-name built-in base (when enabled), then the explicitly inherited parent, then the child's own fields.
  • properties merge by parameter name. An overridden parameter replaces its entire value list, including repeatable parameters such as AddRound. Omitted parameters retain inherited values.
  • items are combined in order, removing case-insensitive duplicates. An empty list does not remove inherited members.
  • propertyModes and exceptions merge by parameter name too. A child entry replaces that parameter's inherited mode or exception list. Use an empty exception list ("Mass": []) to clear an inherited exclusion for that property.
  • propertyModes control application to content-pack lines and earlier categories; they do not change the inheritance merge rules.
  • Untouched built-in categories apply first, followed by user categories in user JSON order. Parent lookup order does not change application order. If both a parent and child contain an item, both categories apply; repeatable properties can therefore be added twice unless an appropriate replace mode is used.
  • Cross-type parents, missing parents, self-inheritance, and inheritance cycles are invalid. Affected categories and their dependents are skipped with an error in the log; unrelated valid categories still load. Use default:Name when a same-name user category should inherit its built-in definition instead of itself.

Restart the game or server after editing category files.

Examples

Tune a Gun Group

File: config/flansmodultimate/gun_categories.json

{
  "Assault Rifle Balance": {
    "properties": {
      "RoundsPerMin": 650,
      "Dispersion": 0.28,
      "Recoil": 1.1
    },
    "items": [
      "ak47",
      "m16a4",
      "g36c"
    ]
  }
}

This applies the same rate of fire, dispersion, and recoil to all listed guns.

Override One Default Weapon Value

File: config/flansmodultimate/gun_categories.json

{
  "My AK Override": {
    "properties": {
      "Dispersion": 0.18
    },
    "items": [
      "ak47"
    ]
  }
}

If a built-in default category also changes ak47 dispersion, this user category wins because user categories load after default categories.

Create Heavy Explosive Ammo

File: config/flansmodultimate/bullet_categories.json

{
  "Heavy Explosive Ammo": {
    "properties": {
      "Mass": 42,
      "ExplosiveMassTNTg": "1.3",
      "PenetrationAt100m": 20
    },
    "items": [
      "barrettexplosiveammo"
    ]
  }
}

This changes the physical and explosive behavior of the listed bullet item.

Add Several Rounds to Ammo

File: config/flansmodultimate/bullet_categories.json

{
  "Mixed 20mm Rounds": {
    "properties": {
      "AddRound": [
        "AP 1 162 0 800 45",
        "HE 2 135 16 835 0"
      ]
    },
    "items": [
      "20mmammo"
    ]
  }
}

Each array entry behaves like one extra AddRound line in the bullet config.

Tune Grenades

File: config/flansmodultimate/grenade_categories.json

{
  "Frag Grenades": {
    "properties": {
      "ExplosiveMassTNTg": "85",
      "FragType": "STD_FRAG",
      "Fuse": 80
    },
    "items": [
      "mk2frag",
      "44_mk2frag"
    ]
  }
}

Fuse is measured in ticks. Minecraft runs 20 ticks per second, so 80 ticks is about 4 seconds.

FragType describes casing construction, while FragPattern describes the directions fragments leave the burst. The engine derives useful reach from effective fragment count, charge-to-metal ratio and distance; individual FragRadius values are no longer used. See Fragmentation Damage for the model and the S-Mine, Claymore and AHEAD examples.

Recommended Workflow

  1. Start the game or server once so the category files are generated.
  2. Open the matching file in config/flansmodultimate/.
  3. Find the item's ShortName in its content-pack .txt file.
  4. Find the property you want in Config Reference.
  5. Add or edit your category JSON.
  6. Restart the game or server.
  7. Test the affected items in-game.

For multiplayer, apply gameplay categories on the server and keep clients in sync with the same content/category setup when the changes affect item behavior, models, or generated assets.

Troubleshooting

Problem What to check
The game fails to start after editing a category file Validate the JSON. Check commas, quotes, brackets, and that the file is not empty. Use {} for an empty file.
A category does not affect an item Check that the item is in the correct type file and that items uses the item's ShortName.
A property is ignored Make sure the property is valid for that item type. Use Config Reference.
A boolean property causes problems Use "true" or "false" as a string, not raw JSON true or false.
A multi-value property only partially works Put the whole right-hand side in one string, such as "AP 1 162 0 800 45".
Default category behavior still applies Override the same property in your user category, or set useDefaultCategories=false.
A property still applies to an excepted item Check that the exceptions key matches a key in properties and that the item short name is spelled the same as in items. Another category may also set that property.
Your custom edits disappeared Make sure you edited config/flansmodultimate/*.json, not config/flansmodultimate/default/*.json.

Mecha category maintenance

Mecha chassis use mecha_categories.json and the mechas definition folder. Tools and upgrades are separate mecha_item definitions. The repository coverage scanner now includes chassis from source packs and ZIP packs; a missing shipped mecha category file leaves all chassis in the research queue.

The maintainer skill's references/mechas.md defines Utility, Recon, Assault and Heavy profiles with fixed movement and part-health targets. These are initial balance assignments, not physical specifications or playtested guarantees. Health categories preserve each model's collision geometry and disable realistic mass-based health scaling. Engine and addon modifiers still affect performance; mounted weapons keep their own categories. Chassis rules do not require tank or aircraft propulsion parameters. Adding these maintenance rules does not itself assign existing mechas to categories.