Last Update: 2023-07-06
Creating a Simple Custom Item
This tutorial walks through creating a basic custom item for Don't Starve Together: a "Frost Axe" that works like a regular axe but has ice-themed effects and properties.
Project Overview
We'll create an axe with these features:
- Increased durability compared to a regular axe
- Freezing effect on enemies when used as a weapon
- Custom appearance with ice/frost theme
- Special effect when chopping trees
Step 1: Set Up the Mod Structure
Create these folders and files:
frost_axe_mod/
├── modinfo.lua
├── modmain.lua
├── scripts/
│ └── prefabs/
│ └── frost_axe.lua
└── images/
└── inventoryimages/
├── frost_axe.png
└── frost_axe.xml
Step 2: Create the modinfo.lua File
name = "Frost Axe"
description = "Adds a magical axe with freezing properties"
author = "Your Name"
version = "1.0.0"
-- Compatible with Don't Starve Together
dst_compatible = true
-- Not compatible with Don't Starve
dont_starve_compatible = false
reign_of_giants_compatible = false
-- This mod is required on clients
all_clients_require_mod = true
-- This mod is not a client-only mod
client_only_mod = false
-- Icon displayed in the server list
icon_atlas = "modicon.xml"
icon = "modicon.tex"
-- Tags that describe your mod
server_filter_tags = {
"item",
"tool"
}
-- Configuration options
configuration_options = {
{
name = "frost_damage",
label = "Frost Damage",
options = {
{description = "Low", data = 25},
{description = "Medium", data = 34, hover = "Default axe damage"},
{description = "High", data = 42}
},
default = 34
},
{
name = "durability",
label = "Durability",
options = {
{description = "Standard", data = 100},
{description = "Improved", data = 150},
{description = "Superior", data = 200}
},
default = 150
}
}
Step 3: Create the modmain.lua File
-- Import globals into the environment
GLOBAL.setmetatable(env, {__index = function(t, k) return GLOBAL.rawget(GLOBAL, k) end})
-- Add asset files
Assets = {
-- Inventory image
Asset("IMAGE", "images/inventoryimages/frost_axe.tex"),
Asset("ATLAS", "images/inventoryimages/frost_axe.xml"),
}
-- Register the prefab
PrefabFiles = {
"frost_axe",
}
-- Add recipe to craft the frost axe
AddRecipe("frost_axe",
{
Ingredient("twigs", 1),
Ingredient("flint", 1),
Ingredient("bluegem", 1)
},
GLOBAL.RECIPETABS.TOOLS,
GLOBAL.TECH.SCIENCE_ONE,
nil, nil, nil, nil, nil,
"images/inventoryimages/frost_axe.xml", "frost_axe.tex")
-- Add custom strings
GLOBAL.STRINGS.NAMES.FROST_AXE = "Frost Axe"
GLOBAL.STRINGS.CHARACTERS.GENERIC.DESCRIBE.FROST_AXE = "It's unnaturally cold to the touch."
GLOBAL.STRINGS.RECIPE_DESC.FROST_AXE = "An axe with freezing properties."
-- Add custom tags for the item
AddPrefabPostInit("frost_axe", function(inst)
inst:AddTag("frostweapon")
end)
-- Add a special effect when chopping trees
AddComponentPostInit("workable", function(self)
local old_WorkedBy = self.WorkedBy
function self:WorkedBy(worker, numworks, ...)
local result = old_WorkedBy(self, worker, numworks, ...)
-- Check if the worker is using our frost axe
if worker and worker.components.inventory then
local tool = worker.components.inventory:GetEquippedItem(GLOBAL.EQUIPSLOTS.HANDS)
if tool and tool.prefab == "frost_axe" and self.action == GLOBAL.ACTIONS.CHOP then
-- Spawn frost effect
local fx = GLOBAL.SpawnPrefab("icespike_fx_1")
if fx then
fx.Transform:SetPosition(self.inst.Transform:GetWorldPosition())
end
-- Apply cold to nearby entities
local x, y, z = self.inst.Transform:GetWorldPosition()
local ents = GLOBAL.TheSim:FindEntities(x, y, z, 3, nil, {"player", "companion"})
for _, ent in ipairs(ents) do
if ent.components.temperature then
ent.components.temperature:DoDelta(-2)
end
end
end
end
return result
end
end)
Step 4: Create the Prefab File
Create scripts/prefabs/frost_axe.lua
:
local assets = {
-- Use the axe animation but we'll recolor it
Asset("ANIM", "anim/axe.zip"),
Asset("ANIM", "anim/swap_axe.zip"),
-- Inventory image
Asset("IMAGE", "images/inventoryimages/frost_axe.tex"),
Asset("ATLAS", "images/inventoryimages/frost_axe.xml"),
}
-- Function called when the axe is equipped
local function onequip(inst, owner)
-- Use the regular axe animation for now
owner.AnimState:OverrideSymbol("swap_object", "swap_axe", "swap_axe")
-- Show the arm holding the tool
owner.AnimState:Show("ARM_carry")
owner.AnimState:Hide("ARM_normal")
-- Apply a blue tint to the axe when equipped
owner.AnimState:SetMultColour(0.8, 0.8, 1, 1)
end
-- Function called when the axe is unequipped
local function onunequip(inst, owner)
-- Restore normal appearance
owner.AnimState:Hide("ARM_carry")
owner.AnimState:Show("ARM_normal")
owner.AnimState:SetMultColour(1, 1, 1, 1)
end
-- Function called when attacking with the axe
local function onattack(inst, owner, target)
-- Apply freezing effect if the target has temperature
if target and target.components.temperature then
target.components.temperature:DoDelta(-5)
-- Slow the target if it has locomotor
if target.components.locomotor then
target.components.locomotor:SetExternalSpeedMultiplier(inst, "frost_axe_slow", 0.7)
-- Remove the slow effect after 3 seconds
if target._frost_axe_task then
target._frost_axe_task:Cancel()
end
target._frost_axe_task = target:DoTaskInTime(3, function()
target.components.locomotor:RemoveExternalSpeedMultiplier(inst, "frost_axe_slow")
target._frost_axe_task = nil
end)
end
-- Spawn a frost effect
local fx = SpawnPrefab("frostbreath")
if fx then
fx.Transform:SetPosition(target.Transform:GetWorldPosition())
end
end
end
-- Main function to create the frost axe
local function fn()
-- Create the entity
local inst = CreateEntity()
-- Add required components
inst.entity:AddTransform()
inst.entity:AddAnimState()
inst.entity:AddNetwork()
-- Set up physics
MakeInventoryPhysics(inst)
-- Set up animation
inst.AnimState:SetBank("axe")
inst.AnimState:SetBuild("axe")
inst.AnimState:PlayAnimation("idle")
-- Apply a blue tint to the axe
inst.AnimState:SetMultColour(0.7, 0.7, 1, 1)
-- Add tags
inst:AddTag("sharp")
inst:AddTag("tool")
inst:AddTag("frostweapon")
-- Make the entity pristine for networking
inst.entity:SetPristine()
if not TheWorld.ismastersim then
return inst
end
-- Add components
inst:AddComponent("inventoryitem")
inst.components.inventoryitem.imagename = "frost_axe"
inst.components.inventoryitem.atlasname = "images/inventoryimages/frost_axe.xml"
-- Make it work as a tool
inst:AddComponent("tool")
inst.components.tool:SetAction(ACTIONS.CHOP, 2) -- Chop efficiency multiplier
-- Make it work as a weapon
inst:AddComponent("weapon")
inst.components.weapon:SetDamage(GetModConfigData("frost_damage"))
inst.components.weapon:SetOnAttack(onattack)
-- Add durability
inst:AddComponent("finiteuses")
inst.components.finiteuses:SetMaxUses(GetModConfigData("durability"))
inst.components.finiteuses:SetUses(GetModConfigData("durability"))
inst.components.finiteuses:SetOnFinished(inst.Remove)
inst.components.finiteuses:SetConsumption(ACTIONS.CHOP, 1)
-- Make it inspectable
inst:AddComponent("inspectable")
-- Make it equippable
inst:AddComponent("equippable")
inst.components.equippable:SetOnEquip(onequip)
inst.components.equippable:SetOnUnequip(onunequip)
-- Add a light component for a subtle glow
inst:AddComponent("lighttweener")
inst.components.lighttweener:StartTween(
inst.entity:AddLight(),
0, 0.6, 0.6, {80/255, 120/255, 255/255},
0,
function()
-- After the light is added, make it flicker slightly
inst:DoPeriodicTask(0.3, function()
local intensity = 0.5 + math.random() * 0.1
inst.Light:SetIntensity(intensity)
end)
end
)
return inst
end
-- Register the prefab
return Prefab("frost_axe", fn, assets)
Step 5: Create the Inventory Image
- Create a 64x64 pixel image for your frost axe
- Save it as
images/inventoryimages/frost_axe.png
- Use a TEX converter tool to create
frost_axe.tex
andfrost_axe.xml
Step 6: Testing Your Mod
- Launch Don't Starve Together
- Enable your mod in the Mods menu
- Start a new game
- Craft your Frost Axe (requires twigs, flint, and a blue gem)
- Test the axe by:
- Chopping trees to see the frost effect
- Attacking creatures to see the freezing effect
- Checking the durability as you use it
Customization Options
Here are some ways to customize your frost axe:
Change the Recipe
-- Make it more expensive
AddRecipe("frost_axe",
{
Ingredient("twigs", 2),
Ingredient("flint", 2),
Ingredient("bluegem", 2)
},
GLOBAL.RECIPETABS.MAGIC, -- Change to magic tab
GLOBAL.TECH.MAGIC_TWO, -- Require prestihatitator
nil, nil, nil, nil, nil,
"images/inventoryimages/frost_axe.xml", "frost_axe.tex")
Add a Custom Animation
For a fully custom appearance, create your own animation files:
- Create
anim/frost_axe.zip
with custom animations - Update the prefab file:
local assets = {
Asset("ANIM", "anim/frost_axe.zip"),
Asset("ANIM", "anim/swap_frost_axe.zip"),
-- Other assets...
}
-- Then in the fn() function:
inst.AnimState:SetBank("frost_axe")
inst.AnimState:SetBuild("frost_axe")
Add More Freezing Effects
Enhance the freezing capabilities:
-- In the onattack function:
if target and target.components.freezable then
target.components.freezable:AddColdness(2)
target.components.freezable:SpawnShatterFX()
end
-- Add a chance to freeze enemies solid
if target and math.random() < 0.1 then -- 10% chance
if target.components.freezable then
target.components.freezable:Freeze(3) -- Freeze for 3 seconds
end
end
Common Issues and Solutions
Problem: Mod doesn't appear in the mod list
Solution: Check your folder structure and ensure modinfo.lua is in the root directory
Problem: Inventory image doesn't show up
Solution: Verify the image paths and ensure the TEX/XML files are correctly generated
Problem: Freezing effect doesn't work
Solution: Make sure you're checking for the temperature component before trying to use it
Problem: Game crashes when using the axe
Solution: Add error checking around critical code:
local function onattack(inst, owner, target)
if not target then return end
if target.components.temperature then
target.components.temperature:DoDelta(-5)
end
-- Rest of the function...
end
Next Steps
Now that you've created a basic custom item, you can:
- Add More Effects: Create additional special abilities for your axe
- Create Custom Animations: Design unique animations for your item
- Expand Your Mod: Add more frost-themed items to create a complete set
- Add Sound Effects: Include custom sounds when the axe is used
For more advanced item creation, check out the Custom Component tutorial to learn how to add entirely new behaviors to your items.