Skip to content

Content Patches

Content patches are a powerful tool for modifying properties of blocks, units and items on a per-map or per-server basis. Some applications of this feature include balance patches, custom game modes, or different game progression.

Some things that content patches can do:

  • Make a factory use more or less of a resource
  • Change the resource requirements of a block
  • Completely change the weapons and bullets of a unit
  • Change the recipes available to a unit factory
  • Change displayed sprites of block or units to other in-game textures
  • Change the build speed, health, armor, etc. of any block or unit
  • Change the type of a unit (e.g. ground to flying)

Some of the things that content patches cannot do:

  • Introduce new textures or assets into the game
  • Introduce new mechanics not present in vanilla
  • Change the types of blocks (e.g. wall into turret)
  • Add new content (items, blocks, units, etc)

Balance patches are not a replacement for mods; they can only tweak existing content.

Writing A Trivial Content Patch

Content patches are written in JSON or HJSON (a superset of JSON). You will need a text editor to write them; there is currently no in-game editor for patches.

For the sake of brevity, this guide will only show how to write patches in HJSON.

To begin, create a text file named mypatch.hjson, with the following contents:

//naming a patch is optional, but helps identify it in the UI
name: My Patch

//makes all conveyors have 50 max health
block.conveyor.health: 50

Applying Content Patches

Applying Patches on Maps

Open your map in the map editor, then open the top-left menu (or press ESC on desktop). Go to Map Info -> Content Patches -> Add, and then specify the patch file you saved in the previous step. You can view any errors generated by the patch by clicking the ⚠️ icon, or reload the file with the 🔁 button.

Applying Patches on Dedicated Servers

Open your server directory (which should already contain folders for plugins, maps, saves, etc), locate the patches directory, and simply drop your patch file into it. Patch files must have a hjson/json/json5 extension to be loaded. They will automatically be applied to any map after any other content patch that the map already contains.

If you've done everything correctly, the server should log the amount of patch files loaded upon startup. Any warnings or errors will also be printed to the console. To reload patches while the server is still running, use the reloadpatches command.

Content Patch Basics

Content patches follow a heirarchy. At the first level, you define the type of content to be changed: block, liquid, item, unit, weather, etc.

At the second level, you define the name of the content to be edited, e.g. conveyor, copper, copper-wall-large. These names are case-sensitive, and will be shown under the content's name in the Core Database if you have the console enabled.

At the third level, you define the properties you will be changing, and their corresponding values. As an example:

block: {
  conveyor: {
    health: 50
    //other properties of the conveyor go here...
  }
  //other blocks here...
}
//other types of content here...

Alternatively, if you are only modifying a single property, it may be more convenient to use the shorthand syntax:

block.conveyor.health: 50

Viewing All Fields for Content

If you are familiar with Java, you can view the relevant content source file, e.g. Block.java for blocks.

If not, you can enable the console in game settings, then click the "View Content Fields" button in the database for a specific block, unit or liquid.

Note that this will only display the fields for that specific class - if you want to see the fields for the superclass, click the link to the page immediately after "extends" on that page.

For example, Conveyors will have all the fields show on their page, as well as everything in the Block superclass.

Accessing Arrays/Sequences

When accessing an array (T[]) or sequence (Seq) is necessary, you may want to do it like so:

//greatly offsets one of dagger's two weapons
unit.dagger.weapons.0.x = 100

Note that modifying the bullet of mirrored weapons will affect both sides, as they share the same bullet type:

//this wall make *both* dagger weapons deal 55 damage
unit.dagger.weapons.0.bullet.damage = 55

Adding vs Overwriting to Arrays/Sequences

Sometimes, it may be necessary to add to a sequence, instead of overwriting it, like so:

//adds a ridiculously overpowered laser to flare's weapons, keeping the others intact
//note the .+ before the field assignment; this adds the element
//also note that it can be a single element, not an array!
unit.flare.weapons.+: {
  x: 0
  y: 0
  reload: 10
  bullet: {
    type: LaserBulletType
    damage: 100
  }
}

Alternatively, you can overwrite the array:

//flare will *only* have this weapon now, its old ones will be overwritten
//also note that, when overwriting, you *have* to use the array brackets [], since you are assigning a new value
unit.flare.weapons: [
  {
    x: 0
    y: 0
    reload: 10
    bullet: {
      type: LaserBulletType
      damage: 100
    }
  }
]

This syntax works for fields of type T[], Seq<T> and ObjectSet.

Extra Examples

'Duoification'

//once again, names are optional, but help identify a patchset in the list
name: Duofication

item: {
  //fissile-matter is an unused item, so use it for demonstration
  fissile-matter: {
    //change the display name of the item to 'Duo'
    localizedName: Duo
    //unhide it
    hidden: false
    //change the in-game icon to 'duo-preview', which is used by the duo turret
    fullIcon: duo-preview
    //change the in-ui icon to 'block-duo-ui', which is also used by the duo turret in UI
    uiIcon: block-duo-ui
  }
}

block: {
  //edit the pulverizer
  pulverizer: {
    //change its name
    localizedName: Duo Factory
    //rewrite the things it consumes
    consumes: {
      //remove all previous consumers - without this line, it would retain its old consumption of scrap
      //you can also remove *only* item consumers by writing `remove: items`
      remove: all
      //consume 1 copper item per craft
      item: copper
    }
    //change the UI display icon
    uiIcon: block-duo-ui
    //change the region
    region: block-duo-full
    //output 1 fissile matter, which was previously patched to have the name 'Duo'
    //note that outputItems is an array, so its contents have to be written as a list with [ and ]
    outputItems: [fissile-matter/1]
    //define the drawers, which define how the block is rendered. they can be defined as an array with []
    drawer: [
      {
        //the first drawer is a simple DrawRegion, which draws the sprite 'block-1', which is the base for 1x1 Serpulo turrets
        type: DrawRegion
        name: block-1
      }
      {
        //the second drawer draws the 'duo-preview' region and rotates it at speed 1
        type: DrawRegion
        rotateSpeed: 1
        name: duo-preview
      }
    ]
  }

}

unit: {
  //patch the dagger unit
  dagger: {
    //change its body region to duo-preview
    region: duo-preview
    //re-define the weapon array (note: this clears all previous weapons)
    weapons: [
      //all weapons in the array are objects of their own, so they need to be encased in {} braces
      {
        //the weapon is centered on the unit
        x: 0
        y: 0
        //reload of 20 ticks (1 second = 60 ticks)
        reload: 20
        //alternate left and right with a spread of 3.5 world units (1 tile = 8 world units)
        shoot: {
          type: ShootAlternate
          spread: 3.5
        }

        //define the bullet the weapon shoots
        bullet: {
          //width and height of the sprite in world units
          width: 7
          height: 9
          //lifetime in ticks (1 second)
          lifetime: 60
          //colors of the bullet as a hex code
          frontColor: eac1a8
          backColor: d39169
        }
      }
    ]
  }
}

Modifying Turret Ammo

block.fuse.ammo: {
  //remove titanium ammo from the ammo map by using the special "-" value
  titanium: "-"
  //add surge alloy ammo that shoots a laser
  surge-alloy: {
    type: LaserBulletType
    //make it produce 1 shot per ammo item
    ammoMultiplier: 1
    //make it shoot half as fast
    reloadMultiplier: 0.5
    damage: 100
    //make it look awful!
    colors: ["000000", "ff0000", "ffffff"]
  }
}

Adding Unit Abilities

//add a new ability to pulsar (note the .+)
unit.pulsar.abilities.+: [
  {
    type: ForceFieldAbility
    //set the maximum health of of the force field to 1000
    max: 1000
  }
]