-
Notifications
You must be signed in to change notification settings - Fork 26
Creating Tools & Tool Models
The guide can also be found in the following GoogleDoc. Creating Tools & Tool Models
This page is under development while images are being created. Please use the google doc above as the best reference.
Zeel Nightwolf and I have been making mods for the server we play on and wanted to share some of what we have learned along the way. (FZM = FishZeelMods, original, we know.) You can find me on Discord FishAus#0367. You can get in touch with Zeel, Zeel Nightwolf#7289.
This tutorial assumes you have either done the tutorial some previous tutorials.
Before we Begin
Compatible Versions (for this tutorial): This tutorial has been tested with the below Versions. If you are using a newer or outdated version this tutorial may not work. We will try to update tutorial with the latest versions.
- Eco Version 7.4.7
- Unity 2017.4.2f2
- Eco ModKit version updated as of 21/06/2018 dd/mm/yyyy
( this must have the scripts AvatarAttachedPart.cs , ToolInteractions.cs and PerformInteraction.cs in the kit. )
As of this date your Unity project needs to be running .NET 4.6. There is potential you will get script errors if you are not.
To change your Unity project goto Edit -> Project Settings -> Player
Find configuration and make sure Runtime Version is set to .NET 4.6
What You Need:
- Have the above versions of Eco , Unity and the Modkit above.
- NotePad++ (or equivalent code editing software)
- Download the NewToolItem.cs and NewToolItem Unity asset package. Download
Background
If you have been making objects for Eco for a while you probably have a handle on the difference between “Objects” as those things that exist in the world separate to the player (work tables, blocks, decorative items etc..) and “items” which really only exist in an inventory (Food, ingots etc..). Every “Object” has an “Item” version of it as the thing the player carries before placing it down.
Tools will never be placed in the world and therefore will not have an “Object” part. This means tools only need a recipe and an “Item” definition in the c# and all code describing the utility of the tool is written in the “Item” class.
In Unity we will just have the “Item” in the hierarchy with some additional nodes on the root “item”
To be clear, the root in this picture is labelled ‘SampleItem’ and the nodes ‘Icon and ‘Tool’ are underneath. ‘Icon’ has two nodes underneath itself ‘Background’ and ‘Foreground’.
Since tools require a model we will need to attach that model to the tool node using the required scripts.
We also want to store the tool on our player avatar when it is not out, so we will need to have some way to do that too.
Poking sticks at stuff is fun. So the tool we will make in this tutorial is a stick that will tell us what we are poking at.
Step 1: Open up the NewToolItem.cs file from the tutorial downloads. It has got a skeleton of what you need to create the code for a new Tool.
Step 2: Replace each instance of “NewToolItem” and “NewToolRecipe” in the code with “PokeyStickItem” and “PokeyStickRecipe” respectively.
Step 3: Change the ‘FriendlyName’ and ‘Description’ of the PokeyStick:
public override string FriendlyName { get { return "Pokey Stick"; } } // the in-game name
public override string Description { get { return "What can you poke a stick at?"; } } // the in-game description
Step 4: Decide if you want the stick to break over time with use. If you do change 0 in the following line to DurabilityMax / 750f.
public override float DurabilityRate { get { return DurabilityMax / 750f; } } // the rate of durability loss with each use
We will ignore the repair costs. This is what you would change to make repair more expensive or limited to a particular profession.
Also decide if you want your tool to burn calories and change up the calories burn value and which efficiency improves it. We will leave it 0 for now.
// calorie costs
private static IDynamicValue caloriesBurn = CreateCalorieValue(0, typeof(LoggingEfficiencySkill), typeof(PokeyStickItem), new PokeyStickItem().UILink());
public override IDynamicValue CaloriesBurn { get { return caloriesBurn; } }
Step 5: change the ‘LeftActionDescription’ to return “Poke”:
public override string LeftActionDescription { get { return "Poke"; } } // on screen display of action on left click.
Step 6: Implement the code to get the information we need in OnLeftClick.
You can copy and paste the following code. Make sure you replace all of the OnActLeft method in the code: (you only need the BurnCalories(context.Player) if you want to burn calories.
public override InteractResult OnActLeft(InteractionContext context) // what the tool will do on left click.
{
if (context.HasBlock)
{
context.Player.SendTemporaryMessageLoc((context.Block.GetType().Name).Substring(0, context.Block.GetType().Name.Length - 5));
return InteractResult.Success;
}
else if (context.HasTarget)
{
context.Player.SendTemporaryMessageLoc((context.Target.GetType().Name).Substring(0, context.Target.GetType().Name.Length - 6));
BurnCalories(context.Player);
return InteractResult.Success;
}
return InteractResult.NoOp;
}
public override bool ShouldHighlight(Type block)
{
return true;
}
This code will put the Name of the target under our interaction cursor into the chat box temporarily. We also are overriding the ‘ShouldHighlight’ method to highlight almost everything in the game.
Step 7: Begin by importing the NewToolItem.unitypackage from the .zip download.
The import screen should look like this. Once the assets are in your project window, duplicate a sample object from the modkit.
Once duplicated drag the ‘ToolName’ prefab to the Tool node of your new Item.
This “should” import the nodes for a new tool with the correct transform values. Each nodes values is gone through below so you can check they did import correctly as we move through the tutorial
Step 8: Rename Sample Item to “PokeyStickItem” in the hierarchy. And rename “ToolName” and “ToolNameRoot” replacing ToolName with PokeyStick
Setting up the Icon using the background and foreground in the Icon subnode can be found in the Ceiling Light tutorial.
Step 9: You will need to ensure the various nodes for the correct placement of the tool in the hand have the right values. The naming of many nodes is important and so are the transform values (found in the inspector tab).
The following images show how to label the nodes under a root node and each of the transform values. We will walk through using the right-hand side as only 1 side needs to exist.
Step 10: Select the renamed ‘PokeyStick’ subnode directly underneath the ‘Tool’ node
On this in the inspector view you will need to add the following components:
- Tool Interactions
- Perform Interaction The transform elements on this node are all 0. Ensure the tool interactions are all unchecked.
Step 11: The ToolRoot needs a rotation of 180 in the y-axis.
Step 12: The next node should be named ShoulderJoint_R and have the following transform values.
Step 13: The next node should be named ElbowJoint_R and have the following transform values.
Step 14: The next node should be named WristJoint_R and have the following transform values.
Step 15: You will now need to attach the PokeyStick.fbx provided. Drag the .fbx under the node ‘Tool_FBXtemp’ this allows us to use the placeholder to set some values on the .fbx. If you are creating your own model then drag it underneath the temp instead.
Once done you can drag the ‘PokeyStick’ under the WristJoint_R. See the values of the PokeyStick change to where we want them.
The ‘Tool_FBXtemp’ can now be deleted.
These values can be tweaked based on how you want the model to look in the view.
Small changes to these numbers are best while you learn how they change the model.
Trial and error to get what you want here is best.
Step 16: ToolNameHeadJoint_R is the final node in the skeleton and extends up the tool. This is most useful if you have a point of contact on the tool you would like to use (especially if a tool is animated). Rename this to PokeyStickHeadJoint_R. Because the point of contact will differ for each tool again these transform values can be different for each too. (though the rotation values will likely be the same).
Step 17: Select the ‘PokeyStick’ subnode directly underneath the ‘Tool’ node again. The tool interaction script has a few options to consider:
- ‘Has Take Animation’ and ‘Has Place Animation’ will allow you to attach animations (using an animator component and animation controller) to the model.
If you want this you will need to have the animation fire an event with the ‘SendInteraction’ function at the point in your animation you want to perform the action. (this method is in the PerformInteraction script that we attached to the tool) Note: Animation can be hard for tools as it requires a sense of positioning of the avatar.
-
‘Must Contain Carried’ is what shovels use to show the contents of the carried slot on the end of the shovel and beyond the scope of this tutorial.
-
‘Take Requires Calories’ and ‘Place Requires Calories’ will burn calories on use of the object. Though this can also be achieved through the code if desired using the ‘BurnCalories’ command.
We are not attaching any of these to this tool but it is useful to know what we can use on other tools.
Step 18: If you don’t already have a node called ‘Avatar’ under the PokeyStickItem then right-click the ‘Tools’ node in your hierarchy and create empty. Rename it to ‘Avatar’ and make sure it is a direct subnode of ‘PokeyStickItem’.
Add the component called AvatarAttachedPart in the inspector view.
Note: The modkit version of this file may be broken, download a working version here until it is updated. Just replace the script in your modkit with this one if the tool won't show in third person when you have completed the tutorial.
In this component add the PokeyStick.fbx object to both the male and female Prefab fields. We also need to give the name of the specific attachment point to which the tool should be placed on the avatar when not being carried.
If you leave this blank or use an incorrect point the tool will not appear on the avatar when it is away. These attachment points are specific to the SLG created avatar so we can’t add new attachment points of our own. Type ‘AttachTool_Sye’ into the field.
The images below show the attachment point names and the positions in game on the avatar:
As you can see not all tools attach to the Avatar. Also animation and graphics updates on the client side are often glitchy so be prepared for this to not always look smooth, or for it look like you have multiple tools in your hand at once, especially in third person.
Note_Left-Hand Side Transform Values:
Now that you have both the c# and unity complete you can build the unity package and place it and the c# file for the Pokey Stick in the mods folder of your Eco Server.
You can give yourself the Pokey Stick by using the command ‘/give PokeyStick’ in the chatbox.
Pull our the Pokey Stick by highlighting it in your action bar. Images below are for both 1st and 3rd person view of the model, as well as the result of a left click on objects.
End of Tutorial.
Extensions of existing tools
{{ Axe, Pickaxe, Shovel, Hammer, Hoe etc..}}
This tutorial has worked through the requirements for adding a new type of tool to the game. However, there are already tools in the game that we may want to make new varieties of.
For example, we may want to add a “Golden Axe” to the game, we will want to make sure that our axe inherits the properties of other axe’s also. In this case you should use IronAxe.cs as a template to create your new Axe.
Below is the IronAxeItem implementation: (You can see that the IronAxeItem inherits from AxeItem and not ToolItem)
[Serialized]
[Weight(1000)]
[Category("Tool")]
public partial class IronAxeItem : AxeItem
{
public override string FriendlyName { get { return "Iron Axe"; } }
private static IDynamicValue caloriesBurn = CreateCalorieValue(17, typeof(LoggingEfficiencySkill), typeof(IronAxeItem), new IronAxeItem().UILink());
public override IDynamicValue CaloriesBurn { get { return caloriesBurn; } }
private static IDynamicValue damage = CreateDamageValue(1.5f, typeof(LoggingDamageSkill), typeof(IronAxeItem), new IronAxeItem().UILink());
public override IDynamicValue Damage { get { return damage; } }
private static SkillModifiedValue skilledRepairCost = new SkillModifiedValue(10, MetalworkingSkill.MultiplicativeStrategy, typeof(MetalworkingSkill), Localizer.Do("repair cost"));
public override IDynamicValue SkilledRepairCost { get { return skilledRepairCost; } }
public override float DurabilityRate { get { return DurabilityMax / 750f; } }
public override Item RepairItem {get{ return Item.Get<IronIngotItem>(); } }
public override int FullRepairAmount {get{ return 10; } }
}
It is important that you use the right class to inherit from:
New tool -> inherit from ToolItem as in the NewToolItem example Existing tool -> Find the Iron version of that tool in the .cs files and use that as a template to ensure you use the correct parent class to inherit from.
The reason is these parent classes have additional details you may want to override in your new version such as damage on an Axe.
You can also see the ‘Iron Axe’ does not override the OnLeftAct method as we did for the ‘Pokey Stick’. This is because the parent class AxeItem already overrides the method to perform the function of an Axe, you would only need to override the method again if you wanted your new tool to perform differently.
Animations for your own Axe will have to be created by you as the animation used on the in-game tools are part of the unavailable game assets.
Events on Animations
Triggering the tool to perform an action via OnActLeft or OnActRight in code is a little more complex, You will need to create your own animation for your tool.
The PerformInteraction script we added on our tool has a single method called ‘SendInteraction’.
When you have created your animation for your tool and have setup the animation controller you will need a single int parameter in the animation controller called ‘Working’
Your tool should move to the Work state on a value of 1 and back to idle on not 1.
Next find your animation and edit it. You will need to put an event on the animation.
Add a new event by clicking marker with a + in the events drop-down and moving the marker to the point in the animation you want the interaction to occur.
Clicking on that marker will allow you to fill in the function you want to fire. Type ‘SendInteraction’ in the field.
Go back to your Interaction script on the Tool and select ‘Has Take Animation’ for an OnActLeft even or ‘Has Place Animation’ for an OnActRight event.
Acknowledgements:
Thanks to the following people in assisting getting this tutorial out in any of it’s revisions…
ZeelNightwolf, for providing editing, information, models for tutorial and general moral support :)
Strange Loop Games, for providing the game, and the EcoModKit.
- Custom-Chat-Commands
- Generic-Authorization
- Item-Callbacks
- Modifying-the-World
- Save-Load
- Reacting to player events
- Debugging store interactions
- Creating skills
- Maintain mods automatically
- Overriding Translations
- Creating UIs for Mods
See all pages (above) for reference & usage tutorials.