Skip to content

Modding: Basics

ErinaSugino edited this page Oct 4, 2023 · 2 revisions

Sexbound, in its core, is an API. That means, the majority of its features are basic frameworks that enable a certain mechanic to exist, which can then be used by other mods to create content. The concept of sex and the mechanic of displaying an entire, custom animated sex scene inside of an object's animator does not natively exist in Starbound. So any mod that wants to use these mechanics is reliant on Sexbound. Vice versa, Sexbound always has been greatly reliant on other people creating addons for it to add new content. Most people that appear for troubleshooting have dozens of mods installed - solely counting those regarding Sexbound content.

As such, the creation of these mods is as important of a task for this community as is the continued development of Sexbound to add more and better features for modders to use. This guide goes over the basics of creating mods for Sexbound, as safely and robust as possible.

Content Addons

The simplest form of mods are those that solely add data. Take for example a mod that adds sex compatibility for a new race, or a mod that adds new sex positions. Maybe add or alter some sextalk dialogue. These mods don't need any scripting and as such are both quiet easy to create and safe to use. Instead of breaking everything, worst case scenario the content added by these mods just doesn't work properly anymore should stuff change in future updates of Sexbound.

Creating these addons consists of two steps. Step one is adding or editing the data. For, e.g., a new sex position this would involve the config file for the position, as well as replacing the (or adding a new) spritesheet for the actors having the new animations. The second step is patching into corresponding config files. Creating a patch is as simple as creating a file in the same folder as the original, then appending .patch to the file. However, what goes into the patch file is a bit more complex than that - make sure to read up on patch file data and always validate your JSON syntax. Also, keep in mind that you can only patch files whose content is JSON data - this means mainly .config, .animation and .object files. With this patch you can safely add or replace data without compromising the original when it updates. For, e.g., new sex positions you would need to patch into the two animation files in order to add the data and part offsets for your new animation states. But details on this would be the topic of other, dedicated guides.

Hooks and Overloads

More complex addons, however, will rely on making changes to the code. This is where 99% of all problems and incompatibilities come from.

Opposite to assets, which just get added onto eachother or cleanly replace their original (like replacing a sprite with another), code is much more finicky. Any single line of code serves a purpose and even the slightest change to it can break the entire system. In proper programming, with a proper programming language, this is where object oriented programming comes into play. A term you might have heard before - it refers to treating parts of a program as autonomous objects which simply interact with eachother in pre-determined ways, following strict rules. As such, these objects can easily be replaces by alternatives that serve the same or more functionality than the ancestor. This techinque usually comes paired with the terms class and instance.

The problem is, Lua does not have this concept of classes. The closest alternative available, and also the one Sexbound Reborn heavily relies upon, is using metatables to create instances from an object serving as blueprint. It's like JavaScript's old prototype inheritance system, in case you're more familiar with that - but even JavaScript upgraded to normal classes by now. Thing about this is that it's mostly just semantic fluff and offers no safety to improper changes being made, allowing a slight error to still crash the entire system. This is why it's important to develop addons as unintrusive and non-destructive as possible. In order to allow addons to be such, Sexbound Reborn introduced more ways for modders to safely modify the system.

Hooks

In case you just want to add new functionality onto old things, event hooks are the way to go. In every proper software development project an event handler system is in place to trigger certain events exactly, and only, when they are needed. Starbound itself, too, has a system like that, offered via the entity message system. Using world.sendEntityMessage(targetId, messageType, messageData...) you can send bits of data when a certain event happens to another entity, object or player script, which listens to that event via message.setHandler(messageType, callbackFunc). This can also be used to both trigger vanilla Starbound functionality (like changing the currently playing background music) and listen to vanilla Starbound events (like damage and death).

Sexbound itself, however, furthermore offers its own event system within a sexnode.
By using Sexbound.Messenger.get('main'):send(from, to, type, data, delay) messages are propagated internally, either instantly (delay = false) or on the next tick (delay = true, default). On the to object, the method onMessage(message) is tried to be executed, which then in turn has the capability to check the message parameters getFrom(), getType() and getData(). By default, every actor is setup to listen to messages and just forward their contents to every activated plugin. So sending a message to an actor results in that actor's pregnancy, climax and all other plugins to receive the same message.

Overloading

However, in most scenarios you will still have to make some form of changes to existing code. Like adding another check for a new message type into an already existing "onMessage" method. Adding something to the execution chain of an entity's "update" or "init" method.

The biggest problem with incompatibilities amongst mods is code overrides. You can't help it if two mods try to change the exact same code snippet in two different ways - something where even convient software like Git, literally made to make the process of merging code easier and more managable forfeits and calls for human input - but most mods just roll an entire new carpet over the whole floor just to hide a stain. Example given, the reason Lustbound is natively incompatible with both original Sexbound and Reborn, is because it makes changes to two crucial files - the actor.lua and climax.lua files. The changes are minimal; in the case of climax.lua it literally just adds a new method which is getting called under one condition in another method. However, instead of making just those changes, the mod contains an entirely new "climax.lua" file, that fully replaces the original. Problem however is, Lustbound was long since abandoned, and the "new" climax.lua actually contains the code of an ancient Sexbound version, plus these two tiny changes. Which obviously means, it won't work on newer versions.

This, however, can be avoided by selective replacement or method overloading. A practice from OOP, reenacted in a different way. Starbound itself and moreso Sexbound offer library loading - or in other words, the ability to patch into a config file (which is much, much safer) to define a whole new lua script to be loaded in a context. For entity's (player, npc, monster) and objects this has always been possible, Sexbound Reborn expands upon this by adding the ability to patch into the actor script too - essentially giving access to the entire sexnode side of things.
By simply patching into sexbound.config and adding your new lua script to override/actor|monster|npc|player your script will be loaded in the respective context. This means the original script is still in tact and on the newest update, but if you define a method that already exists you replace it still.

Example given, you can patch into the actor and then define a function Sexbound.Actor:setup() which will replace the original setup method - and only this. That way, the damage dealt when the original mod updates is minimized to just this one function. Which is much easier fixable, and in some cases not even fatal.

However, in most cases you don't need to actually replace code - you just want to add to it. Like, again, adding a new message handler to the already existing "onMessage" method. This is where overloading comes into play - a mechanic you might have had to deal with before when adding stuff to an entity's "init" or "update" methods. By defining a new reference to the original method and calling that inside your new method, you preserve all old funtionality while still adding your own - completely independent from which version the original might be. Take this example:

local old_onMessage = Sexbound.Actor:onMessage
function Sexbound.Actor:onMessage(m)
    old_onMessage(m)
    -- Your new code
end

This way the original onMessage method is run just fine - which currently just sends the message to all plugins of this actor - before you can then execute whatever code you want with the message yourself. And if this method ever changes in future SBR updates - your addon is still fine. You can of course also run your own code before the original. But in any case, just pay attention to what the method receives in parameters, and what it might return.

   Home

Usage   Installation
  Configuration

   FAQ

Development   Original vs. Reborn
  Roadmap
Guides   Advanced Troubleshooting
  ——————————
  The UI explained
  Mechanics explained
  ——————————
  Modding: Basics
  Modding: Translations
  Modding: POV Module
  Modding: Sextalk
  Modding: Races
Clone this wiki locally