TUG Lua modding guide (TUG Alpha 0.6.3)

tullrichtullrich REGISTERED, Developers Posts: 10 Developer
edited August 2014 in Code
Lua Modding 101

Modding is an important part of Nerd Kingdom's vision for TUG. We try to build much of our tech with modders and modding in mind. To that end our Lua scripting api has been slowly built up over the last few patches, and we have now released the initial revision of the official documentation, found at http://eternusapi.nerdkingdom.com.

Below is a simple quickstart guide to adding scripted content to TUG.

Making a GameObject.txt

The simplest way to mod TUG is to create new objects in the world for the player to interact with. We do this by adding simple text files into the AssetsDataGameObjects directory. You should be able to find the assets folder next to your TUG.exe.

Let's define a GameObject called Magic Wand in the file TUG/Assets/Data/GameObjects/EquipableObjects/MagicWand.txt:
GameObjects
{

	Placeable
	{

		Magic Wand
		{
			
			StaticGraphics
			{
				model ="Models/PlaceableObjects/Harvestables/woodStaff.obj"	
				dontCastShadows = 1.0				
				Diffuse
				{
					0 = "Character/Weapons/0spearB_WLV_New_diff.tga"
				}
				Normal
				{
					0 = "Character/Weapons/0spearB_norm.tga"
				}				
			}
			
			RigidBody
			{
				activePhysics = 1
				mass = 15.0
				friction = 6.0
			}
		}
	}
}

The first thing that we see here is a section entitled "GameObjects" and another nested section entitled "Placeable", these tell the engine that what follows defines a new object that can appear in the world. The next section "Magic Wand" is where our new object's definition begins, in here we specify the different components that makeup its representation.

The first section "StaticGraphics" adds a StaticGraphicsComponent that gives our object a model and assigns a few Diffuse and Normal textures. There are few other rendering properties this component can provide, but for now this is all we need.

The next component is a RigidBodyComponent which allows this object to exist in the physics simulation and provides a mass and friction. The activePhysics flag indicates that this object will be placed in a dynamic state.

Now, when we run TUG and enter a world, we can use the /spawn "Magic Wand" command to plop down an instance of our new object. We can also use /spawn "Magic Wand" 20 to drop a couple more.

T8IAuNsl.png
LypP8TJl.png


Making our wand slightly more magical.

You might have noticed by now that you can't actually pick up the wands, and that they are certainly not doing anything magical... they are mostly just laying there. If yours ARE doing anything magical at this point, please file a bug report.

So lets redesign our text file and make our wand do something:
GameObjects
{

	Placeable
	{

		Magic Wand
		{

			StaticGraphics
			{
				model ="Models/PlaceableObjects/Harvestables/woodStaff.obj"	
				dontCastShadows = 1.0				
				Diffuse
				{
					0 = "Character/Weapons/0spearB_WLV_New_diff.tga"
				}
				Normal
				{
					0 = "Character/Weapons/0spearB_norm.tga"
				}
			}
			
			RigidBody
			{
				activePhysics = 1
				mass = 15.0
				friction = 6.0
			}

			Equipable
			{
				name = "Magic Wand"
				icon = "UI/MenuIcons/2x_ShroomStem.tga"
				resource = 1
				durability = 1
				damageToCharacters = 1

				
				Equipment Slots
				{
					Tool
				}
			}

			Script
			{
				file = "Scripts/Objects/Wand.lua"
				class = "Wand"

            arguments
				{
				}

			}
		}
	}
}

Above we can see that there are two new components attached to the wand. First is an EquipableComponent, this is a natively implemented component that allows the player to pick up and equip this item into his hand. It will also make this item appear in the Creative Mode inventory. The data here provides an inventory name, an icon, and marks this item as a resource that the player can collect. There are many more fields that can appear here that can give this equipment a lot of different behaviors without writing any script at all (deal damage, increase move speed, etc.). You can find a few examples of these fields in Data/GameObjects/Tools/Crude Axe.txt and others in that folder.

While the EquipableComponent might get our Wand off the ground and into our hand, it won't provide us with the magical behavior that we want. For that we need to add some custom logic. We do this via a ScriptComponent. Here the referenced script Wand.lua is loaded by the engine which registers a new script class Wand, which in turn becomes the script class of this gameobject. The arguments field allows us to pass initial values to our Wand’s constructor, our simple class won’t even need a constructor so we’ll just leave this field blank.

Let’s take a look at TUG/Scripts/Objects/Wand.lua
include("Scripts/Objects/Equipable.lua")

-------------------------------------------------------------------------------
-- Define a new script class Wand that derives from Equipable.
if Wand == nil then
	Wand = Equipable.Subclass("Wand")
end

-------------------------------------------------------------------------------
-- Evaluate if this wand has any effect on a target object 'go'.
-- Overridden from Equipable.
function Wand:CanToolAffectObject( go )
	return true
end

-------------------------------------------------------------------------------
-- Called when this wand is swung at a valid object.
-- Overridden from Equipable.
function Wand:AffectObject( hitObj )
	Eternus.GameState:SpawnGameObject("Goat",   hitObj.gameobject:NKGetWorldPosition(), hitObj.gameobject:NKGetWorldOrientation())
	traceResult.gameobject:NKDeleteMe()
end

-------------------------------------------------------------------------------
-- Register the Wand class with the engine so it can be referenced in our MagicWand.txt. 
EntityFramework:RegisterGameObject(Wand)

Here we are looking at the script that will be attached to our Magic Wand. TUG Lua scripts make use of an OOP framework that allows us to reuse existing logic. We define a new script class Wand that subclasses a different script class Equipable. This provides our wand with some pre-existing logic shared between all Equipables.

First we override an equipable function CanToolAffectObject that is called when this item is swung at another object. We always return true here indicating that our Wand affects everything!

Next we override another equipable function AffectObject which implements exactly what our wand should do when we strike another object. Here the code spawns another GameObject called “Goat”, and destroys the object that we struck. Seems simple enough.

Finally we have one more bit of code necessary to use this script, we must call RegisterGameObject to inform the engine of our newly created class.

When we boot up TUG, we can now play with our new Wand:

WholeAcclaimedIraniangroundjay.gif

Adding some flavor.

Finally, you might have noticed the wand in the above video is a bit more vibrant than the one you created. I’ve added a few particle effects near the tip of the object.

Here is what my completed MagicWand.txt now looks like:
GameObjects
{

	Placeable
	{

		Magic Wand
		{
			
			StaticGraphics
			{
				model = "Models/PlaceableObjects/Harvestables/woodStaff.obj"	
				dontCastShadows = 1.0				
				Diffuse
				{
					0 = "Character/Weapons/0spearB_WLV_New_diff.tga"
				}
				Normal
				{
					0 = "Character/Weapons/0spearB_norm.tga"
				}				
			}
			
			
			RigidBody
			{
				activePhysics = 1
				mass = 15.0
				friction = 6.0
			}

			Equipable
			{
				name = "Magic Wand"
				icon = "UI/MenuIcons/2x_ShroomStem.tga"
				durability = 10
				damageToCharacters = 1

				Equipment Slots
				{
					Tool
				}
			} 

			Script
			{
				file = "Scripts/Objects/Wand.lua"
				class = "Wand"

				arguments
				{
				}
			}
			
			Children
			{

				Wisp Purple Body Emitter
				{
					offset = <2, 0, 0>
				}
				Wisp Green Ribbon Emitter
				{
					offset = <2, 0, 0>
				}
			}
		}
	}
}


The only addition is the section entitled Children. This is a special section that does not add any components to the object, but instead attaches entirely distinct GameObjects to our wand. These child objects will stay attached to the wand when it moves in our gameworld. I’ve attached two objects, a Wisp Purple Body Emitter and a Wisp Green Ribbon Emitter. Both of which are GameObjects with their own set of components. You can find their definitions in Wisp Green Emitter.txt and Wisp Purple Emitter.txt found in the Assets/FX/Emitters/Swarm directory near your TUG.exe.

The offset property allows me to position them relative to the origin of my wand. Here I've placed them right at the end of the stick.

5Mzmh7Il.png
oWZmUsil.png

Things to look forward too.

Modding is really important to us here at Nerd Kingdom and we have number of things that we would like to provide the community in the future.
* Full documentation for the lua exposed native functions (anything prefixed with NK). The initial draft can be found at http://eternusapi.nerdkingdom.com.

* Easier distribution and installation of mods. Right now modders must work directly in the Asset/ directory. We are working on a solution that would allow modders to add and modify content in the game within their own mods folder. This system will also allow many mods to be installed and managed at once.

* Scripted server and client gameplay. The script we wrote today will only work in a single player environment. Future scripting APIs will allow modders to write both client and server logic.

* Full scripting control of the GUI allowing simple modifications and complete overhauls.



If you would like the Wand without doing any work, I've attached both files (MagicWand.txt and Wand.lua) inside the zip below. Simply navigate to your TUG install directory and place them at TUG/Assets/Data/GameObjects/EquipableObjects/MagicWand.txt and TUG/Assets/Scripts/Objects/Wand.lua
Sign In or Register to comment.