Rise of Industry Wiki

Introduction[]

This wiki article shows how to add a new building to RoI. We will be creating a new Factory, the Trumpet Factory, which is a factory that can create a new product, the Trumpet. Since we don’t need to implement any custom logic we won’t need to create any code.

You can refer to the Trumpet Factory mod available on Steam Workshop while reading this guide.

Remember that descriptions of all Content Creation Models can be found in the modding documentation and that all built-in RoI assets can be inspected in the Asset Viewer screen reachable from the Main Menu.

We also assume you already read the introductory modding guide on the wiki.

Creating the Assets[]

In this section we show how to create the assets we need for the mod. Remember that in RoI Content Creation the term assets refer to any item in the mod that is not strictly gameplay related, for example an icon or a 3d model.

The Trumpet Factory Visualization[]

The first thing we’ll be doing is creating a visualization for the new factory. To do so we need to use Unity3D. Please download the free edition of Unity3D version 2018.1.0f2 if you don’t have it installed on your system already. Once you are ready create a new Unity3D project and name it however you like, for example TrumpetFactoryContentProject. The purpose of this project is to create an asset bundle from it.

Our goal is to create the prefab that we will use in game as the visual representation of the building. Before doing that we need to import the RoI Modding SDK to the project. When the SDK is imported the menu bar of the Unity3D editor will show a new item called RoI Modding. This menu has only one command: Export Asset Bundles. We will need to invoke this command once all our assets are ready.

The bare minimum we need to import is an FBX file. The dimensions of your building have to be integer numbers because in RoI a world tile measures 1x1 units. For example a building 3d model could measure 3 units along the X axis and 5 units along the Z axis, but not 3.5 or 4.2 units.

Once you have your model showing up correctly in Unity3D we need to create a prefab. To do so we recommend to create an empty GameObject and to parent it to the FBX you imported. We do so because we want our visualization to be positioned in a specific way. The only real rule that you need to make sure to respect is that the origin of your child object is at the center of any of the tiles.

Now we are ready to export the building. First assign an asset bundle to it, any name will do. Then use the menu command RoI Modding -> Export Asset Bundles. This will result in multiple files being created. The only one we need is the one with the *.bundle extension. We will need to put that file inside the content folder of our mod.

In case you want to also add a custom placement sound for your building make sure to import an audio file in the Unity3D project and include it in the asset bundle.

Other Assets[]

We will need an SVG icon for the new building and the product. In our sample mod we used a single SVG for both, but you can add any number of SVG files to the assets folder of your mod.

We also need two more images. An image to show in the Construction Bar and another one to show in the Building Panel header section. In the sample mod you’ll find two *.png files. Adding the image files themselves is not enough, you also need to create *.sprite files.

Example of a *.sprite file:

{

"textureName": "TrumpetFactoryConBarTex",

"rectPos": {

  "x": 0,

  "y": 0

},

"rectSize": {

  "x": 1098,

  "y": 714

},

"pivot": {

  "x": 0.5,

  "y": 0.5

}

}

The textureName field has to be the name of the image file without the file extension. The *.sprite format allows you to specify a rectangle that will crop the image when displayed in the game. The rectPos field represents the X and Y coordinates of the bottom left corner of this rectangle. The rectSize field represents the dimensions of the image. The above example shows how to configure those fields to show the whole image. Last field is pivot and it’s used to specify where the origin of the image is. For our purposes just use 0.5 for both the X and Y coordinates.

Creating the Content[]

In this section we will describe the *.json files needed to add the new Trumpet Factory building and the related new Trumpet product.

The Trumpet Product[]

The first content item we are going to create is the Trumpet product:

{

 "type": "ProjectAutomata.ProductDefinition",

 "object":

 {

   "name": "Trumpet",

   "displayName": "Trumpet",

   "description": "A very special instrument :>",

   "svgIcon": "TrumpetIcon",

   "category": "Row3",

   "tags": ["HomeGoods"],

   "priceFormula": "Row3"

 }

}

Notice how the tags field can be used to indicate which shops sell the product. You can check out existing tags in the Asset Viewer. Same goes for formula, category and any other type of asset. You can even create your own formulas and categories if you want, although that is not showcased in this guide.

The Trumpet Recipe[]

In RoI having a product is not enough, you also need a recipe. A recipe describes how the product is made. This is the content of the *.json file we used to create the Trumpet recipe:

{

 "type":"ProjectAutomata.Recipe",

 "object":

 {

   "name":"TrumpetRecipe",

   "displayName":"Trumpets",

   "description":"A very special instrument :>",

   "svgIcon": "TrumpetIcon",

   "gameDays": 45,

   "ingredients": [

     {

       "productName": "IronOre", "amount": 10

     },

     {

       "productName": "Copper", "amount": 10

     }],

   "result": [

     {

       "productName": "Trumpet", "amount": 1

     }]

 }

}

All fields here should be self explanatory.

The Unlocks[]

We will also need the Tech Tree Unlocks used to unlock the new building and recipe. Let’s being with the building unlock:

{

 "type": "ProjectAutomata.TechTreeBuildingUnlock",

 "object": {

   "name": "TrumpetFactoryUnlock",  

   "building": "TrumpetFactory"

 }

}

This unlock is very simple because it’s not added to any tech tree in the game. The only field we need is the one named building that is used to specify which building is unlocked.

The unlock for the recipe is fairly more complex:

{

 "type": "ProjectAutomata.TechTreeRecipeUnlock",

 "object": {

   "svgIcon": "TrumpetIcon",

   "name": "TrumpetUnlock",

   "displayName": "Trumpets!",

   "description": "Unlocks trumpets!",

   "includedUnlocks": ["TrumpetFactoryUnlock"],

   "researchCost": "Research Cost",

   "researchTime": "Research Time",

   "tier": 2,

   "trees": [

     {

       "tree": "Home Goods",

       "column": 8

     }

   ],

   "recipes": ["TrumpetRecipe"]

 }

}

First of all we set icon, display name and description. These fields are all used by the Tech Tree panel in game. Notice how we have both the name and the displayName fields. The former is used when other *.json files need to reference this unlock, the latter is what is displayed in game. The field includedUnlocks is used to list all unlocks that will be automatically granted to the player together with this unlock. In our case we want the unlock the new factory when the player finishes researching the recipe. This is also how our own recipe unlocks work. The fields researchCost and researchTime refer both to formula assets you can lookup in the AssetViewer. They are the formulas used to compute the cost of researching the unlock and the time needed for it. The tier field indicates the tech tree row where the unlock is displayed. This applies to all trees the unlock may appear into. The field trees is used to specify the trees where the unlock will appear. For each element we specify the name of the tech tree asset (use the Asset Viewer to investigate the existing tech tree assets) and the column where the unlock should appear. Remember that the row is specified by the tier field of the unlock. Finally the recipes field indicates which recipes are unlocked by this unlock. We want to unlock our new recipe which is named TrumpetRecipe.

The Trumpet Factory Building[]

This is the most complex part of this guide as it explains how to set up the new factory building. As you should know a building is described by a set of properties common to all buildings plus a set of components that can be plugged in to add functionality to the building.

Let’s start with the common properties:

{

"type": "ProjectAutomata.Building",

"object": {

  "contextBasedUI": "BuildingPanel",

  "topoXMinOffset": -2,

  "topoXMaxOffset": 1,

  "topoYMinOffset": 0,

  "topoYMaxOffset": 4,

  "restrictions": [

    "Can Afford",

    "Can Build At",

    "Influent Enough",

    "Owns Permit",

    "Factory Settlement Distance",

    "Not Too Close To Any Resource"

  ],

  "nameFormat": "%n %i",

  "parkingPathTransforms": [

    "TrumpetFactoryVisualization"

  ],

  "connections": [

    {

      "x": 0,

      "y": -1,

      "direction": "North",

      "tilesAmt": 1,

      "tier": 1,

      "invisible": false,

      "impliesConnectivities": true,

      "connectionType": "DEFAULT",

      "network": "Road"

    }

  ],

  "visualization": "TrumpetFactoryVisualization",

  "buildingName": "Trumpet Factory",

  "buildingPanelName": "Trumpet Factory",

  "description": "A factory for a very special instrument",

  "baseCost": 150000,

  "spawnDust": "Building_Dust_PS",

  "uiOrder": 0,

  "category": "HeavyIndustry",

  "name": "TrumpetFactory",

  "svgIcon": "TrumpetIcon",

  "headerImage": "TrumpetFactoryHeader",

  "constructionBarIcon": "TrumpetFactoryConBar",

  "placementClip": "Sad Trombone"

},

"components": [

  ... Components here ...

]

}

Here we are going to describe the fields that are the most important to get started. Fields starting with the topo* prefix are used to tell the game how large is the building. For example the Trumpet factory is a 4x5 tiles building. The offsets we use for the X dimensions are -2 and 1. This indicates that the leftmost tile of the building is located 2 tiles to the left of the visualization origin while the rightmost one is located 1 tile to the right of it. That makes up for 4 tiles in total, just as expected. Same reasoning applies to the other axis.

The restrictions are used to specify where the building can be placed. For now you can just use the same ones we used in this example but in the future you may want to refer to the Asset Viewer and the modding documentation to get more details.

The connections field defines where the connection tiles of the building are located with respect to the origin tile. It specifies where the small road tile connected to the building appears. Notice how you can have multiple connections on a building, just like the RoI Train Station.

The field visualization should be set to the name of the prefab you exported in the asset bundle we created earlier.

The placementClip field specified which audio clip to play when the building is placed. In our case the Sad Trombone asset is loaded from the asset bundle together with the building visualization.

Now let’s check out some of the most interesting components:

{

 "type": "ProjectAutomata.Building",

 "object": {

   ... Same as before ...

 },

 "components": [

   {

     "type": "ProjectAutomata.Factory",

     "object": {

       "initialRecipe": "TrumpetRecipe",

       "productionSpeed": 1,

       "availableRecipes": ["TrumpetRecipe"]

     }

   },

   ...

   {

     "type": "ProjectAutomata.JITIVehicleFleet",

     "object": {

       "vehiclePrefab": "BreweryTruck",

       "maximumVehicleAmount": 25

     }

   },

   {

     "type": "ProjectAutomata.LogisticsVehicleDispatcher",

     "object": {

       "dispatchInterval": 2,

       "fleet": 0,

       "dispatchCost":  "AutoWHDispatchCost",

       "dispatchCostBillCategory": "VehicleUpkeep"

     }

   },

   {

     "type": "ProjectAutomata.WarehouseClient",

     "object": {

     }

   },

   {

     "type": "ProjectAutomata.TransportJobDelegator",

     "object": {

       "pathNotFoundNotification": "Path Not Found",

       "storageFullNotification": "Destination Storage Full",

       "fleet":  0,

       "network": "Road",

       "dispatchCostAnalysisItemDef":  "DispatchCosts",

       "dispatchCountAnalysisItemDef": "TrucksDispatched",

       "dispatchCost": "TransportDispatchCost",

       "dispatchCostBillCategory": "VehicleUpkeep",

       "slotCount": 3,

       "trucksPerDay": 3

     }

   },

   {

     "type": "ProjectAutomata.BuildingEfficiency",

     "object": {

       "efficiencyModifierValues": [0.25, 0.50, 0.75, 1, 1.25, 1.5, 2],

       "upkeepModifierValues": [0.4, 0.6, 0.8, 1, 1.5, 2, 3],

       "unlocks": [

         "FactoryEfficiencyL7",

         "FactoryEfficiencyL6",

         "FactoryEfficiencyL3_L5",

         null,

         "FactoryEfficiencyL3_L5",

         "FactoryEfficiencyL6",

         "FactoryEfficiencyL7"

       ],

       "initialEfficiencyIndex": 3

     }

   },

   {

     "type": "ProjectAutomata.BuildingRequirementController",

     "object": {

     }

   },

   {

     "type": "ProjectAutomata.BuildingRequirementStorageSpace",

     "object": {

       "causesBuildingDeactivation":  false,

       "notification": "Storage Full"

     }

   },

  ...

 ]

}

The Factory component specifies that this building is indeed a factory.

The JITIVehicleFleet is used to specify which vehicle type this building will use (use the Asset Viewer). The number of trucks available is specified by the maximumVehicleAmount field. Notice how with RoI Content Creation you can also create your own vehicles (not explained here).

The LogisticsVehicleDispatcher and WarehouseClient components are mandatory if you want the Auto Warehouse feature to work with your building.

The TransportJobDelegator handles manual destinations. You need one if you want to use them.

The BuildingEfficiency component adds the efficiency slider to your building. If you don’t plug it in then your building will always use an efficiency of 100%.

The BuildingRequirementController is the component that checks everything is alright with the building. It is used to display notifications and to stop the building production when something.

Adding the BuildingRequirementController alone is not enough. For each requirement you want to add you’ll need a specific component. The Trumpet Factory has more than one but here we only show the first, the BuildingRequirementStorageSpace. This requirement mandates that the building should not have full storage. If that happens a notification (specified by the notification field which refers to a NotificationSpecification asset) will pop up. Also the causesBuildingDeactivation can be set to true in which case the factory will be forced to stop working while the requirement is not met.

Conclusion[]

We really hope this guide was helpful to get you started with RoI Content Creation of buildings. This is just a summary and more info can be gathered by looking at the mod available on the Steam Workshop.

Also don’t forget to check out the modding wiki and the Asset Viewer.

Now go create some great mods!