Compare commits

...

10 Commits

45 changed files with 1242 additions and 1606 deletions

View File

@ -0,0 +1,111 @@
mcl_damage = {
modifiers = {},
types = {
in_fire = {is_fire = true},
lightning_bolt = {is_lightning = true},
on_fire = {is_fire = true},
lava = {is_fire = true},
hot_floor = {is_fire = true},
in_wall = {bypasses_armor = true},
drown = {bypasses_armor = true},
starve = {bypasses_armor = true, bypasses_magic = true},
cactus = {},
fall = {bypasses_armor = true},
fly_into_wall = {bypasses_armor = true}, -- unused
out_of_world = {bypasses_armor = true, bypasses_invulnerability = true, bypasses_magic = true},
generic = {bypasses_armor = true},
magic = {is_magic = true, bypasses_armor = true},
wither = {bypasses_armor = true}, -- unused
anvil = {},
falling_node = {}, -- unused
dragon_breath = {bypasses_armor = true}, -- unused
mob = {},
player = {},
arrow = {is_projectile = true},
fireball = {is_projectile = true, is_fire = true},
thorns = {is_magic = true},
explosion = {is_explosion = true},
}
}
local old_register_hpchange = minetest.register_on_player_hpchange
function minetest.register_on_player_hpchange(func, modifier)
if modifier then
mcl_damage.register_modifier(func, 0)
else
old_register_hpchange(func, modifier)
end
end
function mcl_damage.register_modifier(func, priority)
table.insert(mcl_damage.modifiers, {func = func, priority = priority or 0})
end
function mcl_damage.get_mcl_damage_reason(mt_reason)
local mcl_reason = {
type = "generic",
}
if mt_reason._mcl_type then
mcl_reason.type = mt_reason._mcl_type
elseif mt_reason.type == "fall" then
mcl_reason.type = "fall"
elseif mt_reason.type == "drown" then
mcl_reason.type = "drown"
elseif mt_reason.type == "punch" then
mcl_reason.direct = mt_reason.object
if mcl_reason.direct then
local luaentity = mcl_reason.direct:get_luaentity()
if luaentity then
if luaentity._is_arrow then
mcl_reason.type = "arrow"
elseif luaentity._is_fireball then
mcl_reason.type = "fireball"
elseif luaentity._cmi_is_mob then
mcl_reason.type = "mob"
end
mcl_reason.source = mcl_reason.source or luaentity._source_object
else
mcl_reason.type = "player"
end
end
elseif mt_reason.type == "node_damage" and mt_reason.node then
if minetest.get_item_group(mt_reason.node, "fire") > 0 then
mcl_reason.type = "in_fire"
end
if minetest.get_item_group(mt_reason.node, "lava") > 0 then
mcl_reason.type = "lava"
end
end
for key, value in pairs(mt_reason) do
if key:find("_mcl_") == 1 then
mcl_reason[key:sub(6, #key)] = value
end
end
mcl_reason.source = mcl_reason.source or mcl_reason.direct
mcl_reason.flags = mcl_damage.types[mcl_reason.type]
return mcl_reason
end
function mcl_damage.register_type(name, def)
mcl_damage.types[name] = def
end
old_register_hpchange(function(player, hp_change, mt_reason)
local mcl_reason = mcl_damage.get_mcl_damage_reason(mt_reason)
for _, modf in ipairs(mcl_damage.modifiers) do
hp_change = modf.func(player, hp_change, mt_reason, mcl_reason) or hp_change
end
return hp_change
end, true)
minetest.register_on_mods_loaded(function()
table.sort(mcl_damage.modifiers, function(a, b) return a.priority < b.priority end)
end)

View File

@ -0,0 +1,3 @@
name = mcl_damage
author = Fleckenstein
description = Minecraft-like damage reason system

View File

@ -150,7 +150,8 @@ end
-- raydirs - The directions for each ray
-- radius - The maximum distance each ray will go
-- info - Table containing information about explosion
-- puncher - object that punches other objects (optional)
-- direct - direct source object of the damage (optional)
-- source - indirect source object of the damage (optional)
--
-- Values in info:
-- drop_chance - The chance that destroyed nodes will drop their items
@ -165,7 +166,7 @@ end
-- Note that this function has been optimized, it contains code which has been
-- inlined to avoid function calls and unnecessary table creation. This was
-- measured to give a significant performance increase.
local function trace_explode(pos, strength, raydirs, radius, info, puncher)
local function trace_explode(pos, strength, raydirs, radius, info, direct, source)
local vm = get_voxel_manip()
local emin, emax = vm:read_from_map(vector.subtract(pos, radius),
@ -247,7 +248,7 @@ local function trace_explode(pos, strength, raydirs, radius, info, puncher)
local ent = obj:get_luaentity()
-- Ignore items to lower lag
if obj:is_player() or (ent and ent.name ~= '__builtin.item') then
if (obj:is_player() or (ent and ent.name ~= '__builtin.item')) and obj:get_hp() > 0 then
local opos = obj:get_pos()
local collisionbox = nil
@ -321,7 +322,6 @@ local function trace_explode(pos, strength, raydirs, radius, info, puncher)
impact = 0
end
local damage = math.floor((impact * impact + impact) * 7 * strength + 1)
local source = puncher or obj
local sleep_formspec_doesnt_close_mt53 = false
if obj:is_player() then
@ -336,23 +336,22 @@ local function trace_explode(pos, strength, raydirs, radius, info, puncher)
if mod_death_messages then
mcl_death_messages.player_damage(obj, S("@1 was caught in an explosion.", name))
end
if rawget(_G, "armor") and armor.last_damage_types then
armor.last_damage_types[name] = "explosion"
end
end
if sleep_formspec_doesnt_close_mt53 then
minetest.after(0.3, function(obj, damage, impact, punch_dir) -- 0.2 is minimum delay for closing old formspec and open died formspec -- TODO: REMOVE THIS IN THE FUTURE
if not obj then return end
obj:punch(obj, 10, { damage_groups = { full_punch_interval = 1, fleshy = damage, knockback = impact * 20.0 } }, punch_dir)
obj:add_velocity(vector.multiply(punch_dir, impact * 20))
end, obj, damage, impact, vector.new(punch_dir))
else
obj:punch(source, 10, { damage_groups = { full_punch_interval = 1, fleshy = damage, knockback = impact * 20.0 } }, punch_dir)
minetest.after(0.3, function() -- 0.2 is minimum delay for closing old formspec and open died formspec -- TODO: REMOVE THIS IN THE FUTURE
if not obj:is_player() then
return
end
mcl_util.deal_damage(obj, damage, {type = "explosion", direct = direct, source = source})
if obj:is_player() then
obj:add_velocity(vector.multiply(punch_dir, impact * 20))
elseif ent.tnt_knockback then
end)
else
mcl_util.deal_damage(obj, damage, {type = "explosion", direct = direct, source = source})
if obj:is_player() or ent.tnt_knockback then
obj:add_velocity(vector.multiply(punch_dir, impact * 20))
end
end
@ -422,7 +421,8 @@ end
-- pos - The position where the explosion originates from
-- strength - The blast strength of the explosion (a TNT explosion uses 4)
-- info - Table containing information about explosion
-- puncher - object that is reported as source of punches/damage (optional)
-- direct - direct source object of the damage (optional)
-- source - indirect source object of the damage (optional)
--
-- Values in info:
-- drop_chance - If specified becomes the drop chance of all nodes in the
@ -436,7 +436,7 @@ end
-- griefing - If true, the explosion will destroy nodes (default: true)
-- grief_protected - If true, the explosion will also destroy nodes which have
-- been protected (default: false)
function mcl_explosions.explode(pos, strength, info, puncher)
function mcl_explosions.explode(pos, strength, info, direct, source)
if info == nil then
info = {}
end
@ -465,7 +465,7 @@ function mcl_explosions.explode(pos, strength, info, puncher)
info.drop_chance = 0
end
trace_explode(pos, strength, shape, radius, info, puncher)
trace_explode(pos, strength, shape, radius, info, direct, source)
if info.particles then
add_particles(pos, radius)

View File

@ -418,3 +418,99 @@ function mcl_util.get_color(colorstr)
return colorstr, hex
end
end
function mcl_util.call_on_rightclick(itemstack, player, pointed_thing)
-- Call on_rightclick if the pointed node defines it
if pointed_thing and pointed_thing.type == "node" then
local node = minetest.get_node(pointed_thing.under)
if player and not player: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(pointed_thing.under, node, user, itemstack) or itemstack
end
end
end
end
function mcl_util.calculate_durability(itemstack)
local unbreaking_level = mcl_enchanting.get_enchantment(itemstack, "unbreaking")
local armor_uses = minetest.get_item_group(itemstack:get_name(), "mcl_armor_uses")
local uses
if armor_uses > 0 then
uses = armor_uses
if unbreaking_level > 0 then
uses = uses / (0.6 + 0.4 / (unbreaking_level + 1))
end
else
local def = itemstack:get_definition()
if def then
local fixed_uses = def._mcl_uses
if fixed_uses then
uses = fixed_uses
if unbreaking_level > 0 then
uses = uses * (unbreaking_level + 1)
end
end
end
if not uses then
local toolcaps = itemstack:get_tool_capabilities()
local groupcaps = toolcaps.groupcaps
for _, v in pairs(groupcaps) do
uses = v.uses
break
end
end
end
return uses or 0
end
function mcl_util.use_item_durability(itemstack, n)
local uses = mcl_util.calculate_durability(itemstack)
itemstack:add_wear(65535 / uses * n)
end
function mcl_util.deal_damage(target, damage, mcl_reason)
mcl_reason = mcl_reason or {}
local luaentity = target:get_luaentity()
if luaentity then
if luaentity.deal_damage then
luaentity:deal_damage(damage, mcl_reason)
return
elseif luaentity._cmi_is_mob then
local puncher = mcl_reason.direct or target
target:punch(puncher, 1.0, {full_punch_interval = 1.0, damage_groups = {fleshy = damage}}, vector.direction(puncher:get_pos(), target:get_pos()), damage)
return
end
end
local mt_reason
if target:is_player() then
mt_reason = {}
for key, value in pairs(mcl_reason) do
mt_reason["_mcl_" .. key] = value
end
end
target:set_hp(target:get_hp() - damage, mt_reason)
end
function mcl_util.get_inventory(object, create)
if object:is_player() then
return object:get_inventory()
else
local luaentity = object:get_luaentity()
local inventory = luaentity.inventory
if create and not inventory and luaentity.create_inventory then
inventory = luaentity:create_inventory()
end
return inventory
end
end

View File

@ -92,7 +92,6 @@ function mcl_burning.damage(obj)
do_damage = false
else
local name = obj:get_player_name()
armor.last_damage_types[name] = "fire"
local deathmsg = S("@1 burned to death.", name)
local reason = mcl_burning.get(obj, "string", "reason")
if reason ~= "" then
@ -107,12 +106,7 @@ function mcl_burning.damage(obj)
end
if do_damage then
local new_hp = hp - 1
if health then
luaentity.health = new_hp
else
obj:set_hp(new_hp)
end
mcl_util.deal_damage(obj, 1, {type = "on_fire"})
end
end

View File

@ -177,7 +177,7 @@ local function object_in_range(self, object)
local factor
-- Apply view range reduction for special player armor
if object:is_player() and mod_armor then
factor = armor:get_mob_view_range_factor(object, self.name)
factor = mcl_armor.get_mob_view_range_factor(object, self.name)
end
-- Distance check
local dist
@ -3906,7 +3906,7 @@ minetest.register_entity(name, {
--default built in engine collision detection
self.object:set_properties({
collide_with_objects = false,
})
})
return mob_activate(self, staticdata, def, dtime)
end,
@ -4367,4 +4367,4 @@ minetest.register_globalstep(function(dtime)
end
timer = 0
end)
]]--
]]--

View File

@ -147,12 +147,10 @@ mobs:register_arrow("mobs_mc:blaze_fireball", {
visual_size = {x = 0.3, y = 0.3},
textures = {"mcl_fire_fire_charge.png"},
velocity = 15,
_is_fireball = true,
-- Direct hit, no fire... just plenty of pain
hit_player = function(self, player)
if rawget(_G, "armor") and armor.last_damage_types then
armor.last_damage_types[player:get_player_name()] = "fireball"
end
mcl_burning.set_on_fire(player, 5, "blaze")
player:punch(self.object, 1.0, {
full_punch_interval = 1.0,

View File

@ -76,18 +76,18 @@ mobs:register_mob("mobs_mc:ghast", {
mobs:spawn_specific(
"mobs_mc:ghast",
"nether",
"mobs_mc:ghast",
"nether",
"ground",
{
"Nether"
},
0,
minetest.LIGHT_MAX+1,
30,
18000,
2,
mobs_mc.spawn_height.nether_min,
0,
minetest.LIGHT_MAX+1,
30,
18000,
2,
mobs_mc.spawn_height.nether_min,
mobs_mc.spawn_height.nether_max)
-- fireball (projectile)
@ -97,11 +97,9 @@ mobs:register_arrow("mobs_mc:fireball", {
textures = {"mcl_fire_fire_charge.png"},
velocity = 15,
collisionbox = {-.5, -.5, -.5, .5, .5, .5},
_is_fireball = true,
hit_player = function(self, player)
if rawget(_G, "armor") and armor.last_damage_types then
armor.last_damage_types[player:get_player_name()] = "fireball"
end
player:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = 6},

View File

@ -139,48 +139,42 @@ lightning.strike = function(pos)
for o=1, #objs do
local obj = objs[o]
local lua = obj:get_luaentity()
if obj:is_player() then
-- Player damage
if has_mcl_death_msg then
-- pig → zombie pigman (no damage)
if lua and lua.name == "mobs_mc:pig" then
local rot = obj:get_yaw()
obj:remove()
obj = add_entity(pos2, "mobs_mc:pigman")
obj:set_yaw(rot)
-- mooshroom: toggle color red/brown (no damage)
elseif lua and lua.name == "mobs_mc:mooshroom" then
if lua.base_texture[1] == "mobs_mc_mooshroom.png" then
lua.base_texture = { "mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" }
else
lua.base_texture = { "mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png" }
end
obj:set_properties({textures = lua.base_texture})
-- villager → witch (no damage)
elseif lua and lua.name == "mobs_mc:villager" then
-- Witches are incomplete, this code is unused
-- TODO: Enable this code when witches are working.
--[[
local rot = obj:get_yaw()
obj:remove()
obj = minetest.add_entity(pos2, "mobs_mc:witch")
obj:set_yaw(rot)
]]
-- charged creeper
elseif lua and lua.name == "mobs_mc:creeper" then
local rot = obj:get_yaw()
obj:remove()
obj = add_entity(pos2, "mobs_mc:creeper_charged")
obj:set_yaw(rot)
-- Other objects: Just damage
else
if obj:is_player() and has_mcl_death_msg then
mcl_death_messages.player_damage(obj, S("@1 was struck by lightning.", obj:get_player_name()))
end
obj:set_hp(obj:get_hp()-5, { type = "punch", from = "mod" })
-- Mobs
elseif lua and lua._cmi_is_mob then
-- pig → zombie pigman (no damage)
if lua.name == "mobs_mc:pig" then
local rot = obj:get_yaw()
obj:remove()
obj = add_entity(pos2, "mobs_mc:pigman")
obj:set_yaw(rot)
-- mooshroom: toggle color red/brown (no damage)
elseif lua.name == "mobs_mc:mooshroom" then
if lua.base_texture[1] == "mobs_mc_mooshroom.png" then
lua.base_texture = { "mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" }
else
lua.base_texture = { "mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png" }
end
obj:set_properties({textures = lua.base_texture})
-- villager → witch (no damage)
elseif lua.name == "mobs_mc:villager" then
-- Witches are incomplete, this code is unused
-- TODO: Enable this code when witches are working.
--[[
local rot = obj:get_yaw()
obj:remove()
obj = minetest.add_entity(pos2, "mobs_mc:witch")
obj:set_yaw(rot)
]]
-- charged creeper
elseif lua.name == "mobs_mc:creeper" then
local rot = obj:get_yaw()
obj:remove()
obj = add_entity(pos2, "mobs_mc:creeper_charged")
obj:set_yaw(rot)
-- Other mobs: Just damage
else
obj:set_hp(obj:get_hp()-5, { type = "punch", from = "mod" })
end
mcl_util.deal_damage(obj, 5, {type = "lightning_bolt"})
end
end

View File

@ -40,7 +40,6 @@ minetest.register_on_mods_loaded(function()
end
self._void_timer = 0
local pos = obj:get_pos()
local void, void_deadly = is_in_void(pos)
if void_deadly then
local ent = obj:get_luaentity()
@ -81,7 +80,7 @@ minetest.register_globalstep(function(dtime)
-- Damage enabled, not immortal: Deal void damage (4 HP / 0.5 seconds)
if player:get_hp() > 0 then
death_msg(player, S("@1 fell into the endless void.", player:get_player_name()))
player:set_hp(player:get_hp() - VOID_DAMAGE)
mcl_util.deal_damage(player, VOID_DAMAGE, {type = "out_of_world"})
end
end
end

View File

@ -263,34 +263,7 @@ function mcl_experience.add_experience(player, experience)
local can = final_candidates[math.random(#final_candidates)]
local stack, list, index, wear = can.stack, can.list, can.index, can.wear
local unbreaking_level = mcl_enchanting.get_enchantment(stack, "unbreaking")
local uses
local armor_uses = minetest.get_item_group(stack:get_name(), "mcl_armor_uses")
if armor_uses > 0 then
uses = armor_uses
if unbreaking_level > 0 then
uses = uses / (0.6 + 0.4 / (unbreaking_level + 1))
end
else
local def = stack:get_definition()
if def then
local fixed_uses = def._mcl_uses
if fixed_uses then
uses = fixed_uses
if unbreaking_level > 0 then
uses = uses * (unbreaking_level + 1)
end
end
end
if not uses then
local toolcaps = stack:get_tool_capabilities()
local groupcaps = toolcaps.groupcaps
for _, v in pairs(groupcaps) do
uses = v.uses
break
end
end
end
uses = uses or 0
local uses = mcl_util.calculate_durability(itemstack)
local multiplier = 2 * 65535 / uses
local repair = experience * multiplier
local new_wear = wear - repair

View File

@ -1,9 +1,5 @@
local S = minetest.get_translator("mcl_hbarmor")
if (not armor) or (not armor.def) then
minetest.log("error", "[mcl_hbarmor] Outdated mcl_armor version. Please update your version of mcl_armor!")
end
local mcl_hbarmor = {}
-- HUD statbar values
@ -60,11 +56,8 @@ end
hb.register_hudbar("armor", 0xFFFFFF, S("Armor"), { icon = "hbarmor_icon.png", bgicon = "hbarmor_bgicon.png", bar = "hbarmor_bar.png" }, 0, 0, 20, mcl_hbarmor.autohide)
function mcl_hbarmor.get_armor(player)
if not player or not armor.def then
return false
end
local name = player:get_player_name()
local pts = armor:get_armor_points(player)
local pts = player:get_meta():get_int("mcl_armor:armor_points")
if not pts then
return false
else

View File

@ -7,8 +7,7 @@ local players = {}
-- Containing all the items for each Creative Mode tab
local inventory_lists = {}
local show_armor = minetest.get_modpath("mcl_armor") ~= nil
local mod_player = minetest.get_modpath("mcl_player") ~= nil
+local mod_player = minetest.get_modpath("mcl_player") ~= nil
-- Create tables
local builtin_filter_ids = {"blocks","deco","redstone","rail","food","tools","combat","mobs","brew","matr","misc","all"}
@ -334,23 +333,7 @@ mcl_inventory.set_creative_formspec = function(player, start_i, pagenum, inv_siz
if minetest.settings:get_bool("3d_player_preview", true) then
player_preview = mcl_player.get_player_formspec_model(player, 3.9, 1.4, 1.2333, 2.4666, "")
else
local img, img_player
if mod_player then
img_player = mcl_player.player_get_preview(player)
else
img_player = "player.png"
end
img = img_player
player_preview = "image[3.9,1.4;1.2333,2.4666;"..img.."]"
if show_armor and armor.textures[playername] and armor.textures[playername].preview then
img = armor.textures[playername].preview
local s1 = img:find("character_preview")
if s1 ~= nil then
s1 = img:sub(s1+21)
img = img_player..s1
end
player_preview = "image[3.9,1.4;1.2333,2.4666;"..img.."]"
end
player_preview = "image[3.9,1.4;1.2333,2.4666;"..mcl_player.player_get_preview(player).."]"
end
-- Background images for armor slots (hide if occupied)
@ -373,10 +356,10 @@ mcl_inventory.set_creative_formspec = function(player, start_i, pagenum, inv_siz
main_list = "list[current_player;main;0,3.75;9,3;9]"..
mcl_formspec.get_itemslot_bg(0,3.75,9,3)..
-- armor
"list[detached:"..playername.."_armor;armor;2.5,1.3;1,1;1]"..
"list[detached:"..playername.."_armor;armor;2.5,2.75;1,1;2]"..
"list[detached:"..playername.."_armor;armor;5.5,1.3;1,1;3]"..
"list[detached:"..playername.."_armor;armor;5.5,2.75;1,1;4]"..
"list[current_player;armor;2.5,1.3;1,1;1]"..
"list[current_player;armor;2.5,2.75;1,1;2]"..
"list[current_player;armor;5.5,1.3;1,1;3]"..
"list[current_player;armor;5.5,2.75;1,1;4]"..
mcl_formspec.get_itemslot_bg(2.5,1.3,1,1)..
mcl_formspec.get_itemslot_bg(2.5,2.75,1,1)..
mcl_formspec.get_itemslot_bg(5.5,1.3,1,1)..

View File

@ -3,7 +3,6 @@ local F = minetest.formspec_escape
mcl_inventory = {}
local show_armor = minetest.get_modpath("mcl_armor") ~= nil
local mod_player = minetest.get_modpath("mcl_player") ~= nil
local mod_craftguide = minetest.get_modpath("mcl_craftguide") ~= nil
@ -68,23 +67,7 @@ local function set_inventory(player, armor_change_only)
if minetest.settings:get_bool("3d_player_preview", true) then
player_preview = mcl_player.get_player_formspec_model(player, 1.0, 0.0, 2.25, 4.5, "")
else
local img, img_player
if mod_player then
img_player = mcl_player.player_get_preview(player)
else
img_player = "player.png"
end
img = img_player
player_preview = "image[0.6,0.2;2,4;"..img.."]"
if show_armor and armor.textures[player_name] and armor.textures[player_name].preview then
img = armor.textures[player_name].preview
local s1 = img:find("character_preview")
if s1 ~= nil then
s1 = img:sub(s1+21)
img = img_player..s1
end
player_preview = "image[1.1,0.2;2,4;"..img.."]"
end
player_preview = "image[1.1,0.2;2,4;"..mcl_player.player_get_preview(player).."]"
end
local armor_slots = {"helmet", "chestplate", "leggings", "boots"}
@ -99,10 +82,10 @@ local function set_inventory(player, armor_change_only)
"background[-0.19,-0.25;9.41,9.49;crafting_formspec_bg.png]"..
player_preview..
--armor
"list[detached:"..player_name.."_armor;armor;0,0;1,1;1]"..
"list[detached:"..player_name.."_armor;armor;0,1;1,1;2]"..
"list[detached:"..player_name.."_armor;armor;0,2;1,1;3]"..
"list[detached:"..player_name.."_armor;armor;0,3;1,1;4]"..
"list[current_player;armor;0,0;1,1;1]"..
"list[current_player;armor;0,1;1,1;2]"..
"list[current_player;armor;0,2;1,1;3]"..
"list[current_player;armor;0,3;1,1;4]"..
mcl_formspec.get_itemslot_bg(0,0,1,1)..
mcl_formspec.get_itemslot_bg(0,1,1,1)..
mcl_formspec.get_itemslot_bg(0,2,1,1)..
@ -133,10 +116,10 @@ local function set_inventory(player, armor_change_only)
"tooltip[__mcl_achievements;"..F(S("Achievements")).."]"..
-- for shortcuts
"listring[current_player;main]"..
"listring[current_player;craft]"..
"listring[current_player;main]"..
"listring[detached:"..player_name.."_armor;armor]"
"listring[current_player;armor]"..
"listring[current_player;main]" ..
"listring[current_player;craft]" ..
"listring[current_player;main]"
player:set_inventory_formspec(form)
end
@ -176,18 +159,10 @@ minetest.register_on_joinplayer(function(player)
player:hud_set_hotbar_image("mcl_inventory_hotbar.png")
player:hud_set_hotbar_selected_image("mcl_inventory_hotbar_selected.png")
if show_armor then
local set_player_armor_original = armor.set_player_armor
local update_inventory_original = armor.update_inventory
armor.set_player_armor = function(self, player)
set_player_armor_original(self, player)
end
armor.update_inventory = function(self, player)
update_inventory_original(self, player)
set_inventory(player, true)
end
armor:set_player_armor(player)
armor:update_inventory(player)
local old_update_player = mcl_armor.update_player
mcl_armor.update_player = function(player, info)
old_update_player(player, info)
set_inventory(player, true)
end
-- In Creative Mode, the initial inventory setup is handled in creative.lua

View File

@ -170,7 +170,7 @@ local dispenserdef = {
minetest.registered_nodes["mcl_armor_stand:armor_stand"].on_metadata_inventory_put(standpos)
stack:take_item()
inv:set_stack("main", stack_id, stack)
armor:play_equip_sound(dropitem, nil, standpos)
mcl_armor.play_equip_sound(dropitem, nil, standpos)
armor_dispensed = true
end
else
@ -202,9 +202,8 @@ local dispenserdef = {
if ainv:get_stack("armor", armor_slot):is_empty() and pinv:get_stack("armor", armor_slot):is_empty() then
ainv:set_stack("armor", armor_slot, dropitem)
pinv:set_stack("armor", armor_slot, dropitem)
armor:set_player_armor(player)
armor:update_inventory(player)
armor:play_equip_sound(dropitem, player)
mcl_armor.update(player)
mcl_armor.play_equip_sound(dropitem, player)
stack:take_item()
inv:set_stack("main", stack_id, stack)

View File

@ -0,0 +1,232 @@
function mcl_armor.play_equip_sound(stack, obj, pos, unequip)
local def = stack:get_definition()
local estr = "equip"
if unequip then
estr = "unequip"
end
local snd = def.sounds and def.sounds["_mcl_armor_" .. estr]
if not snd then
-- Fallback sound
snd = { name = "mcl_armor_" .. estr .. "_generic" }
end
if snd then
local dist = 8
if pos then
dist = 16
end
minetest.sound_play(snd, {object = obj, pos = pos, gain = 0.5, max_hear_distance = dist}, true)
end
end
function mcl_armor.equip(itemstack, obj)
local def = itemstack:get_definition()
local element = mcl_armor.elements[def._mcl_armor_element or ""]
local inv = mcl_util.get_inventory(obj)
if element and inv then
if inv:get_stack("armor", element.index):is_empty() then
local equipping_item = itemstack:take_item()
inv:set_stack("armor", element.index, equipping_item)
if def._on_equip then
def._on_equip(equipping_item)
end
mcl_armor.update(obj)
end
end
return itemstack
end
function mcl_armor.equip_on_use(itemstack, player, pointed_thing)
if not player or not player:is_player() then
return itemstack
end
local new_stack = mcl_util.call_on_rightclick(itemstack, player, pointed_thing)
if new_stack then
return new_stack
end
return mcl_armor.equip(itemstack, player)
end
function mcl_armor.register_set(def)
local modname = minetest.get_current_modname()
local S = minetest.get_translator(modname)
local descriptions = def.descriptions or {}
local groups = def.groups or {}
for name, element in pairs(mcl_armor.elements) do
local itemname = element.name .. "_" .. def.name
local itemstring = modname .. ":" .. itemname
local groups = table.copy(groups)
groups["armor_" .. name] = 1
groups["combat_armor_" .. name] = 1
groups.armor = 1
groups.combat_armor = 1
groups.mcl_armor_points = def.points[name]
groups.mcl_armor_toughness = def.toughness
groups.mcl_armor_uses = math.floor(def.durability * element.durability) + 1
groups.enchantability = def.enchantability
minetest.register_tool(itemstring, {
description = S(def.description .. " " .. (descriptions[name] or element.description)),
_doc_items_longdesc = mcl_armor.longdesc,
_doc_items_usagehelp = mcl_armor.usage,
inventory_image = modname .. "_inv_" .. itemname .. ".png",
_repair_material = def.repair_material or def.craft_material,
groups = groups,
sounds = {
_mcl_armor_equip = def.sound_equip or modname .. "_equip_" .. def.name,
_mcl_armor_unequip = def.sound_unequip or modname .. "_unequip_" .. def.name,
},
on_place = mcl_armor.equip_on_use,
on_secondary_use = mcl_armor.equip_on_use,
_on_equip = def.on_equip,
_on_unequip = def.on_unequip,
_mcl_armor_element = name,
_mcl_armor_texture = modname .. "_" .. itemname .. ".png",
_mcl_armor_preview = modname .. "_" .. itemname .. "_preview.png",
})
if def.craft_material then
minetest.register_craft({
output = itemstring,
recipe = element.craft(def.craft_material),
})
end
if def.cook_material then
minetest.register_craft({
type = "cooking",
output = def.cook_material,
recipe = itemstring,
cooktime = 10,
})
end
end
end
mcl_armor.protection_enchantments = {
flags = {},
types = {},
wildcard = {},
}
function mcl_armor.register_protection_enchantment(def)
local prot_def = {id = def.id, factor = def.factor}
if def.damage_flag then
local tbl = mcl_armor.protection_enchantments.flags[def.damage_flag] or {}
table.insert(tbl, prot_def)
mcl_armor.protection_enchantments.flags = tbl
elseif def.damage_type then
local tbl = mcl_armor.protection_enchantments.types[def.damage_type] or {}
table.insert(tbl, prot_def)
mcl_armor.protection_enchantments.types = tbl
else
table.insert(mcl_armor.protection_enchantments.wildcard, prot_def)
end
mcl_enchanting.enchantments[def.id] = {
name = def.name,
max_level = def.max_level or 4,
primary = def.primary or {combat_armor = true},
secondary = {},
disallow = {},
incompatible = def.incompatible or {},
weight = def.weight or 5,
description = def.description,
curse = false,
on_enchant = function() end,
requires_tool = false,
treasure = def.treasure or false,
power_range_table = def.power_range_table,
inv_combat_tab = true,
inv_tool_tab = false,
}
end
function mcl_armor.get_armor_points(obj)
local points = 0
local inv = mcl_util.get_inventory(obj)
if inv then
for i = 2, 5 do
local itemstack = inv:get_stack("armor", i)
if not itemstack:is_empty() then
points = points + minetest.get_item_group(itemstack:get_name(), "mcl_armor_points")
end
end
end
return points
end
-- Returns a change factor for a mob's view_range for the given object
-- or nil, if there's no change. Certain armors (like mob heads) can
-- affect the view range of mobs.
function mcl_armor.get_mob_view_range_factor(obj, mob)
local inv = mcl_util.get_inventory(obj)
local factor
if inv then
for i = 2, 5 do
local itemstack = inv:get_stack("armor", i)
if not itemstack:is_empty() then
local def = itemstack:get_definition()
if def._mcl_armor_mob_range_mob == mob then
if not factor then
factor = def._mcl_armor_mob_range_factor
elseif factor == 0 then
return 0
else
factor = factor * def._mcl_armor_mob_range_factor
end
end
end
end
end
return factor
end
function mcl_armor.update(obj)
local info = {points = 0}
local inv = mcl_util.get_inventory(obj)
if inv then
for i = 2, 5 do
local itemstack = inv:get_stack("armor", i)
local itemname = itemstack:get_name()
if minetest.registered_aliases[itemname] then
itemname = minetest.registered_aliases[itemname]
end
if not itemstack:is_empty() then
local def = itemstack:get_definition()
if def._mcl_armor_texture then
info.texture = "(" .. def._mcl_armor_texture .. ")" .. (info.texture and "^" .. info.texture or "")
end
if obj:is_player() and def._mcl_armor_preview then
info.preview = "(player.png^[opacity:0^" .. def._mcl_armor_preview .. ")" .. (info.preview and "^" .. info.preview or "" )
end
info.points = info.points + minetest.get_item_group(itemname, "mcl_armor_points")
end
end
end
info.texture = info.texture or "blank.png"
if obj:is_player() then
info.preview = info.preview or "blank.png"
mcl_armor.update_player(obj, info)
else
local luaentity = obj:get_luaentity()
if luaentity.update_armor then
luaentity:update_armor(info)
end
end
end

View File

@ -1,675 +0,0 @@
local ARMOR_INIT_DELAY = 1
local ARMOR_INIT_TIMES = 1
local ARMOR_BONES_DELAY = 1
local skin_mod = nil
local modpath = minetest.get_modpath(minetest.get_current_modname())
armor = {
timer = 0,
elements = {"head", "torso", "legs", "feet"},
physics = {"jump","speed","gravity"},
formspec = "size[8,8.5]image[2,0.75;2,4;armor_preview]"
.."list[current_player;main;0,4.5;8,4;]"
.."list[current_player;craft;4,1;3,3;]"
.."list[current_player;craftpreview;7,2;1,1;]"
.."listring[current_player;main]"
.."listring[current_player;craft]",
textures = {},
default_skin = "character",
last_damage_types = {},
}
if minetest.get_modpath("mcl_skins") then
skin_mod = "mcl_skins"
elseif minetest.get_modpath("skins") then
skin_mod = "skins"
elseif minetest.get_modpath("simple_skins") then
skin_mod = "simple_skins"
elseif minetest.get_modpath("u_skins") then
skin_mod = "u_skins"
elseif minetest.get_modpath("wardrobe") then
skin_mod = "wardrobe"
end
function armor.on_armor_use(itemstack, user, pointed_thing)
if not user or user:is_player() == false then
return itemstack
end
-- Call on_rightclick if the pointed node defines it
if pointed_thing.type == "node" then
local node = minetest.get_node(pointed_thing.under)
if user and not user: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(pointed_thing.under, node, user, itemstack) or itemstack
end
end
end
local name, player_inv, armor_inv = armor:get_valid_player(user, "[on_armor_use]")
if not name then
return itemstack
end
local def = itemstack:get_definition()
local slot
if def.groups and def.groups.armor_head then
slot = 2
elseif def.groups and def.groups.armor_torso then
slot = 3
elseif def.groups and def.groups.armor_legs then
slot = 4
elseif def.groups and def.groups.armor_feet then
slot = 5
end
if slot then
local itemstack_single = ItemStack(itemstack)
itemstack_single:set_count(1)
local itemstack_slot = armor_inv:get_stack("armor", slot)
if itemstack_slot:is_empty() then
armor_inv:set_stack("armor", slot, itemstack_single)
player_inv:set_stack("armor", slot, itemstack_single)
armor:set_player_armor(user)
armor:update_inventory(user)
armor:play_equip_sound(itemstack_single, user)
itemstack:take_item()
elseif itemstack:get_count() <= 1 and not mcl_enchanting.has_enchantment(itemstack_slot, "curse_of_binding") then
armor_inv:set_stack("armor", slot, itemstack_single)
player_inv:set_stack("armor", slot, itemstack_single)
armor:set_player_armor(user)
armor:update_inventory(user)
armor:play_equip_sound(itemstack_single, user)
itemstack = ItemStack(itemstack_slot)
end
end
return itemstack
end
armor.def = {
count = 0,
}
armor.update_player_visuals = function(self, player)
if not player then
return
end
local wielditem = player:get_wielded_item()
local def = wielditem:get_definition()
if def and def._mcl_toollike_wield then
player:set_bone_position("Wield_Item", vector.new(0,3.9,1.3), vector.new(90,0,0))
elseif string.find(wielditem:get_name(), "mcl_bows:bow") then
player:set_bone_position("Wield_Item", vector.new(.5,4.5,-1.6), vector.new(90,0,20))
else
player:set_bone_position("Wield_Item", vector.new(-1.5,4.9,1.8), vector.new(135,0,90))
end
local name = player:get_player_name()
if self.textures[name] then
mcl_player.player_set_textures(player, {
self.textures[name].skin,
self.textures[name].armor,
self.textures[name].wielditem,
})
end
end
armor.set_player_armor = function(self, player)
local name, player_inv = armor:get_valid_player(player, "[set_player_armor]")
if not name then
return
end
local armor_texture = "blank.png"
local armor_level = 0
local mcl_armor_points = 0
local items = 0
local elements = {}
local textures = {}
local physics_o = {speed=1,gravity=1,jump=1}
local material = {type=nil, count=1}
local preview
for _,v in ipairs(self.elements) do
elements[v] = false
end
for i=1, 6 do
local stack = player_inv:get_stack("armor", i)
local item = stack:get_name()
if minetest.registered_aliases[item] then
item = minetest.registered_aliases[item]
end
if stack:get_count() == 1 then
local def = stack:get_definition()
for k, v in pairs(elements) do
if v == false then
local level = def.groups["armor_"..k]
if level then
local texture = def.texture or item:gsub("%:", "_")
local enchanted_addition = (mcl_enchanting.is_enchanted(item) and mcl_enchanting.overlay or "")
table.insert(textures, "("..texture..".png"..enchanted_addition..")")
preview = "(player.png^[opacity:0^"..texture.."_preview.png"..enchanted_addition..")"..(preview and "^"..preview or "")
armor_level = armor_level + level
items = items + 1
mcl_armor_points = mcl_armor_points + (def.groups["mcl_armor_points"] or 0)
for kk,vv in ipairs(self.physics) do
local o_value = def.groups["physics_"..vv]
if o_value then
physics_o[vv] = physics_o[vv] + o_value
end
end
local mat = string.match(item, "%:.+_(.+)$")
if material.type then
if material.type == mat then
material.count = material.count + 1
end
else
material.type = mat
end
elements[k] = true
end
end
end
end
end
preview = (armor:get_preview(name) or "character_preview.png")..(preview and "^"..preview or "")
if minetest.get_modpath("shields") then
armor_level = armor_level * 0.9
end
if material.type and material.count == #self.elements then
armor_level = armor_level * 1.1
end
if #textures > 0 then
armor_texture = table.concat(textures, "^")
end
local armor_groups = player:get_armor_groups()
armor_groups.fleshy = 100
armor_groups.level = nil
if armor_level > 0 then
armor_groups.level = math.floor(armor_level / 20)
armor_groups.fleshy = 100 - armor_level
end
player:set_armor_groups(armor_groups)
-- Physics override intentionally removed because of possible conflicts
self.textures[name].armor = armor_texture
self.textures[name].preview = preview
self.def[name].count = items
self.def[name].level = armor_level
self.def[name].heal = mcl_armor_points
self.def[name].jump = physics_o.jump
self.def[name].speed = physics_o.speed
self.def[name].gravity = physics_o.gravity
self:update_player_visuals(player)
end
armor.update_armor = function(self, player)
-- Legacy support: Called when armor levels are changed
-- Other mods can hook on to this function, see hud mod for example
end
armor.get_armor_points = function(self, player)
local name, player_inv, armor_inv = armor:get_valid_player(player, "[get_armor_points]")
if not name then
return nil
end
local pts = 0
for i=1, 6 do
local stack = player_inv:get_stack("armor", i)
if stack:get_count() > 0 then
local p = minetest.get_item_group(stack:get_name(), "mcl_armor_points")
if p then
pts = pts + p
end
end
end
return pts
end
-- Returns a change factor for a mob's view_range for the given player
-- or nil, if there's no change. Certain armors (like mob heads) can
-- affect the view range of mobs.
armor.get_mob_view_range_factor = function(self, player, mob)
local name, player_inv, armor_inv = armor:get_valid_player(player, "[get_mob_view_range_factor]")
if not name then
return
end
local factor
for i=1, 6 do
local stack = player_inv:get_stack("armor", i)
if stack:get_count() > 0 then
local def = stack:get_definition()
if def._mcl_armor_mob_range_mob == mob then
if not factor then
factor = def._mcl_armor_mob_range_factor
elseif factor == 0 then
return 0
else
factor = factor * def._mcl_armor_mob_range_factor
end
end
end
end
return factor
end
armor.get_player_skin = function(self, name)
local skin = nil
if skin_mod == "mcl_skins" then
skin = mcl_skins.skins[name]
elseif skin_mod == "skins" or skin_mod == "simple_skins" then
skin = skins.skins[name]
elseif skin_mod == "u_skins" then
skin = u_skins.u_skins[name]
elseif skin_mod == "wardrobe" then
skin = string.gsub(wardrobe.playerSkins[name], "%.png$","")
end
return skin or armor.default_skin
end
armor.get_preview = function(self, name)
if skin_mod == "skins" then
return armor:get_player_skin(name).."_preview.png"
end
end
armor.get_armor_formspec = function(self, name)
if not armor.textures[name] then
minetest.log("error", "mcl_armor: Player texture["..name.."] is nil [get_armor_formspec]")
return ""
end
if not armor.def[name] then
minetest.log("error", "mcl_armor: Armor def["..name.."] is nil [get_armor_formspec]")
return ""
end
local formspec = armor.formspec.."list[detached:"..name.."_armor;armor;0,1;2,3;]"
formspec = formspec:gsub("armor_preview", armor.textures[name].preview)
formspec = formspec:gsub("armor_level", armor.def[name].level)
formspec = formspec:gsub("mcl_armor_points", armor.def[name].heal)
return formspec
end
armor.update_inventory = function(self, player)
end
armor.get_valid_player = function(self, player, msg)
msg = msg or ""
if not player then
minetest.log("error", "mcl_armor: Player reference is nil "..msg)
return
end
local name = player:get_player_name()
if not name then
minetest.log("error", "mcl_armor: Player name is nil "..msg)
return
end
local pos = player:get_pos()
local player_inv = player:get_inventory()
local armor_inv = minetest.get_inventory({type="detached", name=name.."_armor"})
if not pos then
minetest.log("error", "mcl_armor: Player position is nil "..msg)
return
elseif not player_inv then
minetest.log("error", "mcl_armor: Player inventory is nil "..msg)
return
elseif not armor_inv then
minetest.log("error", "mcl_armor: Detached armor inventory is nil "..msg)
return
end
return name, player_inv, armor_inv, pos
end
armor.play_equip_sound = function(self, stack, player, pos, unequip)
local def = stack:get_definition()
local estr = "equip"
if unequip then
estr = "unequip"
end
local snd = def.sounds and def.sounds["_mcl_armor_"..estr]
if not snd then
-- Fallback sound
snd = { name = "mcl_armor_"..estr.."_generic" }
end
if snd then
local dist = 8
if pos then
dist = 16
end
minetest.sound_play(snd, {object=player, pos=pos, gain=0.5, max_hear_distance=dist}, true)
end
end
-- Register Player Model
mcl_player.player_register_model("mcl_armor_character.b3d", {
animation_speed = 30,
textures = {
armor.default_skin..".png",
"blank.png",
"blank.png",
},
animations = {
stand = {x=0, y=79},
lay = {x=162, y=166},
walk = {x=168, y=187},
mine = {x=189, y=198},
walk_mine = {x=200, y=219},
sit = {x=81, y=160},
sneak_stand = {x=222, y=302},
sneak_mine = {x=346, y=365},
sneak_walk = {x=304, y=323},
sneak_walk_mine = {x=325, y=344},
swim_walk = {x=368, y=387},
swim_walk_mine = {x=389, y=408},
swim_stand = {x=434, y=434},
swim_mine = {x=411, y=430},
run_walk = {x=440, y=459},
run_walk_mine = {x=461, y=480},
sit_mount = {x=484, y=484},
die = {x=498, y=498},
fly = {x=502, y=581},
},
})
mcl_player.player_register_model("mcl_armor_character_female.b3d", {
animation_speed = 30,
textures = {
armor.default_skin..".png",
"blank.png",
"blank.png",
},
animations = {
stand = {x=0, y=79},
lay = {x=162, y=166},
walk = {x=168, y=187},
mine = {x=189, y=198},
walk_mine = {x=200, y=219},
sit = {x=81, y=160},
sneak_stand = {x=222, y=302},
sneak_mine = {x=346, y=365},
sneak_walk = {x=304, y=323},
sneak_walk_mine = {x=325, y=344},
swim_walk = {x=368, y=387},
swim_walk_mine = {x=389, y=408},
swim_stand = {x=434, y=434},
swim_mine = {x=411, y=430},
run_walk = {x=440, y=459},
run_walk_mine = {x=461, y=480},
sit_mount = {x=484, y=484},
die = {x=498, y=498},
fly = {x=502, y=581},
},
})
-- Register Callbacks
minetest.register_on_player_receive_fields(function(player, formname, fields)
local name = armor:get_valid_player(player, "[on_player_receive_fields]")
if not name then
return
end
if fields.armor then
return
end
for field, _ in pairs(fields) do
if string.find(field, "skins_set") then
minetest.after(0, function(name)
local player = minetest.get_player_by_name(name)
if not player then
return
end
local skin = armor:get_player_skin(name)
armor.textures[name].skin = skin..".png"
armor:set_player_armor(player)
end, player:get_player_name())
end
end
end)
minetest.register_on_joinplayer(function(player)
mcl_player.player_set_model(player, "mcl_armor_character.b3d")
local name = player:get_player_name()
local player_inv = player:get_inventory()
local armor_inv = minetest.create_detached_inventory(name.."_armor", {
on_put = function(inv, listname, index, stack, player)
player:get_inventory():set_stack(listname, index, stack)
armor:set_player_armor(player)
armor:update_inventory(player)
armor:play_equip_sound(stack, player)
end,
on_take = function(inv, listname, index, stack, player)
player:get_inventory():set_stack(listname, index, nil)
armor:set_player_armor(player)
armor:update_inventory(player)
armor:play_equip_sound(stack, player, nil, true)
end,
on_move = function(inv, from_list, from_index, to_list, to_index, count, player)
local plaver_inv = player:get_inventory()
local stack = inv:get_stack(to_list, to_index)
player_inv:set_stack(to_list, to_index, stack)
player_inv:set_stack(from_list, from_index, nil)
armor:set_player_armor(player)
armor:update_inventory(player)
armor:play_equip_sound(stack, player)
end,
allow_put = function(inv, listname, index, stack, player)
local iname = stack:get_name()
local g
local groupcheck
if index == 2 then
g = minetest.get_item_group(iname, "armor_head")
elseif index == 3 then
g = minetest.get_item_group(iname, "armor_torso")
elseif index == 4 then
g = minetest.get_item_group(iname, "armor_legs")
elseif index == 5 then
g = minetest.get_item_group(iname, "armor_feet")
end
-- Minor FIXME: If player attempts to place stack into occupied slot, this is rejected.
-- It would be better if 1 item is placed in exchanged for the item in the slot.
if g ~= 0 and g ~= nil and (inv:get_stack(listname, index):is_empty() or (inv:get_stack(listname, index):get_name() ~= stack:get_name()) and stack:get_count() <= 1) then
return 1
else
return 0
end
end,
allow_take = function(inv, listname, index, stack, player)
if mcl_enchanting.has_enchantment(stack, "curse_of_binding") and not minetest.settings:get_bool("creative") then
return 0
end
return stack:get_count()
end,
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
return 0
end,
}, name)
armor_inv:set_size("armor", 6)
player_inv:set_size("armor", 6)
for i=1, 6 do
local stack = player_inv:get_stack("armor", i)
armor_inv:set_stack("armor", i, stack)
end
armor.def[name] = {
count = 0,
level = 0,
heal = 0,
jump = 1,
speed = 1,
gravity = 1,
}
armor.textures[name] = {
skin = armor.default_skin..".png",
armor = "blank.png",
wielditem = "blank.png",
preview = armor.default_skin.."_preview.png",
}
if skin_mod == "mcl_skins" then
local skin = mcl_skins.skins[name]
if skin then
armor.textures[name].skin = skin..".png"
end
elseif skin_mod == "skins" then
local skin = skins.skins[name]
if skin and skins.get_type(skin) == skins.type.MODEL then
armor.textures[name].skin = skin..".png"
end
elseif skin_mod == "simple_skins" then
local skin = skins.skins[name]
if skin then
armor.textures[name].skin = skin..".png"
end
elseif skin_mod == "u_skins" then
local skin = u_skins.u_skins[name]
if skin and u_skins.get_type(skin) == u_skins.type.MODEL then
armor.textures[name].skin = skin..".png"
end
elseif skin_mod == "wardrobe" then
local skin = wardrobe.playerSkins[name]
if skin then
armor.textures[name].skin = skin
end
end
if minetest.get_modpath("player_textures") then
local filename = minetest.get_modpath("player_textures").."/textures/player_"..name
local f = io.open(filename..".png")
if f then
f:close()
armor.textures[name].skin = "player_"..name..".png"
end
end
for i=1, ARMOR_INIT_TIMES do
minetest.after(ARMOR_INIT_DELAY * i, function(name)
local player = minetest.get_player_by_name(name)
if not player then
return
end
armor:set_player_armor(player)
end, player:get_player_name())
end
end)
minetest.register_on_player_hpchange(function(player, hp_change, reason)
local name, player_inv, armor_inv = armor:get_valid_player(player, "[on_hpchange]")
if name and hp_change < 0 then
local damage_type = armor.last_damage_types[name]
armor.last_damage_types[name] = nil
-- Armor doesn't protect from set_hp (commands like /kill),
if reason.type == "set_hp" then
return hp_change
end
local regular_reduction = reason.type ~= "drown" and reason.type ~= "fall" and reason.other ~= "harming" and reason.other ~= "poison"
local heal_max = 0
local items = 0
local armor_damage = math.max(1, math.floor(math.abs(hp_change)/4))
local total_points = 0
local total_toughness = 0
local epf = 0
local thorns_damage = 0
local thorns_damage_regular = 0
for i=1, 6 do
local stack = player_inv:get_stack("armor", i)
if stack:get_count() > 0 then
local enchantments = mcl_enchanting.get_enchantments(stack)
local pts = stack:get_definition().groups["mcl_armor_points"] or 0
local tough = stack:get_definition().groups["mcl_armor_toughness"] or 0
total_points = total_points + pts
total_toughness = total_toughness + tough
local protection_level = enchantments.protection or 0
if protection_level > 0 then
epf = epf + protection_level * 1
end
local blast_protection_level = enchantments.blast_protection or 0
if blast_protection_level > 0 and damage_type == "explosion" then
epf = epf + blast_protection_level * 2
end
local fire_protection_level = enchantments.fire_protection or 0
if fire_protection_level > 0 and (damage_type == "burning" or damage_type == "fireball" or reason.type == "node_damage" and
(reason.node == "mcl_fire:fire" or reason.node == "mcl_core:lava_source" or reason.node == "mcl_core:lava_flowing")) then
epf = epf + fire_protection_level * 2
end
local projectile_protection_level = enchantments.projectile_protection or 0
if projectile_protection_level and (damage_type == "projectile" or damage_type == "fireball") then
epf = epf + projectile_protection_level * 2
end
local feather_falling_level = enchantments.feather_falling or 0
if feather_falling_level and reason.type == "fall" then
epf = epf + feather_falling_level * 3
end
local did_thorns_damage = false
local thorns_level = enchantments.thorns or 0
if thorns_level then
if thorns_level > 10 then
thorns_damage = thorns_damage + thorns_level - 10
did_thorns_damage = true
elseif thorns_damage_regular < 4 and thorns_level * 0.15 > math.random() then
local thorns_damage_regular_new = math.min(4, thorns_damage_regular + math.random(4))
thorns_damage = thorns_damage + thorns_damage_regular_new - thorns_damage_regular
thorns_damage_regular = thorns_damage_regular_new
did_thorns_damage = true
end
end
-- Damage armor
local use = stack:get_definition().groups["mcl_armor_uses"] or 0
if use > 0 and regular_reduction then
local unbreaking_level = enchantments.unbreaking or 0
if unbreaking_level > 0 then
use = use / (0.6 + 0.4 / (unbreaking_level + 1))
end
local wear = armor_damage * math.floor(65536/use)
if did_thorns_damage then
wear = wear * 3
end
stack:add_wear(wear)
end
local item = stack:get_name()
armor_inv:set_stack("armor", i, stack)
player_inv:set_stack("armor", i, stack)
items = items + 1
if stack:get_count() == 0 then
armor:set_player_armor(player)
armor:update_inventory(player)
end
end
end
local damage = math.abs(hp_change)
if regular_reduction then
-- Damage calculation formula (from <https://minecraft.gamepedia.com/Armor#Damage_protection>)
damage = damage * (1 - math.min(20, math.max((total_points/5), total_points - damage / (2+(total_toughness/4)))) / 25)
end
damage = damage * (1 - (math.min(20, epf) / 25))
damage = math.floor(damage+0.5)
if reason.type == "punch" and thorns_damage > 0 then
local obj = reason.object
if obj then
local luaentity = obj:get_luaentity()
if luaentity then
local shooter = obj._shooter
if shooter then
obj = shooter
end
end
obj:punch(player, 1.0, {
full_punch_interval=1.0,
damage_groups = {fleshy = thorns_damage},
})
end
end
hp_change = -math.abs(damage)
armor.def[name].count = items
armor:update_armor(player)
end
return hp_change
end, true)

View File

@ -0,0 +1,99 @@
function mcl_armor.damage_modifier(obj, hp_change, reason)
if hp_change > 0 then
return hp_change
end
local damage = -hp_change
local flags = reason.flags
if flags.bypasses_armor and flags.bypasses_magic then
return hp_change
end
local uses = math.max(1, math.floor(damage / 4))
local points = 0
local toughness = 0
local enchantment_protection_factor = 0
local thorns_damage_regular = 0
local thorns_damage_irregular = 0
local thorns_pieces = {}
local inv = mcl_util.get_inventory(obj)
if inv then
for name, element in pairs(mcl_armor.elements) do
local itemstack = inv:get_stack("armor", element.index)
if not itemstack:is_empty() then
local itemname = itemstack:get_name()
local enchantments = mcl_enchanting.get_enchantments(itemstack)
if not flags.bypasses_armor then
points = points + minetest.get_item_group(itemname, "mcl_armor_points")
toughness = toughness + minetest.get_item_group(itemname, "mcl_armor_toughness")
mcl_util.use_item_durability(itemstack, uses)
inv:set_stack("armor", element.index, itemstack)
end
if not flags.bypasses_magic then
local function add_enchantments(tbl)
if tbl then
for _, enchantment in pairs(tbl) do
local level = enchantments[enchantment.id]
if level > 0 then
enchantment_protection_factor = enchantment_protection_factor + level * enchantment.factor
end
end
end
end
add_enchantments(mcl_armor.protection_enchantments.wildcard)
add_enchantments(mcl_armor.protection_enchantments.types[reason.type])
for flag, value in pairs(flags) do
if value then
add_enchantments(mcl_armor.protection_enchantments.flags[flag])
end
end
end
if reason.source and enchantments.thorns > 0 then
local do_irregular_damage = enchantments.thorns > 10
if do_irregular_damage or thorns_damage_regular < 4 and math.random() < enchantments.thorns * 0.15 then
if do_irregular_damage then
thorns_damage_irregular = thorns_damage_irregular + throrns_level - 10
else
thorns_damage_regular = math.min(4, thorns_damage_regular + math.random(4))
end
end
table.insert(thorns_pieces, {index = element.index, itemstack = itemstack})
end
end
end
end
-- https://minecraft.gamepedia.com/Armor#Damage_protection
damage = damage * (1 - math.min(20, math.max((points / 5), points - damage / (2 + (toughness / 4)))) / 25)
-- https://minecraft.gamepedia.com/Armor#Enchantments
damage = damage * (1 - math.min(20, enchantment_protection_factor) / 25)
local thorns_damage = thorns_damage_regular + thorns_damage_irregular
if thorns_damage > 0 and reason.source ~= obj then
mcl_util.deal_damage(reason.source, {type = "thorns", direct = obj, source = reason.source})
local thorns_item = thorns_pieces[math.random(#thorns_pieces)]
mcl_util.use_item_durability(thorns_item.itemstack, 2)
inv:set_stack("armor", thorns_item.index, thorns_item.itemstack)
end
mcl_armor.update(obj)
return -math.floor(damage + 0.5)
end

View File

@ -1,405 +1,67 @@
local S = minetest.get_translator("mcl_armor")
dofile(minetest.get_modpath(minetest.get_current_modname()).."/armor.lua")
dofile(minetest.get_modpath(minetest.get_current_modname()).."/alias.lua")
-- Regisiter Head Armor
local longdesc = S("This is a piece of equippable armor which reduces the amount of damage you receive.")
local usage = S("To equip it, put it on the corresponding armor slot in your inventory menu.")
minetest.register_tool("mcl_armor:elytra", {
description = S("Elytra"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_elytra.png",
groups = {armor_torso=1, mcl_armor_points=0, mcl_armor_uses=10, enchantability=0},
sounds = {
_mcl_armor_equip = "mcl_armor_equip_leather",
_mcl_armor_unequip = "mcl_armor_unequip_leather",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
minetest.register_tool("mcl_armor:helmet_leather", {
description = S("Leather Cap"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_helmet_leather.png",
groups = {armor_head=1, mcl_armor_points=1, mcl_armor_uses=56, enchantability=15},
_repair_material = "mcl_mobitems:leather",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_leather",
_mcl_armor_unequip = "mcl_armor_unequip_leather",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
minetest.register_tool("mcl_armor:helmet_iron", {
description = S("Iron Helmet"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_helmet_iron.png",
groups = {armor_head=1, mcl_armor_points=2, mcl_armor_uses=166, enchantability=9 },
_repair_material = "mcl_core:iron_ingot",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_iron",
_mcl_armor_unequip = "mcl_armor_unequip_iron",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
minetest.register_tool("mcl_armor:helmet_gold", {
description = S("Golden Helmet"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_helmet_gold.png",
groups = {armor_head=1, mcl_armor_points=2, mcl_armor_uses=78, enchantability=25 },
_repair_material = "mcl_core:gold_ingot",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_iron",
_mcl_armor_unequip = "mcl_armor_unequip_iron",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
minetest.register_tool("mcl_armor:helmet_diamond",{
description = S("Diamond Helmet"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_helmet_diamond.png",
groups = {armor_head=1, mcl_armor_points=3, mcl_armor_uses=364, mcl_armor_toughness=2, enchantability=10 },
_repair_material = "mcl_core:diamond",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_diamond",
_mcl_armor_unequip = "mcl_armor_unequip_diamond",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
minetest.register_tool("mcl_armor:helmet_chain", {
description = S("Chain Helmet"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_helmet_chain.png",
groups = {armor_head=1, mcl_armor_points=2, mcl_armor_uses=166, enchantability=12 },
_repair_material = "mcl_core:iron_ingot",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_chainmail",
_mcl_armor_unequip = "mcl_armor_unequip_chainmail",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
-- Regisiter Torso Armor
minetest.register_tool("mcl_armor:chestplate_leather", {
description = S("Leather Tunic"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_chestplate_leather.png",
groups = {armor_torso=1, mcl_armor_points=3, mcl_armor_uses=81, enchantability=15 },
_repair_material = "mcl_mobitems:leather",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_leather",
_mcl_armor_unequip = "mcl_armor_unequip_leather",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
minetest.register_tool("mcl_armor:chestplate_iron", {
description = S("Iron Chestplate"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_chestplate_iron.png",
groups = {armor_torso=1, mcl_armor_points=6, mcl_armor_uses=241, enchantability=9 },
_repair_material = "mcl_core:iron_ingot",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_iron",
_mcl_armor_unequip = "mcl_armor_unequip_iron",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
minetest.register_tool("mcl_armor:chestplate_gold", {
description = S("Golden Chestplate"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_chestplate_gold.png",
groups = {armor_torso=1, mcl_armor_points=5, mcl_armor_uses=113, enchantability=25 },
_repair_material = "mcl_core:gold_ingot",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_iron",
_mcl_armor_unequip = "mcl_armor_unequip_iron",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
minetest.register_tool("mcl_armor:chestplate_diamond",{
description = S("Diamond Chestplate"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_chestplate_diamond.png",
groups = {armor_torso=1, mcl_armor_points=8, mcl_armor_uses=529, mcl_armor_toughness=2, enchantability=10 },
_repair_material = "mcl_core:diamond",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_diamond",
_mcl_armor_unequip = "mcl_armor_unequip_diamond",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
minetest.register_tool("mcl_armor:chestplate_chain", {
description = S("Chain Chestplate"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_chestplate_chain.png",
groups = {armor_torso=1, mcl_armor_points=5, mcl_armor_uses=241, enchantability=12 },
_repair_material = "mcl_core:iron_ingot",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_chainmail",
_mcl_armor_unequip = "mcl_armor_unequip_chainmail",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
-- Regisiter Leg Armor
minetest.register_tool("mcl_armor:leggings_leather", {
description = S("Leather Pants"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_leggings_leather.png",
groups = {armor_legs=1, mcl_armor_points=2, mcl_armor_uses=76, enchantability=15 },
_repair_material = "mcl_mobitems:leather",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_leather",
_mcl_armor_unequip = "mcl_armor_unequip_leather",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
minetest.register_tool("mcl_armor:leggings_iron", {
description = S("Iron Leggings"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_leggings_iron.png",
groups = {armor_legs=1, mcl_armor_points=5, mcl_armor_uses=226, enchantability=9 },
_repair_material = "mcl_core:iron_ingot",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_iron",
_mcl_armor_unequip = "mcl_armor_unequip_iron",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
minetest.register_tool("mcl_armor:leggings_gold", {
description = S("Golden Leggings"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_leggings_gold.png",
groups = {armor_legs=1, mcl_armor_points=3, mcl_armor_uses=106, enchantability=25 },
_repair_material = "mcl_core:gold_ingot",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_iron",
_mcl_armor_unequip = "mcl_armor_unequip_iron",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
minetest.register_tool("mcl_armor:leggings_diamond",{
description = S("Diamond Leggings"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_leggings_diamond.png",
groups = {armor_legs=1, mcl_armor_points=6, mcl_armor_uses=496, mcl_armor_toughness=2, enchantability=10 },
_repair_material = "mcl_core:diamond",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_diamond",
_mcl_armor_unequip = "mcl_armor_unequip_diamond",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
minetest.register_tool("mcl_armor:leggings_chain", {
description = S("Chain Leggings"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_leggings_chain.png",
groups = {armor_legs=1, mcl_armor_points=4, mcl_armor_uses=226, enchantability=12 },
_repair_material = "mcl_core:iron_ingot",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_chainmail",
_mcl_armor_unequip = "mcl_armor_unequip_chainmail",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
-- Regisiter Boots
minetest.register_tool("mcl_armor:boots_leather", {
description = S("Leather Boots"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_boots_leather.png",
groups = {armor_feet=1, mcl_armor_points=1, mcl_armor_uses=66, enchantability=15 },
_repair_material = "mcl_mobitems:leather",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_leather",
_mcl_armor_unequip = "mcl_armor_unequip_leather",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
minetest.register_tool("mcl_armor:boots_iron", {
description = S("Iron Boots"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_boots_iron.png",
groups = {armor_feet=1, mcl_armor_points=2, mcl_armor_uses=196, enchantability=9 },
_repair_material = "mcl_core:iron_ingot",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_iron",
_mcl_armor_unequip = "mcl_armor_unequip_iron",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
minetest.register_tool("mcl_armor:boots_gold", {
description = S("Golden Boots"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_boots_gold.png",
groups = {armor_feet=1, mcl_armor_points=1, mcl_armor_uses=92, enchantability=25 },
_repair_material = "mcl_core:gold_ingot",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_iron",
_mcl_armor_unequip = "mcl_armor_unequip_iron",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
minetest.register_tool("mcl_armor:boots_diamond",{
description = S("Diamond Boots"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_boots_diamond.png",
groups = {armor_feet=1, mcl_armor_points=3, mcl_armor_uses=430, mcl_armor_toughness=2, enchantability=10 },
_repair_material = "mcl_core:diamond",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_diamond",
_mcl_armor_unequip = "mcl_armor_unequip_diamond",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
minetest.register_tool("mcl_armor:boots_chain", {
description = S("Chain Boots"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usage,
inventory_image = "mcl_armor_inv_boots_chain.png",
groups = {armor_feet=1, mcl_armor_points=1, mcl_armor_uses=196, enchantability=12 },
_repair_material = "mcl_core:iron_ingot",
sounds = {
_mcl_armor_equip = "mcl_armor_equip_chainmail",
_mcl_armor_unequip = "mcl_armor_unequip_chainmail",
},
on_place = armor.on_armor_use,
on_secondary_use = armor.on_armor_use,
})
-- Register Craft Recipies
local craft_ingreds = {
leather = { "mcl_mobitems:leather" },
iron = { "mcl_core:iron_ingot", "mcl_core:iron_nugget" },
gold = { "mcl_core:gold_ingot", "mcl_core:gold_nugget" },
diamond = { "mcl_core:diamond" },
chain = { nil, "mcl_core:iron_nugget"} ,
mcl_armor = {
longdesc = S("This is a piece of equippable armor which reduces the amount of damage you receive."),
usage = S("To equip it, put it on the corresponding armor slot in your inventory menu."),
elements = {
head = {
name = "helmet",
description = "Helmet",
durability = 0.6857,
index = 2,
craft = function(m)
return {
{ m, m, m},
{ m, "", m},
{"", "", ""},
}
end,
},
torso = {
name = "chestplate",
description = "Chestplate",
durability = 1.0,
index = 3,
craft = function(m)
return {
{ m, "", m},
{ m, m, m},
{ m, m, m},
}
end,
},
legs = {
name = "leggings",
description = "Leggings",
durability = 0.9375,
index = 4,
craft = function(m)
return {
{ m, m, m},
{ m, "", m},
{ m, "", m},
}
end,
},
feet = {
name = "boots",
description = "Boots",
durability = 0.8125,
index = 5,
craft = function(m)
return {
{ m, "", m},
{ m, "", m},
}
end,
}
}
}
for k, v in pairs(craft_ingreds) do
-- material
local m = v[1]
-- cooking result
local c = v[2]
if m ~= nil then
minetest.register_craft({
output = "mcl_armor:helmet_"..k,
recipe = {
{m, m, m},
{m, "", m},
{"", "", ""},
},
})
minetest.register_craft({
output = "mcl_armor:chestplate_"..k,
recipe = {
{m, "", m},
{m, m, m},
{m, m, m},
},
})
minetest.register_craft({
output = "mcl_armor:leggings_"..k,
recipe = {
{m, m, m},
{m, "", m},
{m, "", m},
},
})
minetest.register_craft({
output = "mcl_armor:boots_"..k,
recipe = {
{m, "", m},
{m, "", m},
},
})
end
if c ~= nil then
minetest.register_craft({
type = "cooking",
output = c,
recipe = "mcl_armor:helmet_"..k,
cooktime = 10,
})
minetest.register_craft({
type = "cooking",
output = c,
recipe = "mcl_armor:chestplate_"..k,
cooktime = 10,
})
minetest.register_craft({
type = "cooking",
output = c,
recipe = "mcl_armor:leggings_"..k,
cooktime = 10,
})
minetest.register_craft({
type = "cooking",
output = c,
recipe = "mcl_armor:boots_"..k,
cooktime = 10,
})
end
end
local modpath = minetest.get_modpath("mcl_armor")
dofile(modpath .. "/api.lua")
dofile(modpath .. "/player.lua")
dofile(modpath .. "/damage.lua")
dofile(modpath .. "/register.lua")
dofile(modpath .. "/alias.lua")

View File

@ -0,0 +1,145 @@
mcl_player.player_register_model("mcl_armor_character.b3d", {
animation_speed = 30,
textures = {
"character.png",
"blank.png",
"blank.png",
},
animations = {
stand = {x=0, y=79},
lay = {x=162, y=166},
walk = {x=168, y=187},
mine = {x=189, y=198},
walk_mine = {x=200, y=219},
sit = {x=81, y=160},
sneak_stand = {x=222, y=302},
sneak_mine = {x=346, y=365},
sneak_walk = {x=304, y=323},
sneak_walk_mine = {x=325, y=344},
swim_walk = {x=368, y=387},
swim_walk_mine = {x=389, y=408},
swim_stand = {x=434, y=434},
swim_mine = {x=411, y=430},
run_walk = {x=440, y=459},
run_walk_mine = {x=461, y=480},
sit_mount = {x=484, y=484},
die = {x=498, y=498},
fly = {x=502, y=581},
},
})
mcl_player.player_register_model("mcl_armor_character_female.b3d", {
animation_speed = 30,
textures = {
"character.png",
"blank.png",
"blank.png",
},
animations = {
stand = {x=0, y=79},
lay = {x=162, y=166},
walk = {x=168, y=187},
mine = {x=189, y=198},
walk_mine = {x=200, y=219},
sit = {x=81, y=160},
sneak_stand = {x=222, y=302},
sneak_mine = {x=346, y=365},
sneak_walk = {x=304, y=323},
sneak_walk_mine = {x=325, y=344},
swim_walk = {x=368, y=387},
swim_walk_mine = {x=389, y=408},
swim_stand = {x=434, y=434},
swim_mine = {x=411, y=430},
run_walk = {x=440, y=459},
run_walk_mine = {x=461, y=480},
sit_mount = {x=484, y=484},
die = {x=498, y=498},
fly = {x=502, y=581},
},
})
function mcl_armor.update_player(player, info)
mcl_player.player_set_armor(player, info.texture, info.preview)
player:get_meta():set_int("mcl_armor:armor_point", info.points)
end
local function is_armor_action(inventory_info)
return inventory_info.from_list == "armor" or inventory_info.to_list == "armor" or inventory_info.listname == "armor"
end
local function limit_put(player, inventory, index, stack, count)
local def = stack:get_definition()
if not def then
return 0
end
local element = def._mcl_armor_element
if not element then
return 0
end
if mcl_armor.elements[element].index ~= index then
return 0
end
local old_stack = inventory:get_stack("armor", index)
if old_stack:is_empty() or old_stack:get_name() ~= stack:get_name() and count <= 1 then
return count
else
return 0
end
end
local function limit_take(player, inventory, index, stack, count)
if mcl_enchanting.has_enchantment(stack, "curse_of_binding") and not minetest.is_creative_enabled(player:get_player_name()) then
return 0
end
return count
end
minetest.register_allow_player_inventory_action(function(player, action, inventory, inventory_info)
if not is_armor_action(inventory_info) then
return
end
if action == "put" then
return limit_put(player, inventory, inventory_info.index, inventory_info.stack, inventory_info.stack:get_count())
elseif action == "take" then
return limit_take(player, inventory, inventory_info.index, inventory_info.stack, inventory_info.stack:get_count())
else
if inventory_info.from_list ~= "armor" then
return limit_put(player, inventory, inventory_info.to_index, inventory:get_stack(inventory_info.from_list, inventory_info.from_index), inventory_info.count)
elseif inventory_info.to_list ~= "armor" then
return limit_take(player, inventory, inventory_info.from_index, inventory:get_stack(inventory_info.from_list, inventory_info.from_index), inventory_info.count)
else
return 0
end
end
end)
-- ToDo: Call unequip callbacks & play uneqip sound
minetest.register_on_player_inventory_action(function(player, action, inventory, inventory_info)
if is_armor_action(inventory_info) then
mcl_armor.update(player)
end
end)
minetest.register_on_joinplayer(function(player)
mcl_player.player_set_model(player, "mcl_armor_character.b3d")
player:get_inventory():set_size("armor", 5)
minetest.after(1, function()
if player:is_player() then
mcl_armor.update(player)
end
end)
end)
mcl_damage.register_modifier(function(player, hp_change, _, reason)
return mcl_armor.damage_modifier(player, hp_change, reason)
end)

View File

@ -0,0 +1,204 @@
local S = minetest.get_translator("mcl_armor")
mcl_armor.register_set({
name = "leather",
description = "Leather",
descriptions = {
head = "Cap",
torso = "Tunic",
legs = "Pants",
},
durability = 80,
enchantability = 15,
points = {
head = 1,
torso = 3,
legs = 2,
feet = 1,
},
craft_material = "mcl_mobitems:leather",
})
mcl_armor.register_set({
name = "gold",
description = "Golden",
durability = 112,
enchantability = 25,
points = {
head = 2,
torso = 5,
legs = 3,
feet = 1,
},
craft_material = "mcl_core:gold_ingot",
cook_material = "mcl_core:gold_nugget",
sound_equip = "mcl_armor_equip_iron",
sound_unequip = "mcl_armor_unequip_iron",
})
mcl_armor.register_set({
name = "chain",
description = "Chain",
durability = 240,
enchantability = 12,
points = {
head = 2,
torso = 5,
legs = 4,
feet = 1,
},
repair_material = "mcl_core:iron_ingot",
cook_material = "mcl_core:iron_nugget",
})
mcl_armor.register_set({
name = "iron",
description = "Iron",
durability = 240,
enchantability = 9,
points = {
head = 2,
torso = 6,
legs = 5,
feet = 2,
},
craft_material = "mcl_core:iron_ingot",
cook_material = "mcl_core:iron_nugget",
})
mcl_armor.register_set({
name = "diamond",
description = "Diamond",
durability = 528,
enchantability = 10,
points = {
head = 3,
torso = 8,
legs = 6,
feet = 3,
},
toughness = 2,
craft_material = "mcl_core:diamond",
})
mcl_armor.register_protection_enchantment({
id = "projectile_protection",
name = S("Projectile Protection"),
description = S("Reduces projectile damage."),
power_range_table = {{1, 16}, {11, 26}, {21, 36}, {31, 46}, {41, 56}},
incompatible = {blast_protection = true, fire_protection = true, protection = true},
factor = 2,
damage_flag = "is_projectile",
})
mcl_armor.register_protection_enchantment({
id = "blast_protection",
name = S("Blast Protection"),
description = S("Reduces explosion damage and knockback."),
power_range_table = {{5, 13}, {13, 21}, {21, 29}, {29, 37}},
weight = 2,
incompatible = {fire_protection = true, protection = true, projectile_protection = true},
factor = 2,
damage_flag = "is_explosion",
})
mcl_armor.register_protection_enchantment({
id = "fire_protection",
name = S("Fire Protection"),
description = S("Reduces fire damage."),
power_range_table = {{5, 13}, {13, 21}, {21, 29}, {29, 37}},
incompatible = {blast_protection = true, protection = true, projectile_protection = true},
factor = 2,
damage_flag = "is_fire",
})
mcl_armor.register_protection_enchantment({
id = "protection",
name = S("Protection"),
description = S("Reduces most types of damage by 4% for each level."),
power_range_table = {{1, 12}, {12, 23}, {23, 34}, {34, 45}},
incompatible = {blast_protection = true, fire_protection = true, projectile_protection = true},
factor = 1,
})
mcl_armor.register_protection_enchantment({
id = "feather_falling",
name = S("Feather Falling"),
description = S("Reduces fall damage."),
power_range_table = {{5, 11}, {11, 17}, {17, 23}, {23, 29}},
factor = 3,
primary = {combat_armor_feet = true},
damage_type = "fall",
})
-- requires engine change
--[[mcl_enchanting.enchantments.aqua_affinity = {
name = S("Aqua Affinity"),
max_level = 1,
primary = {armor_head = true},
secondary = {},
disallow = {non_combat_armor = true},
incompatible = {},
weight = 2,
description = S("Increases underwater mining speed."),
curse = false,
on_enchant = function() end,
requires_tool = false,
treasure = false,
power_range_table = {{1, 41}},
inv_combat_tab = true,
inv_tool_tab = false,
}]]--
mcl_enchanting.enchantments.curse_of_binding = {
name = S("Curse of Binding"),
max_level = 1,
primary = {},
secondary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true},
disallow = {},
incompatible = {},
weight = 1,
description = S("Item cannot be removed from armor slots except due to death, breaking or in Creative Mode."),
curse = true,
on_enchant = function() end,
requires_tool = false,
treasure = true,
power_range_table = {{25, 50}},
inv_combat_tab = true,
inv_tool_tab = false,
}
mcl_enchanting.enchantments.thorns = {
name = S("Thorns"),
max_level = 3,
primary = {combat_armor_chestplate = true},
secondary = {combat_armor = true},
disallow = {},
incompatible = {},
weight = 1,
description = S("Reflects some of the damage taken when hit, at the cost of reducing durability with each proc."),
curse = false,
on_enchant = function() end,
requires_tool = false,
treasure = false,
power_range_table = {{10, 61}, {30, 71}, {50, 81}},
inv_combat_tab = true,
inv_tool_tab = false,
}
-- Elytra
minetest.register_tool("mcl_armor:elytra", {
description = S("Elytra"),
_doc_items_longdesc = mcl_armor.longdesc,
_doc_items_usagehelp = mcl_armor.usage,
inventory_image = "mcl_armor_inv_elytra.png",
groups = {armor = 1, non_combat_armor = 1, armor_torso = 1, non_combat_torso = 1, mcl_armor_uses = 10},
sounds = {
_mcl_armor_equip = "mcl_armor_equip_leather",
_mcl_armor_unequip = "mcl_armor_unequip_leather",
},
on_place = mcl_armor.equip_on_use,
on_secondary_use = mcl_armor.equip_on_use,
_mcl_armor_element = "torso",
})

View File

@ -150,7 +150,7 @@ minetest.register_node("mcl_armor_stand:armor_stand", {
single_item:set_count(1)
if inv:is_empty(list) then
inv:add_item(list, single_item)
armor:play_equip_sound(single_item, nil, pos)
mcl_armor.play_equip_sound(single_item, nil, pos)
update_entity(pos)
itemstack:take_item()
return itemstack
@ -175,7 +175,7 @@ minetest.register_node("mcl_armor_stand:armor_stand", {
taken = true
end
if taken then
armor:play_equip_sound(stand_armor, nil, pos, true)
mcl_armor.play_equip_sound(stand_armor, nil, pos, true)
stand_armor:take_item()
inv:set_stack("armor_" .. elements[e], 1, stand_armor)
end

View File

@ -69,6 +69,7 @@ local ARROW_ENTITY={
_stuckrechecktimer=nil,-- An additional timer for periodically re-checking the stuck status of an arrow
_stuckin=nil, --Position of node in which arow is stuck.
_shooter=nil, -- ObjectRef of player or mob who shot it
_is_arrow = true,
_viscosity=0, -- Viscosity of node the arrow is currently in
_deflection_cooloff=0, -- Cooloff timer after an arrow deflection, to prevent many deflections in quick succession
@ -254,9 +255,6 @@ ARROW_ENTITY.on_step = function(self, dtime)
-- Punch target object but avoid hurting enderman.
if not lua or lua.name ~= "mobs_mc:enderman" then
if obj:is_player() and rawget(_G, "armor") and armor.last_damage_types then
armor.last_damage_types[obj:get_player_name()] = "projectile"
end
if self._in_player == false then
damage_particles(self.object:get_pos(), self._is_critical)
end

View File

@ -59,6 +59,7 @@ mcl_bows.shoot_arrow = function(arrow_item, pos, dir, yaw, shooter, power, damag
obj:set_yaw(yaw-math.pi/2)
local le = obj:get_luaentity()
le._shooter = shooter
le._source_object = shooter
le._damage = damage
le._is_critical = is_critical
le._startpos = pos

View File

@ -203,7 +203,7 @@ S("• When lava is directly above water, the water turns into stone."),
_mcl_node_death_message = lava_death_messages,
post_effect_color = {a=245, r=208, g=73, b=10},
stack_max = 64,
groups = { lava=3, lava_source=1, liquid=2, destroys_items=1, not_in_creative_inventory=1, dig_by_piston=1, set_on_fire=15},
groups = { lava=3, lava_source=1, liquid=2, destroys_items=1, not_in_creative_inventory=1, dig_by_piston=1, set_on_fire=15, fire_damage=1},
_mcl_blast_resistance = 100,
-- Hardness intentionally set to infinite instead of 100 (Minecraft value) to avoid problems in creative mode
_mcl_hardness = -1,

View File

@ -10,25 +10,6 @@ local function increase_damage(damage_group, factor)
end
end
-- requires engine change
--[[mcl_enchanting.enchantments.aqua_affinity = {
name = S("Aqua Affinity"),
max_level = 1,
primary = {armor_head = true},
secondary = {},
disallow = {non_combat_armor = true},
incompatible = {},
weight = 2,
description = S("Increases underwater mining speed."),
curse = false,
on_enchant = function() end,
requires_tool = false,
treasure = false,
power_range_table = {{1, 41}},
inv_combat_tab = true,
inv_tool_tab = false,
}]]--
-- implemented via on_enchant and additions in mobs_mc; Slowness IV part unimplemented
mcl_enchanting.enchantments.bane_of_arthropods = {
name = S("Bane of Arthropods"),
@ -48,25 +29,6 @@ mcl_enchanting.enchantments.bane_of_arthropods = {
inv_tool_tab = false,
}
-- implemented in mcl_armor
mcl_enchanting.enchantments.blast_protection = {
name = S("Blast Protection"),
max_level = 4,
primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true},
secondary = {},
disallow = {non_combat_armor = true},
incompatible = {fire_protection = true, protection = true, projectile_protection = true},
weight = 2,
description = S("Reduces explosion damage and knockback."),
curse = false,
on_enchant = function() end,
requires_tool = false,
treasure = false,
power_range_table = {{5, 13}, {13, 21}, {21, 29}, {29, 37}},
inv_combat_tab = true,
inv_tool_tab = false,
}
-- requires missing MineClone2 feature
--[[mcl_enchanting.enchantments.channeling = {
name = S("Channeling"),
@ -86,25 +48,6 @@ mcl_enchanting.enchantments.blast_protection = {
inv_tool_tab = false,
}]]--
-- implemented in mcl_armor
mcl_enchanting.enchantments.curse_of_binding = {
name = S("Curse of Binding"),
max_level = 1,
primary = {},
secondary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true},
disallow = {},
incompatible = {},
weight = 1,
description = S("Item cannot be removed from armor slots except due to death, breaking or in Creative Mode."),
curse = true,
on_enchant = function() end,
requires_tool = false,
treasure = true,
power_range_table = {{25, 50}},
inv_combat_tab = true,
inv_tool_tab = false,
}
-- implemented in mcl_death_drop
mcl_enchanting.enchantments.curse_of_vanishing = {
name = S("Curse of Vanishing"),
@ -164,24 +107,6 @@ mcl_enchanting.enchantments.efficiency = {
inv_tool_tab = true,
}
-- implemented in mcl_armor
mcl_enchanting.enchantments.feather_falling = {
name = S("Feather Falling"),
max_level = 4,
primary = {armor_feet = true},
secondary = {},
disallow = {non_combat_armor = true},
incompatible = {},
weight = 5,
description = S("Reduces fall damage."),curse = false,
on_enchant = function() end,
requires_tool = false,
treasure = false,
power_range_table = {{5, 11}, {11, 17}, {17, 23}, {23, 29}},
inv_combat_tab = true,
inv_tool_tab = false,
}
-- implemented in mcl_mobs and via register_on_punchplayer callback
mcl_enchanting.enchantments.fire_aspect = {
name = S("Fire Aspect"),
@ -213,25 +138,6 @@ minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch,
end
end)
-- implemented in mcl_armor
mcl_enchanting.enchantments.fire_protection = {
name = S("Fire Protection"),
max_level = 4,
primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true},
secondary = {},
disallow = {non_combat_armor = true},
incompatible = {blast_protection = true, protection = true, projectile_protection = true},
weight = 5,
description = S("Reduces fire damage."),
curse = false,
on_enchant = function() end,
requires_tool = false,
treasure = false,
power_range_table = {{10, 18}, {18, 26}, {26, 34}, {34, 42}},
inv_combat_tab = true,
inv_tool_tab = false,
}
mcl_enchanting.enchantments.flame = {
name = S("Flame"),
max_level = 1,
@ -530,44 +436,6 @@ mcl_enchanting.enchantments.power = {
inv_tool_tab = false,
}
-- implemented in mcl_armor
mcl_enchanting.enchantments.projectile_protection = {
name = S("Projectile Protection"),
max_level = 4,
primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true},
secondary = {},
disallow = {non_combat_armor = true},
incompatible = {blast_protection = true, fire_protection = true, protection = true},
weight = 5,
description = S("Reduces projectile damage."),
curse = false,
on_enchant = function() end,
requires_tool = false,
treasure = false,
power_range_table = {{1, 16}, {11, 26}, {21, 36}, {31, 46}, {41, 56}},
inv_combat_tab = true,
inv_tool_tab = false,
}
-- implemented in mcl_armor
mcl_enchanting.enchantments.protection = {
name = S("Protection"),
max_level = 4,
primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true},
secondary = {},
disallow = {non_combat_armor = true},
incompatible = {blast_protection = true, fire_protection = true, projectile_protection = true},
weight = 10,
description = S("Reduces most types of damage by 4% for each level."),
curse = false,
on_enchant = function() end,
requires_tool = false,
treasure = false,
power_range_table = {{1, 12}, {12, 23}, {23, 34}, {34, 45}},
inv_combat_tab = true,
inv_tool_tab = false,
}
-- implemented via minetest.calculate_knockback (together with the Knockback enchantment) and mcl_bows
mcl_enchanting.enchantments.punch = {
name = S("Punch"),
@ -739,25 +607,6 @@ mcl_enchanting.enchantments.soul_speed = {
inv_tool_tab = false,
}]]--
-- implemented in mcl_armor
mcl_enchanting.enchantments.thorns = {
name = S("Thorns"),
max_level = 3,
primary = {armor_head = true},
secondary = {armor_torso = true, armor_legs = true, armor_feet = true},
disallow = {non_combat_armor = true},
incompatible = {},
weight = 1,
description = S("Reflects some of the damage taken when hit, at the cost of reducing durability with each proc."),
curse = false,
on_enchant = function() end,
requires_tool = false,
treasure = false,
power_range_table = {{10, 61}, {30, 71}, {50, 81}},
inv_combat_tab = true,
inv_tool_tab = false,
}
-- for tools & weapons implemented via on_enchant; for bows implemented in mcl_bows; for armor implemented in mcl_armor and mcl_tt; for fishing rods implemented in mcl_fishing
mcl_enchanting.enchantments.unbreaking = {
name = S("Unbreaking"),

View File

@ -266,7 +266,8 @@ function mcl_enchanting.initialize()
new_def.groups.not_in_creative_inventory = 1
new_def.groups.not_in_craft_guide = 1
new_def.groups.enchanted = 1
new_def.texture = itemdef.texture or itemname:gsub("%:", "_")
new_def._mcl_armor_texture = new_def._mcl_armor_texture and new_def._mcl_armor_texture .. mcl_enchanting.overlay
new_def._mcl_armor_preview = new_def._mcl_armor_preview and new_def._mcl_armor_preview .. mcl_enchanting.overlay
new_def._mcl_enchanting_enchanted_tool = new_name
new_def.after_use = get_after_use_callback(itemdef)
local register_list = register_item_list

View File

@ -111,12 +111,16 @@ pumpkin_face_base_def.description = S("Pumpkin")
pumpkin_face_base_def._doc_items_longdesc = S("A pumpkin can be worn as a helmet. Pumpkins grow from pumpkin stems, which in turn grow from pumpkin seeds.")
pumpkin_face_base_def._doc_items_usagehelp = nil
pumpkin_face_base_def.tiles = {"farming_pumpkin_top.png", "farming_pumpkin_top.png", "farming_pumpkin_side.png", "farming_pumpkin_side.png", "farming_pumpkin_side.png", "farming_pumpkin_face.png"}
pumpkin_face_base_def.groups.armor=1
pumpkin_face_base_def.groups.non_combat_armor=1
pumpkin_face_base_def.groups.armor_head=1
pumpkin_face_base_def.groups.non_combat_armor_head=1
pumpkin_face_base_def._mcl_armor_mob_range_factor = 0
pumpkin_face_base_def._mcl_armor_mob_range_mob = "mobs_mc:enderman"
pumpkin_face_base_def._mcl_armor_entry = "head"
pumpkin_face_base_def.groups.non_combat_armor=1
if minetest.get_modpath("mcl_armor") then
pumpkin_face_base_def.on_secondary_use = armor.on_armor_use
pumpkin_face_base_def.on_secondary_use = mcl_armor.equip_on_use
end
-- Register stem growth

View File

@ -5,7 +5,7 @@ local mod_screwdriver = minetest.get_modpath("screwdriver")
local equip_armor
if minetest.get_modpath("mcl_armor") then
equip_armor = armor.on_armor_use
equip_armor = mcl_armor.equip_on_use
end
-- Heads system

View File

@ -114,7 +114,7 @@ minetest.register_node("mcl_nether:magma", {
if mod_death_messages then
mcl_death_messages.player_damage(player, S("@1 stood too long on a magma block.", player:get_player_name()))
end
player:set_hp(player:get_hp() - 1, { type = "punch", from = "mod" })
mcl_util.deal_damage(player, 1, {type = "hot_floor"})
end
end,
_mcl_blast_resistance = 0.5,

View File

@ -603,21 +603,18 @@ function mcl_potions.make_invisible(player, toggle)
return
end
if minetest.get_modpath("mcl_armor") and player:is_player() then
armor.textures[playername].skin = skin_file
armor:update_player_visuals(player)
elseif not player:is_player() and minetest.get_modpath("mcl_armor") or not player:is_player() and not minetest.get_modpath("mcl_armor") then
if player:is_player() then
mcl_player.player_set_skin(player, "mobs_mc_empty.png")
elseif not player:is_player() then
player:set_properties({visual_size = {x = 0, y = 0}})
end
player:set_nametag_attributes({color = {a = 0}})
elseif EF.invisible[player] then -- show player
if minetest.get_modpath("mcl_armor") and player:is_player() then
skin_file = mcl_skins.skins[playername] .. ".png"
armor.textures[playername].skin = skin_file
armor:update_player_visuals(player)
elseif not player:is_player() and minetest.get_modpath("mcl_armor") or not player:is_player() and not minetest.get_modpath("mcl_armor") then
if player:is_player() then
mcl_skins.update_player_skin(player)
elseif not player:is_player() then
player:set_properties({visual_size = EF.invisible[player].old_size})
end
player:set_nametag_attributes({color = {r = 255, g = 255, b = 255, a = 255}})

View File

@ -257,7 +257,7 @@ minetest.register_lbm({
nodenames = {"group:torch_particles"},
run_at_every_load = true,
action = function(pos, node)
local torch_group = minetest.get_node_group(node.name, "torch")
local torch_group = minetest.get_item_group(node.name, "torch")
if torch_group == 1 then
spawn_flames_floor(pos)
elseif torch_group == 2 then

View File

@ -157,7 +157,7 @@ screwdriver.handler = function(itemstack, user, pointed_thing, mode, uses)
if should_rotate and new_param2 ~= node.param2 then
node.param2 = new_param2
minetest.swap_node(pos, node)
minetest.check_for_falling(pos)
if ndef.after_rotate then
ndef.after_rotate(vector.new(pos))

View File

@ -11,7 +11,6 @@ end
mcl_death_drop.register_dropped_list("PLAYER", "main", true)
mcl_death_drop.register_dropped_list("PLAYER", "craft", true)
mcl_death_drop.register_dropped_list("PLAYER", "armor", true)
mcl_death_drop.register_dropped_list(function(player) return select(3, armor:get_valid_player(player)) end , "armor", false)
minetest.register_on_dieplayer(function(player)
local keep = minetest.settings:get_bool("mcl_keepInventory", false)
@ -50,7 +49,6 @@ minetest.register_on_dieplayer(function(player)
inv:set_list(listname, {})
end
end
armor:set_player_armor(player)
armor:update_inventory(player)
mcl_armor.update(player)
end
end)

View File

@ -164,7 +164,7 @@ minetest.register_globalstep(function(dtime)
if mod_death_messages then
mcl_death_messages.player_damage(player, S("@1 starved to death.", name))
end
player:set_hp(hp-1)
mcl_util.deal_damage(player, 1, {type = "starve"})
end
end
end

View File

@ -88,22 +88,41 @@ function mcl_player.player_set_model(player, model_name)
player_model[name] = model_name
end
function mcl_player.player_set_textures(player, textures, preview)
local name = player:get_player_name()
player_textures[name] = textures
player:set_properties({textures = textures,})
if preview then
player:get_meta():set_string("mcl_player:preview", preview)
end
local function set_texture(player, index, texture)
local textures = player_textures[player:get_player_name()]
textures[index] = texture
player:set_properties({textures = textures})
end
local function set_preview(player, field, preview)
player:get_meta():set_string("mcl_player:" .. field .. "_preview", preview)
end
function mcl_player.player_set_skin(player, texture, preview)
set_texture(player, 1, texture)
set_preview(player, "skin", preview)
end
function mcl_player.player_set_armor(player, texture, preview)
set_texture(player, 2, texture)
set_preview(player, "armor", preview)
end
function mcl_player.player_set_wielditem(player, texture)
set_texture(player, 3, texture)
end
function mcl_player.player_get_preview(player)
local preview = player:get_meta():get_string("mcl_player:preview")
if preview == nil or preview == "" then
return "player.png"
else
return preview
local preview = player:get_meta():get_string("mcl_player:skin_preview")
if preview == "" then
preview = "player.png"
end
local armor_preview = player:get_meta():set_string("mcl_player:armor_preview")
if armor_preview ~= "" then
preview = preview .. "^" .. armor_preview
end
return preview
end
function mcl_player.get_player_formspec_model(player, x, y, w, h, fsname)
@ -129,8 +148,10 @@ end
-- Update appearance when the player joins
minetest.register_on_joinplayer(function(player)
mcl_player.player_attached[player:get_player_name()] = false
local name = player:get_player_name()
mcl_player.player_attached[name] = false
mcl_player.player_set_model(player, "character.b3d")
player_textures[name] = {"blank.png", "blank.png", "blank.png"}
--player:set_local_animation({x=0, y=79}, {x=168, y=187}, {x=189, y=198}, {x=200, y=219}, 30)
player:set_fov(86.1) -- see <https://minecraft.gamepedia.com/Options#Video_settings>>>>
end)

View File

@ -183,6 +183,8 @@ minetest.register_globalstep(function(dtime)
local wielded = player:get_wielded_item()
local player_velocity = player:get_velocity() or player:get_player_velocity()
local wielded_def = wielded:get_definition()
-- control head bone
local pitch = - degrees(player:get_look_vertical())
local yaw = degrees(player:get_look_horizontal())
@ -197,7 +199,7 @@ minetest.register_globalstep(function(dtime)
if minetest.get_node_or_nil({x=player:get_pos().x, y=player:get_pos().y - 0.5, z=player:get_pos().z}) then
node_stand_return = minetest.get_node_or_nil({x=player:get_pos().x, y=player:get_pos().y - 0.1, z=player:get_pos().z}).name
else
minetest.log("action", "somehow player got of loaded areas")
-- minetest.log("action", "somehow player got of loaded areas")
end
local chestplate = player:get_inventory():get_stack("armor", 3)
@ -253,6 +255,14 @@ minetest.register_globalstep(function(dtime)
playerphysics.remove_physics_factor(player, "gravity", "mcl_playerplus:elytra")
end
if wielded_def and wielded_def._mcl_toollike_wield then
player:set_bone_position("Wield_Item", vector.new(0,3.9,1.3), vector.new(90,0,0))
elseif string.find(wielded:get_name(), "mcl_bows:bow") then
player:set_bone_position("Wield_Item", vector.new(.5,4.5,-1.6), vector.new(90,0,20))
else
player:set_bone_position("Wield_Item", vector.new(-1.5,4.9,1.8), vector.new(135,0,90))
end
-- controls right and left arms pitch when shooting a bow
if string.find(wielded:get_name(), "mcl_bows:bow") and control.RMB and not control.LMB and not control.up and not control.down and not control.left and not control.right then
player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(pitch+90,-30,pitch * -1 * .35))
@ -430,7 +440,7 @@ minetest.register_globalstep(function(dtime)
and (not check_player_privs(name, {noclip = true})) then
if player:get_hp() > 0 then
mcl_death_messages.player_damage(player, S("@1 suffocated to death.", name))
player:set_hp(player:get_hp() - 1)
mcl_util.deal_damage(player, 1, {type = "in_wall"})
end
end
@ -446,7 +456,7 @@ minetest.register_globalstep(function(dtime)
if dist < 1.1 or dist_feet < 1.1 then
if player:get_hp() > 0 then
mcl_death_messages.player_damage(player, S("@1 was prickled to death by a cactus.", name))
player:set_hp(player:get_hp() - 1, { type = "punch", from = "mod" })
mcl_util.deal_damage(player, 1, {type = "cactus"})
end
end
end

View File

@ -7,7 +7,6 @@ mcl_skins = {
}
local S = minetest.get_translator("mcl_skins")
local has_mcl_armor = minetest.get_modpath("mcl_armor")
local has_mcl_inventory = minetest.get_modpath("mcl_inventory")
-- load skin list and metadata
@ -115,10 +114,6 @@ mcl_skins.set_player_skin = function(player, skin_id)
mcl_skins.previews[playername] = preview
player:get_meta():set_string("mcl_skins:skin_id", tostring(skin_id))
mcl_skins.update_player_skin(player)
if has_mcl_armor then
armor.textures[playername].skin = skin_file
armor:update_player_visuals(player)
end
if has_mcl_inventory then
mcl_inventory.update_inventory_formspec(player)
end
@ -134,7 +129,7 @@ mcl_skins.update_player_skin = function(player)
return
end
local playername = player:get_player_name()
mcl_player.player_set_textures(player, { mcl_skins.skins[playername] .. ".png" }, mcl_skins.previews[playername] .. ".png" )
mcl_player.player_set_skin(player, mcl_skins.skins[playername] .. ".png", mcl_skins.previews[playername] .. ".png")
end
-- load player skin on join

View File

@ -2,4 +2,4 @@ name = mcl_skins
author = TenPlus1
description = Mod that allows players to set their individual skins.
depends = mcl_player
optional_depends = mcl_inventory, intllib, mcl_armor
optional_depends = mcl_inventory, intllib

View File

@ -0,0 +1,122 @@
mcl_wieldview = {
players = {}
}
function mcl_wieldview.get_item_texture(itemname)
if itemname == "" then
return
end
local def = minetest.registered_items[itemname]
if not def then
return
end
local inv_image = def.inventory_image
if inv_image == "" then
return
end
local texture = inv_image
local transform = minetest.get_item_group(itemname, "wieldview_transform")
if transform then
-- This actually works with groups ratings because transform1, transform2, etc.
-- have meaning and transform0 is used for identidy, so it can be ignored
texture = texture .. "^[transform" .. transform
end
return texture
end
function mcl_wieldview.update_wielded_item(player)
if not player then
return
end
local name = player:get_player_name()
local itemstack = player:get_wielded_item()
local itemname = itemstack:get_name()
local def = mcl_wieldview.players[name]
if def.item == itemname then
return
end
def.item = itemname
def.texture = mcl_wieldview.get_item_texture(itemname) or "blank.png"
mcl_player.player_set_wielditem(player, def.texture)
end
minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
mcl_wieldview.players[name] = {item = "", texture = "blank.png"}
minetest.after(0, function()
if not player:is_player() then
return
end
mcl_wieldview.update_wielded_item(player)
local itementity = minetest.add_entity(player:get_pos(), "mcl_wieldview:wieldnode")
itementity:set_attach(player, "Hand_Right", vector.new(0, 1, 0), vector.new(90, 0, 45))
itementity:get_luaentity().wielder = name
end)
end)
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
mcl_wieldview.players[name] = nil
end)
minetest.register_globalstep(function()
for _, player in pairs(minetest.get_connected_players()) do
mcl_wieldview.update_wielded_item(player)
end
end)
minetest.register_entity("mcl_wieldview:wieldnode", {
initial_properties = {
hp_max = 1,
visual = "wielditem",
physical = false,
textures = {""},
automatic_rotate = 1.5,
is_visible = true,
pointable = false,
collide_with_objects = false,
static_save = false,
collisionbox = {-0.21, -0.21, -0.21, 0.21, 0.21, 0.21},
selectionbox = {-0.21, -0.21, -0.21, 0.21, 0.21, 0.21},
visual_size = {x = 0.21, y = 0.21},
},
itemstring = "",
on_step = function(self)
local player = minetest.get_player_by_name(self.wielder)
if player then
local wielded = player:get_wielded_item()
local itemstring = wielded:get_name()
if self.itemstring ~= itemstring then
local def = minetest.registered_items[itemstring]
self.object:set_properties({glow = def and def.light_source or 0})
-- wield item as cubic
if mcl_wieldview.players[self.wielder].texture == "blank.png" then
self.object:set_properties({textures = {itemstring}})
-- wield item as flat
else
self.object:set_properties({textures = {""}})
end
self.itemstring = itemstring
end
else
self.object:remove()
end
end,
})

View File

@ -1,5 +1,4 @@
name = wieldview
name = mcl_wieldview
author = stujones11
description = Makes hand wielded items visible to other players.
depends = mcl_armor
depends = mcl_player

View File

@ -1,132 +0,0 @@
local time = 0
local update_time = tonumber(minetest.settings:get("wieldview_update_time"))
if not update_time then
update_time = 2
minetest.settings:set("wieldview_update_time", tostring(update_time))
end
local node_tiles = minetest.settings:get_bool("wieldview_node_tiles")
if not node_tiles then
node_tiles = false
minetest.settings:set("wieldview_node_tiles", "false")
end
wieldview = {
wielded_item = {},
transform = {},
}
dofile(minetest.get_modpath(minetest.get_current_modname()).."/transform.lua")
wieldview.get_item_texture = function(self, item)
local texture = "blank.png"
if item ~= "" then
if minetest.registered_items[item] then
if minetest.registered_items[item].inventory_image ~= "" then
texture = minetest.registered_items[item].inventory_image
elseif node_tiles == true and minetest.registered_items[item].tiles
and type(minetest.registered_items[item].tiles[1]) == "string"
and minetest.registered_items[item].tiles[1] ~= "" then
texture = minetest.inventorycube(minetest.registered_items[item].tiles[1])
end
end
-- Get item image transformation, first from group, then from transform.lua
local transform = minetest.get_item_group(item, "wieldview_transform")
if transform == 0 then
transform = wieldview.transform[item]
end
if transform then
-- This actually works with groups ratings because transform1, transform2, etc.
-- have meaning and transform0 is used for identidy, so it can be ignored
texture = texture.."^[transform"..tostring(transform)
end
end
return texture
end
wieldview.update_wielded_item = function(self, player)
if not player then
return
end
local name = player:get_player_name()
local stack = player:get_wielded_item()
local item = stack:get_name()
if not item then
return
end
if self.wielded_item[name] then
if self.wielded_item[name] == item then
return
end
if not armor.textures[name] then
return
end
armor.textures[name].wielditem = self:get_item_texture(item)
armor:update_player_visuals(player)
end
self.wielded_item[name] = item
end
minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
wieldview.wielded_item[name] = ""
minetest.after(0, function(player)
-- if the player left :is_player() will return nil
if not player:is_player() then
return
end
wieldview:update_wielded_item(player)
local itementity = minetest.add_entity(player:get_pos(), "wieldview:wieldnode")
itementity:set_attach(player, "Hand_Right", vector.new(0, 1, 0), vector.new(90, 0, 45))
itementity:get_luaentity().wielder = name
end, player)
end)
minetest.register_globalstep(function()
for _,player in pairs(minetest.get_connected_players()) do
wieldview:update_wielded_item(player)
end
end)
minetest.register_entity("wieldview:wieldnode", {
initial_properties = {
hp_max = 1,
visual = "wielditem",
physical = false,
textures = {""},
automatic_rotate = 1.5,
is_visible = true,
pointable = false,
collide_with_objects = false,
static_save = false,
collisionbox = {-0.21, -0.21, -0.21, 0.21, 0.21, 0.21},
selectionbox = {-0.21, -0.21, -0.21, 0.21, 0.21, 0.21},
visual_size = {x = 0.21, y = 0.21},
},
itemstring = "",
on_step = function(self)
local player = minetest.get_player_by_name(self.wielder)
if player then
local wielded = player:get_wielded_item()
local itemstring = wielded:get_name()
if self.itemstring ~= itemstring then
local def = minetest.registered_items[itemstring]
self.object:set_properties({glow = def and def.light_source or 0})
-- wield item as cubic
if armor.textures[self.wielder].wielditem == "blank.png" then
self.object:set_properties({textures = {itemstring}})
-- wield item as flat
else
self.object:set_properties({textures = {""}})
end
self.itemstring = itemstring
end
else
self.object:remove()
end
end,
})

View File

@ -1,10 +0,0 @@
-- Wielded Item Transformations - http://dev.minetest.net/texture
wieldview.transform = {
["screwdriver:screwdriver"]="R90",
["screwdriver:screwdriver1"]="R90",
["screwdriver:screwdriver2"]="R90",
["screwdriver:screwdriver3"]="R90",
["screwdriver:screwdriver4"]="R90",
}