Your first tech mod

A group for modders!

  1. Silverfeelin

    Silverfeelin Bacon Manager Modder

    19
    80%
    BCash: ß 1,080
    In this tutorial we'll go over some of the basics you need to set up a (multiplayer compatible) tech mod. As the blink tech no longer exists in 1.0, we'll set up a functional alternative.
    Before you get started, it is recommended to unpack the assets of the game; the video guide in this thread should help with that. It is also expected that you have some basic knowledge of Lua.
    We'll be using the Keybinds library, so we only have to focus on getting the results we desire. The installation of Keybinds is described later on.

    To give you a rough idea of what you can do with a custom tech, I've linked some of my own tech mods below.
    LuAnimator, WEdit, Pigmenter.

    Contents
    1. Setting up a new mod
    2. Setting up the tech
    3. Understanding what's there
    4. Setting up Keybinds
    5. Setting up the blink
    6. Adding flair
    7. Additional notes

    Thanks to Magicks for helping me write this guide. Credits for the section 'Adding flair' go to him.
     
    Last edited: Aug 24, 2016
  2. Silverfeelin

    Silverfeelin Bacon Manager Modder

    19
    80%
    BCash: ß 1,080
    1. Setting up a new mod
    The modinfo file is deprecated; a metadata file should now be used instead. This post will be updated at a later time (if I don't forget). Note that a metadata file is not required for your mod to load.


    Every mod starts with one thing; the modinfo file. This file is required in every mod as it is used by the game to identify what files should be loaded.
    • Locate and enter the 'mods' folder in your Starbound folder.
      • If it does not exist, create it. The path to the mods folder should look something like this: '../Starbound/mods/'.
    • Create a new folder, and add a new text file to it named 'pak.modinfo'.
      • It is recommended to give the folder the same name as your mod.
    • Open the newly created modinfo file with a text editor, and paste the below code in it.
      • You'll probably want to edit the mod name; any value will work.
      • It is highly recommended to give every mod a unique name.
    • Save and close the modinfo file.
    Code:
    {
      "name" : "MyTechMod",
      "path" : "."
    }
    At this point, your mod should be recognized. Loaded mods will appear as asset sources in the bottom right corner of the main menu.

    [​IMG]
    [​IMG]
    [​IMG]
     
    Last edited: Aug 24, 2016
  3. Silverfeelin

    Silverfeelin Bacon Manager Modder

    19
    80%
    BCash: ß 1,080
    2. Setting up the tech
    As we're going to make our tech mod multiplayer compatible, we can not simply create a new tech. Instead, we'll have to modify an existing tech.
    Available techs can be found in the tech folder of unpacked assets. For now, let's go with the distortion sphere, as it's available for new characters.

    Copy '/tech/distortionsphere/distortionsphere.lua' from your unpacked assets to '../Starbound/mods/MyTechMod/tech/distortionsphere/distortionsphere.lua'. You'll have to create the directories in your mod folder so that the copied Lua file is in the right place.

    The distortionsphere.lua from your mod will now be used. It's time to modify the script now!

    [​IMG]
     
    Last edited: Apr 19, 2016
  4. Silverfeelin

    Silverfeelin Bacon Manager Modder

    19
    80%
    BCash: ß 1,080
    3. Understanding what's there
    Let's take a look at the contents of the copied distortionsphere.lua file.
    You'll see a bunch of code within functions. Although you may want to modify this code, generally you don't have to touch it to add your own code.

    There are a few noteworthy functions in tech scripts. These are called by the game (something you have no control over), but not having to manage this is actually a good thing!

    function init()
    This function is called whenever you enter the game, or warp somewhere else (this includes dying). It is most commonly used to set default values.
    [​IMG]

    function update(args)
    This function is called every game tick (1/60th of a second). This function is what you use to check and interact with the world around you. You can use the update function to see if a key is held down, and run a function if it is.
    [​IMG]

    function uninit()
    This function is called whenever you're leaving the game, or before you're warped somewhere (this includes dying). I generally don't use this function. You could use this to, for example, store your position when leaving a planet to teleport back to it later.
    [​IMG]
     
    Last edited: Apr 21, 2016
  5. Silverfeelin

    Silverfeelin Bacon Manager Modder

    19
    80%
    BCash: ß 1,080
    4. Setting up Keybinds
    Setting up Keybinds is very easy. I've included it in this tutorial as it allows us to focus on getting the blink to work rather than how we check if the user has pressed a button (which actually takes more work than this easy teleport implementation).
    After downloading the Keybinds mod and installing it as a regular mod, go back to your distortionsphere script and add the following line at the top:
    Code:
    require "/scripts/keybinds.lua"
    [​IMG]

    Next up, let's create our own function that is executed when you press the G key. For now, we'll make the function log a line of text to the starbound.log file.
    Keep in mind that you have to prevent using duplicate names. If you define your own function named update, issues will surface.
    Outside of other functions (or at the very bottom just to be sure), create a new function that logs some text.
    Code:
    function myFunction()
      sb.logInfo("You pressed the G key!")
    end
    [​IMG]

    As this function is not called anywhere, it's currently dead code. To run the function after pressing the G key, we'll create a Keybind.
    As the init function is generally used to set default values and such, we'll create it here.
    You can look at the syntax of Keybinds on the official page if you're interested, as there's a bunch of other options besides pressing one button.
    Code:
    Bind.create("g", myFunction)
    [​IMG]

    At this point, you should be able to log the text by pressing your G key. Make sure you have the basic distortion sphere tech active on your character!
    [​IMG]
     
    Last edited: Apr 19, 2016
  6. Silverfeelin

    Silverfeelin Bacon Manager Modder

    19
    80%
    BCash: ß 1,080
    5. Setting up the blink
    Now that we have our function that will be executed every time we press the G key, it's time to implement our own simple teleportation.
    For a full list of (undocumented) available functions, you can log the script's environment by putting this code in the init (or you could create a keybind for it):
    Code:
    for k,v in pairs(_ENV) do
      if type(v) == "table" then
        for k2,v2 in pairs(v) do
          sb.logInfo("%s.%s", k, k2)
        end
      else
        sb.logInfo("%s", k)
      end
    end
    
    Until the official documentation comes back online, a bunch of information can be found by digging around in the assets or searching for it on forums. For the rest, it's usually trial and error.

    To teleport, we want to set the position of our character. The mcontroller table (movement controller) deals with this kind of stuff, so looking at what functions this table has available is the best way to start.
    By looking at the available functions, we can see that there's a function called mcontroller.setPosition; just what we need!
    [​IMG]
    The problem here is that we do not know what parameter this function expects. This is where you would look it up online or search the assets for it. The setPosition function takes a table with two numbers in it; the X and Y coordinate.
    An example call, that sets your position to (100,200), would be:
    Code:
    mcontroller.setPosition({100,200})
    Of course, we do not want to teleport to one point in the world. We want to teleport to the cursor, so let's find a function that allows us to do this.
    [​IMG]
    The tech.aimPosition function returns the perfect value for this. If you want to see exactly what it returns, you could log it:
    Code:
    sb.logInfo("%s", tech.aimPosition())
    Now to actually set our position, we'll use the tech.aimPosition return value.
    Code:
    local aimPosition = tech.aimPosition()
    mcontroller.setPosition(aimPosition)
    [​IMG]
    At this point you'll notice our position is updated when we press the G key. The only problem is that we're falling awfully quick.
    In /debug mode, we can see that our vertical velocity is actually at -1.27 (may vary) while standing on the ground. To fix this, we'll want to set our vertical velocity back to 0 when we blink at the moment we blink.
    [​IMG]
    Code:
    mcontroller.setYVelocity(0)
    You could also set the velocity to a value greater than 0 to increase the air time, but keep in mind this will actually slightly elevate your character after teleporting.

    Now that we have our simple teleport tech ready, it's time to try it out. Start up your game, aim where you'd like to go and hit G!
    [​IMG]
     
    Last edited: Apr 19, 2016
  7. Silverfeelin

    Silverfeelin Bacon Manager Modder

    19
    80%
    BCash: ß 1,080
    6. Adding flair
    As you can see in the previous picture, those vines look a lot more appealing than the teleportation we've created. Why use a boring teleport when you can embrace some nice looking vines instead? No worries, it's time to add some flair to our tech mod!

    There are a few ways to add flair through tech mods, but the most common and yet very expansive method is spawning projectiles with custom parameters. That's what we'll be looking at here.
    Going back to the logged functions we can use in our tech script, there's a couple of functions related to projectiles. The one we're looking to use is world.spawnProjectile.
    [​IMG]
    As usual, we have no clue right now what arguments this function requires. This one is a lot trickier than other functions as well. As this is a pretty well known function, it's been documented online. Although this gives us just what we need, finding an answer isn't always that easy. The assets can also be useful for finding examples.
    I regularly use Agent Ransack to search through the entire assets for a search phrase. After doing so for 'world.spawnProjectile', I found a couple of helpful assets. As they do regularly involve more experimenting, we'll use the wiki for now.

    Okay, so before we get onto the specifics I'll just briefly explain the terminology Vector2 or Vec2. So starbound is a 2D game; we have up and down and left and right. To describe how things move, we use vectors which (in Lua) are written as {x,y} where x is how far across we go and y is how far along we go. As you get more advanced you'll see how useful this system is and I'm making a small assumption that you know a little about how vectors work. Now from the wiki entry we can fill in our world.spawnProjectile :
    Code:
    world.spawnProjectile("a projectile name",mcontroller.position(),entity.id(),{0,0},false,configTable)
    
    So, for our blink effect we will want something invisible. After looking through /projectiles in the assets you will almost immediately spot invisibleprojectile. This is great for us because it has no other effects that will conflict and is completely invisible. The use of entity.id() here is is to signify the projectile is ours however, you need not worry about that until you start tracking the source entity which we won't. I've left configTable as a Lua variable because, often for our own readability, it is nice to write tables without the function wrapped around it. We want to make a gassy vine-like blink effect so we should look in the assets for some particle images or animations, I would recommend starcheat's image browser:
    [​IMG]
    For this tutorial we will use this as our image. To get this to appear in a burst at the start of the blink we will use a particle action on the projectile. To start off this process we should set up the config table variable.
    Code:
    local configTable = {
                     timeToLive = 0.01,
                     actionOnReap = {}
               }
    
    We want to add our wildvine image to the projectile spawned using a particle. First we need to set up a loop action in action on reap. We then add particle actions to the body of the loop to spawn a nice amount of vine images to make the effect more visible.
    Code:
    local configTable = {
                     timeToLive = 0.01,
                     actionOnReap = {
                         {
                              action = "loop",
                              count = 6.0,
                              body = { }
                         }
                     }
               }
    
    Now we are ready to add particle actions. I personally think seeing a complete particle structure and learning the parameters by tweaking it work best. I have fully written a particle for you to read through and use here:
    [​IMG]
    Looking at the config we can see:
    • type: this is the kind of particle, you can have "textured","animated","ember" and "streak" particles. Both animated and textured need an image field with either a path to a .animation or .png file respectively.
    • timeToLive: how long the particle is "alive".
    • destructionAction: the way the particle disappears, you can have : "none","fade" and "shrink".
    • destructionTime: is the time destructionAction runs for until the particle disappears. The timeToLive + destructionTime gives you the time the particle is visible.
    • layer: can be "front","back or "middle" and that describes where the particle is rendered, front is over the top of all other sprites and back is behind everything but the background block layer.
    • size: which works like ?scalenearest for embers, textured and animated particles.
    • rotation: is the particle's rotation in degrees.
    • velocity: is the direction and speed of the particle and position is where it spawns in relation to the projectile.
    • variance: allows you to make things like velocity randomised, the value inside variance is like a +- maximum.
    • angularVelocity: how fast it spins. Set it to 0 or leave it out to have particles with no spin.
    To use a particle in our projectile simply add it's table inside the body field.
    [​IMG]

    Feel free to try out this example code and make modifications; experiment! It will look something like this:
    [​IMG]
    If you'd like the particles to appear at your destination rather than your original location, just swap the world.spawnProjectile and mcontroller.setPosition functions. If you'd like particles to appear at both places instead, copy the world.spawnProjectile function call and make sure it's called both in front of and after the mcontroller.setPosition call. The below code accomplishes the latter.
    Code:
    world.spawnProjectile("invisibleprojectile",mcontroller.position(),entity.id(),{0,0},false,configTable)
    mcontroller.setPosition(aimPosition)
    world.spawnProjectile("invisibleprojectile",mcontroller.position(),entity.id(),{0,0},false,configTable)
    
     
    Last edited: Apr 19, 2016
  8. Silverfeelin

    Silverfeelin Bacon Manager Modder

    19
    80%
    BCash: ß 1,080
    7. Additional notes
    Nothing to see here yet!
     
    Last edited: Apr 19, 2016
  9. Riamz

    Riamz Sizzling Bacon Syndicate

    15
    20%
    BCash: ß 500
    are you going to list other features that could be made with other key-binds? that would be super cool and the people that actually want to learn will get a better understanding or can I not fathom how hard something like this could be and asking is ridiculous.
     
  10. Silverfeelin

    Silverfeelin Bacon Manager Modder

    19
    80%
    BCash: ß 1,080
    It's kind of difficult to give you a list of things you can make; you can make A LOT of different things. It's why I included some examples in the first post.
     
    Riamz likes this.
  11. Reno_fezzed_one

    Reno_fezzed_one Cooked Bacon

    5
     
    BCash: ß 500
    Nice modding tutorial!
     
    Silverfeelin likes this.
Loading...

Share This Page

Loading...