MineClone2/mods/ITEMS/mcl_heads/init.lua

289 lines
9.9 KiB
Lua
Raw Normal View History

local S = minetest.get_translator(minetest.get_current_modname())
2022-08-07 11:45:39 +02:00
local minetest = minetest
2020-02-18 19:30:33 +01:00
local mod_doc = minetest.get_modpath("doc")
2020-02-18 20:04:15 +01:00
local mod_screwdriver = minetest.get_modpath("screwdriver")
2020-02-18 19:30:33 +01:00
local equip_armor
if minetest.get_modpath("mcl_armor") then
2021-04-14 15:46:52 +02:00
equip_armor = mcl_armor.equip_on_use
end
2022-08-07 11:45:39 +02:00
mcl_heads = {}
-- rotations of head nodes within a quadrant (0° ≤ θ ≤ 90°)
mcl_heads.FLOOR_DEGREES = { [0]='', '22_5', '45', '67_5', }
2022-08-07 11:45:39 +02:00
-- box of head nodes
mcl_heads.FLOOR_BOX = { -0.25, -0.5, -0.25, 0.25, 0.0, 0.25, }
-- floor head node nodedef template ------------------------------------------------------------------------------------
--- node definition template for floor mod heads
mcl_heads.deftemplate_floor = {
2024-08-22 00:03:39 +02:00
drawtype = "mesh",
mesh = "mcl_heads_floor.obj",
selection_box = {
type = "fixed",
fixed = mcl_heads.FLOOR_BOX,
},
collision_box = {
2022-08-07 11:45:39 +02:00
type = "fixed",
fixed = mcl_heads.FLOOR_BOX,
},
groups = {
handy = 1,
armor = 1,
armor_head = 1,
non_combat_armor = 1,
non_combat_armor_head = 1,
head = 1,
deco_block = 1,
dig_by_piston = 1,
},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
paramtype = "light",
2024-08-22 00:03:39 +02:00
paramtype2 = "degrotate",
2022-08-07 11:45:39 +02:00
stack_max = 64,
sunlight_propagates = true,
sounds = mcl_sounds.node_sound_defaults{
footstep = {name="default_hard_footstep", gain=0.3},
},
is_ground_content = false,
_mcl_armor_element = "head",
_mcl_blast_resistance = 1,
_mcl_hardness = 1,
on_secondary_use = equip_armor,
}
function mcl_heads.deftemplate_floor.on_rotate(pos, node, user, mode, new_param2)
2024-08-22 00:03:39 +02:00
if not (user and user:is_player()) then return end
2022-08-07 11:45:39 +02:00
if mode == screwdriver.ROTATE_AXIS then
node.name = node.name .. "_wall"
node.param2 = minetest.dir_to_wallmounted(minetest.facedir_to_dir(node.param2))
minetest.set_node(pos, node)
return true
end
end
function mcl_heads.deftemplate_floor.on_place(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then
return itemstack
end
local under = pointed_thing.under
local node = minetest.get_node(under)
local def = minetest.registered_nodes[node.name]
if not def then return itemstack end
-- Allow pointed node's on_rightclick callback to override place.
if placer and not placer:get_player_control().sneak then
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
return minetest.registered_nodes[node.name].on_rightclick(under, node, placer, itemstack) or itemstack
2020-02-18 20:04:15 +01:00
end
2017-12-05 14:09:39 +01:00
end
2022-08-07 11:45:39 +02:00
local above = pointed_thing.above
local dir = {x = under.x - above.x, y = under.y - above.y, z = under.z - above.z}
local wdir = minetest.dir_to_wallmounted(dir)
local itemstring = itemstack:get_name()
local placestack = ItemStack(itemstack)
-- place wall head node (elsewhere)
if wdir ~= 0 and wdir ~= 1 then
placestack:set_name(itemstring .."_wall")
itemstack = minetest.item_place(placestack, placer, pointed_thing, wdir)
-- place floor head node (floor and ceiling)
else
-- determine the head node rotation based on player's yaw (in cw direction from North/Z+)
2024-08-22 00:03:39 +02:00
local rotate_level = math.round(placer:get_look_horizontal() * 8/math.pi)
itemstack = minetest.item_place(placestack, placer, pointed_thing, rotate_level*15)
end
-- restore item from angled and wall head nodes
2022-08-07 11:45:39 +02:00
itemstack:set_name(itemstring)
return itemstack
end
-- wall head node nodedef template -------------------------------------------------------------------------------------
--- node definition template for wall mod heads
mcl_heads.deftemplate_wall = {
drawtype = "nodebox",
node_box = {
type = "wallmounted",
wall_bottom = { -0.25, -0.5, -0.25, 0.25, 0.0, 0.25, },
wall_top = { -0.25, 0.0, -0.25, 0.25, 0.5, 0.25, },
wall_side = { -0.5, -0.25, -0.25, 0.0, 0.25, 0.25, },
},
groups = {
handy = 1,
head = 1,
deco_block = 1,
dig_by_piston = 1,
not_in_creative_inventory = 1,
},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
paramtype = "light",
paramtype2 = "wallmounted",
stack_max = 64,
sunlight_propagates = true,
sounds = mcl_sounds.node_sound_defaults{
footstep = {name="default_hard_footstep", gain=0.3},
},
is_ground_content = false,
_doc_items_create_entry = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 1,
}
function mcl_heads.deftemplate_wall.on_rotate(pos, node, user, mode, new_param2)
2024-08-22 00:03:39 +02:00
if not (user and user:is_player()) then return end
2022-08-07 11:45:39 +02:00
if mode == screwdriver.ROTATE_AXIS then
node.name = string.sub(node.name, 1, string.len(node.name)-5)
node.param2 = minetest.dir_to_facedir(minetest.wallmounted_to_dir(node.param2))
minetest.set_node(pos, node)
return true
end
end
-- API functions -------------------------------------------------------------------------------------------------------
--- @class HeadDef
--- @field name string identifier for node
--- @field texture string armor texture for node
2022-08-07 11:45:39 +02:00
--- @field description string translated description
--- @field longdesc string translated doc description
--- @field range_mob string name of mob affected by range reduction
--- @field range_factor number factor of range reduction
--- registers a head
--- @param head_def HeadDef head node definition
function mcl_heads.register_head(head_def)
local name = "mcl_heads:" ..head_def.name
-- register the floor head node
minetest.register_node(name, table.update(table.copy(mcl_heads.deftemplate_floor), {
description = head_def.description,
_doc_items_longdesc = head_def.longdesc,
2024-08-22 00:03:39 +02:00
tiles = { head_def.texture },
2022-08-07 11:45:39 +02:00
_mcl_armor_mob_range_mob = head_def.range_mob,
_mcl_armor_mob_range_factor = head_def.range_factor,
_mcl_armor_texture = head_def.texture
2022-08-07 11:45:39 +02:00
}))
-- register the wall head node
minetest.register_node(name .."_wall", table.update(table.copy(mcl_heads.deftemplate_wall), {
2020-02-18 19:30:33 +01:00
-- The head textures are based off the textures of an actual mob.
-- Note: -x coords go right per-pixel, -y coords go down per-pixel
2020-02-18 19:30:33 +01:00
tiles = {
{ name = "[combine:16x16:-36,-4=" ..head_def.texture, align_style = "world" }, -- front
{ name = "[combine:16x16:-52,-4="..head_def.texture, align_style = "world" }, -- back
{ name = "[combine:16x16:-40,-4=" ..head_def.texture, align_style = "world" }, -- right
{ name = "[combine:16x16:-32,-4=" ..head_def.texture, align_style = "world" }, -- left
{ name = "([combine:16x16:-36,0=" ..head_def.texture ..")^[transformR180", align_style = "node" }, -- top
2022-08-07 11:45:39 +02:00
-- Note: bottom texture is overlaid over top texture to get rid of possible transparency.
-- This is required for skeleton skull and wither skeleton skull.
{ name = "([combine:16x16:-36,0=" ..head_def.texture ..")^([combine:16x16:-44,8=" ..head_def.texture..")", align_style = "node" }, -- bottom
2020-02-18 19:30:33 +01:00
},
2022-08-07 11:45:39 +02:00
drop = name,
}))
2015-06-29 19:55:56 +02:00
end
2022-08-07 11:45:39 +02:00
-- initial heads -------------------------------------------------------------------------------------------------------
mcl_heads.register_head{
name = "zombie",
texture = "mcl_heads_zombie.png",
2022-08-07 11:45:39 +02:00
description = S("Zombie Head"),
longdesc = S("A zombie head is a small decorative block which resembles the head of a zombie. It can also be worn as a helmet, which reduces the detection range of zombies by 50%."),
range_mob = "mobs_mc:zombie",
range_factor = 0.5,
}
mcl_heads.register_head{
2024-05-12 06:21:37 +02:00
name = "stalker",
texture = "mcl_heads_stalker.png",
description = S("Stalker Head"),
longdesc = S("A stalker head is a small decorative block which resembles the head of a stalker. It can also be worn as a helmet, which reduces the detection range of stalkers by 50%."),
range_mob = "mobs_mc:stalker",
2022-08-07 11:45:39 +02:00
range_factor = 0.5,
}
2017-03-11 18:51:39 +01:00
-- Original Minecraft name: “Head”
2022-08-07 11:45:39 +02:00
mcl_heads.register_head{
name = "steve",
texture = "mcl_heads_steve.png",
2022-08-07 11:45:39 +02:00
description = S("Human Head"),
longdesc = S("A human head is a small decorative block which resembles the head of a human (i.e. a player character). It can also be worn as a helmet for fun, but does not offer any protection."),
}
mcl_heads.register_head{
name = "skeleton",
texture = "mcl_heads_skeleton.png",
2022-08-07 11:45:39 +02:00
description = S("Skeleton Skull"),
longdesc = S("A skeleton skull is a small decorative block which resembles the skull of a skeleton. It can also be worn as a helmet, which reduces the detection range of skeletons by 50%."),
range_mob = "mobs_mc:skeleton",
range_factor = 0.5,
}
mcl_heads.register_head{
name = "wither_skeleton",
texture = "mcl_heads_wither_skeleton.png",
2022-08-07 11:45:39 +02:00
description = S("Wither Skeleton Skull"),
longdesc = S("A wither skeleton skull is a small decorative block which resembles the skull of a wither skeleton. It can also be worn as a helmet for fun, but does not offer any protection."),
}
2024-08-22 00:03:39 +02:00
-- Alias old creeper heads
minetest.register_alias("mcl_heads:creeper_wall", "mcl_heads:stalker_wall")
minetest.register_alias("mcl_heads:creeper", "mcl_heads:stalker")
-- Register LBM updates for old floor heads
local old_heads_all = {"mcl_heads:zombie", "mcl_heads:creeper", "mcl_heads:stalker", "mcl_heads:steve", "mcl_heads:skeleton", "mcl_heads:wither_skeleton"}
local old_heads_angled = {}
for i=1,#old_heads_all do
for j=1,#mcl_heads.FLOOR_DEGREES do
old_heads_angled[#old_heads_angled+1] = old_heads_all[i]..mcl_heads.FLOOR_DEGREES[j]
end
end
-- add the angled heads to old_heads_all
for i=1,#old_heads_angled do
old_heads_all[#old_heads_all+1] = old_heads_angled[i]
end
2024-08-22 00:03:39 +02:00
local facedir_to_degrotate = {0, 180, 120, 60}
minetest.register_lbm({
name = "mcl_heads:heads_update_angled",
nodenames = old_heads_all,
action = function(pos, node)
local degrotate = 0
if node.name:sub(-4) == "22_5" then
node.name = node.name:sub(1, #node.name-4)
degrotate = ((4 - node.param2) * 90 - 22.5) / 1.5
elseif node.name:sub(-4) == "67_5" then
node.name = node.name:sub(1, #node.name-4)
degrotate = ((4 - node.param2) * 90 - 67.5) / 1.5
elseif node.name:sub(-2) == "45" then
node.name = node.name:sub(1, #node.name-2)
degrotate = ((4 - node.param2) * 90 - 45) / 1.5
else
degrotate = facedir_to_degrotate[node.param2+1]
end
if not degrotate then
return
end
node.param2 = degrotate
minetest.set_node(pos, node)
end,
})