Tutorial Making a simple crafting station

Discussion in 'Starbound Modding' started by projectmayhem, May 7, 2017.

  1. projectmayhem

    projectmayhem Spaceman Spiff

    Seen a few people asking how to do crafting stations, and have their recipes show on it, so thought I'd do a quick and simple tutorial.

    First, design your crafting table. You can have something as simple or complex as you want. I'll use my Bazaar Terminal as an example.

    [​IMG]

    8 frames with a little moving on some lights based off SWG's Bazaar Terminals.


    Second, create your frames file for the object.
    Code:
    {
    
      "frameGrid" : {
        "size" : [16, 22],
        "dimensions" : [8, 1],
        "names" : [
          [ "default.0", "default.1", "default.2", "default.3", "default.4", "default.5", "default.6", "default.7" ]
        ]
      },
    
      "aliases" : {
        "default.default" : "default.0"
      }
    }
    
    "size" is the width and height of each frame, not the entire png file. Each one of my terminal frames is 16 pixel wide, 22 high

    "dimensions" is how many columns and rows there are. I have 8 columns and 1 row.

    "names" are the names of each frame.

    "aliases" are other names you give the frames.


    Now that you have your image and frame file, you need your object file.

    Code:
    {
      "objectName" : "SWMbazaarterminal",
      "printable" : false,
      "rarity" : "Legendary",
      "description" : "Use Republic Credits to purchase armour",
      "shortdescription" : "Bazaar Terminal",
      "race" : "generic",
      "category" : "crafting",
    
      "interactAction" : "OpenCraftingInterface",
      "interactData" : {
        "config" : "/interface/windowconfig/SWMbazaarterminal.config",
        "filter" : [ "bazaar" ]
      },
    
      "inventoryIcon" : "SWMbazaarterminalicon.png",
      "orientations" : [
        {
          "dualImage" : "SWMbazaarterminal.png:<color>.<frame>",
         
          "imagePosition" : [-20, 0],
          "frames" : 8,
          "animationCycle" : 3.0,
         
          "spaceScan" : 0.1,
          "anchors" : [ "bottom" ]
    
        }
      ]
    
    }
    
    Pretty short and sweet.

    "objectName" is the name of your crafting object/station. This is used in the /spawnitem command.

    "printable" sets if you can use the printer to copy it

    "interactAction" lets the game know to open a crafting interface

    "interactData" lets it know WHICH interface to open.

    "filter" sets a keyword so that all recipes with that filter tag show up in your station/object

    The rest should be pretty obvious.


    Now that you have your object file, make your icon and then make a interface folder in your mods main directory, and add a windowconfigfolder to it. Then make a config file for your crafting station/object. Name it what you used for the interactData in the object file. The easiest thing to do, is copy the crafting.config from the unpacked assets, it is in the interface/windowconfig folder.


    Code:
    {
      "requiresBlueprint" : true,
      "craftingSound" : "/sfx/interface/crafting_hands.ogg",
    
      "paneLayout" : {
        "background" : {
          "type" : "background",
          "fileHeader" : "/interface/crafting/craftingheader.png",
          "fileBody" : "/interface/crafting/craftingbody.png",
          "fileFooter" : "/interface/crafting/craftingfooter.png"
        },
        "close" : {
          "type" : "button",
          "base" : "/interface/x.png",
          "hover" : "/interface/xhover.png",
          "pressed" : "/interface/xpress.png",
          "pressedOffset" : [0, 0],
          "position" : [321, 261]
        },
        "windowtitle" : {
          "type" : "title",
          "title" : " Basic Crafting",
          "subtitle" : " ^#b9b5b2;Just you, your ingredients and your hands ^green;[C]",
          "position" : [-5, 252],
          "icon" : {
            "type" : "image",
            "file" : "/interface/crafting/craftingicon.png",
            "position" : [0, -20],
            "zlevel" : -1
          }
        },
        "bgShine" : {
          "type" : "image",
          "file" : "/interface/crafting/shine.png",
          "position" : [-15, 0],
          "zlevel" : -10
        },
        "btnUpgrade" : {
          "type" : "button",
          "disabledImage" : "/interface/crafting/upgradeUnready.png",
          "base" : "/interface/crafting/upgradeReady.png",
          "position" : [139, 258],
          "zlevel" : 5
        },
        "lblSchematics" : {
          "type" : "label",
          "position" : [88, 245],
          "hAnchor" : "mid",
          "value" : "^#b9b5b2;BLUEPRINTS"
        },
        "lblProducttitle" : {
          "type" : "label",
          "position" : [265, 245],
          "hAnchor" : "mid",
          "value" : "^#b9b5b2;PRODUCT"
        },
        "spinCount" : {
          "type" : "spinner",
          "position" : [220, 46],
          "upOffset" : 36
        },
        "tbSpinCount" : {
          "type" : "textbox",
          "position" : [232, 46],
          "textAlign" : "center",
          "maxWidth" : 16,
          "regex" : "x?\\d{0,4}",
          "hint" : ""
        },
        "imgAmountInput" : {
          "type" : "image",
          "file" : "/interface/crafting/amount.png",
          "position" : [226, 45],
          "zlevel" : -3
        },
        "btnCraft" : {
          "type" : "button",
          "base" : "/interface/button.png",
          "hover" : "/interface/buttonhover.png",
          "position" : [271, 43],
          "caption" : "Craft"
        },
        "btnStopCraft" : {
          "type" : "button",
          "base" : "/interface/buttonactive.png",
          "hover" : "/interface/buttonactivehover.png",
          "position" : [271, 43],
          "caption" : "Stop"
        },
        "imgCraftBg" : {
          "type" : "image",
          "file" : "/interface/crafting/craftbg.png",
          "position" : [196, 40],
          "zlevel" : -5
        },
        "currentRecipeIcon" : {
          "type" : "itemslot",
          "callback" : "null",
          "position" : [197, 41]
        },
        "btnFilterHaveMaterials" : {
          "type" : "button",
          "base" : "/interface/crafting/checkboxnocheck.png",
          "baseImageChecked" : "/interface/crafting/checkboxcheck.png",
          "checkable" : true,
          "checked" : false,
          "position" : [40, 59]
        },
        "lblProduct" : {
          "type" : "label",
          "position" : [51, 58],
          "hAnchor" : "left",
          "value" : "MATERIALS AVAILABLE"
        },
    
        "scrollArea" : {
          "type" : "scrollArea",
          "rect" : [5, 69, 174, 230],
          "children" : {
            "itemList" : {
              "type" : "list",
              "schema" : {
                "selectedBG" : "/interface/crafting/craftableselected2.png",
                "unselectedBG" : "/interface/crafting/craftablebackground.png",
                "spacing" : [0, 1],
                "memberSize" : [159, 20],
                "listTemplate" : {
                  "background" : {
                    "type" : "image",
                    "file" : "/interface/crafting/craftablebackground.png",
                    "position" : [2, 0],
                    "zlevel" : -1
                  },
                  "itemName" : {
                    "type" : "label",
                    "position" : [25, 5],
                    "hAnchor" : "left",
                    "wrapWidth" : 116,
                    "value" : "Replace Me"
                  },
                  "itemIcon" : {
                    "type" : "itemslot",
                    "position" : [3, 1],
                    "callback" : "null"
                  },
                  "newIcon" : {
                    "type" : "image",
                    "position" : [119, 5],
                    "file" : "/interface/crafting/new.png",
                    "zlevel" : 2
                  },
                  "moneyIcon" : {
                    "type" : "image",
                    "position" : [122, 1],
                    "file" : "/interface/money.png"
                  },
                  "priceLabel" : {
                    "type" : "label",
                    "position" : [134, 1],
                    "hAnchor" : "left",
                    "value" : "0"
                  },
                  "notcraftableoverlay" : {
                    "type" : "image",
                    "file" : "/interface/crafting/notcraftableoverlay.png",
                    "position" : [2, 0],
                    "zlevel" : 1
                  }
                }
              }
            }
          }
        },
        "description" : {
          "type" : "widget",
          "position" : [190, 41],
          "size" : [140, 220]
        },
        "filter" : {
          "type" : "textbox",
          "position" : [60, 43],
          "hint" : "Search",
          "maxWidth" : 70,
          "escapeKey" : "close",
          "enterKey" : "filter",
          "focus" : true
        },
        "categories" : {
          "type" : "radioGroup",
          "toggleMode" : true,
          "buttons" : [
          ]
        },
        "rarities" : {
          "type" : "radioGroup",
          "toggleMode" : true,
          "buttons" : [
          ]
        }
      }
    }
    


    There are only a couple things you would need to change here. Change the file name, to match your interactData.
    Under Window Title and Subtitle, change those to suit your purposes.

    Wham, you're done.

    Now when you make a recipe, just add the filter from your object to the recipe file.

    {
    "input" : [
    { "item" : "WhatItTakesToCraft", "count" : 1 }
    ],
    "output" : { "item" : "WhateverYourItemIs", "count" : 1 },
    "groups" : [ "bazaar" ]
    }


    The "groups" is the filter you set in your object file. Since mine was bazaar, any items in the bazaar group show up when I open my bazaar.
     
    lazarus78 likes this.
  2. mizterpstefo

    mizterpstefo Void-Bound Voyager

    I dont quite understand,how can i put custom items in the custom crafting station?
     
  3. projectmayhem

    projectmayhem Spaceman Spiff


    Inside your object file for the crafting station, look for this part..
    Code:
    "interactAction" : "OpenCraftingInterface",
      "interactData" : {
        "config" : "/interface/windowconfigYourConfigFileNameHere.config",
        "filter" : [ "YourFilterHere" ]
      },
    The filter is like saying.. Hey game, if the recipe says "this filter" then make sure the item shows up when they use my crafting station. So, for example, my star wars mod has a crafting station called Bazaar Terminal. As you can see in the post above, I have "filter" : [ "bazaar" ] in my crafting station. So the game says, "Hey, if a recipe has "bazaar" in the group tag, then it shows up when the player opens the Bazaar Terminal.

    As you can see in my recipe example above, it says
    Code:
    {
    "input" : [
    { "item" : "WhatItTakesToCraft", "count" : 1 }
    ],
    "output" : { "item" : "WhateverYourItemIs", "count" : 1 },
    "groups" : [ "bazaar" ]
    }
    So if i put this...

    Code:
    {
    "input" : [
    { "item" : "ironbar", "count" : 5 }
    ],
    "output" : { "item" : "SWMmastersaber", "count" : 1 },
    "groups" : [ "bazaar" ]
    }
    Then when you opened up the bazaar terminal, you would see an item called Lightsaber that takes 5 iron bars to craft.

    Hopefully this helps. If you still have trouble with it, let me know.


    *EDIT*

    As an added note, in order to get it to show up, you need to patch the player.config file. If you do not know how to do that, let me know.
     
    Windtalkers and cpeosphoros like this.
  4. mizterpstefo

    mizterpstefo Void-Bound Voyager

    if you could show me how to do it i would realy apreciate it.
     
  5. projectmayhem

    projectmayhem Spaceman Spiff

    alright, going to send you a pm
     
  6. cpeosphoros

    cpeosphoros Orbital Explorer

    Great tutorial, short, to the point and very accurate. Thank you.

    About the patching thing, I'll post it here, so all the information can be in the same place. @projectmayhem, feel free to grab it and complement the OP if you want to.

    1. You will have to replicate in your mod's folder the exact folder structure for the item you want to patch. So, let's say you want to have your bazaar crafting Copper Bars. copperbar.item is located at assets/items/generic/crafting in the vanilla tree, so create a yourmod/items/generic/crafting folder.

    2. Create a copperbar.item.patch empty text file in that new folder. Notice the file has to have the exact same name as the item you are patching, with .patch added in the end.

    3. Go to http://chbrown.github.io/rfc6902/ and paste the contents of copperbar.item into both input and output fields.

    4. Edit the output field with any modifications you want to do in the target item. In this case, we are adding
    "groups" : [ "bazaar" ] to it. Look out for missing or extra commas, matching brackets and quote marks, etc. The app will complain in bright red lights if you make some mistake.

    5. While you are editing, the app will update the result field, just below input and output.

    6. Finally, when you are done editing, just copy and past the result into the .patch file you created in step 2.

    That is it. Easily done. For large modifications, you will probably want to do the editing of output in some text editor and just paste the result into the app.

    More advanced:

    This will not work if some other mod also tries to add "/groups" to the Copper Bar. This is because copperbar.item doesn't originally have that path and you are actually creating it, instead of just adding. To work around that, you have to take the following further steps:

    Take the result from the app, which in this case is (I've edited the line breaks out):
    Code:
    [
        { "op": "add", "path": "/groups", "value": [ "bazaar" ] }
    ]
    And change it so it reads:

    Code:
    [
        [
            { "op": "test", "path": "/groups", "inverse" : true },
            { "op": "add", "path": "/groups", "value": [ ] }
        ],
        [
            { "op": "add", "path": "/groups/-", "value": [ "bazaar" ] }
        ]
    ]
    Mind the new set of square brackets, commas, etc. Also mind the /- after groups in the second set.

    What this do is check for the existence of the "/groups" path, and create it as an empty one if there is none. Only them it adds the "bazaar" value.
     
    Last edited: Jul 10, 2017

Share This Page