Hello There, Guest! Login Register

Thread Rating:
  • 1 Vote(s) - 5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Tutorial: Implementing a New Object in SWGEmu
So you're working on a server - maybe your own, or maybe you're contributing to another project - and you want to add a new object. Maybe it's a piece of armor or clothing; maybe it's a chair converted from the NGE; or perhaps you're taking something previously unacquirable and putting it in player hands.

This tutorial is written to help you.

(I've done a fair number of object implementations; Lasko is probably the master of it at this point, due to the massive number of conversions he's done from NGE to pre-CU. In fact, if you're looking at implementing an NGE object, you should probably start by looking at the Mod the Galaxy repository and public TREs - most likely it'll have most of the code already done to make this work.)

This tutorial assumes a basic working knowledge of SIE and access to a SWGEmu development environment. Before you begin, make sure you have SIE running and you are familiar with the tool. You won't need to get on your SWGEmu server until the 6th checklist entry.

Here's your checklist of everything necessary for your new item:

1.) Object IFF file
2.) Object model file (.apt or .sat)
3.) String files entries (optional)
4.) CRC entry
5.) Custom TRE file
6.) Object .lua file
7.) objects.lua file entry
8.) serverobjects.lua file entry

We'll handle this piece by piece. If you're following this as a tutorial, we'll do it by implementing a new object using existing models - in this case, we'll be taking the Endor-style hat and implementing it as an armor helmet.
1.) Object IFF file

All of the relevant files for object IFFs are, fittingly enough, in the object folder. Thes are broken down by type. Most commonly, people will be working in object/tangible, with object/weapon being the next most common and probably object/mobile being third.

*Technical information: SWG works heavily with the concept of inheritance, defined via "base objects". For example, object/tangible/wearables/backpack/shared_backpack_s01.iff has a base type of object/tangible/wearables/base/shared_base_backpack.iff. Anything that backpack_s01.iff doesn't explicitly define is inherited from base_backpack.iff. Largely, this makes implementing new objects fairly easy, since you can create your new objects with relatively small changes and inherit the major properties you need. We'll be depending on this as we move on.*

To start on our helmet project, navigate to object/tangible/wearables/armor/marine/shared_armor_marine_helmet.iff. Right-click and extract that file (not the chain!) to a new folder - for simplicity sake, let's call that folder "tutorial".

If you check "tutorial", you'll see that the extract created a chain of folders - do *not* delete or change this chain. It'll make creating the TRE file in Checklist Entry 5 easier. For now, navigate down the folders until you find the shared_armor_marine_helmet.iff we just extracted; rename it to shared_armor_endor_helmet.iff.

Switch back to SIE, click "New Editor", and then select "New Iff Editor". Click "Open" and select the shared_armor_endor_helmet.iff.
2.) Object model file (.apt or .sat)

Take your time looking through the fields. SIE will likely be using a default template, which is okay for our purposes. You'll see a lot of different fields and you'll have no idea what most of them do. That's okay, though, because we're not worried about most of them! In this case, we're looking for the entry called appearanceFilename - this is the entry that determines what model an object uses. In this case, the entry for it will be appearance/armor_marine_helmet_f.sat.

Once you've found it, swap back over to the SIE repository. Navigate to object/tangible/wearables/helmet/shared_helmet_s06.iff and double-click it in the SIE window to open it. Scroll down until you find the appearanceFilename entry in the Rebel Endor-style helmet. You'll find that its appearanceFilename entry is appearance/helmet_s06_f.sat.

*Technical information: SWGEmu models generally come in two flavors, .apt and .sat files. A file with .apt is a static model - things like furniture, houses, etc use the .apt format. A file with .sat is a file using a skeleton - creatures, clothing, armor, and the like. At the time this tutorial is being written, we have okay tools for converting .apt files, but nothing that can handle bringing a new .sat file into the game.*

*Conversion note: models exported from the NGE often require a downgrade of sorts to work in the pre-CU client - this can take the form of LOD file changes, shader changes, or even chunk type changes in one of the model files. Check the MtG TREs, curated by Lasko - he's done an amazing job converting most of them. It's an ongoing project, and sometime soon they will all be done. Handling this conversion is beyond the scope of this tutorial.*

SIE uses a "template" system for reading IFF data. Most likely, your current template is simply:

String[Slot, -1]

Now, you have two options here. One is to simply copy and paste the hex code from shared_helmet_s06_f.sat to shared_armor_endor_helmet.iff. There's nothing wrong with that, and it'll get the job done - if you take this approach, I strongly recommend making sure you copy and paste the entire hex code from one over the entire hex code in the other to ensure you don't leave stray data to screw something up. If you want to learn a bit more, though, you can learn a bit about SIE's template system.

Many of the object IFF entries follow a simple format for a template:


The first string is the entry type (in this case, appearanceFilename); the second entry is a boolean, indicating whether the field is used (in this case, Yes), and the second string is the actual entry. Depending on the field, you might have an extra spacer byte after the bool, followed by an integer or float. If there's another string following the first, they'll use a byte as a spacer. (We'll see that in just a minute.)

Once you've made the change to your shared_armor_endor_helmet.iff file, save it. Don't close your shared_helmet_s06.iff file, though - we're not done with it.
3.) String file entries

The entries objectName, detailedDescription, and lookAtText specify text entries for the object. If you want to take the very quick way through this tutorial, copy and paste the hex code for those same entries as you did the appearanceFilename as you did above. If you're in a hurry, you can skip over the explanation here and return at your leisure; otherwise, read on for some explanation.

*Technical information: It's important to remember that SWG sprung from an age when bandwidth was at a premium. In 2003 when SWG launched, maybe 10% of US Internet subscribers had broadband. SWG was written to take a minimum of bandwidth, and that meant cutting corners in every way possible. In this case, many object names and descriptions are actually stored in the TRE files rather than sent from the server. Of those that are sent from the server, the SWGEmu Core3 server still references those same string files, so correct entries are important.*

Plug in this as your template and apply it:


It'll clear up the output to something you can work with more easily. The first field, as before, is your entry type - in this case, if you're on the first entry, objectName. The second field is your boolean on whether the field is in use, set to True. The number 1 in the third and fifth slots can be ignored; they're just fillers from the "byte" type. And finally, you have "wearables_name" and "armor_marine_helmet" as your remaining text entries. "wearables_name" is a string file; "armor_marine_helmet" is the entry.

Head back over to the SIE repository and browse to string/en/wearables_name.stf - go ahead and double-click it to open the file. Scroll down until you find "armor_marine_helmet" and you'll note the corresponding entry is "Marine Armor Helmet". That's the text that will actually be used in-game for the object. If you're going to be adding completely custom objects, including new names, you'll need to extract these STF files to your "tutorial" directory and add your new entries; however, in this case, you can flip back over to shared_helmet_s06.iff and mirror your entries for objectName, detailedDescription, and lookAtText. When you're done, save your shared_armor_endor_helmet.iff. You're done with this file, but you've got a ways to go before you're done!
4.) CRC Entry

In the SIE repository, browse to misc/object_template_crc_string_table.iff and extract it to our "tutorial" folder. Open it then using SIE's CRC editor, which is different than the previous editors you've worked with - it's much simpler, actually. Put simply, this CRC table is a list of every single item in the object/ folder.

*Technical information: Remember the earlier note about bandwidth savings? That's at play here, too. When the server tells the client an object is at a location, it doesn't use the file path; it uses the CRC number, which is calculated from the file path and name, as it's much smaller and requires less bandwidth. The CRC table is the client's way of looking up that number to see which file it needs. If the client receives a CRC number and doesn't have an entry for it, it won't display anything. If you've done a new object implementation and tried to spawn it, it doesn't appear, but no errors show up on the server console, there's a very good chance you forgot your CRC entry.*

*Technical information: The CRC table needs EVERY object file. If you're working on a project that already has non-stock objects added, make sure you're working from their latest CRC table. If you forget and create a new CRC table that's missing other custom entries, you can save yourself work by merging the two CRC tables using SIE's built-in functionality for it.*

(Note: at the time this is being written, the most recent release of SIE will not sort by filename; it's actually broken. This will be patched.)

At the bottom, there's a "filter" box. If you type in object/tangible/wearables/armor/marine, you'll see it displays only the entries matching that folder string.

We need to add our new shared_armor_endor_helmet.iff to this list. The quickest way is to put the full path into the box and click the plus arrow (in this case, object/tangible/wearables/armor/marine/shared_armor_endor_helmet.iff). You can also use the "add from" function at the top of the CRC tool.

Double-check your new entry for typos. In my experience, this is the most common point of failure for new developers and modders.
5.) Custom TRE file

At this point, we're ready to build a new TRE. Double check your "tutorial" folder - you should have two files. One will be tutorial/object/tangible/wearables/armor/marine/shared_armor_endor_helmet.iff; the other will be tutorial/misc/object_template_crc_string_table.iff, in those exact folder locations.

Assuming everything looks good, hit the drop-down arrow next to TOC/TRE builder in SIE and select "Create tre from directory on disk". Select your "tutorial" folder, then browse to a new location and name your new tre "tutorial.tre". Given the small size of the TRE, it'll only take a second or two to build. (Larger TREs can take some time - 100+ MB TREs can take 10-30 seconds on my dev machine, for example.) Now in SIE, click "Open tree(s)" and select "tutorial.tre". If everything has gone well, when you browse to object/tangible/wearables/armor/marine/shared_armor_endor_helmet.iff you'll see a preview of the classic Endor helmet rotating in the graphical display.

Now you'll need to copy your TRE to two places - your SWG directory (example: C:\SWGEmu) and to your SWGEmu server.

In your SWG client directory, you'll need to add it to your load order so the client uses it. Look for swgemu_live.cfg and open it in Notepad (or other text editor of your choice) and add it to the top of your load order. Adjust the maxSearchPriority and searchTree entries appropriately.

On your SWGEmu server, you'll need to put your tutorial.tre with the rest of the server's TREs. (If you're running EmuYoda, they live in the SwgEmu folder on your desktop.) You'll also need to edit your config.lua to add tutorial.tre to the top of your load order there as well.

*Technical information: TREs at the top of the load order overwrite TREs lower down in the order. For example, if you browse the stock TREs, you'll note that there's a "object_template_crc_string_table.iff" file in most of them; the one furthest up the load order takes precedence. Keep that in mind as you continue to add new objects and new TREs.*
6.) Object LUA file

On the server, browse to MMOCoreORB/bin/scripts/object/tangible/wearables/armor/marine. You'll notice that there are a number of lua files here, each matching a files you previously saw in the SWG TREs in SIE. This is by design; files on the server mirror files in the TREs to make it easy to find and add or alter appropriately.

Make a copy of armor_marine_helmet.lua and rename it armor_endor_helmet.lua, then open it in the text editor of your choice. (I use geddit on my server.)

There's a few changes we'll need to make here. Quickest way to search is for "armor_marine_helmet" - it'll highlight the four places in the file you *must* make changes. Change each of those "armor_marine_helmet" bits to "armor_endor_helmet" to match our new filename.

*Technical information: the data in this file are the standard values the object is spawned with. Note that if we were using a craftable helmet, there would also be crafting information in here. Alter as necessary.*

Save your changes.
7.) objects.lua file

In your MMOCoreORB/bin/scripts/object/tangible/wearables/armor/marine, look for objects.lua and open it. (Again, I use geddit - use your text editor of choice.) At the bottom of this file, we'll need to add some new entries for our armored Endor helmet. If you're eager to test, you can add this and go; else, read on for a more technical explanation:

object_tangible_wearables_armor_marine_shared_armor_marine_helmet = SharedTangibleObjectTemplate:new {
clientTemplateFileName = "object/tangible/wearables/armor/marine/shared_armor_marine_helmet.iff"}

ObjectTemplates:addClientTemplate(object_tangible_wearables_armor_marine_shared_armor_marine_helmet, "object/tangible/wearables/armor/marine/shared_armor_marine_helmet.iff")

*Technical information: you'll notice that stock SWGEmu entries have a huge amount more text - also note that it's commented out. At one point in Core3 development, that information wasn't loaded from the object.iff files but was specified manually on the server. At some point, if you get far enough into doing weird shit on your server, you'll appreciate having that information available in the neatly commented format. It's helped me understand some issues. In the event that you're adding an entirely new folder, you'll also need to seek out allobjects.lua and add an entry there pointing to your new objects.lua file. Objectception, I know.*
8.) serverobjects.lua file

Again in MMOCoreORB/bin/scripts/object/tangible/wearables/armor/marine look for "serverobjects.lua" and open it in your text editor. This one's pretty simple - just add an entry for armor_endor_helmet.lua, save, and close.

*Technical information: the serverobjects.lua file tells the server what object lua files exist to load. They also chain - if you look at the serverobjects.lua in MMOCoreORB/bin/scripts/object/tangible/wearables/armor, you'll note that among other files, it calls the serverobjects.lua in the marine folder.*

At this point, you should be ready to start up your server. Watch for errors when it's loading templates - that will be your indication something's wrong. Note that SWGEmu by default has some errors during the template load that don't hurt anything. Watch specifically for anything relating to our new armor helmet.

Assuming everything looks good and the server loads normally, log into an admin character on your dev environment and see if you can spawn your new object.

/object createitem object/tangible/wearables/armor/marine/armor_endor_helmet.iff

If you get an error, check for typos. If you get no feedback and the object doesn't appear in your inventory, check your CRC table for the appropriate entry *and* check the server console for errors. If the object appears in your inventory, you're ready to go...or at least, to keep working.

And that concludes my new object tutorial.

Forum Jump:

Browsing: 1 Guest(s)