2017-02-27 23:34:35 -07:00
---------------------------------------------------------------------------------------
-- simple anvil that can be used to repair tools
---------------------------------------------------------------------------------------
-- * can be used to repair tools
-- * the hammer gets dammaged a bit at each repair step
---------------------------------------------------------------------------------------
minetest.register_alias ( " castle:anvil " , " anvil:anvil " )
-- internationalization boilerplate
local MP = minetest.get_modpath ( minetest.get_current_modname ( ) )
local S , NS = dofile ( MP .. " /intllib.lua " )
2017-03-07 22:39:25 -07:00
local item_displacement = 7 / 16
2017-02-27 23:34:35 -07:00
-- the hammer for the anvil
minetest.register_tool ( " anvil:hammer " , {
2017-03-07 22:39:25 -07:00
description = S ( " Steel blacksmithing hammer " ) ,
_doc_items_longdesc = S ( " A tool for repairing other tools at a blacksmith's anvil. " ) ,
_doc_items_usagehelp = S ( " Use this hammer to strike blows upon an anvil bearing a damaged tool and you can repair it. It can also be used for smashing stone, but it is not well suited to this task. " ) ,
image = " anvil_tool_steelhammer.png " ,
inventory_image = " anvil_tool_steelhammer.png " ,
tool_capabilities = {
full_punch_interval = 0.8 ,
max_drop_level = 1 ,
groupcaps = {
-- about equal to a stone pick (it's not intended as a tool)
cracky = { times = { [ 2 ] = 2.00 , [ 3 ] = 1.20 } , uses = 30 , maxlevel = 1 } ,
} ,
damage_groups = { fleshy = 6 } ,
}
2017-02-27 23:34:35 -07:00
} )
2017-03-07 22:39:25 -07:00
local tmp = { }
minetest.register_entity ( " anvil:item " , {
hp_max = 1 ,
visual = " wielditem " ,
visual_size = { x = .33 , y = .33 } ,
collisionbox = { 0 , 0 , 0 , 0 , 0 , 0 } ,
physical = false ,
textures = { " air " } ,
on_activate = function ( self , staticdata )
if tmp.nodename ~= nil and tmp.texture ~= nil then
self.nodename = tmp.nodename
tmp.nodename = nil
self.texture = tmp.texture
tmp.texture = nil
else
if staticdata ~= nil and staticdata ~= " " then
local data = staticdata : split ( ' ; ' )
if data and data [ 1 ] and data [ 2 ] then
self.nodename = data [ 1 ]
self.texture = data [ 2 ]
end
end
end
if self.texture ~= nil then
self.object : set_properties ( { textures = { self.texture } } )
end
end ,
get_staticdata = function ( self )
if self.nodename ~= nil and self.texture ~= nil then
return self.nodename .. ' ; ' .. self.texture
end
return " "
end ,
} )
2017-02-27 23:34:35 -07:00
2017-03-07 22:39:25 -07:00
local remove_item = function ( pos , node )
local objs = minetest.env : get_objects_inside_radius ( { x = pos.x , y = pos.y + item_displacement , z = pos.z } , .5 )
if objs then
for _ , obj in ipairs ( objs ) do
if obj and obj : get_luaentity ( ) and obj : get_luaentity ( ) . name == " anvil:item " then
obj : remove ( )
end
end
end
end
2017-02-27 23:34:35 -07:00
2017-03-07 22:39:25 -07:00
local update_item = function ( pos , node )
local meta = minetest.env : get_meta ( pos )
local inv = meta : get_inventory ( )
if not inv : is_empty ( " input " ) then
pos.y = pos.y + item_displacement
tmp.nodename = node.name
tmp.texture = inv : get_stack ( " input " , 1 ) : get_name ( )
local e = minetest.env : add_entity ( pos , " anvil:item " )
local yaw = math.pi * 2 - node.param2 * math.pi / 2
e : setyaw ( yaw )
end
end
2017-02-27 23:34:35 -07:00
2017-03-09 20:27:01 -07:00
local metal_sounds
-- Apparently node_sound_metal_defaults is a newer thing, I ran into games using an older version of the default mod without it.
if default.node_sound_metal_defaults ~= nil then
metal_sounds = default.node_sound_metal_defaults ( )
else
metal_sounds = default.node_sound_stone_defaults ( )
end
2017-02-27 23:34:35 -07:00
minetest.register_node ( " anvil:anvil " , {
drawtype = " nodebox " ,
2017-03-07 22:39:25 -07:00
description = S ( " Anvil " ) ,
_doc_items_longdesc = S ( " A tool for repairing other tools in conjunction with a blacksmith's hammer. " ) ,
_doc_items_usagehelp = S ( " Right-click on this anvil with a damaged tool to place the damaged tool upon it. You can then repair the damaged tool by striking it with a blacksmith's hammer. Repeated blows may be necessary to fully repair a badly worn tool. To retrieve the tool either punch or right-click the anvil with an empty hand. " ) ,
2017-02-27 23:34:35 -07:00
tiles = { " default_stone.png " } ,
paramtype = " light " ,
2017-03-07 22:39:25 -07:00
paramtype2 = " facedir " ,
2017-02-27 23:34:35 -07:00
groups = { cracky = 2 } ,
2017-03-09 20:27:01 -07:00
sounds = metal_sounds ,
2017-02-27 23:34:35 -07:00
-- the nodebox model comes from realtest
node_box = {
type = " fixed " ,
fixed = {
2017-03-07 22:39:25 -07:00
{ - 0.5 , - 0.5 , - 0.3 , 0.5 , - 0.4 , 0.3 } ,
{ - 0.35 , - 0.4 , - 0.25 , 0.35 , - 0.3 , 0.25 } ,
{ - 0.3 , - 0.3 , - 0.15 , 0.3 , - 0.1 , 0.15 } ,
{ - 0.35 , - 0.1 , - 0.2 , 0.35 , 0.1 , 0.2 } ,
} ,
2017-02-27 23:34:35 -07:00
} ,
selection_box = {
type = " fixed " ,
fixed = {
2017-03-07 22:39:25 -07:00
{ - 0.5 , - 0.5 , - 0.3 , 0.5 , - 0.4 , 0.3 } ,
{ - 0.35 , - 0.4 , - 0.25 , 0.35 , - 0.3 , 0.25 } ,
{ - 0.3 , - 0.3 , - 0.15 , 0.3 , - 0.1 , 0.15 } ,
{ - 0.35 , - 0.1 , - 0.2 , 0.35 , 0.1 , 0.2 } ,
}
2017-02-27 23:34:35 -07:00
} ,
on_construct = function ( pos )
2017-03-07 22:39:25 -07:00
local meta = minetest.get_meta ( pos )
local inv = meta : get_inventory ( )
inv : set_size ( " input " , 1 )
end ,
2017-02-27 23:34:35 -07:00
after_place_node = function ( pos , placer )
local meta = minetest.get_meta ( pos )
2017-03-07 22:39:25 -07:00
meta : set_string ( " owner " , placer : get_player_name ( ) or " " )
end ,
can_dig = function ( pos , player )
local meta = minetest.get_meta ( pos )
local inv = meta : get_inventory ( )
if not inv : is_empty ( " input " ) then
return false
2017-02-27 23:34:35 -07:00
end
2017-03-07 22:39:25 -07:00
return true
2017-02-27 23:34:35 -07:00
end ,
2017-03-07 22:39:25 -07:00
2017-02-27 23:34:35 -07:00
allow_metadata_inventory_put = function ( pos , listname , index , stack , player )
local meta = minetest.get_meta ( pos )
2017-03-07 22:39:25 -07:00
if listname ~= " input " then
2017-03-09 20:27:01 -07:00
return 0
2017-02-27 23:34:35 -07:00
end
2017-03-07 22:39:25 -07:00
if ( listname == ' input '
and ( stack : get_wear ( ) == 0
or stack : get_name ( ) == " technic:water_can "
or stack : get_name ( ) == " technic:lava_can " ) ) then
2017-03-09 20:27:01 -07:00
minetest.chat_send_player ( player : get_player_name ( ) , S ( ' This anvil is for damaged tools only. ' ) )
2017-03-07 22:39:25 -07:00
return 0
2017-02-27 23:34:35 -07:00
end
2017-03-07 22:39:25 -07:00
if meta : get_inventory ( ) : room_for_item ( " input " , stack ) then
return stack : get_count ( )
end
return 0
2017-02-27 23:34:35 -07:00
end ,
2017-03-07 22:39:25 -07:00
2017-02-27 23:34:35 -07:00
allow_metadata_inventory_take = function ( pos , listname , index , stack , player )
2017-03-07 22:39:25 -07:00
if listname ~= " input " then
return 0
2017-02-27 23:34:35 -07:00
end
return stack : get_count ( )
end ,
2017-03-07 22:39:25 -07:00
on_rightclick = function ( pos , node , clicker , itemstack )
if itemstack : get_count ( ) == 0 then
local meta = minetest.env : get_meta ( pos )
local inv = meta : get_inventory ( )
if not inv : is_empty ( " input " ) then
local return_stack = inv : get_stack ( " input " , 1 )
inv : set_stack ( " input " , 1 , nil )
clicker : get_inventory ( ) : add_item ( " main " , return_stack )
remove_item ( pos , node )
return return_stack
end
end
local this_def = minetest.registered_nodes [ node.name ]
if this_def.allow_metadata_inventory_put ( pos , " input " , 1 , itemstack : peek_item ( ) , clicker ) > 0 then
local s = itemstack : take_item ( )
local meta = minetest.env : get_meta ( pos )
local inv = meta : get_inventory ( )
inv : add_item ( " input " , s )
update_item ( pos , node )
end
return itemstack
end ,
2017-02-27 23:34:35 -07:00
on_punch = function ( pos , node , puncher )
if ( not ( pos ) or not ( node ) or not ( puncher ) ) then
2017-03-09 20:27:01 -07:00
return
2017-02-27 23:34:35 -07:00
end
2017-03-09 20:27:01 -07:00
local wielded = puncher : get_wielded_item ( )
local meta = minetest.get_meta ( pos )
local inv = meta : get_inventory ( )
2017-03-07 22:39:25 -07:00
if wielded : get_count ( ) == 0 then
if not inv : is_empty ( " input " ) then
local return_stack = inv : get_stack ( " input " , 1 )
inv : set_stack ( " input " , 1 , nil )
puncher : get_inventory ( ) : add_item ( " main " , return_stack )
remove_item ( pos , node )
end
end
-- only punching with the hammer is supposed to work
if wielded : get_name ( ) ~= ' anvil:hammer ' then
2017-03-09 20:27:01 -07:00
return
2017-03-07 22:39:25 -07:00
end
2017-03-09 20:27:01 -07:00
local input = inv : get_stack ( ' input ' , 1 )
2017-03-07 22:39:25 -07:00
2017-02-27 23:34:35 -07:00
-- only tools can be repaired
if ( not ( input )
2017-03-07 22:39:25 -07:00
or input : is_empty ( )
or input : get_name ( ) == " technic:water_can "
or input : get_name ( ) == " technic:lava_can " ) then
2017-03-09 20:27:01 -07:00
return
2017-02-27 23:34:35 -07:00
end
2017-03-07 22:39:25 -07:00
2017-02-27 23:34:35 -07:00
-- 65535 is max damage
2017-03-09 20:27:01 -07:00
local damage_state = 40 - math.floor ( input : get_wear ( ) / 1638 )
2017-03-07 22:39:25 -07:00
2017-03-09 20:27:01 -07:00
local tool_name = input : get_name ( )
2017-03-07 22:39:25 -07:00
2017-03-09 20:27:01 -07:00
local hud2 = nil
local hud3 = nil
2017-02-27 23:34:35 -07:00
if ( input : get_wear ( ) > 0 ) then
hud2 = puncher : hud_add ( {
hud_elem_type = " statbar " ,
text = " default_cloud.png^[colorize:#ff0000:256 " ,
number = 40 ,
direction = 0 , -- left to right
position = { x = 0.5 , y = 0.65 } ,
alignment = { x = 0 , y = 0 } ,
offset = { x = - 320 , y = 0 } ,
size = { x = 32 , y = 32 } ,
} )
hud3 = puncher : hud_add ( {
hud_elem_type = " statbar " ,
text = " default_cloud.png^[colorize:#00ff00:256 " ,
number = damage_state ,
direction = 0 , -- left to right
position = { x = 0.5 , y = 0.65 } ,
alignment = { x = 0 , y = 0 } ,
offset = { x = - 320 , y = 0 } ,
size = { x = 32 , y = 32 } ,
2017-03-09 20:27:01 -07:00
} )
2017-02-27 23:34:35 -07:00
end
minetest.after ( 2 , function ( )
if ( puncher ) then
2017-03-09 20:27:01 -07:00
puncher : hud_remove ( hud2 )
puncher : hud_remove ( hud3 )
2017-02-27 23:34:35 -07:00
end
end )
2017-03-07 22:39:25 -07:00
2017-02-27 23:34:35 -07:00
-- tell the player when the job is done
if ( input : get_wear ( ) == 0 ) then
2017-03-09 20:27:01 -07:00
minetest.chat_send_player ( puncher : get_player_name ( ) , S ( ' Your @1 has been repaired successfully. ' , tool_name ) )
return
else
pos.y = pos.y + item_displacement
minetest.sound_play ( { name = " anvil_clang " } , { pos = pos } )
minetest.add_particlespawner ( {
amount = 10 ,
time = 0.1 ,
minpos = pos ,
maxpos = pos ,
minvel = { x = 2 , y = 3 , z = 2 } ,
maxvel = { x =- 2 , y = 1 , z =- 2 } ,
minacc = { x = 0 , y = - 10 , z = 0 } ,
maxacc = { x = 0 , y = - 10 , z = 0 } ,
minexptime = 0.5 ,
maxexptime = 1 ,
minsize = 1 ,
maxsize = 1 ,
collisiondetection = true ,
vertical = false ,
texture = " anvil_spark.png " ,
} )
2017-02-27 23:34:35 -07:00
end
2017-03-07 22:39:25 -07:00
2017-02-27 23:34:35 -07:00
-- do the actual repair
2017-03-09 20:27:01 -07:00
input : add_wear ( - 5000 ) -- equals to what technic toolshop does in 5 seconds
2017-02-27 23:34:35 -07:00
inv : set_stack ( " input " , 1 , input )
2017-03-07 22:39:25 -07:00
2017-02-27 23:34:35 -07:00
-- damage the hammer slightly
2017-03-09 20:27:01 -07:00
wielded : add_wear ( 100 )
puncher : set_wielded_item ( wielded )
2017-02-27 23:34:35 -07:00
end ,
is_ground_content = false ,
} )
2017-03-07 22:39:25 -07:00
-- automatically restore entities lost due to /clearobjects or similar
2017-03-09 20:27:01 -07:00
minetest.register_lbm ( {
name = " anvil:anvil_item_restoration " ,
2017-03-07 22:39:25 -07:00
nodenames = { " anvil:anvil " } ,
2017-03-09 20:27:01 -07:00
run_at_every_load = true ,
2017-03-07 22:39:25 -07:00
action = function ( pos , node , active_object_count , active_object_count_wider )
2017-03-09 20:27:01 -07:00
test_pos = { x = pos.x , y = pos.y + item_displacement , z = pos.z }
if # minetest.get_objects_inside_radius ( test_pos , 0.5 ) > 0 then return end
2017-03-07 22:39:25 -07:00
update_item ( pos , node )
end
} )
2017-02-27 23:34:35 -07:00
2017-03-07 22:39:25 -07:00
-- Transfer the hammer from the old hammer storage slot to the main slot, or else drop it in world
minetest.register_lbm ( {
name = " anvil:hammer_ejection " ,
nodenames = " anvil:anvil " ,
2017-03-09 20:27:01 -07:00
run_at_every_load = false ,
2017-03-07 22:39:25 -07:00
action = function ( pos , node )
2017-03-09 20:27:01 -07:00
local meta = minetest.get_meta ( pos )
local inv = meta : get_inventory ( )
2017-03-07 22:39:25 -07:00
if not inv : is_empty ( " hammer " ) then
local hammer = inv : get_stack ( " hammer " , 1 )
inv : set_stack ( " hammer " , 1 , nil )
inv : set_size ( " hammer " , 0 )
if inv : is_empty ( " input " ) then
inv : set_stack ( " input " , 1 , hammer ) -- the abm will ensure there's an entity showing the hammer is here
else
minetest.add_item ( { x = pos.x , y = pos.y + 1 , z = pos.z } , hammer )
end
end
end
} )
2017-02-27 23:34:35 -07:00
---------------------------------------------------------------------------------------
-- crafting receipes
---------------------------------------------------------------------------------------
minetest.register_craft ( {
output = " anvil:anvil " ,
recipe = {
{ " default:steel_ingot " , " default:steel_ingot " , " default:steel_ingot " } ,
{ ' ' , " default:steel_ingot " , ' ' } ,
{ " default:steel_ingot " , " default:steel_ingot " , " default:steel_ingot " } } ,
} )
minetest.register_craft ( {
output = " anvil:hammer " ,
recipe = {
{ " default:steel_ingot " , " default:steel_ingot " , " default:steel_ingot " } ,
{ " default:steel_ingot " , " default:steel_ingot " , " default:steel_ingot " } ,
{ ' ' , " group:stick " , ' ' } }
} )