Reassembly Guide

shapes.lua Guide for Reassembly

shapes.lua Guide

Overview

[about 1.5 months into lockdown]me: im bored, what dobrain: reassemblyme: what about itbrain: idk think about reassembly thingsme: ♥♥♥♥ it i’ll write a guide on how to make custom shapesbrain: kool

1. Modeling

Before you make your custom shape, you want to do something similar to what architects do: make a model first. Modeling your shapes will not only make it easier to make your shapes, but also help you do a better job at deciding what shape you want it to be.

Most reassembly modders recommend this graph calculator[lymia.moe]. I used to use something else but honestly this has so many more features, now I recommend it too. I won’t be giving a tutorial on how to use it, i’ll be honest, mainly because I want to focus on the rest of this guide, but also because the graphing calculator is really easy to learn. I became good with it within minutes.

Also, a note: A normal 1×1 block in game is actually 10×10 units. So for example, this:

would appear as this:

So, yeah. When you model your blocks, remember this.

And just an example of how useful the program’s tools are, here is the most complex group of shapes i’ve made so far:

In case you’re wondering, the faction that uses that shape is unreleased so you’ll get to see it eventually. Also, again, note that it only took me minutes to learn how to use these features.

Alright, back to our main lesson. As an example of a shape, let’s make… How about a large trapezoid, with a large size length of 2 blocks (20 units), a small side length of 1 block (10 units) and a thickness of 1 block (again 10 units).
This is the model I made for it:

Yes it’s off center but don’t worry, the game automatically adjusts the block’s center of volume.

2. Identifier

Now that we know what shape we want to make, we can start coding it.
The way i’m going to explain this is by starting off grossly oversimplified, and add small details one-by-one until it gets just as complex as the actual thing.
Let’s start off by creating some basic things with a shapes file and making a block with an ID. A block ID is like the block’s name, it cannot be text and cannot be the same ID as another shape, and is used for telling blocks to become what shape.

Again, we’ll start off simple. Lines with these two dashes — are called “comments”. They exist in many programming languages, but are unique in most of them. In LUA, a comment can either be the two dashes, a # hashtag, or –[[ in between these ]]. Comments are ignored by the program, and are for human readers only. I will include them in these examples, so when we have a finalized shape, copy+pasting it directly into a blank shapes.lua file will work just fine.

Let’s make our custom identifier… *literally punches numpad* 3125.

{ — This curvy bracket opens the list of custom shapes {3125, — Identifier of shape. Again, must be number {}, — For now these brackets are empty, but later we will add the shapes code into here }, — Closes shape } — Closes list of custom shapes

3. Verts

Now we begin with verts.

{ {3125, { — Opens shape contents verts={ — Verts go here }, — Closes verts }, — Closes shape contents }, — Closes shape } — Closes list of all shapes

Reassembly makes shapes by connecting the dots. It goes from the first defined vert, draws a line to the next vert, and repeat until it gets to the last vert, where it draws a line to the last vert. Concave shapes do not work, unfortunately, as well as the order must be clockwise or the hitbox will glitch. I made that mistake before, trust me, isn’t fun to experience nor fix. I don’t know if there’s a certain point you’re supposed to pick as your first point, but i haven’t encountered any issues after dozens of custom shapes so I would assume any point can be your first.

But anyway, remember that model I made earlier?

Yep, just like that, I have all the verts I need instead of guessing and checking. This is why modeling is important.

Now here’s how you code the verts:

{ {3125, { verts={ {0, -10}, {0, 10}, {10, 5}, {10, -5}, }, }, }, }

4. Ports

We have made excellent progress but there’s still more to do before our shape becomes usable. The connection points, what makes a block able to be part of a ship, needs to be added. They’re called ports in the game’s code.

{ {3125, { verts={ {0, -10}, {0, 10}, {10, 5}, {10, -5}, }, ports={ — Ports go here }, — Closes ports }, }, }

The way ports work, is that you have two numers just like a vert:

  1. The first number is the line that the point is on. 0 for in between the first and second verts, 1 for in between second and third verts, and so on.
  2. The second number is the distance between the first vert and second vert, in the form of a decimal between 0 and 1. Some examples:

    If you remembered the first vert was the bottom-left one, maybe you realized that the port’s first value was 1 because they were on the second line. And for some reason, Reassembly and other computer things like to start counting at 0, instead of 1 like us humans.

    Anyway, let’s say we just want ports on all lines, seperated by units of 10 so they attach to 1×1 blocks.
    Now, the easy way to find ports is to take the distance between the first vert of the line and where you want your port to go. How do we find that? If you take the side length and divive it by half, you get the distance between the first vert and halfway. If you divide half the line by the entire line, you get 0.5. Yeah we can get something that’s already easy to get, but this strategy can get much harder port spots. The long side of our trapezoid is 2 blocks long, so there shouldn’t be a port in the middle. If we go to the center, which is 20/2=10, take away 5 to move towards the first vert by half a block. We get 5. 5/20=0.25. Add 10 to our location of 5 to move towards the second vert by 1 block. 15/20=0.75. Our port locations for the long side are 0.25 and 0.75.

    { {3125, { verts={ {0, -10}, {0, 10}, {10, 5}, {10, -5}, }, ports={ {0, 0.25}, {0, 0.75}, {1, 0.5}, {2, 0.5}, {3, 0.5}, }, }, }, }

    If our shape were usable by now (which it isn’t), it should look like this:

5. Types

This is a very simple topic so let’s just try to get through this one quickly.
Ports can actually have three values.

{0, 0.5, WEAPON_OUT}

The third value is the type of port.

Port type
Usage
NORMAL
A white port that connects to other white ports. Default port type, meaning if you do not specify a port type, it will become this.
NONE
Not sure what this is for, because i never used it, but I do know if a side has no unused ports the outline for that side turns invisible. So, maybe these ports can be used to prevent lines from hiding.
ROOT
People say seeds attach with a ROOT port, but actually that’s not true. They attach with the first port. So i really don’t know what this does besides being yellow. Also, it can connect to NORMAL ports, or other ROOT ports.
LAUNCHER
If used on a launcher block, this port replicates blocks to be launched. Cannot replicate if it connects to another port.
MISSILE
If used on a launcher’s replicateBlock block, this port is forced to be where it connects to the launcher.
WEAPON_OUT
If used on a non-turreted cannon, this port becomes where the shells come out of. Note that the front of the shape, or the direction the bullets go, is right. Connects to WEAPON_IN but not NORMAL ports.
WEAPON_IN
Blocks can connect to a cannon with this port, allowing the bullets to conduct through them, out of its own WEAPON_OUT port. The tinkrell cannons are a perfect example of this. Useful for cannon boost blocks. Does not connect to NORMAL ports.
THRUSTER_OUT
Like WEAPON_OUT, but for thrusters. The point where thrust exhaust comes out of is moved to this port. Again the front of the shape is right, so the left is the back, and where you want your thrust to go. Only connects to THRUSTER_IN.
THRUSTER_IN
Again, similar to the weapon ports. Conducts thrust exhaust and thrust force. Connects to NORMAL and THRUSTER_OUT ports.

6. Scales

Stock shapes can come in several similar sizes.

— blocks.lua code shape=SQUARE, scale=5,

But can we do that to custom shapes? Yes, yes we can! Let’s make our scale 2 trapezoid 3 to 2 blocks. Again, first we model.

Then eventually come the hard part, ports.
We already did ports for a side with a length with 20, so we can reuse those values. But we haven’t done a side length of 30, and my previous explanation was messy, so let’s try to stay organized this time.

  1. Since we know there is an odd number of ports, one will be exactly in the center at 0.5 so we can ignore that.
  2. Next we start off at the end of the line, a decimal of 1, a distance of 30.
  3. Divide by half to go to a distance of 15. This is where the 0.5 port is.
  4. Subtract 10 to go to a distance of 5. Or, go down by a distance of one block.
  5. Divide 10 by the length of the entire side to get 0.16666… That is another one of our ports.
  6. Add 20 to go to 25. We are now one block ahead of the middle port.
  7. 25/30=0.83333, which is our last port.

Let’s get to work.

{ {3125, { { — Another set of brackets, this one opens the first scale of the block. verts={ {0, -10}, {0, 10}, {10, 5}, {10, -5}, }, ports={ {0, 0.25}, {0, 0.75}, {1, 0.5}, {2, 0.5}, {3, 0.5}, }, }, — Closes first scale { — Opens second scale verts={ {0, -15}, {0, 15}, {10, 10}, {10, -10}, }, ports={ {0, 0.166667}, {0, 0.5}, {0, 0.833333}, {1, 0.5}, {2, 0.25}, {2, 0.75}, {3, 0.5}, }, }, — Closes second scale }, }, }

Our shape is now fully functional. You can now literally copy+paste the code into an empty shapes.lua file and it will work just fine, zero errors.

As ready as you might feel already, there’s still more to learn.

7. mirror_of=

mirror_of is very simple to use.
Our trapezoid shape is symmetrical so it has no use here, so just pretend it’s asymmetrical.
If it’s asymmetrical, we may want to make a mirrored version of it. This is the easiest way to do it, and it even copes all scales and makes the shape work with the mirror hotkey in the ship editor.

{ {3125, { { verts={ {0, -10}, {0, 10}, {10, 5}, {10, -5}, }, ports={ {0, 0.25}, {0, 0.75}, {1, 0.5}, {2, 0.5}, {3, 0.5}, }, }, { verts={ {0, -15}, {0, 15}, {10, 10}, {10, -10}, }, ports={ {0, 0.166667}, {0, 0.5}, {0, 0.833333}, {1, 0.5}, {2, 0.25}, {2, 0.75}, {3, 0.5}, }, }, }, }, {3126, — Opens new shape and names it 3126 {}, — Leave block contents empty mirror_of=3125, — Makes the shape 3125, but reflected across the X axis. }, — Closes 3126’s code }

Yep. That’s it. Perfectly functional. You can still copy and paste this and it will work just fine.

8. Multiple

To teach you how to add multiple shapes in a single file, let me throw in a 1×1 block and explain what every bracket does.

{ — Opens list of shapes {3125, — Opens 3125 { — Opens shape contents { — Opens scale 1 verts={ — Opens verts {0, -10}, {0, 10}, {10, 5}, {10, -5}, }, — Closes verts ports={ — Opens ports {0, 0.25}, {0, 0.75}, {1, 0.5}, {2, 0.5}, {3, 0.5}, }, — Closes ports }, — Closes scale 1 { — Opens scale 2 verts={ — Opens verts {0, -15}, {0, 15}, {10, 10}, {10, -10}, }, — Closes verts ports={ — Opens ports {0, 0.166667}, {0, 0.5}, {0, 0.833333}, {1, 0.5}, {2, 0.25}, {2, 0.75}, {3, 0.5}, }, — Closes ports }, — Closes scale 2 }, — Closes shape contents }, — Closes shape {3126, — Open 3126 {}, — Leave block contents empty mirror_of=3125, — Make the shape 3125, but reflected across the Y axis. }, — Closes 3126 {3127, — Opens 3127 { — Opens shape contents { — Opens scale 1 verts={ — Opens verts {-2.5, -2.5}, {-2.5, 2.5}, {2.5, 2.5}, {2.5, -2.5}, }, — Closes verts ports={ — Opens ports {0, 0.5}, {1, 0.5}, {2, 0.5}, {3, 0.5}, }, — Closes ports }, — Closes scale }, — Closes shape contents }, — Closes shape }

9. Organization

Our code is actually very messy. It’s helpful to organize things, condensing more repetitive stuff while separating things that tend to differ. As well as things get confusing when names are just numbers. Reminds me of when Jerma was talking about if food names were numbers, like you pull up to a Burger King and your choices are Food 13513509, Food 13501421, Food 1010341, etc. I saw that clip a while ago and no clue where either, so I might never see it again.

As an example, here’s an actual screenshot of some custom blocks from my Industrians faction:

… just… Please don’t talk about the fact that the screenshot was taken at 1:30 AM.

You may also notice that my code doesn’t contain any commas. Yes it works without commas, as long as numbers are seperated with a space, a TAB or a return.
However, this is just how LUA, Reassembly’s programming language, behaves. Other programming languages may require commas in certain spots, but not this one, so it’s up to you if you want to worry about it. If you only plan on coding in LUA, you can neglect commas. But if you code in languages that depend on it, maybe get used to it.

Now, let’s take the way I organize my factions and apply it to our code.
But I want you to understand that there is no correct way to organize code, it all just boils down to your own personal preference. But the way I organize it, is inherited from Arkas Union since I looked at the mod’s shapes file when I was learning how to make custom shapes. If you download that mod and check it’s shapes.lua file, you’ll see it’s organized similar to how I organize, again it’s because my style is inspired by this mod.

{ — Trapezoid with thickness of 1 block, long sides: 1-2, 2-3 {3125 { {verts={ {0 -10} {0 10} {10 5} {10 -5} } ports={ {0 0.25} {0 0.75} {1 0.5} {2 0.5} {3 0.5} }} {verts={ {0 -15} {0 15} {10 10} {10 -10} } ports={ {0 0.166667} {0 0.5} {0 0.833333} {1 0.5} {2 0.25} {2 0.75} {3 0.5} }} }} {3126 {} mirror_of=3125} — 1×1 square {3127 { {verts={ {-2.5 -2.5} {-2.5 2.5} {2.5 2.5} {2.5 -2.5} } ports={ {0 0.5} {1 0.5} {2 0.5} {3 0.5} }} }} }

This is now our entire shapes.lua file. Drastically nicer to look at.

Well, that’s all I have for now. I might explain the graph if I ever get enough motivation to actually do it, but for now i’ll fix anything but that. Unless everyone asks me to. Then i might. If you have any questions, please comment. Judging by the fact that it’s 2:29 AM right now, you should be able to tell that I will respond swiftly. Well, hopefully. It’s not impossible that i’ll take a while.

SteamSolo.com