Difference between revisions of "Furniture Modding"

From Software Inc.
Jump to navigation Jump to search
 
(81 intermediate revisions by the same user not shown)
Line 1: Line 1:
 +
Furniture packages should be located in subfolders in the "Furniture" folder with the game. A furniture package will inherit its name from the folder name. Furniture is created using the [[TyD|TyD]] data language.
 +
 +
== Helpful console commands ==
 +
 +
* '''RELOAD_FURNITURE''' - Reloads all furniture mods immediately, does not affect already placed furniture
 +
* '''FURNITURE_DEBUG True''' - Adds an in-game overlay to the selected furniture showing its boundary, navigation mesh, interaction points and snap points
 +
* '''FURNITURE_THUMBNAIL X''' - Generates a thumbnail for the the furniture named X and places it in the Furniture folder. This command only works in the main menu
 +
* '''EXPORT_FURNITURE_BOUNDS X''' - Exports the auto generated furniture boundaries (created by adding the '''AutoBounds True''' record) and puts it in the TyD file for the furniture named X. This should be done when you're finished with the furniture, to avoid having the game generate them on every startup. This also allows you to change them in the TyD file. Note that this action removes any special formatting and comments.
 +
* '''EXPORT_FURNITURE_POINTS X''' - Exports snap and interaction points for the the furniture named X and writes it to its TyD file. You can use this to inspect snap and interaction points for any furniture in the game, by using the Base furniture override. If these are already overridden in the file, it will just write out the same points twice.
 +
* '''UNLOCK_FURNITURE''' - Allows you to place furniture that hasn't been unlocked in-game
 +
* '''GENERATE_LOCALIZATION''' X - Generates localization files based on the mod named X
 +
 
== Furniture modding ==
 
== Furniture modding ==
Furniture modding is available as of Alpha 8.10.13
+
=== Tutorial ===
 +
Check out a video tutorial on how to create furniture mods here:
 +
 
 +
‎<youtube>Lz_0CHwb74Q</youtube>
 +
 
 +
=== TyD file layout ===
 +
[[File:FurnitureModLayout.png]]
 +
 
 +
Each furniture should be defined in separate  [[TyD|TyD]] files.
 +
 
 +
The root table should have a '''Thumbnail''' record with a relative path to a 128x128 thumbnail to use in-game.
  
Furniture packages should be located in subfolders in the “Furniture” folder with the game. A furniture package will inherit its name from the folder name.
+
The root table can also have a '''Base''' record to inherit from an existing furniture from the game. If you define the record '''AutoBounds True''', the game will auto generate the navigation mesh, building boundary, vertical span, x and y grid offset, width and vertical offset for wall furniture, and collision box for selection, based on the furniture meshes, otherwise these can be controlled in the Furniture component by setting the variables BuildBoundary, NavBoundary, Height1, Height2, OnXEdge, OnYEdge, WallWidth, YOffset and the BoxCollider component.
  
You can reload furniture while in-game by bringing up the console and executing the RELOAD_FURNITURE command.
+
You can check your build and navigation boundary, and interaction and snap points by enabling furniture debugging using the command '''FURNITURE_DEBUG True''' in the console and selecting the furniture you want to review in-game. The navigation boundary is located on the floor and goes from green to pink. The build boundary also illustrates Height1 and Height2 and goes from cyan to red. Interaction points are blue and snap points are yellow:
You can generate thumbnails by bringing up the console in the main menu and executing the FURNITURE_THUMBNAIL command with the name of your furniture as parameter.
 
  
=== XML Generator ===
+
[[File:FurnDebug.png]]
[http://demannu.com/softwareinc/gen.php Furniture XML Generator]
 
This tool is currently under development, it is stable for producing basic XML files for objects
 
  
=== The XML and basic tags ===
+
'''It is highly recommended that you run the command EXPORT_FURNITURE_BOUNDS with your furniture name as parameter, if you've used the ''AutoBounds True'' record. This command bakes the bounds information in the TyD file so it doesn't have to be recalculated each time the game launches. Note that it reformats and removes comments from your file.'''
Each furniture should be defined in separate XML files.
 
  
The root tag in a furniture xml file should have a Thumbnail attribute with a relative path to a 128x128 thumbnail it should use in-game.
+
=== Hierarchy ===
 +
Every object you add to your furniture can be given a name using a '''ComponentName''' record and can be added as a child transform to another object by using a '''TransformParent''' with the ComponentName of the other object. If '''TransformParent''' is not defined, the object will be added to the root furniture object.
  
The root tag can also have a Base attribute to inherit from an existing furniture from the game. If you define the attribute AutoBounds to “True”, the game will auto generate the navigation mesh, building boundary, vertical span, x and y grid offset, width and vertical offset for wall furniture, and collision box for selection, based on the furniture meshes, otherwise these can be controlled in the Furniture component by setting the variables BuildBoundary, NavBoundary, Height1, Height2, OnXEdge, OnYEdge, WallWidth, YOffset and the BoxCollider component.
+
You can define a list of empty Transforms using a '''Transform''' list with tables that define a '''Name''' (instead of '''ComponentName'''), '''Position''' and '''Rotation''' (in degrees as Euler angles).
  
You can check your build and navigation boundary, and interaction and snap points by enabling furniture debugging using the command "FURNITURE_DEBUG True" in the console and selecting the furniture you want to review in-game. The navigation boundary is located on the floor and goes from green to pink. The build boundary also illustrates Height1 and Height2 and goes from cyan to red. Interaction points are blue and snap points are yellow:
+
You can add Unity components to any tranforms and objects by using the '''TransformParent''' record in a table that has the same name as the UnityComponent you want to add. As an example, you can add a Unity '''Light''' component to a '''Transform''' and pass the transform's name to the '''Furniture''' component's '''ColorableLights''' list and you now have a light that changes color based on what the player picks. Just make sure they are defined in the correct order (You can't refer to a TransformParent that hasn't been created yet).
  
[[File:FurnDebug.png]]
+
'''Transforms'''
 +
[
 +
{
 +
'''Name''' <span style="color:blue">LightUp</span>
 +
'''Position''' [ <span style="color:blue">0</span>; <span style="color:blue">0.5</span>; <span style="color:blue">0</span> ]
 +
'''Rotation''' [ <span style="color:blue">0</span>; <span style="color:blue">0</span>; <span style="color:blue">0</span> ]
 +
}
 +
]
 +
'''Light'''
 +
{
 +
'''TransformParent <span style="color:blue">LightUp</span>
 +
'''range''' <span style="color:blue">10</span> <span style="color:green">#This is a variable from the Unity Light component, refer to the Unity docs</span>
 +
'''intensity''' <span style="color:blue">10</span>
 +
}
 +
'''Furniture'''
 +
{
 +
'''ColorPrimaryEnabled''' <span style="color:blue">True</span>
 +
'''LightPrimary''' <span style="color:blue">True</span>
 +
'''ColorableLights''' [ <span style="color:blue">LightUp</span> ]
 +
}
  
'''It is highly recommended that you run the command EXPORT_FURNITURE_BOUNDS with your furniture name as parameter if you've used the AutoBounds attribute. This command bakes the bounds information in the XML file so it doesn't have to be recalculated each time the game launches.''' This command has been introduced in alpha 8.10.15.
+
=== Naming your furniture ===
 +
Your furniture will take its name from the '''Name''' record in the root table of your TyD file or from the filename, if it is an XML file. As of Alpha 11.4.10, this name should be considered an ID and not what the player will see, so you should try and make it as unique as possible, to avoid clashing with vanilla furniture or furniture from other mods. To name your furniture in the UI use the '''LocalizedName''' variable in the '''Furniture''' component table (Not the root table! [[Furniture_Modding#Furniture|See all varibles here]]) and use the '''GENERATE_LOCALIZATION your_mod_name''' console command to generate the localization files for your mod. To find your furniture's name in the UI, the game will lookup your mods ID/filename and return the LocalizedName that has been exported with the GENERATE_LOCALIZATION command. This has the added benefit of allowing people to translate your mod to other languages.
  
 
=== Meshes and materials ===
 
=== Meshes and materials ===
Meshes will be loaded from the Models tag. The Models tag should contain children tags that define meshes. Each mesh tag should have a File tag, with the relative path to an obj file, a Position, Rotation and Scale. Optionally, the mesh tag can have a Parent tag, to make it a child transform of the ith mesh loaded (Zero index), a ComponentName tag to name the mesh for later reference and a Material tag to give it a material.
+
Meshes will be loaded from the Models list. The Models list should contain a list of tables that define meshes. Each mesh table should have a File record, with the relative path to an .obj file, a Position, Rotation (in degrees as Euler angles) and Scale (Should always be positive). Optionally, the mesh tag can have a '''TransformParent''' record, to make it a child transform of an object with the specified name, a '''ComponentName''' record to name the mesh for later reference(e.g. to make it a parent for another mesh or transform) and a '''Material''' record to give it a material.
  
Materials can either be any material you want or the default material, which is much better performance wise and allows the player to colorize the furniture. If you don't specify a material, the default material will be used and the meshes should be UV mapped according to the texture shown below. You can also supply your own texture to be used by the default material, in which the red color channel will be mapped to color 1, green is color 2 and blue is color 3. Grayscale pixels will not be color mapped. The alpha channel controls smoothness/specularity where 99% transparent means full specularity. 100% transparency is specifically used for glow in the dark materials, but note that Photoshop destroys RGB channels for transparent pixels when you save as PNG, unless you keep the alpha mask on your layers before you save and you need to have a color defined for the glow.
+
If you omit the Material record, it will automatically select the in-game default furniture material, which has great performance and allows the player to colorize the furniture. The default material works by mapping the Red, Green and Blue channels to the colors the players has picked for the furniture, while greyscale pixels remain greyscale. Furthermore, the alpha channel is used to control material smoothness and emission/glow. 100% alpha will make the material rough and then smoother as the alpha decreases, 0% alpha will make the material glow in the dark (Note that some image editing software will destroy your RGB channels if the alpha channels is 0%, e.g. Photoshop). If you use the default material, you should UV map your furniture to the texture pictured below. You can also set the Material record to '''Glass''' to use the in-game glass shader.
  
 
[[File:NewFurnUV.png]]
 
[[File:NewFurnUV.png]]
  
If you decide to use your own materials, you should have a Materials XML file in your furniture package folder, in which you define your materials. The Materials.xml file should have a root tag with material tags as children and each material will be named as its tag. If a material tag has the the Standard attribute as shown below, you should supply a relative path to one 256x256 texture in the a child <Texture> tag, which will be used for the standard colorable texture (as described above), any other child tag will be ignored:
+
If you want to use your own materials and textures, you need to add a '''Materials.tyd''' file. It should contain a list of tables that define your materials. The first record in a material table should be the '''Type''', which can be one of the following values:
 
+
* Unity, the default Unity standard shader as of Unity 2017.4 (http://unity3d.com/get-unity/download/archive)
<MyMaterial Standard="True">
+
* Standard, the default furniture shader used in-game
 +
* Atlas, a shader that allows the player to change the furniture texture, which works well for paintings
 +
* Masked, works like the standard shader with RGB mapping, but has 100% emission and transparency from the alpha channel using dithering
  
If you want a completely custom material, you should have up to three children: Textures, Floats and Colors. All materials use Unity’s default material. If you want to set the texture you would write <_MainTex>test.png</_MainTex>. All textures will be loaded in 256x256. If you want to see all the colors, floats and textures you can change, refer to Unity’s default shader, which can be downloaded here: http://unity3d.com/get-unity/download/archive . Some variables include:
+
For each material you can add a '''Texture''' record to refer directly to an image file to use as the materials main texture. Each material table can have 3 tables
 +
* Textures
 +
* Floats
 +
* Colors
 +
Each can contain a set of records that define textures, numbers and colors, where the record names should reference actual shader variables as defined in Unity, e.g:
 
* _MainTex
 
* _MainTex
 
* _BumpMap
 
* _BumpMap
Line 44: Line 89:
 
* _Color
 
* _Color
  
To apply the material to a model, simply add a Material tag to the model naming your material.
+
==== The standard furniture shader ====
 +
As described above the default standard furniture shader works by mapping the Red, Green and Blue channels to the colors the players has picked for the furniture. This also means that dark red will darken the color the player has chosen, so the color #800000, will darken the player's primary color by 50%. This can be used to add shadows and occlusion to your textures, while still allowing for player coloring.
 +
 
 +
Outside of the '''Texture''' record, this shader can also have a '''NormalMap''' record, to add normal maps to your furniture. Note that this incurs a small performance penalty. The alpha value of the normal map is used to make the material more or less metal looking, a value of 0% alpha will make the material look completely metallic.
 +
 
 +
There is also an '''ExtraMap''' record, which allows you to control smoothness with the Red channel, Emission strength with the Green channel and finally the Blue channel controls whether to use the color in the main texture as is or map it to the player color. The Blue channel of this texture will allow you to have static colors on parts of your furniture, while still allowing for player coloring. Having an ExtraMap makes the shader ignore the alpha channel of the main texture.
 +
 
 +
Watch a tutorial on how to create textures for the standard shader here:
 +
 
 +
<Youtube>Xq_ysZb-bAA</Youtube>
 +
 
 +
==== The atlas shader ====
 +
The atlas shader allows you to use a texture as grid, and only map a section of it to the furniture at a time. For this you need to define these variables in the Furniture table:
 +
* AtlasObject - The mesh that should use atlas texturing, this should be the '''ComponentName''' defined in the '''Models''' section of your furniture.
 +
* AtlasDimensions - The width and height of your texture atlas, e.g. '''[ 2; 2 ]''' if you have a 2 by 2 texture atlas
 +
* AtlasCount - The amount of images in your atlas, e.g. 3 if you're only using the (first row) and (second row, first column) of your atlas
 +
* AtlasColorable - Whether the atlas texture can also be RGB mapped like the standard shader. Remember to set "RGBMapping True" in your atlas material definition for this to work
 +
* AtlasOff - How many images to skip in atlas, most likely zero, relevant if using the same atlas for multiple furniture
 +
* AtlasSkip - Only take every Xth image in atlas(after skip), most likely one, relevant if using the same atlas for multiple furniture
  
 
=== Interaction points ===
 
=== Interaction points ===
Line 50: Line 113:
 
Interaction points control how employees can interact with a piece of furniture.
 
Interaction points control how employees can interact with a piece of furniture.
  
If you have used the Base attribute, the furniture will inherit its interaction points from the base furniture, unless you add the “InteractionPoints” tag.
+
If you have used the '''Base''' record, the furniture will inherit its interaction points from the base furniture, unless you add the "InteractionPoints" list.
  
Interaction points should define a Name, which at this point in time includes “Use”, “Repair”, “Serve”, “Social” and “Visit” for the base game. They should also have Position and Rotation defined.
+
Interaction points should define a '''Name''', which at this point in time includes "Use", "Repair", "Serve", "Social" and "Visit" for the base game. They should also have '''Position''' and '''Rotation''' defined.
You can define a ComponentName tag to name the interaction points for later reference.
+
You can define a '''ComponentName''' record to name the interaction points for later reference.
  
Interaction points can also define Animation(main animation used when interacting, ignored for some interactions), SubAnimation(used for repairs, 0, 1 or 2 for repair height), MinimumNeeded(how many need to be reachable before the player gets a warning) and ReachCheck(whether we should warn the player at all).
+
Interaction points can also define '''Animation'''(main animation used when interacting, ignored for some interactions), '''SubAnimation'''(used for repairs, 0, 1 or 2 for repair height), '''MinimumNeeded'''(how many need to be reachable before the player gets a warning), '''ReachCheck'''(whether we should warn the player at all), '''MainAction'''(whether the feet graphic should appear dark or not to tell the player whether it's important), '''ShowOnBuild'''(can be used to hide the feet graphic) and '''Outside'''(tells the game that this interaction point is used from the outside, which currently only used for garage ports).
  
 
Finally, it can define a Child, which is the ith interaction point defined (Zero index). If you want a number of interaction points to only be used by one employee at a time you should define children such that they form a dependency loop(E.g. 0->1->2->3->0). When one interaction point gets reserved, the children will recursively get reserved as well.
 
Finally, it can define a Child, which is the ith interaction point defined (Zero index). If you want a number of interaction points to only be used by one employee at a time you should define children such that they form a dependency loop(E.g. 0->1->2->3->0). When one interaction point gets reserved, the children will recursively get reserved as well.
Line 62: Line 125:
 
Snap points are points at which certain furniture can be snapped to other furniture, like chairs to tables.
 
Snap points are points at which certain furniture can be snapped to other furniture, like chairs to tables.
  
If you have used the Base attribute, the furniture will inherit its snap points from the base furniture, unless you add the “SnapPoints” tag.
+
If you have used the '''Base''' record, the furniture will inherit its snap points from the base furniture, unless you add the "SnapPoints" list.
 +
 
 +
Snap points should define a Name, which will control which furniture can snap to it, currently in use in the base game is "PCAddon", "AtTable" and "OnTable". "Food" is also used in the game for tables which should allow for food but not OnTable furniture, like benches. They should also have Position and Rotation defined.
  
Snap points should define a Name, which will control which furniture can snap to it, currently in use in the base game is “PCAddon”, “AtTable” and “OnTable”. “Food” is also used in the game for tables which should allow for food but not OnTable furniture, like benches. They should also have Position and Rotation defined.
+
You can define a '''ComponentName''' record to name the snap point for later reference.
  
You can define a ComponentName tag to name the snap point for later reference.
+
Snap points can also have '''CheckValid''' defined, which controls whether the game should allow for something to be placed no matter if there are collisions. This collision calculation is heavy, but not needed for stuff like computers and computer add-ons, so you can leave this off in most cases.
  
Snap points can also have “CheckValid” defined, which controls whether the game should allow for something to be placed no matter if there are collisions. This calculation is heavy, but not needed for stuff like computers and computer add-ons.
+
You can also define its '''Group''', which should be a number above 0, all snap points with the same group number will be grouped together such that only one of them can be used at any time.
  
Finally, snap points can define Links, which is a comma separated list of linked snap points, referencing the ith snap point defined (zero index). Links are currently used to link chairs with computers and chairs with food. E.g. for the square table, the OnTable point is linked to all AtTable points around it. The bench does not have chairs and instead the “Use” interaction points are defined in the same order as its “Food” snap points so the game knows where to put the employee’s food and how to save it to a file.
+
Finally, snap points can define Links, which is a comma separated list of linked snap points, referencing the ith snap point defined (zero index). Links are currently used to link chairs with computers and chairs with food. E.g. for the square table, the OnTable point is linked to all AtTable points around it. The bench does not have chairs and instead the "Use" interaction points are defined in the same order as its "Food" snap points so the game knows where to put the employee’s food and how to save it to a file.
  
 
=== Replacements/upgrading ===
 
=== Replacements/upgrading ===
The root tag can use the UpgradeFrom and UpgradeTo attributes to control which furniture can be replaced with your furniture and which furniture your furniture can be replaced with. A furniture can be replaced by any furniture which UpgradeFrom or UpgradeTo matches the furniture's UpgradeTo.
+
You can add '''UpgradeFrom''' and '''UpgradeTo''' records to control which furniture can be replaced with your furniture and which furniture your furniture can be replaced with. A furniture can be replaced by any furniture which UpgradeFrom or UpgradeTo matches the furniture's UpgradeTo. Example:
<pre><Root UpgradeFrom="Server" UpgradeTo="Big Server"></pre>
+
'''UpgradeFrom''' <span style="color:blue">Server</span>
This furniture can be replaced by any furniture that has UpgradeFrom="Big Server" or UpgradeTo="Big Server", and any furniture that has UpgradeTo="Server" or UpgradeTo="Big Server" can be replaced by this furniture, but this furniture cannot be replaced by furniture that has UpgradeTo="Server". This is used to avoid upgrading a server that sits on the floor to a server that sits on a table, as the table would have to be created out of thin air.
+
'''UpgradeTo''' <span style="color:blue">"Big Server"</span>
 +
This furniture can be replaced by any furniture that has '''UpgradeFrom "Big Server"''' or '''UpgradeTo "Big Server"''', and any furniture that has '''UpgradeTo "Server"''' or '''UpgradeTo "Big Server"''' can be replaced by this furniture, but this furniture cannot be replaced by furniture that has '''UpgradeTo "Server"'''. This is used to avoid upgrading a server that sits on the floor to a server that sits on a table, as the table would have to be created out of thin air.
  
 
[[File:UpgradePath.png|frame|Boxes represent furniture with the corresponding upgrade groups and arrows show what they can be replaced with.]]
 
[[File:UpgradePath.png|frame|Boxes represent furniture with the corresponding upgrade groups and arrows show what they can be replaced with.]]
  
 
==== In-game upgrade groups ====
 
==== In-game upgrade groups ====
*'''Big ProductPrinter''' (Large Product Printer)
 
 
*'''Big Server''' (Tower Server, Server Rack, Big Server Rack)
 
*'''Big Server''' (Tower Server, Server Rack, Big Server Rack)
*'''Chair''' (Cheap Chair, Office Chair, Executive Chair)
+
*'''Chair''' (Cheap Chair, Office Chair, Executive Chair, ErgoChair, Yoga Ball)
 
*'''Coffee''' (Instant Coffee, Coffee, Espresso Machine)
 
*'''Coffee''' (Instant Coffee, Coffee, Espresso Machine)
 +
*'''CompanyLogo''' (Company Logo, Company Logo Big, Company Logo High)
 
*'''Computer''' (Old Computer, 90s Computer, Laptop, Modern Computer, HoloComputer)
 
*'''Computer''' (Old Computer, 90s Computer, Laptop, Modern Computer, HoloComputer)
*'''Couch''' (Waiting Chairs, Couch)
+
*'''Conveyor''' (Component Recycler, Conveyor Belt, Ceiling-mounted Conveyor Belt, Conveyor Ramp, Conveyor Splitter)
 +
*'''ConveyorPallet''' (Pallet Drop Point, Pallet Pickup Point)
 +
*'''Couch''' (Waiting Chairs, Couch, ModernCouch, LeatherCouch)
 
*'''Cubicle''' (Cubicle wall)
 
*'''Cubicle''' (Cubicle wall)
*'''Floor Decoration''' (Floor Lamp, Outdoor Lamp, Floor Plant, Big Plant)
+
*'''Desk''' (Desk, MordernDesk, ServingTable)
*'''Misc Ceiling''' (Ceiling Fan, Lamp, Fluorescent lamp)
+
*'''Floor Decoration''' (Floor Lamp, Outdoor Lamp, Floor Light, Floor Plant, Big Plant, SquareCarpet, CornerCarpet, RoundedCarpet, InvRoundedCarpet, BigCarpet, RoundCarpet, Cozy Tree)
 +
*'''FloorGrill''' (Heating Floor Grill, Cooling Floor Grill)
 +
*'''Manufacturing''' (Component Printer, Component Assembler)
 +
*'''Misc Ceiling''' (Ceiling Fan, Lamp, Fluorescent lamp, Sprinkler)
 
*'''Misc Food''' (Vending Machine, Fridge, Stove, WaterCooler)
 
*'''Misc Food''' (Vending Machine, Fridge, Stove, WaterCooler)
*'''PCAddon''' (Phone, Drawing Tablet, Calculator, Inbox)
+
*'''PCAddon''' (Phone, Drawing Tablet, Calculator, Inbox, Headphones)
*'''ProductPrinter''' (Large Product Printer, Small Product Printer, Medium Product Printer)
+
*'''ProductPrinter''' (Small Product Printer, Medium Product Printer)
 
*'''Server''' (Tower Server, Server Rack, Big Server Rack, Small Server, Medium Server)
 
*'''Server''' (Tower Server, Server Rack, Big Server Rack, Small Server, Medium Server)
*'''Standard Table''' (Table, Glass Table)
+
*'''Standard Table''' (Table, Corner Table, Glass Table)
 
*'''Table Decoration''' (Desk Lamp, Table Plant, Table Cactus)
 
*'''Table Decoration''' (Desk Lamp, Table Plant, Table Cactus)
 
*'''Toilet''' (Toilet)
 
*'''Toilet''' (Toilet)
*'''Tree''' (Small tree, Small pine tree)
+
*'''Tree''' (Small tree, Small pine tree, Money Tree)
*'''WallDeco''' (Wall Lamp, Painting, TV, Clock)
+
*'''WallDeco''' (Wall Lamp, Painting, Acoustic Foam, Acoustic Diamond Panel, Acoustic Hex Panel, TV, Clock)
*'''WallVent''' (Ventilation, AC Unit, Industrial ventilation)
+
*'''WallSec''' (Fire Alarm, Security camera)
 +
*'''WallVent''' (AC Unit, Ventilation, Industrial ventilation)
  
 
==== Limitations ====
 
==== Limitations ====
 
The game will be able to destroy tables if you're replacing something on a table with something that is not on a table, e.g. small server and server rack, but not the other way around. The game won't build new tables automatically, so you should be careful in differentiating between "UpgradeFrom" and "UpgradeTo", as these will not always be the same.
 
The game will be able to destroy tables if you're replacing something on a table with something that is not on a table, e.g. small server and server rack, but not the other way around. The game won't build new tables automatically, so you should be careful in differentiating between "UpgradeFrom" and "UpgradeTo", as these will not always be the same.
 +
 +
=== Mesh replacements ===
 +
You can add mesh replacements, which work kind of like the texture atlas, but allow the player to replace entire meshes + materials for a piece of furniture. This feature is only available as of Beta 1.7.35.
 +
 +
Replacements are grouped together, replacement groups can be mapped to one or more furniture. As an example, all stairs in the game use 2 replacement groups: "Stairs" and "Railings". Each group contains a list of possible replacements for that group, e.g. "metal", "glass", "fence". The replacement has a thumbnail for the UI and a material that all meshes that get replaced will use, when that replacement is active. Each replacement also has a list of key/mesh pairs, which tell the game which objects should use which mesh when that replacement is active, e.g "Stairs", "Platform" and "Support" for the "Stairs" replacement, and "Pole" and "Railing" for the "Railing" replacement.
 +
 +
So the overall structure is:
 +
 +
Replacement group -> replacements -> meshes
 +
 +
To add mesh replacements, you need to add a "replacements.tyd" to the root of your mod folder. Here's an example of a replacement file:
 +
'''TelephoneReplacementGroup'''
 +
{
 +
'''OldTelephone'''
 +
{
 +
'''Material''' "Old Telephone Material"
 +
'''Thumbnail''' "Old telephone thumbnail.png"
 +
'''Meshes'''
 +
[
 +
{
 +
'''Name''' "KeyPad"
 +
'''Mesh''' "OldKeyPad.obj"
 +
'''LOD1''' "OldKeyPad-LOD1.obj"
 +
'''LOD2''' "OldKeyPad-LOD2.obj"
 +
}
 +
{
 +
'''Name''' "Handle"
 +
'''Mesh''' "OldHandle.obj"
 +
'''LOD1''' "OldHandle-LOD1.obj"
 +
'''LOD2''' "OldHandle-LOD2.obj"
 +
}
 +
]
 +
}
 +
'''NewTelephone'''
 +
{
 +
'''Material''' "New Telephone Material"
 +
'''ThumbnailRGB''' "New telephone thumbnail.png"
 +
'''Meshes'''
 +
[
 +
{
 +
'''Name''' "KeyPad"
 +
'''Mesh''' "NewKeyPad.obj"
 +
'''LOD1''' "NewKeyPad-LOD1.obj"
 +
'''LOD2''' "NewKeyPad-LOD2.obj"
 +
}
 +
{
 +
'''Name''' "Handle"
 +
'''Mesh''' "NewHandle.obj"
 +
'''LOD1''' "NewHandle-LOD1.obj"
 +
'''LOD2''' "NewHandle-LOD2.obj"
 +
}
 +
]
 +
}
 +
}
 +
 +
Note that each mesh can optionally have LOD1 and LOD2 defined and that all meshes in a replacement uses the same material, so if you have multiple meshes for one replacement, they need to share materials and textures. The Thumbnail should either be defined as "Thumbnail" or "ThumbnailRGB", depending on whether it should be RGB color mapped in the selection menu.
 +
 +
To make replacements work for your furniture, edit your furniture in the furniture editor and under the Replacement Options tab for your furniture add however many Replacement groups the furniture will use and add a default selection for each, in the same order. Then go to your mesh and select which mesh replacement it will be mapped to. As an example the telephone furniture could use the "TelephoneReplacementGroup" group, with "OldTelephone" as its default and then its keypad and handle meshes would be mapped to "KeyPad" and "Handle" mesh replacements.
  
 
=== Components ===
 
=== Components ===
Other than the tags described so far, all tags are interpreted as Unity MonoBehaviour components. If you added a tag called “<BoxCollider>”, the children tags would be interpreted as variables of the BoxCollider component and if the component does not exist, it will be instantiated for the Furniture. All MonoBehaviour variables in a Component will use the ComponentName reference set in the other tags, or alternatively you can add a Transforms tag to define empty objects with a Name, Position and Rotation. Using “self” as a value for a MonoBehaviour variable will find the corresponding component in the furniture object itself. This allows for anything to be added to a furniture, even MonoBehaviors from custom mods.
+
Other than the elements described so far, all tables added to the root table are interpreted as Unity MonoBehaviour components. If you added a table called '''BoxCollider''', the children records would be interpreted as variables of the BoxCollider component and if the component does not exist, it will be instantiated for the Furniture. All MonoBehaviour variables in a Component will use the '''ComponentName''' record set in the other tags, or alternatively you can add a Transforms list to define empty transforms with a Name, Position and Rotation. Using '''self''' as a value for a MonoBehaviour variable will find the corresponding component in the root furniture object itself. This allows for anything to be added to a furniture, even MonoBehaviors from custom mods.
  
If you set the Parent attribute to a ComponentName reference or Transforms reference, the component will be fetched/added to the object instead. This could be used to add a PointLight component to an empty object to make your own lights. Make sure to add a LampScript component to your furniture object if you’re making a custom lamp, so the game can control shadows and lighting.
+
If you set the '''TransformParent''' record to a '''ComponentName''' reference, the component will be fetched/added to that object instead of the root furniture object. This could be used to add a Light component to an empty object to make your own lights. Make sure to add a '''LampScript''' component to your furniture object if you’re making a custom lamp, so the game can control shadows and lighting.
  
Setting a Destroy attribute to “True” for a tag will remove that MonoBehavior from the furniture.
+
Adding a '''RemoveComponent True''' record for a table will remove that MonoBehavior from the furniture or '''TransformParent'''.
  
Note that using MonoBehaviors from other mods requires setting the Namespace attribute and the Assembly attribute so the game knows where to find the classes, e.g. <MyCustomComponent Namespace=”MyMod.Behaviours.Assembly=”MyMod”>.
+
Note that using MonoBehaviors from other mods requires adding a '''Namespace''' and '''Assembly''' record, so the game knows where to find the classes, e.g.
 +
'''Namespace''' "MyMod.Behaviours."
 +
'''Assembly''' MyMod
  
 
==== Furniture ====
 
==== Furniture ====
This component will always be present in a furniture. These variables have been extracted directly from the class description, note that some of these variables should remain unchanged:
+
This component will always be present in a furniture. These variables have been extracted directly from the class description.
* BuildBoundary
+
* '''BuildBoundary''' (List of Vector2) - The boundary to use when checking for collisions
* NavBoundary
+
* '''NavBoundary''' (List of Vector2) - The navigation mesh, which employees will pathfind around
* FinalBoundary
+
* '''OnXEdge''' (True/False) - Should be placed on the grid border on the x-axis
* OnXEdge
+
* '''OnYEdge''' (True/False) - Should be placed on the grid border on the y-axis
* OnYEdge
+
* '''CanRotate''' (True/False) - Can be rotated when placed, e.g. not chairs
* GenerateBoundaryOnStart
+
* '''Only180Rotation''' (True/False) - Whether this furniture can only be rotated at 180 degrees, if snapping
* CanRotate
+
* '''IsDraggable''' (True/False) - Whether this furniture can be dragged out to multiple when placing
* Height1
+
* '''DragDistance''' (Decimal number) - How far between each placement when dragging
* Height2
+
* '''Height1''' (Decimal number) - The bottom coordinate of the furniture, should be -0.1 for carpets
* IgnoreBoundary
+
* '''Height2''' (Decimal number) - The top coordinate of the furniture, 2 is max, should be -0.05 for carpets
* BasementValid
+
* '''BasementValid''' (True/False) - Can be placed in the basement
* OnlyExteriorWalls
+
* '''OnlyExteriorWalls''' (True/False) - Has to be placed on exterior walls
* WallFurn
+
* '''WallFurn''' (True/False) - Should be placed on a wall
* SnapPoints
+
* '''InFloor''' (True/False) - Whether this furniture is placed into the floor, e.g. floor vents
* SnappedTo
+
* '''BlocksFloor''' (True/False) - Whether this furniture blocks furniture that is placed into the floor, e.g. couches
* IsSnapping
+
* '''IsSnapping''' (True/False) - Should snap to another furniture
* SnapsTo
+
* '''SnapsTo''' (List of String) - The name(s) of snap point(s) it should snap to
* CanAssign
+
* '''CanAssign''' (True/False) - Can be assigned to an employee
* ReverseLowPass
+
* '''ReverseLowPass''' (True/False) - Whether the sound should be muffled when inside or outside the parent room
* ValidIndoors
+
* '''ValidIndoors''' (True/False) - Can be placed rooms
* ValidOutdoors
+
* '''ValidOutdoors''' (True/False) - Can be placed in outdoor areas
* ValidOnFence
+
* '''ValidOnFence''' (True/False) - Can be placed on a fence if WallFurn
* NeedsChair
+
* '''OnlyOnGrass''' (True/False) - Can only be placed on outdoor green areas
* ManualUsageCalculation
+
* '''PokesThroughWall''' (True/False) - Whether the furniture pokes through the wall it's placed on
* Thumbnail
+
* '''PokesThroughRoof''' (True/False) - Whether the furniture pokes through the roof (see next item)
* InteractAnimation
+
* '''OnRoofObject''' (GameObject) - Object that contains meshes that sits on next floor
* MaxQueue
+
* '''NeedsChair''' (True/False) - Should warn the player if no chair is opposite
* InteractStartClip
+
* '''ManualUsageCalculation''' (True/False) - True for temperature furniture to manually account for the water/electricity costs based on room temperature
* InteractEndClip
+
* '''CanSteal''' (True/False) - Can be stolen be burglar
* UpgradeFrom
+
* '''IsIconic''' (List of String) - Should use thumbnail for furniture categories
* UpgradeTo
+
* '''MaxQueue''' (Whole number) - How many can queue up to use this furniture
* InDemo
+
* '''ForceAccessible''' (True/False) - Force employees to pathfind to this furniture through other teams' rooms
* ForceAccessible
+
* '''ITFix''' (True/False) - Should be repaired by IT or Maintenance
* ITFix
+
* '''UnlockYear''' (Whole number) - Which year to unlock, default 0
* UnlockYear
+
* '''TemperatureController''' (True/False) - Whether furniture controls temperature outputs
* TemperatureController
+
* '''TemperatureOutput''' (True/False) - Whether furniture changes room temperature
* AlwaysOn
+
* '''TempControlType''' (TemperatureType) - None, Heating or Cooling
* OnWithParent
+
* '''TempControlDependency''' (String) - Name of temperature controller we depends on, e.g. Central Heating or Roof AC
* ComputerTransform
+
* '''TempAccessPoint''' (Transform) - Position where the pipes connect up to
* OriginalOffset
+
* '''AlwaysOn''' (True/False) - Is always on and using water/electrity and/or degrading
* PCAddonOffset
+
* '''OnWithParent''' (True/False) - Turns on when parent snap point does
* OriginalRotation
+
* '''ComputerTransform''' (Transform) - Transform of computer mesh, or parent of computer meshes
* PCAddonRotation
+
* '''OriginalOffset''' (Vector3) - PC's original position
* PokesThroughWall
+
* '''PCAddonOffset''' (Vector3) - PC's position when addon is present
* CanLean
+
* '''OriginalRotation''' (Vector3) - PC's original rotation
* UseStandardMat
+
* '''PCAddonRotation''' (Vector3) - PC's rotation when addon is present
* TwoFloors
+
* '''PokesThroughWall''' (True/False) - Whether furniture pokes through wall
* OffsetPoints
+
* '''PokesThroughRoof''' (True/False) - Whether furniture pokes through roof
* InterPoints
+
* '''CanLean''' (True/False) - Can employee lean on this furniture
* InterPointsReversed
+
* '''UseStandardMat''' (True/False) - Whether funriture uses default furniture shader
* UpperFloorFrame
+
* '''TwoFloors''' (True/False) - Does furniture use up 2 floors, e.g. stairs
* HoldablePoints
+
* '''OffsetPoints''' (List of Transform) - Start and end position of employee paths for stairs
* DespawnHoldables
+
* '''InterPoints''' (List of Transform) - Points to go through to get up for stairs
* DespawnHour
+
* '''InterPointsReversed''' (List of Transform) - Points to go through to get down for stairs
* RandomSFX
+
* '''UpperFloorFrame''' (Renderer) - Mesh to render when looking at upper floor, basically a frame to give floors thickness for stairs
* SFXFiles
+
* '''OnRoofMesh''' (Renderer) - Mesh to only render when looking at upper floor for furniture that pokes through roof
* RandomSFXMin
+
* '''HoldablePoints''' (List of Transform) - Points where stuff can be placed, e.g. food
* RandomSFXMax
+
* '''DespawnHoldables''' (True/False) - Whether stuff that is placed should get removed automatically
* DisableTableGrouping
+
* '''DespawnHour''' (Decimal number) - How many hours to wait before despawning
* InRentMode
+
* '''DisableTableGrouping''' (True/False) - Whether this table should not be grouped with others
* Type
+
* '''InRentMode''' (True/False) - Whether this furniture can be placed in rent mode
* Category
+
* '''LookAtPoints''' (List of Transform) - Points employee should look at when interacting with furniture
* FunctionCategory
+
* '''ActiveWithOn''' (GameObject) - Object that should activate/deactivate with the On state of furniture
* Cost
+
* '''AtlasObject''' (MeshRenderer) - See material guide
* ButtonDescription
+
* '''AtlasDimensions''' (Vector2) - See material guide
* ComputerPower
+
* '''AtlasCount''' (Whole number) - See material guide
* HeatCoolPotential
+
* '''AtlasSkip''' (Whole number) - See material guide
* HeatCoolArea
+
* '''AtlasOff''' (Whole number) - See material guide
* EqualizeTemperature
+
* '''AtlasColorable''' (True/False) - See material guide
* RoleBuffs
+
* '''Type''' (String) - The type of furniture, used to query funritures by employees and in other places
* Lighting
+
* '''LocalizedName''' (String) - The actual name in the UI as it will be localized in English
* Coffee
+
* '''Category''' (List of String) - Which categories to use in build menu
* Wait
+
* '''FunctionCategory''' (String) - Which functional category to use in build menu
* AuraValues
+
* '''Cost''' (Decimal number) - The cost of the furniture
* Wattage
+
* '''ButtonDescription''' (String) - The description to display in build menu
* Water
+
* '''ComputerPowerModifier''' (Decimal number) - How much computer power differs from standard, 1 = 100% = no difference
* Noisiness
+
* '''IgnorePCRelease''' (True/False) - Whether PC should affect the decline of PC performance when unlocked
* Comfort
+
* '''HeatCoolArea''' (Decimal number) - The amount of room area this furniture can heat/cool
* Environment
+
* '''EqualizeTemperature''' (True/False) - Should make temperature 21c or just go ham, e.g. industrial fans
* HasConnectionBeam
+
* '''RoleBuffs''' (List of Single) - Roles that furniture buffs, used in PC addons, 0 = 0% = no buff
* ConnectionBeam
+
* '''Lighting''' (Decimal number) - How much this furniture lights the room up
* PlacedInEditMode
+
* '''Wait''' (Decimal number) - How long to wait on furniture, e.g. for coffee machines
* MeshBoundary
+
* '''MiscPotential''' (Decimal number) - Used to determine power for different furniture, used for coffee and security cam
* RotationOffset
+
* '''Capacity''' (Whole number) - How many perishables furniture can hold
* OriginalPosition
+
* '''RefillCapacity''' (True/False) - Whether to refill automatically
* AudioSrc
+
* '''UnitCost''' (Decimal number) - How much a s ingle perishable costs
* isTemporary
+
* '''AuraValues''' (List of Single) - Buffs to [effectiveness, skill, mood] in parent room, -1 ignored, 0 = 0% = no buff
* upg
+
* '''Wattage''' (Decimal number) - How much electricy costs
* PathFailCount
+
* '''Water''' (Decimal number) - How much water costs
* InteractionPoints
+
* '''Noisiness''' (Decimal number) - How muich noise
* Parent
+
* '''ExpectedOn''' (Decimal number) - How long furniture is expected to be on per day in hours, for build menu info panel
* EnvironmentNoise
+
* '''Comfort''' (Decimal number)
* ActorNoise
+
* '''Environment''' (Decimal number) - 100% = no effect
* FinalNoise
+
* '''MeshBoundary''' (List of Vector2) - Boundary to use when offsetting furniture from wall, empty for no offsetting
* ComputerChair
+
* '''Table''' (TableScript) - Reference to TableScript if table
* Undo
+
* '''PrimaryColorName''' (String) - Name of primary color, mapped to Red
* LastWattUse
+
* '''SecondaryColorName''' (String) - Name of secondary color, mapped to Green
* LastWaterUse
+
* '''TertiaryColorName''' (String) - Name of tertiary color, mapped to Blue
* Table
+
* '''EmissionOnWithFurniture''' (True/False) - Whether to turn emission on/off with furniture On state
* _defaultColorGroup
+
* '''EmissionWarmUp''' (True/False) - Whether emission should slowly turn on/off
* PrimaryColorName
+
* '''ColorPrimaryEnabled''' (True/False) - Whether player can pick primary color
* SecondaryColorName
+
* '''ColorSecondaryEnabled''' (True/False) - Whether player can pick secondary color
* TertiaryColorName
+
* '''ColorTertiaryEnabled''' (True/False) - whether player can pick tertiary color
* ColorPrimaryEnabled
+
* '''ForceColorSecondary''' (True/False) - Whether secondary color should be forced to default value
* ColorSecondaryEnabled
+
* '''ForceColorTertiary''' (True/False) - Whether tertiary color should be forced to default value
* ColorTertiaryEnabled
+
* '''ColorPrimaryDefault''' (Color) - Default primary color
* ForceColorSecondary
+
* '''ColorSecondaryDefault''' (Color) - Default secondary color
* ForceColorTertiary
+
* '''ColorTertiaryDefault''' (Color) - Default tertiary color
* ColorPrimaryDefault
+
* '''AltStyles''' (List of FurnitureStyle) - A list of extra colors/atlas index the game will include by default for the furniture, should be a list of tables with optional values: Color1, Color2 and Color3
* ColorSecondaryDefault
+
* '''ColorableLights''' (List of Light) - Reference to Light scripts that can be colored by player
* ColorTertiaryDefault
+
* '''FullColorMaterial''' (True/False) - Whether entire material should be colored, e.g. if default Unity material
* Colorable
+
* '''LightPrimary''' (True/False) - Whether primary color or tertiary color should control light color
* ColorableLights
+
* '''TreeLeaves''' (Renderer) - Reference to tree mesh to use in-game tree shader
* FullColorMaterial
+
* '''WallWidth''' (Decimal number) - How wide this furniture is on a wall if it is a wall furniture
* LightPrimary
+
* '''YOffset''' (Decimal number) - How high the mouse should be projected from the floor when placing
* TreeLeaves
+
* '''ReverseWallSide''' (True/False) - Whether this furniture sits on the etxerior of the wall it's placed on, like the company sign
 +
* '''CustomHeight''' (True/False) - Whether the furniture can be placed freely vertically on a wall, note that the furniture meshes should be placed around (0,0,0) in world position
 +
* '''ValidHeights''' (List of Single) - A list of valid vertical placements between 0 and 2 in descending order, if furniture has custom height enabled
 +
* '''WallHeight''' (Decimal number) - The default placement vertically on the wall, if furniture has custom height enabled
 +
* '''GridSizeOverride''' (Decimal number) - Whether to override the grid size when placing, e.g. 2 for half size grid
  
 
==== Upgradable ====
 
==== Upgradable ====
This component makes this furniture repairable. These variables have been extracted directly from the class description, note that some of these variables should remain unchanged:
+
This component makes this furniture repairable. These variables have been extracted directly from the class description:
* TheScreen
+
* '''TheScreen''' (GameObject) - Reference to screen of object, e.g. from PC
* SmokePosition
+
* '''SmokePosition''' (Transform) - Position where smoke should emit when broken
* SmokeEmitter
+
* '''RepairTime''' (Decimal number) - How long it takes to repair
* Quality
+
* '''FireStarter''' (Decimal number) - Whether furniture can start fires
* RepairTime
+
* '''DisableObjs''' (List of GameObject) - Objects to activate/deactiveate with furniture On state
* AtrophyModifier
+
* '''TimeToAtrophy''' (Decimal number) - How long it takes to break object in months
* LastRepair
+
* '''OnMat''' (Material) - Material to use on screen when furniture turns on
* Descriptions
+
* '''OffMat''' (Material) - Material to use on screen when furniture is off
* DisableObjs
+
* '''DegradeAlways''' (True/False) - Whether furniture is always degrading
* TimeToAtrophy
+
* '''ModifiableAtrophy''' (True/False) - Whether furniture degration can be modified by external factors
* OnMat
+
* '''ManualDegrade''' (True/False) - Whether to calculate degration manually, used for temperature furniture based on room temperature
* OffMat
+
* '''AffectedByTemp''' (True/False) - Whether furniture breaks faster in hot rooms
* DegradeAlways
+
* '''CanBreak''' (True/False) - Whether furniture can break at all, e.g. not chairs
* ModifiableAtrophy
+
* '''ChangeColorOffSecondary''' (True/False) - Whether to make secondary color black when furniture is turned off
* AffectedByTemp
+
* '''ChangeColorOffTertiary''' (True/False) - Whether to make tertiary color black when furniture is turned off
* Broken
 
* CanBreak
 
* ChangeColorOffSecondary
 
* ChangeColorOffTertiary
 
* furn
 
* Anim
 
  
 
==== TableScript ====
 
==== TableScript ====
Line 259: Line 389:
  
 
==== LampScript ====
 
==== LampScript ====
This component handles lighting and shadows for lamps.
+
This component handles lighting and shadows for lamps. For best results, the "Lights" variable should contain references to the light components in your furniture, by using the name of the transforms you added the Light components to.
  
 
==== Server ====
 
==== Server ====
Line 265: Line 395:
  
 
=== Example ===
 
=== Example ===
==== XML layout ====
+
==== TyD layout ====
<pre><Root Base="Server Rack" Thumbnail="BigServerRackThumb.png" UpgradeFrom="Server Rack">
+
'''Furniture'''
<Models>
+
    {
<Model>
+
    '''Base'''              <span style="color:blue">"Server Rack"</span>
<File>BigServerRack.obj</File>
+
    '''Name'''              <span style="color:blue">"BigServerRack"</span>
<Position>0,0,0</Position>
+
    '''Thumbnail'''        <span style="color:blue">"BigServerRackThumb.png"</span>
<Rotation>0,270,0</Rotation>
+
    '''UpgradeFrom'''      <span style="color:blue">"Server Rack"</span>
<Scale>1,1,1</Scale>
+
    '''Models'''
</Model>
+
        [
</Models>
+
            {
<InteractionPoints>
+
            '''File'''    <span style="color:blue">BigServerRack.obj</span>
<InteractionPoint>
+
            '''Position''' [ <span style="color:blue">0</span>; <span style="color:blue">0</span>; <span style="color:blue">0</span> ]
<Name>Repair</Name>
+
            '''Rotation''' [ <span style="color:blue">0</span>; <span style="color:blue">270</span>; <span style="color:blue">0</span> ]
<Position>0,0,1</Position>
+
            '''Scale'''    [ <span style="color:blue">1</span>; <span style="color:blue">1</span>; <span style="color:blue">1</span> ]
<Rotation>0,180,0</Rotation>
+
            }
<Animation>Repair</Animation>
+
        ]
<Child>1</Child>
+
    '''InteractionPoints'''
</InteractionPoint>
+
        [
<InteractionPoint>
+
            {
<Name>Repair</Name>
+
            '''Name'''      <span style="color:blue">Repair</span>
<Position>0,0,-1</Position>
+
            '''Position'''  [ <span style="color:blue">0</span>; <span style="color:blue">0</span>; <span style="color:blue">1</span> ]
<Rotation>0,0,0</Rotation>
+
            '''Rotation'''  [ <span style="color:blue">0</span>; <span style="color:blue">180</span>; <span style="color:blue">0</span> ]
<Animation>Repair</Animation>
+
            '''Animation''' <span style="color:blue">Repair</span>
<Child>0</Child>
+
            '''Child'''    <span style="color:blue">1</span>
</InteractionPoint>
+
            }
</InteractionPoints>
+
            {
<Furniture>
+
            '''Name'''      <span style="color:blue">Repair</span>
<Cost>12000</Cost>
+
            '''Position'''  [ <span style="color:blue">0</span>; <span style="color:blue">0</span>; <span style="color:blue">-1</span> ]
<Wattage>50</Wattage>
+
            '''Rotation'''  [ <span style="color:blue">0</span>; <span style="color:blue">0</span>; <span style="color:blue">0</span> ]
<Noisiness>2</Noisiness>
+
            '''Animation''' <span style="color:blue">Repair</span>
<UnlockYear>2010</UnlockYear>
+
            '''Child'''    <span style="color:blue">0</span>
<ButtonDescription>When you can't get enough server</ButtonDescription>
+
            }
<ColorPrimaryDefault>0.2,0.2,0.2,1</ColorPrimaryDefault>
+
        ]
<PrimaryColorName>0.2,0.2,0.2,1</PrimaryColorName>
+
    '''Furniture'''
<ColorSecondaryDefault>0.3,0.3,0.3,1</ColorSecondaryDefault>
+
        {
<ColorTertiaryDefault>0,0.8,1,1</ColorTertiaryDefault>
+
        '''LocalizedName'''        <span style="color:blue">"Big Server Rack"</span>
<ColorSecondaryEnabled>True</ColorSecondaryEnabled>
+
        '''Cost'''                  <span style="color:blue">12000</span>
<ColorTertiaryEnabled>True</ColorTertiaryEnabled>
+
        '''Wattage'''              <span style="color:blue">50</span>
<ForceColorSecondary>False</ForceColorSecondary>
+
        '''Noisiness'''            <span style="color:blue">2</span>
<ForceColorTertiary>False</ForceColorTertiary>
+
        '''UnlockYear'''            <span style="color:blue">2010</span>
<PrimaryColorName>Casing</PrimaryColorName>
+
        '''Height1'''              <span style="color:blue">0</span>
<SecondaryColorName>Casing</SecondaryColorName>
+
        '''Height2'''              <span style="color:blue">1.8</span>
<TertiaryColorName>LED</TertiaryColorName>
+
        '''OnXEdge'''              <span style="color:blue">True</span>
<BuildBoundary>
+
        '''ButtonDescription'''    <span style="color:blue">"When you can't get enough server"</span>
-0.99,-0.49
+
        '''ColorPrimaryDefault'''  <span style="color:blue">333333</span>
0.99,-0.49
+
        '''ColorSecondaryDefault''' <span style="color:blue">4D4D4D</span>
0.99,0.49
+
        '''ColorTertiaryDefault'''  <span style="color:blue">00C8AA</span>
-0.99,0.49</BuildBoundary>
+
        '''ColorPrimaryEnabled'''  <span style="color:blue">True</span>
<NavBoundary>
+
        '''ColorSecondaryEnabled''' <span style="color:blue">True</span>
-1,-0.5
+
        '''ColorTertiaryEnabled'''  <span style="color:blue">True</span>
1,-0.5
+
        '''ForceColorSecondary'''  <span style="color:blue">False</span>
1,0.5
+
        '''ForceColorTertiary'''    <span style="color:blue">False</span>
-1,0.5</NavBoundary>
+
        '''PrimaryColorName'''      <span style="color:blue">Casing</span>
<Height1>0</Height1>
+
        '''SecondaryColorName'''    <span style="color:blue">Casing</span>
<Height2>1.8</Height2>
+
        '''TertiaryColorName'''    <span style="color:blue">LED</span>
<OnXEdge>True</OnXEdge>
+
        '''BuildBoundary'''
</Furniture>
+
            [
<Upgradable>
+
            [ <span style="color:blue">-0.99</span>; <span style="color:blue">-0.49</span> ]
<UpgradePrice>1000</UpgradePrice>
+
            [ <span style="color:blue">0.99</span>; <span style="color:blue">-0.49</span> ]
</Upgradable>
+
            [ <span style="color:blue">0.99</span>; <span style="color:blue">0.49</span> ]
<Server>
+
            [ <span style="color:blue">-0.99</span>; <span style="color:blue">0.49</span> ]
<Power>10000</Power>
+
            ]
</Server>
+
        '''NavBoundary'''
<BoxCollider>
+
            [
<center>0,0.9,0</center>
+
            [ <span style="color:blue">-1</span>; <span style="color:blue">-0.5</span> ]
<size>2,1.8,1</size>
+
            [ <span style="color:blue">1</span>; <span style="color:blue">-0.5</span> ]
</BoxCollider>
+
            [ <span style="color:blue">1</span>; <span style="color:blue">0.5</span> ]
</Root></pre>
+
            [ <span style="color:blue">-1</span>; <span style="color:blue">0.5</span> ]
 +
            ]
 +
        '''AltStyles'''
 +
            [
 +
                  {
 +
                  '''Color1'''  <span style="color:blue">FF0000</span>
 +
                  '''Color2'''  <span style="color:blue">00FF00</span>
 +
                  '''Color3'''  <span style="color:blue">0000FF</span>
 +
                  }
 +
            ]
 +
        }
 +
    '''Upgradable'''        { '''TimeToAtrophy''' <span style="color:blue">96</span> }
 +
    '''Server'''            { '''Power''' <span style="color:blue">50000</span> }
 +
    '''BoxCollider'''
 +
        {
 +
        '''center''' [ <span style="color:blue">0</span>; <span style="color:blue">0.9</span>; <span style="color:blue">0</span> ]
 +
        '''size'''  [ <span style="color:blue">2</span>; <span style="color:blue">1.8</span>; <span style="color:blue">1</span> ]
 +
        }
 +
    }
 +
 
 +
==== Textures used for the in-game tower server ====
 +
Main RGB map:
 +
 
 +
[[File:TowerServer Albedo.png]]
 +
 
 +
Normal map, with alpha for metallic look (Reversed here, so 100% alpha means 100% metallic):
 +
 
 +
[[File:TowerServer NormalMap.png]]
 +
 
 +
Extra map (Smoothness in R channel, emission in G channel, RGB map mask in B channel):
  
==== Texture used for the in-game waiting chairs ====
+
[[File:TowerServer SpecEmissMask.png]]
[[File:WChairsExample.png]]
 

Latest revision as of 17:38, 29 August 2025

Furniture packages should be located in subfolders in the "Furniture" folder with the game. A furniture package will inherit its name from the folder name. Furniture is created using the TyD data language.

Helpful console commands

  • RELOAD_FURNITURE - Reloads all furniture mods immediately, does not affect already placed furniture
  • FURNITURE_DEBUG True - Adds an in-game overlay to the selected furniture showing its boundary, navigation mesh, interaction points and snap points
  • FURNITURE_THUMBNAIL X - Generates a thumbnail for the the furniture named X and places it in the Furniture folder. This command only works in the main menu
  • EXPORT_FURNITURE_BOUNDS X - Exports the auto generated furniture boundaries (created by adding the AutoBounds True record) and puts it in the TyD file for the furniture named X. This should be done when you're finished with the furniture, to avoid having the game generate them on every startup. This also allows you to change them in the TyD file. Note that this action removes any special formatting and comments.
  • EXPORT_FURNITURE_POINTS X - Exports snap and interaction points for the the furniture named X and writes it to its TyD file. You can use this to inspect snap and interaction points for any furniture in the game, by using the Base furniture override. If these are already overridden in the file, it will just write out the same points twice.
  • UNLOCK_FURNITURE - Allows you to place furniture that hasn't been unlocked in-game
  • GENERATE_LOCALIZATION X - Generates localization files based on the mod named X

Furniture modding

Tutorial

Check out a video tutorial on how to create furniture mods here:

TyD file layout

FurnitureModLayout.png

Each furniture should be defined in separate TyD files.

The root table should have a Thumbnail record with a relative path to a 128x128 thumbnail to use in-game.

The root table can also have a Base record to inherit from an existing furniture from the game. If you define the record AutoBounds True, the game will auto generate the navigation mesh, building boundary, vertical span, x and y grid offset, width and vertical offset for wall furniture, and collision box for selection, based on the furniture meshes, otherwise these can be controlled in the Furniture component by setting the variables BuildBoundary, NavBoundary, Height1, Height2, OnXEdge, OnYEdge, WallWidth, YOffset and the BoxCollider component.

You can check your build and navigation boundary, and interaction and snap points by enabling furniture debugging using the command FURNITURE_DEBUG True in the console and selecting the furniture you want to review in-game. The navigation boundary is located on the floor and goes from green to pink. The build boundary also illustrates Height1 and Height2 and goes from cyan to red. Interaction points are blue and snap points are yellow:

FurnDebug.png

It is highly recommended that you run the command EXPORT_FURNITURE_BOUNDS with your furniture name as parameter, if you've used the AutoBounds True record. This command bakes the bounds information in the TyD file so it doesn't have to be recalculated each time the game launches. Note that it reformats and removes comments from your file.

Hierarchy

Every object you add to your furniture can be given a name using a ComponentName record and can be added as a child transform to another object by using a TransformParent with the ComponentName of the other object. If TransformParent is not defined, the object will be added to the root furniture object.

You can define a list of empty Transforms using a Transform list with tables that define a Name (instead of ComponentName), Position and Rotation (in degrees as Euler angles).

You can add Unity components to any tranforms and objects by using the TransformParent record in a table that has the same name as the UnityComponent you want to add. As an example, you can add a Unity Light component to a Transform and pass the transform's name to the Furniture component's ColorableLights list and you now have a light that changes color based on what the player picks. Just make sure they are defined in the correct order (You can't refer to a TransformParent that hasn't been created yet).

Transforms
	[
		{
		Name 		LightUp
		Position	[ 0; 0.5; 0 ]
		Rotation	[ 0; 0; 0 ]
		}
	]
Light
	{
	TransformParent		LightUp
	range			10 #This is a variable from the Unity Light component, refer to the Unity docs
	intensity		10
	}
Furniture
	{
	ColorPrimaryEnabled		True
	LightPrimary			True
	ColorableLights			[ LightUp ]
	}

Naming your furniture

Your furniture will take its name from the Name record in the root table of your TyD file or from the filename, if it is an XML file. As of Alpha 11.4.10, this name should be considered an ID and not what the player will see, so you should try and make it as unique as possible, to avoid clashing with vanilla furniture or furniture from other mods. To name your furniture in the UI use the LocalizedName variable in the Furniture component table (Not the root table! See all varibles here) and use the GENERATE_LOCALIZATION your_mod_name console command to generate the localization files for your mod. To find your furniture's name in the UI, the game will lookup your mods ID/filename and return the LocalizedName that has been exported with the GENERATE_LOCALIZATION command. This has the added benefit of allowing people to translate your mod to other languages.

Meshes and materials

Meshes will be loaded from the Models list. The Models list should contain a list of tables that define meshes. Each mesh table should have a File record, with the relative path to an .obj file, a Position, Rotation (in degrees as Euler angles) and Scale (Should always be positive). Optionally, the mesh tag can have a TransformParent record, to make it a child transform of an object with the specified name, a ComponentName record to name the mesh for later reference(e.g. to make it a parent for another mesh or transform) and a Material record to give it a material.

If you omit the Material record, it will automatically select the in-game default furniture material, which has great performance and allows the player to colorize the furniture. The default material works by mapping the Red, Green and Blue channels to the colors the players has picked for the furniture, while greyscale pixels remain greyscale. Furthermore, the alpha channel is used to control material smoothness and emission/glow. 100% alpha will make the material rough and then smoother as the alpha decreases, 0% alpha will make the material glow in the dark (Note that some image editing software will destroy your RGB channels if the alpha channels is 0%, e.g. Photoshop). If you use the default material, you should UV map your furniture to the texture pictured below. You can also set the Material record to Glass to use the in-game glass shader.

NewFurnUV.png

If you want to use your own materials and textures, you need to add a Materials.tyd file. It should contain a list of tables that define your materials. The first record in a material table should be the Type, which can be one of the following values:

  • Unity, the default Unity standard shader as of Unity 2017.4 (http://unity3d.com/get-unity/download/archive)
  • Standard, the default furniture shader used in-game
  • Atlas, a shader that allows the player to change the furniture texture, which works well for paintings
  • Masked, works like the standard shader with RGB mapping, but has 100% emission and transparency from the alpha channel using dithering

For each material you can add a Texture record to refer directly to an image file to use as the materials main texture. Each material table can have 3 tables

  • Textures
  • Floats
  • Colors

Each can contain a set of records that define textures, numbers and colors, where the record names should reference actual shader variables as defined in Unity, e.g:

  • _MainTex
  • _BumpMap
  • _OcclusionMap
  • _Metallic
  • _Glossiness
  • _BumpScale
  • _Color

The standard furniture shader

As described above the default standard furniture shader works by mapping the Red, Green and Blue channels to the colors the players has picked for the furniture. This also means that dark red will darken the color the player has chosen, so the color #800000, will darken the player's primary color by 50%. This can be used to add shadows and occlusion to your textures, while still allowing for player coloring.

Outside of the Texture record, this shader can also have a NormalMap record, to add normal maps to your furniture. Note that this incurs a small performance penalty. The alpha value of the normal map is used to make the material more or less metal looking, a value of 0% alpha will make the material look completely metallic.

There is also an ExtraMap record, which allows you to control smoothness with the Red channel, Emission strength with the Green channel and finally the Blue channel controls whether to use the color in the main texture as is or map it to the player color. The Blue channel of this texture will allow you to have static colors on parts of your furniture, while still allowing for player coloring. Having an ExtraMap makes the shader ignore the alpha channel of the main texture.

Watch a tutorial on how to create textures for the standard shader here:

The atlas shader

The atlas shader allows you to use a texture as grid, and only map a section of it to the furniture at a time. For this you need to define these variables in the Furniture table:

  • AtlasObject - The mesh that should use atlas texturing, this should be the ComponentName defined in the Models section of your furniture.
  • AtlasDimensions - The width and height of your texture atlas, e.g. [ 2; 2 ] if you have a 2 by 2 texture atlas
  • AtlasCount - The amount of images in your atlas, e.g. 3 if you're only using the (first row) and (second row, first column) of your atlas
  • AtlasColorable - Whether the atlas texture can also be RGB mapped like the standard shader. Remember to set "RGBMapping True" in your atlas material definition for this to work
  • AtlasOff - How many images to skip in atlas, most likely zero, relevant if using the same atlas for multiple furniture
  • AtlasSkip - Only take every Xth image in atlas(after skip), most likely one, relevant if using the same atlas for multiple furniture

Interaction points

Interaction points control how employees can interact with a piece of furniture.

If you have used the Base record, the furniture will inherit its interaction points from the base furniture, unless you add the "InteractionPoints" list.

Interaction points should define a Name, which at this point in time includes "Use", "Repair", "Serve", "Social" and "Visit" for the base game. They should also have Position and Rotation defined. You can define a ComponentName record to name the interaction points for later reference.

Interaction points can also define Animation(main animation used when interacting, ignored for some interactions), SubAnimation(used for repairs, 0, 1 or 2 for repair height), MinimumNeeded(how many need to be reachable before the player gets a warning), ReachCheck(whether we should warn the player at all), MainAction(whether the feet graphic should appear dark or not to tell the player whether it's important), ShowOnBuild(can be used to hide the feet graphic) and Outside(tells the game that this interaction point is used from the outside, which currently only used for garage ports).

Finally, it can define a Child, which is the ith interaction point defined (Zero index). If you want a number of interaction points to only be used by one employee at a time you should define children such that they form a dependency loop(E.g. 0->1->2->3->0). When one interaction point gets reserved, the children will recursively get reserved as well.

Snap points

Snap points are points at which certain furniture can be snapped to other furniture, like chairs to tables.

If you have used the Base record, the furniture will inherit its snap points from the base furniture, unless you add the "SnapPoints" list.

Snap points should define a Name, which will control which furniture can snap to it, currently in use in the base game is "PCAddon", "AtTable" and "OnTable". "Food" is also used in the game for tables which should allow for food but not OnTable furniture, like benches. They should also have Position and Rotation defined.

You can define a ComponentName record to name the snap point for later reference.

Snap points can also have CheckValid defined, which controls whether the game should allow for something to be placed no matter if there are collisions. This collision calculation is heavy, but not needed for stuff like computers and computer add-ons, so you can leave this off in most cases.

You can also define its Group, which should be a number above 0, all snap points with the same group number will be grouped together such that only one of them can be used at any time.

Finally, snap points can define Links, which is a comma separated list of linked snap points, referencing the ith snap point defined (zero index). Links are currently used to link chairs with computers and chairs with food. E.g. for the square table, the OnTable point is linked to all AtTable points around it. The bench does not have chairs and instead the "Use" interaction points are defined in the same order as its "Food" snap points so the game knows where to put the employee’s food and how to save it to a file.

Replacements/upgrading

You can add UpgradeFrom and UpgradeTo records to control which furniture can be replaced with your furniture and which furniture your furniture can be replaced with. A furniture can be replaced by any furniture which UpgradeFrom or UpgradeTo matches the furniture's UpgradeTo. Example:

UpgradeFrom	Server
UpgradeTo	"Big Server"

This furniture can be replaced by any furniture that has UpgradeFrom "Big Server" or UpgradeTo "Big Server", and any furniture that has UpgradeTo "Server" or UpgradeTo "Big Server" can be replaced by this furniture, but this furniture cannot be replaced by furniture that has UpgradeTo "Server". This is used to avoid upgrading a server that sits on the floor to a server that sits on a table, as the table would have to be created out of thin air.

Boxes represent furniture with the corresponding upgrade groups and arrows show what they can be replaced with.

In-game upgrade groups

  • Big Server (Tower Server, Server Rack, Big Server Rack)
  • Chair (Cheap Chair, Office Chair, Executive Chair, ErgoChair, Yoga Ball)
  • Coffee (Instant Coffee, Coffee, Espresso Machine)
  • CompanyLogo (Company Logo, Company Logo Big, Company Logo High)
  • Computer (Old Computer, 90s Computer, Laptop, Modern Computer, HoloComputer)
  • Conveyor (Component Recycler, Conveyor Belt, Ceiling-mounted Conveyor Belt, Conveyor Ramp, Conveyor Splitter)
  • ConveyorPallet (Pallet Drop Point, Pallet Pickup Point)
  • Couch (Waiting Chairs, Couch, ModernCouch, LeatherCouch)
  • Cubicle (Cubicle wall)
  • Desk (Desk, MordernDesk, ServingTable)
  • Floor Decoration (Floor Lamp, Outdoor Lamp, Floor Light, Floor Plant, Big Plant, SquareCarpet, CornerCarpet, RoundedCarpet, InvRoundedCarpet, BigCarpet, RoundCarpet, Cozy Tree)
  • FloorGrill (Heating Floor Grill, Cooling Floor Grill)
  • Manufacturing (Component Printer, Component Assembler)
  • Misc Ceiling (Ceiling Fan, Lamp, Fluorescent lamp, Sprinkler)
  • Misc Food (Vending Machine, Fridge, Stove, WaterCooler)
  • PCAddon (Phone, Drawing Tablet, Calculator, Inbox, Headphones)
  • ProductPrinter (Small Product Printer, Medium Product Printer)
  • Server (Tower Server, Server Rack, Big Server Rack, Small Server, Medium Server)
  • Standard Table (Table, Corner Table, Glass Table)
  • Table Decoration (Desk Lamp, Table Plant, Table Cactus)
  • Toilet (Toilet)
  • Tree (Small tree, Small pine tree, Money Tree)
  • WallDeco (Wall Lamp, Painting, Acoustic Foam, Acoustic Diamond Panel, Acoustic Hex Panel, TV, Clock)
  • WallSec (Fire Alarm, Security camera)
  • WallVent (AC Unit, Ventilation, Industrial ventilation)

Limitations

The game will be able to destroy tables if you're replacing something on a table with something that is not on a table, e.g. small server and server rack, but not the other way around. The game won't build new tables automatically, so you should be careful in differentiating between "UpgradeFrom" and "UpgradeTo", as these will not always be the same.

Mesh replacements

You can add mesh replacements, which work kind of like the texture atlas, but allow the player to replace entire meshes + materials for a piece of furniture. This feature is only available as of Beta 1.7.35.

Replacements are grouped together, replacement groups can be mapped to one or more furniture. As an example, all stairs in the game use 2 replacement groups: "Stairs" and "Railings". Each group contains a list of possible replacements for that group, e.g. "metal", "glass", "fence". The replacement has a thumbnail for the UI and a material that all meshes that get replaced will use, when that replacement is active. Each replacement also has a list of key/mesh pairs, which tell the game which objects should use which mesh when that replacement is active, e.g "Stairs", "Platform" and "Support" for the "Stairs" replacement, and "Pole" and "Railing" for the "Railing" replacement.

So the overall structure is:

Replacement group -> replacements -> meshes

To add mesh replacements, you need to add a "replacements.tyd" to the root of your mod folder. Here's an example of a replacement file:

TelephoneReplacementGroup
	{
	OldTelephone
		{
		Material "Old Telephone Material"
		Thumbnail "Old telephone thumbnail.png"
		Meshes
			[
				{
				Name "KeyPad"
				Mesh "OldKeyPad.obj"
				LOD1 "OldKeyPad-LOD1.obj"
				LOD2 "OldKeyPad-LOD2.obj"
				}
				{
				Name "Handle"
				Mesh "OldHandle.obj"
				LOD1 "OldHandle-LOD1.obj"
				LOD2 "OldHandle-LOD2.obj"
				}
			]
		}
	NewTelephone
		{
		Material "New Telephone Material"
		ThumbnailRGB "New telephone thumbnail.png"
		Meshes
			[
				{
				Name "KeyPad"
				Mesh "NewKeyPad.obj"
				LOD1 "NewKeyPad-LOD1.obj"
				LOD2 "NewKeyPad-LOD2.obj"
				}
				{
				Name "Handle"
				Mesh "NewHandle.obj"
				LOD1 "NewHandle-LOD1.obj"
				LOD2 "NewHandle-LOD2.obj"
				}
			]
		}
	}

Note that each mesh can optionally have LOD1 and LOD2 defined and that all meshes in a replacement uses the same material, so if you have multiple meshes for one replacement, they need to share materials and textures. The Thumbnail should either be defined as "Thumbnail" or "ThumbnailRGB", depending on whether it should be RGB color mapped in the selection menu.

To make replacements work for your furniture, edit your furniture in the furniture editor and under the Replacement Options tab for your furniture add however many Replacement groups the furniture will use and add a default selection for each, in the same order. Then go to your mesh and select which mesh replacement it will be mapped to. As an example the telephone furniture could use the "TelephoneReplacementGroup" group, with "OldTelephone" as its default and then its keypad and handle meshes would be mapped to "KeyPad" and "Handle" mesh replacements.

Components

Other than the elements described so far, all tables added to the root table are interpreted as Unity MonoBehaviour components. If you added a table called BoxCollider, the children records would be interpreted as variables of the BoxCollider component and if the component does not exist, it will be instantiated for the Furniture. All MonoBehaviour variables in a Component will use the ComponentName record set in the other tags, or alternatively you can add a Transforms list to define empty transforms with a Name, Position and Rotation. Using self as a value for a MonoBehaviour variable will find the corresponding component in the root furniture object itself. This allows for anything to be added to a furniture, even MonoBehaviors from custom mods.

If you set the TransformParent record to a ComponentName reference, the component will be fetched/added to that object instead of the root furniture object. This could be used to add a Light component to an empty object to make your own lights. Make sure to add a LampScript component to your furniture object if you’re making a custom lamp, so the game can control shadows and lighting.

Adding a RemoveComponent True record for a table will remove that MonoBehavior from the furniture or TransformParent.

Note that using MonoBehaviors from other mods requires adding a Namespace and Assembly record, so the game knows where to find the classes, e.g.

Namespace	"MyMod.Behaviours." 
Assembly	MyMod

Furniture

This component will always be present in a furniture. These variables have been extracted directly from the class description.

  • BuildBoundary (List of Vector2) - The boundary to use when checking for collisions
  • NavBoundary (List of Vector2) - The navigation mesh, which employees will pathfind around
  • OnXEdge (True/False) - Should be placed on the grid border on the x-axis
  • OnYEdge (True/False) - Should be placed on the grid border on the y-axis
  • CanRotate (True/False) - Can be rotated when placed, e.g. not chairs
  • Only180Rotation (True/False) - Whether this furniture can only be rotated at 180 degrees, if snapping
  • IsDraggable (True/False) - Whether this furniture can be dragged out to multiple when placing
  • DragDistance (Decimal number) - How far between each placement when dragging
  • Height1 (Decimal number) - The bottom coordinate of the furniture, should be -0.1 for carpets
  • Height2 (Decimal number) - The top coordinate of the furniture, 2 is max, should be -0.05 for carpets
  • BasementValid (True/False) - Can be placed in the basement
  • OnlyExteriorWalls (True/False) - Has to be placed on exterior walls
  • WallFurn (True/False) - Should be placed on a wall
  • InFloor (True/False) - Whether this furniture is placed into the floor, e.g. floor vents
  • BlocksFloor (True/False) - Whether this furniture blocks furniture that is placed into the floor, e.g. couches
  • IsSnapping (True/False) - Should snap to another furniture
  • SnapsTo (List of String) - The name(s) of snap point(s) it should snap to
  • CanAssign (True/False) - Can be assigned to an employee
  • ReverseLowPass (True/False) - Whether the sound should be muffled when inside or outside the parent room
  • ValidIndoors (True/False) - Can be placed rooms
  • ValidOutdoors (True/False) - Can be placed in outdoor areas
  • ValidOnFence (True/False) - Can be placed on a fence if WallFurn
  • OnlyOnGrass (True/False) - Can only be placed on outdoor green areas
  • PokesThroughWall (True/False) - Whether the furniture pokes through the wall it's placed on
  • PokesThroughRoof (True/False) - Whether the furniture pokes through the roof (see next item)
  • OnRoofObject (GameObject) - Object that contains meshes that sits on next floor
  • NeedsChair (True/False) - Should warn the player if no chair is opposite
  • ManualUsageCalculation (True/False) - True for temperature furniture to manually account for the water/electricity costs based on room temperature
  • CanSteal (True/False) - Can be stolen be burglar
  • IsIconic (List of String) - Should use thumbnail for furniture categories
  • MaxQueue (Whole number) - How many can queue up to use this furniture
  • ForceAccessible (True/False) - Force employees to pathfind to this furniture through other teams' rooms
  • ITFix (True/False) - Should be repaired by IT or Maintenance
  • UnlockYear (Whole number) - Which year to unlock, default 0
  • TemperatureController (True/False) - Whether furniture controls temperature outputs
  • TemperatureOutput (True/False) - Whether furniture changes room temperature
  • TempControlType (TemperatureType) - None, Heating or Cooling
  • TempControlDependency (String) - Name of temperature controller we depends on, e.g. Central Heating or Roof AC
  • TempAccessPoint (Transform) - Position where the pipes connect up to
  • AlwaysOn (True/False) - Is always on and using water/electrity and/or degrading
  • OnWithParent (True/False) - Turns on when parent snap point does
  • ComputerTransform (Transform) - Transform of computer mesh, or parent of computer meshes
  • OriginalOffset (Vector3) - PC's original position
  • PCAddonOffset (Vector3) - PC's position when addon is present
  • OriginalRotation (Vector3) - PC's original rotation
  • PCAddonRotation (Vector3) - PC's rotation when addon is present
  • PokesThroughWall (True/False) - Whether furniture pokes through wall
  • PokesThroughRoof (True/False) - Whether furniture pokes through roof
  • CanLean (True/False) - Can employee lean on this furniture
  • UseStandardMat (True/False) - Whether funriture uses default furniture shader
  • TwoFloors (True/False) - Does furniture use up 2 floors, e.g. stairs
  • OffsetPoints (List of Transform) - Start and end position of employee paths for stairs
  • InterPoints (List of Transform) - Points to go through to get up for stairs
  • InterPointsReversed (List of Transform) - Points to go through to get down for stairs
  • UpperFloorFrame (Renderer) - Mesh to render when looking at upper floor, basically a frame to give floors thickness for stairs
  • OnRoofMesh (Renderer) - Mesh to only render when looking at upper floor for furniture that pokes through roof
  • HoldablePoints (List of Transform) - Points where stuff can be placed, e.g. food
  • DespawnHoldables (True/False) - Whether stuff that is placed should get removed automatically
  • DespawnHour (Decimal number) - How many hours to wait before despawning
  • DisableTableGrouping (True/False) - Whether this table should not be grouped with others
  • InRentMode (True/False) - Whether this furniture can be placed in rent mode
  • LookAtPoints (List of Transform) - Points employee should look at when interacting with furniture
  • ActiveWithOn (GameObject) - Object that should activate/deactivate with the On state of furniture
  • AtlasObject (MeshRenderer) - See material guide
  • AtlasDimensions (Vector2) - See material guide
  • AtlasCount (Whole number) - See material guide
  • AtlasSkip (Whole number) - See material guide
  • AtlasOff (Whole number) - See material guide
  • AtlasColorable (True/False) - See material guide
  • Type (String) - The type of furniture, used to query funritures by employees and in other places
  • LocalizedName (String) - The actual name in the UI as it will be localized in English
  • Category (List of String) - Which categories to use in build menu
  • FunctionCategory (String) - Which functional category to use in build menu
  • Cost (Decimal number) - The cost of the furniture
  • ButtonDescription (String) - The description to display in build menu
  • ComputerPowerModifier (Decimal number) - How much computer power differs from standard, 1 = 100% = no difference
  • IgnorePCRelease (True/False) - Whether PC should affect the decline of PC performance when unlocked
  • HeatCoolArea (Decimal number) - The amount of room area this furniture can heat/cool
  • EqualizeTemperature (True/False) - Should make temperature 21c or just go ham, e.g. industrial fans
  • RoleBuffs (List of Single) - Roles that furniture buffs, used in PC addons, 0 = 0% = no buff
  • Lighting (Decimal number) - How much this furniture lights the room up
  • Wait (Decimal number) - How long to wait on furniture, e.g. for coffee machines
  • MiscPotential (Decimal number) - Used to determine power for different furniture, used for coffee and security cam
  • Capacity (Whole number) - How many perishables furniture can hold
  • RefillCapacity (True/False) - Whether to refill automatically
  • UnitCost (Decimal number) - How much a s ingle perishable costs
  • AuraValues (List of Single) - Buffs to [effectiveness, skill, mood] in parent room, -1 ignored, 0 = 0% = no buff
  • Wattage (Decimal number) - How much electricy costs
  • Water (Decimal number) - How much water costs
  • Noisiness (Decimal number) - How muich noise
  • ExpectedOn (Decimal number) - How long furniture is expected to be on per day in hours, for build menu info panel
  • Comfort (Decimal number)
  • Environment (Decimal number) - 100% = no effect
  • MeshBoundary (List of Vector2) - Boundary to use when offsetting furniture from wall, empty for no offsetting
  • Table (TableScript) - Reference to TableScript if table
  • PrimaryColorName (String) - Name of primary color, mapped to Red
  • SecondaryColorName (String) - Name of secondary color, mapped to Green
  • TertiaryColorName (String) - Name of tertiary color, mapped to Blue
  • EmissionOnWithFurniture (True/False) - Whether to turn emission on/off with furniture On state
  • EmissionWarmUp (True/False) - Whether emission should slowly turn on/off
  • ColorPrimaryEnabled (True/False) - Whether player can pick primary color
  • ColorSecondaryEnabled (True/False) - Whether player can pick secondary color
  • ColorTertiaryEnabled (True/False) - whether player can pick tertiary color
  • ForceColorSecondary (True/False) - Whether secondary color should be forced to default value
  • ForceColorTertiary (True/False) - Whether tertiary color should be forced to default value
  • ColorPrimaryDefault (Color) - Default primary color
  • ColorSecondaryDefault (Color) - Default secondary color
  • ColorTertiaryDefault (Color) - Default tertiary color
  • AltStyles (List of FurnitureStyle) - A list of extra colors/atlas index the game will include by default for the furniture, should be a list of tables with optional values: Color1, Color2 and Color3
  • ColorableLights (List of Light) - Reference to Light scripts that can be colored by player
  • FullColorMaterial (True/False) - Whether entire material should be colored, e.g. if default Unity material
  • LightPrimary (True/False) - Whether primary color or tertiary color should control light color
  • TreeLeaves (Renderer) - Reference to tree mesh to use in-game tree shader
  • WallWidth (Decimal number) - How wide this furniture is on a wall if it is a wall furniture
  • YOffset (Decimal number) - How high the mouse should be projected from the floor when placing
  • ReverseWallSide (True/False) - Whether this furniture sits on the etxerior of the wall it's placed on, like the company sign
  • CustomHeight (True/False) - Whether the furniture can be placed freely vertically on a wall, note that the furniture meshes should be placed around (0,0,0) in world position
  • ValidHeights (List of Single) - A list of valid vertical placements between 0 and 2 in descending order, if furniture has custom height enabled
  • WallHeight (Decimal number) - The default placement vertically on the wall, if furniture has custom height enabled
  • GridSizeOverride (Decimal number) - Whether to override the grid size when placing, e.g. 2 for half size grid

Upgradable

This component makes this furniture repairable. These variables have been extracted directly from the class description:

  • TheScreen (GameObject) - Reference to screen of object, e.g. from PC
  • SmokePosition (Transform) - Position where smoke should emit when broken
  • RepairTime (Decimal number) - How long it takes to repair
  • FireStarter (Decimal number) - Whether furniture can start fires
  • DisableObjs (List of GameObject) - Objects to activate/deactiveate with furniture On state
  • TimeToAtrophy (Decimal number) - How long it takes to break object in months
  • OnMat (Material) - Material to use on screen when furniture turns on
  • OffMat (Material) - Material to use on screen when furniture is off
  • DegradeAlways (True/False) - Whether furniture is always degrading
  • ModifiableAtrophy (True/False) - Whether furniture degration can be modified by external factors
  • ManualDegrade (True/False) - Whether to calculate degration manually, used for temperature furniture based on room temperature
  • AffectedByTemp (True/False) - Whether furniture breaks faster in hot rooms
  • CanBreak (True/False) - Whether furniture can break at all, e.g. not chairs
  • ChangeColorOffSecondary (True/False) - Whether to make secondary color black when furniture is turned off
  • ChangeColorOffTertiary (True/False) - Whether to make tertiary color black when furniture is turned off

TableScript

This component handles tables and table grouping for meeting, canteens, etc.

LampScript

This component handles lighting and shadows for lamps. For best results, the "Lights" variable should contain references to the light components in your furniture, by using the name of the transforms you added the Light components to.

Server

This component makes this furniture a server. It is recommended to inherit from a server furniture, as the server component uses some in-game objects, like a text mesh and a wire mesh. Use the Power variable to change its power in mb.

Example

TyD layout

Furniture
    {
    Base              "Server Rack"
    Name              "BigServerRack"
    Thumbnail         "BigServerRackThumb.png"
    UpgradeFrom       "Server Rack"
    Models
        [
            {
            File     BigServerRack.obj
            Position [ 0; 0; 0 ]
            Rotation [ 0; 270; 0 ]
            Scale    [ 1; 1; 1 ]
            }
        ]
    InteractionPoints
        [
            {
            Name      Repair
            Position  [ 0; 0; 1 ]
            Rotation  [ 0; 180; 0 ]
            Animation Repair
            Child     1
            }
            {
            Name      Repair
            Position  [ 0; 0; -1 ]
            Rotation  [ 0; 0; 0 ]
            Animation Repair
            Child     0
            }
        ]
    Furniture
        {
        LocalizedName         "Big Server Rack"
        Cost                  12000
        Wattage               50
        Noisiness             2
        UnlockYear            2010
        Height1               0
        Height2               1.8
        OnXEdge               True
        ButtonDescription     "When you can't get enough server"
        ColorPrimaryDefault   333333
        ColorSecondaryDefault 4D4D4D
        ColorTertiaryDefault  00C8AA
        ColorPrimaryEnabled   True
        ColorSecondaryEnabled True
        ColorTertiaryEnabled  True
        ForceColorSecondary   False
        ForceColorTertiary    False
        PrimaryColorName      Casing
        SecondaryColorName    Casing
        TertiaryColorName     LED
        BuildBoundary
            [
            [ -0.99; -0.49 ]
            [ 0.99; -0.49 ]
            [ 0.99; 0.49 ]
            [ -0.99; 0.49 ]
            ]
        NavBoundary
            [
            [ -1; -0.5 ]
            [ 1; -0.5 ]
            [ 1; 0.5 ]
            [ -1; 0.5 ]
            ]
        AltStyles
            [
                 {
                 Color1   FF0000
                 Color2   00FF00
                 Color3   0000FF
                 }
            ]
        }
    Upgradable        { TimeToAtrophy 96 }
    Server            { Power 50000 }
    BoxCollider
        {
        center [ 0; 0.9; 0 ]
        size   [ 2; 1.8; 1 ]
        }
    }

Textures used for the in-game tower server

Main RGB map:

TowerServer Albedo.png

Normal map, with alpha for metallic look (Reversed here, so 100% alpha means 100% metallic):

TowerServer NormalMap.png

Extra map (Smoothness in R channel, emission in G channel, RGB map mask in B channel):

TowerServer SpecEmissMask.png