forked from VoxeLibre/VoxeLibre
Merge branch 'master' into mineclone5
This commit is contained in:
commit
6eadeb21c0
|
@ -0,0 +1,164 @@
|
||||||
|
mcl_damage = {
|
||||||
|
modifiers = {},
|
||||||
|
damage_callbacks = {},
|
||||||
|
death_callbacks = {},
|
||||||
|
types = {
|
||||||
|
in_fire = {is_fire = true},
|
||||||
|
lightning_bolt = {is_lightning = true},
|
||||||
|
on_fire = {is_fire = true, bypasses_armor = 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_magic = true, bypasses_invulnerability = true},
|
||||||
|
generic = {bypasses_armor = true},
|
||||||
|
magic = {is_magic = true, bypasses_armor = true},
|
||||||
|
dragon_breath = {is_magic = true, bypasses_armor = true}, -- this is only used for dragon fireball; dragon fireball does not actually deal impact damage tho, so this is unreachable
|
||||||
|
wither = {bypasses_armor = true}, -- unused
|
||||||
|
wither_skull = {is_magic = true, is_explosion = true}, -- this is non-MC but a workaround to get the proper death message
|
||||||
|
anvil = {},
|
||||||
|
falling_node = {}, -- this is falling_block in MC
|
||||||
|
mob = {},
|
||||||
|
player = {},
|
||||||
|
arrow = {is_projectile = true},
|
||||||
|
fireball = {is_projectile = true, is_fire = true},
|
||||||
|
thorns = {is_magic = true},
|
||||||
|
explosion = {is_explosion = true},
|
||||||
|
cramming = {bypasses_armor = true}, -- unused
|
||||||
|
fireworks = {is_explosion = true}, -- unused
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mcl_damage.register_modifier(func, priority)
|
||||||
|
table.insert(mcl_damage.modifiers, {func = func, priority = priority or 0})
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_damage.register_on_damage(func)
|
||||||
|
table.insert(mcl_damage.damage_callbacks, func)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_damage.register_on_death(func)
|
||||||
|
table.insert(mcl_damage.death_callbacks, func)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_damage.run_modifiers(obj, damage, reason)
|
||||||
|
for _, modf in ipairs(mcl_damage.modifiers) do
|
||||||
|
damage = modf.func(obj, damage, reason) or damage
|
||||||
|
if damage == 0 then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return damage
|
||||||
|
end
|
||||||
|
|
||||||
|
local function run_callbacks(funcs, ...)
|
||||||
|
for _, func in pairs(funcs) do
|
||||||
|
func(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_damage.run_damage_callbacks(obj, damage, reason)
|
||||||
|
run_callbacks(mcl_damage.damage_callbacks, obj, damage, reason)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_damage.run_death_callbacks(obj, reason)
|
||||||
|
run_callbacks(mcl_damage.death_callbacks, obj, reason)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_damage.from_punch(mcl_reason, object)
|
||||||
|
mcl_reason.direct = object
|
||||||
|
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
|
||||||
|
|
||||||
|
function mcl_damage.finish_reason(mcl_reason)
|
||||||
|
mcl_reason.source = mcl_reason.source or mcl_reason.direct
|
||||||
|
mcl_reason.flags = mcl_damage.types[mcl_reason.type]
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_damage.from_mt(mt_reason)
|
||||||
|
if mt_reason._mcl_chached_reason then
|
||||||
|
return mt_reason._mcl_chached_reason
|
||||||
|
end
|
||||||
|
|
||||||
|
local mcl_reason
|
||||||
|
|
||||||
|
if mt_reason._mcl_reason then
|
||||||
|
mcl_reason = mt_reason._mcl_reason
|
||||||
|
else
|
||||||
|
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_damage.from_punch(mcl_reason, mt_reason.object)
|
||||||
|
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
|
||||||
|
end
|
||||||
|
|
||||||
|
mcl_damage.finish_reason(mcl_reason)
|
||||||
|
mt_reason._mcl_cached_reason = mcl_reason
|
||||||
|
|
||||||
|
return mcl_reason
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_damage.register_type(name, def)
|
||||||
|
mcl_damage.types[name] = def
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_on_player_hpchange(function(player, hp_change, mt_reason)
|
||||||
|
if hp_change < 0 then
|
||||||
|
if player:get_hp() <= 0 then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
hp_change = -mcl_damage.run_modifiers(player, -hp_change, mcl_damage.from_mt(mt_reason))
|
||||||
|
end
|
||||||
|
return hp_change
|
||||||
|
end, true)
|
||||||
|
|
||||||
|
minetest.register_on_player_hpchange(function(player, hp_change, mt_reason)
|
||||||
|
if hp_change < 0 then
|
||||||
|
mcl_damage.run_damage_callbacks(player, -hp_change, mcl_damage.from_mt(mt_reason))
|
||||||
|
end
|
||||||
|
end, false)
|
||||||
|
|
||||||
|
minetest.register_on_dieplayer(function(player, mt_reason)
|
||||||
|
mcl_damage.run_death_callbacks(player, mcl_damage.from_mt(mt_reason))
|
||||||
|
end)
|
||||||
|
|
||||||
|
minetest.register_on_mods_loaded(function()
|
||||||
|
table.sort(mcl_damage.modifiers, function(a, b) return a.priority < b.priority end)
|
||||||
|
end)
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
name = mcl_damage
|
||||||
|
author = Fleckenstein
|
||||||
|
description = Minecraft-like damage reason system
|
|
@ -12,7 +12,6 @@ under the LGPLv2.1 license.
|
||||||
|
|
||||||
mcl_explosions = {}
|
mcl_explosions = {}
|
||||||
|
|
||||||
local mod_death_messages = minetest.get_modpath("mcl_death_messages") ~= nil
|
|
||||||
local mod_fire = minetest.get_modpath("mcl_fire") ~= nil
|
local mod_fire = minetest.get_modpath("mcl_fire") ~= nil
|
||||||
local CONTENT_FIRE = minetest.get_content_id("mcl_fire:fire")
|
local CONTENT_FIRE = minetest.get_content_id("mcl_fire:fire")
|
||||||
|
|
||||||
|
@ -150,7 +149,8 @@ end
|
||||||
-- raydirs - The directions for each ray
|
-- raydirs - The directions for each ray
|
||||||
-- radius - The maximum distance each ray will go
|
-- radius - The maximum distance each ray will go
|
||||||
-- info - Table containing information about explosion
|
-- 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:
|
-- Values in info:
|
||||||
-- drop_chance - The chance that destroyed nodes will drop their items
|
-- drop_chance - The chance that destroyed nodes will drop their items
|
||||||
|
@ -165,7 +165,7 @@ end
|
||||||
-- Note that this function has been optimized, it contains code which has been
|
-- Note that this function has been optimized, it contains code which has been
|
||||||
-- inlined to avoid function calls and unnecessary table creation. This was
|
-- inlined to avoid function calls and unnecessary table creation. This was
|
||||||
-- measured to give a significant performance increase.
|
-- 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 vm = get_voxel_manip()
|
||||||
|
|
||||||
local emin, emax = vm:read_from_map(vector.subtract(pos, radius),
|
local emin, emax = vm:read_from_map(vector.subtract(pos, radius),
|
||||||
|
@ -247,7 +247,7 @@ local function trace_explode(pos, strength, raydirs, radius, info, puncher)
|
||||||
local ent = obj:get_luaentity()
|
local ent = obj:get_luaentity()
|
||||||
|
|
||||||
-- Ignore items to lower lag
|
-- 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 opos = obj:get_pos()
|
||||||
local collisionbox = nil
|
local collisionbox = nil
|
||||||
|
|
||||||
|
@ -321,7 +321,6 @@ local function trace_explode(pos, strength, raydirs, radius, info, puncher)
|
||||||
impact = 0
|
impact = 0
|
||||||
end
|
end
|
||||||
local damage = math.floor((impact * impact + impact) * 7 * strength + 1)
|
local damage = math.floor((impact * impact + impact) * 7 * strength + 1)
|
||||||
local source = puncher or obj
|
|
||||||
|
|
||||||
local sleep_formspec_doesnt_close_mt53 = false
|
local sleep_formspec_doesnt_close_mt53 = false
|
||||||
if obj:is_player() then
|
if obj:is_player() then
|
||||||
|
@ -333,26 +332,22 @@ local function trace_explode(pos, strength, raydirs, radius, info, puncher)
|
||||||
sleep_formspec_doesnt_close_mt53 = true
|
sleep_formspec_doesnt_close_mt53 = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
||||||
if sleep_formspec_doesnt_close_mt53 then
|
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
|
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 then return end
|
if not obj:is_player() then
|
||||||
obj:punch(obj, 10, { damage_groups = { full_punch_interval = 1, fleshy = damage, knockback = impact * 20.0 } }, punch_dir)
|
return
|
||||||
obj:add_velocity(vector.multiply(punch_dir, impact * 20))
|
end
|
||||||
end, obj, damage, impact, vector.new(punch_dir))
|
|
||||||
else
|
mcl_util.deal_damage(obj, damage, {type = "explosion", direct = direct, source = source})
|
||||||
obj:punch(source, 10, { damage_groups = { full_punch_interval = 1, fleshy = damage, knockback = impact * 20.0 } }, punch_dir)
|
|
||||||
|
|
||||||
if obj:is_player() then
|
|
||||||
obj:add_velocity(vector.multiply(punch_dir, impact * 20))
|
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))
|
obj:add_velocity(vector.multiply(punch_dir, impact * 20))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -422,7 +417,8 @@ end
|
||||||
-- pos - The position where the explosion originates from
|
-- pos - The position where the explosion originates from
|
||||||
-- strength - The blast strength of the explosion (a TNT explosion uses 4)
|
-- strength - The blast strength of the explosion (a TNT explosion uses 4)
|
||||||
-- info - Table containing information about explosion
|
-- 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:
|
-- Values in info:
|
||||||
-- drop_chance - If specified becomes the drop chance of all nodes in the
|
-- drop_chance - If specified becomes the drop chance of all nodes in the
|
||||||
|
@ -436,7 +432,7 @@ end
|
||||||
-- griefing - If true, the explosion will destroy nodes (default: true)
|
-- griefing - If true, the explosion will destroy nodes (default: true)
|
||||||
-- grief_protected - If true, the explosion will also destroy nodes which have
|
-- grief_protected - If true, the explosion will also destroy nodes which have
|
||||||
-- been protected (default: false)
|
-- 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
|
if info == nil then
|
||||||
info = {}
|
info = {}
|
||||||
end
|
end
|
||||||
|
@ -465,7 +461,7 @@ function mcl_explosions.explode(pos, strength, info, puncher)
|
||||||
info.drop_chance = 0
|
info.drop_chance = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
trace_explode(pos, strength, shape, radius, info, puncher)
|
trace_explode(pos, strength, shape, radius, info, direct, source)
|
||||||
|
|
||||||
if info.particles then
|
if info.particles then
|
||||||
add_particles(pos, radius)
|
add_particles(pos, radius)
|
||||||
|
|
|
@ -418,3 +418,120 @@ function mcl_util.get_color(colorstr)
|
||||||
return colorstr, hex
|
return colorstr, hex
|
||||||
end
|
end
|
||||||
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 pos = pointed_thing.under
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
if player and not player:get_player_control().sneak then
|
||||||
|
local nodedef = minetest.registered_nodes[node.name]
|
||||||
|
local on_rightclick = nodedef and nodedef.on_rightclick
|
||||||
|
if on_rightclick then
|
||||||
|
return on_rightclick(pos, node, player, itemstack, pointed_thing) 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)
|
||||||
|
local luaentity = target:get_luaentity()
|
||||||
|
|
||||||
|
if luaentity then
|
||||||
|
if luaentity.deal_damage then
|
||||||
|
luaentity:deal_damage(damage, mcl_reason or {type = "generic"})
|
||||||
|
return
|
||||||
|
elseif luaentity._cmi_is_mob then
|
||||||
|
-- local puncher = mcl_reason and 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)
|
||||||
|
luaentity.health = luaentity.health - damage
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
target:set_hp(target:get_hp() - damage, {_mcl_reason = mcl_reason})
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_util.get_hp(obj)
|
||||||
|
local luaentity = obj:get_luaentity()
|
||||||
|
|
||||||
|
if luaentity and luaentity._cmi_is_mob then
|
||||||
|
return luaentity.health
|
||||||
|
else
|
||||||
|
return obj:get_hp()
|
||||||
|
end
|
||||||
|
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
|
||||||
|
|
||||||
|
function mcl_util.get_wielded_item(object)
|
||||||
|
if object:is_player() then
|
||||||
|
return object:get_wielded_item()
|
||||||
|
else
|
||||||
|
-- ToDo: implement getting wielditems from mobs as soon as mobs have wielditems
|
||||||
|
return ItemStack()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_util.get_object_name(object)
|
||||||
|
if object:is_player() then
|
||||||
|
return object:get_player_name()
|
||||||
|
else
|
||||||
|
local luaentity = object:get_luaentity()
|
||||||
|
|
||||||
|
return luaentity.nametag and luaentity.nametag ~= "" and luaentity.nametag or luaentity.description or luaentity.name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -35,7 +35,7 @@ function mcl_burning.get_touching_nodes(obj, nodenames, storage)
|
||||||
return nodes
|
return nodes
|
||||||
end
|
end
|
||||||
|
|
||||||
function mcl_burning.set_on_fire(obj, burn_time, reason)
|
function mcl_burning.set_on_fire(obj, burn_time)
|
||||||
if obj:get_hp() < 0 then
|
if obj:get_hp() < 0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -47,27 +47,27 @@ function mcl_burning.set_on_fire(obj, burn_time, reason)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local max_fire_prot_lvl = 0
|
if obj:is_player() and minetest.is_creative_enabled(obj:get_player_name()) then
|
||||||
|
burn_time = 0
|
||||||
|
else
|
||||||
|
local max_fire_prot_lvl = 0
|
||||||
|
local inv = mcl_util.get_inventory(obj)
|
||||||
|
local armor_list = inv and inv:get_list("armor")
|
||||||
|
|
||||||
if obj:is_player() then
|
if armor_list then
|
||||||
if minetest.is_creative_enabled(obj:get_player_name()) then
|
for _, stack in pairs(armor_list) do
|
||||||
burn_time = burn_time / 100
|
local fire_prot_lvl = mcl_enchanting.get_enchantment(stack, "fire_protection")
|
||||||
|
if fire_prot_lvl > max_fire_prot_lvl then
|
||||||
|
max_fire_prot_lvl = fire_prot_lvl
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local inv = obj:get_inventory()
|
if max_fire_prot_lvl > 0 then
|
||||||
|
burn_time = burn_time - math.floor(burn_time * max_fire_prot_lvl * 0.15)
|
||||||
for i = 2, 5 do
|
|
||||||
local stack = inv:get_stack("armor", i)
|
|
||||||
|
|
||||||
local fire_prot_lvl = mcl_enchanting.get_enchantment(stack, "fire_protection")
|
|
||||||
max_fire_prot_lvl = math.max(max_fire_prot_lvl, fire_prot_lvl)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if max_fire_prot_lvl > 0 then
|
|
||||||
burn_time = burn_time - math.floor(burn_time * max_fire_prot_lvl * 0.15)
|
|
||||||
end
|
|
||||||
|
|
||||||
if not storage.burn_time or burn_time >= storage.burn_time then
|
if not storage.burn_time or burn_time >= storage.burn_time then
|
||||||
if obj:is_player() and not storage.fire_hud_id then
|
if obj:is_player() and not storage.fire_hud_id then
|
||||||
storage.fire_hud_id = obj:hud_add({
|
storage.fire_hud_id = obj:hud_add({
|
||||||
|
@ -79,7 +79,6 @@ function mcl_burning.set_on_fire(obj, burn_time, reason)
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
storage.burn_time = burn_time
|
storage.burn_time = burn_time
|
||||||
storage.burn_reason = reason
|
|
||||||
storage.fire_damage_timer = 0
|
storage.fire_damage_timer = 0
|
||||||
|
|
||||||
local fire_entity = minetest.add_entity(obj:get_pos(), "mcl_burning:fire")
|
local fire_entity = minetest.add_entity(obj:get_pos(), "mcl_burning:fire")
|
||||||
|
@ -120,7 +119,6 @@ function mcl_burning.extinguish(obj)
|
||||||
mcl_burning.storage[obj] = {}
|
mcl_burning.storage[obj] = {}
|
||||||
else
|
else
|
||||||
storage.burn_time = nil
|
storage.burn_time = nil
|
||||||
storage.burn_reason = nil
|
|
||||||
storage.fire_damage_timer = nil
|
storage.fire_damage_timer = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -140,36 +138,9 @@ function mcl_burning.tick(obj, dtime, storage)
|
||||||
storage.fire_damage_timer = 0
|
storage.fire_damage_timer = 0
|
||||||
|
|
||||||
local luaentity = obj:get_luaentity()
|
local luaentity = obj:get_luaentity()
|
||||||
local is_mob = luaentity and luaentity._cmi_is_mob
|
|
||||||
local hp = is_mob and luaentity.health or obj:get_hp()
|
|
||||||
|
|
||||||
if hp > 0 then
|
if not luaentity or not luaentity.fire_damage_resistant then
|
||||||
local do_damage = true
|
mcl_util.deal_damage(obj, 1, {type = "on_fire"})
|
||||||
|
|
||||||
if obj:is_player() then
|
|
||||||
if mcl_potions.player_has_effect(obj, "fire_proof") then
|
|
||||||
do_damage = false
|
|
||||||
else
|
|
||||||
local name = obj:get_player_name()
|
|
||||||
armor.last_damage_types[name] = "fire"
|
|
||||||
local deathmsg = S("@1 burned to death.", name)
|
|
||||||
if storage.reason then
|
|
||||||
deathmsg = S("@1 was burned by @2.", name, storage.reason)
|
|
||||||
end
|
|
||||||
mcl_death_messages.player_damage(obj, deathmsg)
|
|
||||||
end
|
|
||||||
elseif luaentity.fire_damage_resistant then
|
|
||||||
do_damage = false
|
|
||||||
end
|
|
||||||
|
|
||||||
if do_damage then
|
|
||||||
local new_hp = hp - 1
|
|
||||||
if is_mob then
|
|
||||||
luaentity.health = new_hp
|
|
||||||
else
|
|
||||||
obj:set_hp(new_hp)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
local S = minetest.get_translator("mcl_falling_nodes")
|
local S = minetest.get_translator("mcl_falling_nodes")
|
||||||
local dmes = minetest.get_modpath("mcl_death_messages") ~= nil
|
|
||||||
local has_mcl_armor = minetest.get_modpath("mcl_armor")
|
local has_mcl_armor = minetest.get_modpath("mcl_armor")
|
||||||
|
|
||||||
local is_creative_enabled = minetest.is_creative_enabled
|
|
||||||
|
|
||||||
local get_falling_depth = function(self)
|
local get_falling_depth = function(self)
|
||||||
if not self._startpos then
|
if not self._startpos then
|
||||||
-- Fallback
|
-- Fallback
|
||||||
|
@ -23,80 +20,31 @@ local deal_falling_damage = function(self, dtime)
|
||||||
-- Fallback
|
-- Fallback
|
||||||
self._startpos = pos
|
self._startpos = pos
|
||||||
end
|
end
|
||||||
local objs = minetest.get_objects_inside_radius(pos, 1)
|
self._hit = self._hit or {}
|
||||||
for _,v in ipairs(objs) do
|
for _, obj in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
|
||||||
if v:is_player() then
|
if mcl_util.get_hp(obj) > 0 and not self._hit[obj] then
|
||||||
local hp = v:get_hp()
|
self._hit[obj] = true
|
||||||
local name = v:get_player_name()
|
local way = self._startpos.y - pos.y
|
||||||
if hp ~= 0 then
|
local damage = (way - 1) * 2
|
||||||
if not self._hit_players then
|
damage = math.min(40, math.max(0, damage))
|
||||||
self._hit_players = {}
|
if damage >= 1 then
|
||||||
end
|
-- Reduce damage if wearing a helmet
|
||||||
local hit = false
|
local inv = mcl_util.get_inventory(obj)
|
||||||
for _,v in ipairs(self._hit_players) do
|
if inv then
|
||||||
if name == v then
|
local helmet = inv:get_stack("armor", 2)
|
||||||
hit = true
|
if minetest.get_item_group(helmet:get_name(), "combat_armor") > 0 then
|
||||||
|
damage = damage / 4 * 3
|
||||||
|
mcl_util.use_item_durability(helmet, 1)
|
||||||
|
inv:set_stack("armor", 2, helmet)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not hit then
|
local deathmsg, dmg_type
|
||||||
table.insert(self._hit_players, name)
|
if minetest.get_item_group(self.node.name, "anvil") ~= 0 then
|
||||||
local way = self._startpos.y - pos.y
|
dmg_type = "anvil"
|
||||||
local damage = (way - 1) * 2
|
else
|
||||||
damage = math.min(40, math.max(0, damage))
|
dmg_type = "falling_node"
|
||||||
if damage >= 1 then
|
|
||||||
hp = hp - damage
|
|
||||||
if hp < 0 then
|
|
||||||
hp = 0
|
|
||||||
end
|
|
||||||
-- Reduce damage if wearing a helmet
|
|
||||||
local inv = v:get_inventory()
|
|
||||||
local helmet = inv:get_stack("armor", 2)
|
|
||||||
if has_mcl_armor and not helmet:is_empty() then
|
|
||||||
hp = hp/4*3
|
|
||||||
if not is_creative_enabled(name) then
|
|
||||||
helmet:add_wear(65535/helmet:get_definition().groups.mcl_armor_uses) --TODO: be sure damage is exactly like mc (informations are missing in the mc wiki)
|
|
||||||
inv:set_stack("armor", 2, helmet)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local msg
|
|
||||||
if minetest.get_item_group(self.node.name, "anvil") ~= 0 then
|
|
||||||
msg = S("@1 was smashed by a falling anvil.", v:get_player_name())
|
|
||||||
else
|
|
||||||
msg = S("@1 was smashed by a falling block.", v:get_player_name())
|
|
||||||
end
|
|
||||||
if dmes then
|
|
||||||
mcl_death_messages.player_damage(v, msg)
|
|
||||||
end
|
|
||||||
v:set_hp(hp, { type = "punch", from = "mod" })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local hp = v:get_luaentity().health
|
|
||||||
if hp and hp ~= 0 then
|
|
||||||
if not self._hit_mobs then
|
|
||||||
self._hit_mobs = {}
|
|
||||||
end
|
|
||||||
local hit = false
|
|
||||||
for _,mob in ipairs(self._hit_mobs) do
|
|
||||||
if v == mob then
|
|
||||||
hit = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
--TODO: reduce damage for mobs then they will be able to wear armor
|
|
||||||
if not hit then
|
|
||||||
table.insert(self._hit_mobs, v)
|
|
||||||
local way = self._startpos.y - pos.y
|
|
||||||
local damage = (way - 1) * 2
|
|
||||||
damage = math.min(40, math.max(0, damage))
|
|
||||||
if damage >= 1 then
|
|
||||||
hp = hp - damage
|
|
||||||
if hp < 0 then
|
|
||||||
hp = 0
|
|
||||||
end
|
|
||||||
v:get_luaentity().health = hp
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
mcl_util.deal_damage(obj, damage, {type = dmg_type})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -166,7 +114,7 @@ minetest.register_entity(":__builtin:falling_node", {
|
||||||
|
|
||||||
on_activate = function(self, staticdata)
|
on_activate = function(self, staticdata)
|
||||||
self.object:set_armor_groups({immortal = 1})
|
self.object:set_armor_groups({immortal = 1})
|
||||||
|
|
||||||
local ds = minetest.deserialize(staticdata)
|
local ds = minetest.deserialize(staticdata)
|
||||||
if ds then
|
if ds then
|
||||||
self._startpos = ds._startpos
|
self._startpos = ds._startpos
|
||||||
|
@ -200,7 +148,7 @@ minetest.register_entity(":__builtin:falling_node", {
|
||||||
local np = {x = pos.x, y = pos.y + 0.3, z = pos.z}
|
local np = {x = pos.x, y = pos.y + 0.3, z = pos.z}
|
||||||
local n2 = minetest.get_node(np)
|
local n2 = minetest.get_node(np)
|
||||||
if n2.name == "mcl_portals:portal_end" then
|
if n2.name == "mcl_portals:portal_end" then
|
||||||
-- TODO: Teleport falling node.
|
-- TODO: Teleport falling node.
|
||||||
self.object:remove()
|
self.object:remove()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -239,7 +187,7 @@ minetest.register_entity(":__builtin:falling_node", {
|
||||||
end
|
end
|
||||||
local nd = minetest.registered_nodes[n2.name]
|
local nd = minetest.registered_nodes[n2.name]
|
||||||
if n2.name == "mcl_portals:portal_end" then
|
if n2.name == "mcl_portals:portal_end" then
|
||||||
-- TODO: Teleport falling node.
|
-- TODO: Teleport falling node.
|
||||||
|
|
||||||
elseif (nd and nd.buildable_to == true) or minetest.get_item_group(self.node.name, "crush_after_fall") ~= 0 then
|
elseif (nd and nd.buildable_to == true) or minetest.get_item_group(self.node.name, "crush_after_fall") ~= 0 then
|
||||||
-- Replace destination node if it's buildable to
|
-- Replace destination node if it's buildable to
|
||||||
|
|
|
@ -196,7 +196,7 @@ function mobs:register_mob(name, def)
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_entity(name, {
|
minetest.register_entity(name, {
|
||||||
|
description = def.description,
|
||||||
use_texture_alpha = def.use_texture_alpha,
|
use_texture_alpha = def.use_texture_alpha,
|
||||||
stepheight = def.stepheight or 0.6,
|
stepheight = def.stepheight or 0.6,
|
||||||
stepheight_backup = def.stepheight or 0.6,
|
stepheight_backup = def.stepheight or 0.6,
|
||||||
|
@ -542,7 +542,7 @@ function mobs:register_arrow(name, def)
|
||||||
local vel = self.object:get_velocity()
|
local vel = self.object:get_velocity()
|
||||||
|
|
||||||
local pos = self.object:get_pos()
|
local pos = self.object:get_pos()
|
||||||
|
|
||||||
if self.timer > 150
|
if self.timer > 150
|
||||||
or not mobs.within_limits(pos, 0) then
|
or not mobs.within_limits(pos, 0) then
|
||||||
mcl_burning.extinguish(self.object)
|
mcl_burning.extinguish(self.object)
|
||||||
|
|
|
@ -64,7 +64,6 @@ function mobs:alias_mob(old_name, new_name)
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Spawn a child
|
-- Spawn a child
|
||||||
function mobs:spawn_child(pos, mob_type)
|
function mobs:spawn_child(pos, mob_type)
|
||||||
local child = minetest_add_entity(pos, mob_type)
|
local child = minetest_add_entity(pos, mob_type)
|
||||||
|
@ -1323,13 +1322,19 @@ end
|
||||||
|
|
||||||
-- Return true if object is in view_range
|
-- Return true if object is in view_range
|
||||||
local function object_in_range(self, object)
|
local function object_in_range(self, object)
|
||||||
|
if not object then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local factor
|
||||||
|
-- Apply view range reduction for special player armor
|
||||||
if not object then
|
if not object then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
local factor
|
local factor
|
||||||
-- Apply view range reduction for special player armor
|
-- Apply view range reduction for special player armor
|
||||||
if object:is_player() and mod_armor then
|
if object:is_player() and mod_armor then
|
||||||
factor = armor:get_mob_view_range_factor(object, self.name)
|
local factors = mcl_armor.player_view_range_factors[object]
|
||||||
|
factor = factors and factors[self.name]
|
||||||
end
|
end
|
||||||
-- Distance check
|
-- Distance check
|
||||||
local dist
|
local dist
|
||||||
|
@ -2150,7 +2155,7 @@ local mob_detach_child = function(self, child)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function do_states(self)
|
function do_states(self)
|
||||||
|
|
||||||
if self.state == "stand" then
|
if self.state == "stand" then
|
||||||
|
|
||||||
|
@ -2706,8 +2711,8 @@ function do_states(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- above function exported for mount.lua
|
-- above function exported for mount.lua
|
||||||
function mobs:set_animation(self, anim)
|
function mobs:set_animation(self, anim)
|
||||||
set_animation(self, anim)
|
set_animation(self, anim)
|
||||||
|
@ -2934,7 +2939,7 @@ mob_step = function()
|
||||||
-- end
|
-- end
|
||||||
--end
|
--end
|
||||||
|
|
||||||
|
|
||||||
-- Add water flowing for mobs from mcl_item_entity
|
-- Add water flowing for mobs from mcl_item_entity
|
||||||
--[[
|
--[[
|
||||||
local p, node, nn, def
|
local p, node, nn, def
|
||||||
|
|
|
@ -516,8 +516,6 @@ end
|
||||||
|
|
||||||
-- Evoker
|
-- Evoker
|
||||||
if c("totem") then
|
if c("totem") then
|
||||||
local hud_totem = {}
|
|
||||||
|
|
||||||
-- Totem of Undying
|
-- Totem of Undying
|
||||||
minetest.register_craftitem("mobs_mc:totem", {
|
minetest.register_craftitem("mobs_mc:totem", {
|
||||||
description = S("Totem of Undying"),
|
description = S("Totem of Undying"),
|
||||||
|
@ -527,66 +525,8 @@ if c("totem") then
|
||||||
inventory_image = "mcl_totems_totem.png",
|
inventory_image = "mcl_totems_totem.png",
|
||||||
wield_image = "mcl_totems_totem.png",
|
wield_image = "mcl_totems_totem.png",
|
||||||
stack_max = 1,
|
stack_max = 1,
|
||||||
|
groups = {combat_item=1},
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_on_leaveplayer(function(player)
|
|
||||||
hud_totem[player:get_player_name()] = nil
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- Save the player from death when holding totem of undying in hand
|
|
||||||
minetest.register_on_player_hpchange(function(player, hp_change)
|
|
||||||
local hp = player:get_hp()
|
|
||||||
-- Fatal damage?
|
|
||||||
if hp + hp_change <= 0 then
|
|
||||||
local wield = player:get_wielded_item()
|
|
||||||
if wield:get_name() == "mobs_mc:totem" then
|
|
||||||
local ppos = player:get_pos()
|
|
||||||
local pnname = minetest.get_node(ppos).name
|
|
||||||
-- Some exceptions when _not_ to save the player
|
|
||||||
for n=1, #mobs_mc.misc.totem_fail_nodes do
|
|
||||||
if pnname == mobs_mc.misc.totem_fail_nodes[n] then
|
|
||||||
return hp_change
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Reset breath as well
|
|
||||||
if player:get_breath() < 11 then
|
|
||||||
player:set_breath(10)
|
|
||||||
end
|
|
||||||
if not minetest.is_creative_enabled(player:get_player_name()) then
|
|
||||||
wield:take_item()
|
|
||||||
player:set_wielded_item(wield)
|
|
||||||
end
|
|
||||||
-- Effects
|
|
||||||
minetest.sound_play({name = "mcl_totems_totem", gain=1}, {pos=ppos, max_hear_distance=16}, true)
|
|
||||||
|
|
||||||
-- Big totem overlay
|
|
||||||
if not hud_totem[player:get_player_name()] then
|
|
||||||
hud_totem[player:get_player_name()] = player:hud_add({
|
|
||||||
hud_elem_type = "image",
|
|
||||||
text = "mcl_totems_totem.png",
|
|
||||||
position = { x=0.5, y=1 },
|
|
||||||
scale = { x=17, y=17 },
|
|
||||||
offset = { x=0, y=-178 },
|
|
||||||
z_index = 100,
|
|
||||||
})
|
|
||||||
minetest.after(3, function(name)
|
|
||||||
local player = minetest.get_player_by_name(name)
|
|
||||||
if player and player:is_player() then
|
|
||||||
local name = player:get_player_name()
|
|
||||||
if hud_totem[name] then
|
|
||||||
player:hud_remove(hud_totem[name])
|
|
||||||
hud_totem[name] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end, player:get_player_name())
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set HP to exactly 1
|
|
||||||
return -hp + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return hp_change
|
|
||||||
end, true)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Rotten flesh
|
-- Rotten flesh
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
local S = minetest.get_translator("mobs_mc")
|
local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:bat", {
|
mobs:register_mob("mobs_mc:bat", {
|
||||||
|
description = S("Bat"),
|
||||||
type = "animal",
|
type = "animal",
|
||||||
spawn_class = "ambient",
|
spawn_class = "ambient",
|
||||||
can_despawn = true,
|
can_despawn = true,
|
||||||
|
|
|
@ -11,6 +11,7 @@ local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:blaze", {
|
mobs:register_mob("mobs_mc:blaze", {
|
||||||
|
description = S("Blaze"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
hp_min = 20,
|
hp_min = 20,
|
||||||
|
@ -84,7 +85,7 @@ mobs:register_mob("mobs_mc:blaze", {
|
||||||
shoot_arrow = function(self, pos, dir)
|
shoot_arrow = function(self, pos, dir)
|
||||||
-- 2-4 damage per arrow
|
-- 2-4 damage per arrow
|
||||||
local dmg = math.random(2,4)
|
local dmg = math.random(2,4)
|
||||||
mobs.shoot_projectile_handling("mobs_mc:blaze_fireball", pos, dir, self.object:get_yaw(), self.object, 7, dmg,nil,nil,nil,-0.4)
|
mobs.shoot_projectile_handling("mobs_mc:blaze_fireball", pos, dir, self.object:get_yaw(), self.object, 7, dmg,nil,nil,nil,-0.4)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
do_custom = function(self)
|
do_custom = function(self)
|
||||||
|
@ -164,13 +165,11 @@ mobs:register_arrow("mobs_mc:blaze_fireball", {
|
||||||
tail_texture = "mobs_mc_spit.png^[colorize:black:255", --repurpose spit texture
|
tail_texture = "mobs_mc_spit.png^[colorize:black:255", --repurpose spit texture
|
||||||
tail_size = 2,
|
tail_size = 2,
|
||||||
tail_distance_divider = 3,
|
tail_distance_divider = 3,
|
||||||
|
_is_fireball = true,
|
||||||
|
|
||||||
-- Direct hit, no fire... just plenty of pain
|
-- Direct hit, no fire... just plenty of pain
|
||||||
hit_player = function(self, player)
|
hit_player = function(self, player)
|
||||||
if rawget(_G, "armor") and armor.last_damage_types then
|
mcl_burning.set_on_fire(player, 5)
|
||||||
armor.last_damage_types[player:get_player_name()] = "fireball"
|
|
||||||
end
|
|
||||||
mcl_burning.set_on_fire(player, 5, "blaze")
|
|
||||||
player:punch(self.object, 1.0, {
|
player:punch(self.object, 1.0, {
|
||||||
full_punch_interval = 1.0,
|
full_punch_interval = 1.0,
|
||||||
damage_groups = {fleshy = self._damage},
|
damage_groups = {fleshy = self._damage},
|
||||||
|
|
|
@ -9,6 +9,7 @@ local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:chicken", {
|
mobs:register_mob("mobs_mc:chicken", {
|
||||||
|
description = S("Chicken"),
|
||||||
type = "animal",
|
type = "animal",
|
||||||
spawn_class = "passive",
|
spawn_class = "passive",
|
||||||
|
|
||||||
|
@ -129,8 +130,8 @@ mobs:register_mob("mobs_mc:chicken", {
|
||||||
|
|
||||||
--spawn
|
--spawn
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:chicken",
|
"mobs_mc:chicken",
|
||||||
"overworld",
|
"overworld",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"FlowerForest_beach",
|
"FlowerForest_beach",
|
||||||
|
@ -181,10 +182,10 @@ mobs:spawn_specific(
|
||||||
"JungleEdge",
|
"JungleEdge",
|
||||||
"SavannaM",
|
"SavannaM",
|
||||||
},
|
},
|
||||||
9,
|
9,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30, 17000,
|
30, 17000,
|
||||||
3,
|
3,
|
||||||
mobs_mc.spawn_height.water,
|
mobs_mc.spawn_height.water,
|
||||||
mobs_mc.spawn_height.overworld_max)
|
mobs_mc.spawn_height.overworld_max)
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
local S = minetest.get_translator("mobs_mc")
|
local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
local cow_def = {
|
local cow_def = {
|
||||||
|
description = S("Cow"),
|
||||||
type = "animal",
|
type = "animal",
|
||||||
spawn_class = "passive",
|
spawn_class = "passive",
|
||||||
hp_min = 10,
|
hp_min = 10,
|
||||||
|
@ -45,7 +46,7 @@ local cow_def = {
|
||||||
stand_speed = 25, walk_speed = 40,
|
stand_speed = 25, walk_speed = 40,
|
||||||
run_speed = 60, stand_start = 0,
|
run_speed = 60, stand_start = 0,
|
||||||
stand_end = 0, walk_start = 0,
|
stand_end = 0, walk_start = 0,
|
||||||
walk_end = 40, run_start = 0,
|
walk_end = 40, run_start = 0,
|
||||||
run_end = 40,
|
run_end = 40,
|
||||||
},
|
},
|
||||||
--follow = mobs_mc.follow.cow,
|
--follow = mobs_mc.follow.cow,
|
||||||
|
@ -105,7 +106,7 @@ mobs:register_mob("mobs_mc:cow", cow_def)
|
||||||
|
|
||||||
-- Mooshroom
|
-- Mooshroom
|
||||||
local mooshroom_def = table.copy(cow_def)
|
local mooshroom_def = table.copy(cow_def)
|
||||||
|
mooshroom_def.description = S("Mooshroom")
|
||||||
mooshroom_def.mesh = "mobs_mc_cow.b3d"
|
mooshroom_def.mesh = "mobs_mc_cow.b3d"
|
||||||
mooshroom_def.textures = { {"mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png"}, {"mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" } }
|
mooshroom_def.textures = { {"mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png"}, {"mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" } }
|
||||||
mooshroom_def.on_rightclick = function(self, clicker)
|
mooshroom_def.on_rightclick = function(self, clicker)
|
||||||
|
@ -175,7 +176,7 @@ mobs:register_mob("mobs_mc:mooshroom", mooshroom_def)
|
||||||
-- Spawning
|
-- Spawning
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:cow",
|
"mobs_mc:cow",
|
||||||
"overworld",
|
"overworld",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"FlowerForest_beach",
|
"FlowerForest_beach",
|
||||||
|
@ -226,30 +227,30 @@ mobs:spawn_specific(
|
||||||
"JungleEdge",
|
"JungleEdge",
|
||||||
"SavannaM",
|
"SavannaM",
|
||||||
},
|
},
|
||||||
9,
|
9,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
17000,
|
17000,
|
||||||
10,
|
10,
|
||||||
mobs_mc.spawn_height.water,
|
mobs_mc.spawn_height.water,
|
||||||
mobs_mc.spawn_height.overworld_max)
|
mobs_mc.spawn_height.overworld_max)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:mooshroom",
|
"mobs_mc:mooshroom",
|
||||||
"overworld",
|
"overworld",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"MushroomIslandShore",
|
"MushroomIslandShore",
|
||||||
"MushroomIsland"
|
"MushroomIsland"
|
||||||
},
|
},
|
||||||
9,
|
9,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
17000,
|
17000,
|
||||||
5,
|
5,
|
||||||
mobs_mc.spawn_height.overworld_min,
|
mobs_mc.spawn_height.overworld_min,
|
||||||
mobs_mc.spawn_height.overworld_max)
|
mobs_mc.spawn_height.overworld_max)
|
||||||
|
|
||||||
-- spawn egg
|
-- spawn egg
|
||||||
|
|
|
@ -148,6 +148,7 @@ mobs:register_mob("mobs_mc:creeper", {
|
||||||
})
|
})
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:creeper_charged", {
|
mobs:register_mob("mobs_mc:creeper_charged", {
|
||||||
|
description = S("Creeper"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
hp_min = 20,
|
hp_min = 20,
|
||||||
|
@ -160,7 +161,7 @@ mobs:register_mob("mobs_mc:creeper_charged", {
|
||||||
mesh = "mobs_mc_creeper.b3d",
|
mesh = "mobs_mc_creeper.b3d",
|
||||||
|
|
||||||
--BOOM
|
--BOOM
|
||||||
|
|
||||||
textures = {
|
textures = {
|
||||||
{"mobs_mc_creeper.png",
|
{"mobs_mc_creeper.png",
|
||||||
"mobs_mc_creeper_charge.png"},
|
"mobs_mc_creeper_charge.png"},
|
||||||
|
@ -274,8 +275,8 @@ mobs:register_mob("mobs_mc:creeper_charged", {
|
||||||
})
|
})
|
||||||
|
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:creeper",
|
"mobs_mc:creeper",
|
||||||
"overworld",
|
"overworld",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"Mesa",
|
"Mesa",
|
||||||
|
@ -418,12 +419,12 @@ mobs:spawn_specific(
|
||||||
"ExtremeHillsM_underground",
|
"ExtremeHillsM_underground",
|
||||||
"JungleEdgeM_underground",
|
"JungleEdgeM_underground",
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
7,
|
7,
|
||||||
20,
|
20,
|
||||||
16500,
|
16500,
|
||||||
2,
|
2,
|
||||||
mobs_mc.spawn_height.overworld_min,
|
mobs_mc.spawn_height.overworld_min,
|
||||||
mobs_mc.spawn_height.overworld_max)
|
mobs_mc.spawn_height.overworld_max)
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
local S = minetest.get_translator("mobs_mc")
|
local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:enderdragon", {
|
mobs:register_mob("mobs_mc:enderdragon", {
|
||||||
|
description = S("Ender Dragon"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
attacks_animals = true,
|
attacks_animals = true,
|
||||||
|
|
|
@ -190,6 +190,7 @@ end
|
||||||
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
|
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:enderman", {
|
mobs:register_mob("mobs_mc:enderman", {
|
||||||
|
description = S("Enderman"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "passive",
|
spawn_class = "passive",
|
||||||
neutral = true,
|
neutral = true,
|
||||||
|
@ -347,7 +348,7 @@ mobs:register_mob("mobs_mc:enderman", {
|
||||||
end
|
end
|
||||||
-- Check to see if people are near by enough to look at us.
|
-- Check to see if people are near by enough to look at us.
|
||||||
for _,obj in pairs(minetest.get_connected_players()) do
|
for _,obj in pairs(minetest.get_connected_players()) do
|
||||||
|
|
||||||
--check if they are within radius
|
--check if they are within radius
|
||||||
local player_pos = obj:get_pos()
|
local player_pos = obj:get_pos()
|
||||||
if player_pos then -- prevent crashing in 1 in a million scenario
|
if player_pos then -- prevent crashing in 1 in a million scenario
|
||||||
|
@ -372,7 +373,7 @@ mobs:register_mob("mobs_mc:enderman", {
|
||||||
local ender_eye_pos = vector.new(enderpos.x, enderpos.y + 2.75, enderpos.z)
|
local ender_eye_pos = vector.new(enderpos.x, enderpos.y + 2.75, enderpos.z)
|
||||||
local eye_distance_from_player = vector.distance(ender_eye_pos, look_pos)
|
local eye_distance_from_player = vector.distance(ender_eye_pos, look_pos)
|
||||||
look_pos = vector.add(look_pos, vector.multiply(look_dir, eye_distance_from_player))
|
look_pos = vector.add(look_pos, vector.multiply(look_dir, eye_distance_from_player))
|
||||||
|
|
||||||
--if looking in general head position, turn hostile
|
--if looking in general head position, turn hostile
|
||||||
if minetest.line_of_sight(ender_eye_pos, look_pos_base) and vector.distance(look_pos, ender_eye_pos) <= 0.4 then
|
if minetest.line_of_sight(ender_eye_pos, look_pos_base) and vector.distance(look_pos, ender_eye_pos) <= 0.4 then
|
||||||
self.provoked = "staring"
|
self.provoked = "staring"
|
||||||
|
@ -386,7 +387,7 @@ mobs:register_mob("mobs_mc:enderman", {
|
||||||
self.hostile = true
|
self.hostile = true
|
||||||
self.state = "attack"
|
self.state = "attack"
|
||||||
self.attacking = obj
|
self.attacking = obj
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -584,23 +585,23 @@ mobs:register_mob("mobs_mc:enderman", {
|
||||||
|
|
||||||
-- End spawn
|
-- End spawn
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:enderman",
|
"mobs_mc:enderman",
|
||||||
"end",
|
"end",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"End"
|
"End"
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
3000,
|
3000,
|
||||||
12,
|
12,
|
||||||
mobs_mc.spawn_height.end_min,
|
mobs_mc.spawn_height.end_min,
|
||||||
mobs_mc.spawn_height.end_max)
|
mobs_mc.spawn_height.end_max)
|
||||||
-- Overworld spawn
|
-- Overworld spawn
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:enderman",
|
"mobs_mc:enderman",
|
||||||
"overworld",
|
"overworld",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"Mesa",
|
"Mesa",
|
||||||
|
@ -743,28 +744,28 @@ mobs:spawn_specific(
|
||||||
"ExtremeHillsM_underground",
|
"ExtremeHillsM_underground",
|
||||||
"JungleEdgeM_underground",
|
"JungleEdgeM_underground",
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
7,
|
7,
|
||||||
30,
|
30,
|
||||||
19000,
|
19000,
|
||||||
2,
|
2,
|
||||||
mobs_mc.spawn_height.overworld_min,
|
mobs_mc.spawn_height.overworld_min,
|
||||||
mobs_mc.spawn_height.overworld_max)
|
mobs_mc.spawn_height.overworld_max)
|
||||||
|
|
||||||
-- Nether spawn (rare)
|
-- Nether spawn (rare)
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:enderman",
|
"mobs_mc:enderman",
|
||||||
"nether",
|
"nether",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"Nether"
|
"Nether"
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
7,
|
7,
|
||||||
30,
|
30,
|
||||||
27500,
|
27500,
|
||||||
4,
|
4,
|
||||||
mobs_mc.spawn_height.nether_min,
|
mobs_mc.spawn_height.nether_min,
|
||||||
mobs_mc.spawn_height.nether_max)
|
mobs_mc.spawn_height.nether_max)
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
local S = minetest.get_translator("mobs_mc")
|
local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:endermite", {
|
mobs:register_mob("mobs_mc:endermite", {
|
||||||
|
description = S("Endermite"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
passive = false,
|
passive = false,
|
||||||
|
|
|
@ -11,6 +11,7 @@ local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:ghast", {
|
mobs:register_mob("mobs_mc:ghast", {
|
||||||
|
description = S("Ghast"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
group_attack = true,
|
group_attack = true,
|
||||||
|
@ -67,7 +68,7 @@ mobs:register_mob("mobs_mc:ghast", {
|
||||||
shoot_arrow = function(self, pos, dir)
|
shoot_arrow = function(self, pos, dir)
|
||||||
-- 2-4 damage per arrow
|
-- 2-4 damage per arrow
|
||||||
local dmg = math.random(2,4)
|
local dmg = math.random(2,4)
|
||||||
mobs.shoot_projectile_handling("mobs_mc:ghast_fireball", pos, dir, self.object:get_yaw(), self.object, 11, dmg,nil,nil,nil,-0.6)
|
mobs.shoot_projectile_handling("mobs_mc:ghast_fireball", pos, dir, self.object:get_yaw(), self.object, 11, dmg,nil,nil,nil,-0.6)
|
||||||
end,
|
end,
|
||||||
--[[
|
--[[
|
||||||
do_custom = function(self)
|
do_custom = function(self)
|
||||||
|
@ -84,18 +85,18 @@ mobs:register_mob("mobs_mc:ghast", {
|
||||||
|
|
||||||
|
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:ghast",
|
"mobs_mc:ghast",
|
||||||
"nether",
|
"nether",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"Nether"
|
"Nether"
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
18000,
|
18000,
|
||||||
2,
|
2,
|
||||||
mobs_mc.spawn_height.nether_min,
|
mobs_mc.spawn_height.nether_min,
|
||||||
mobs_mc.spawn_height.nether_max)
|
mobs_mc.spawn_height.nether_max)
|
||||||
|
|
||||||
-- fireball (projectile)
|
-- fireball (projectile)
|
||||||
|
@ -108,11 +109,9 @@ mobs:register_arrow("mobs_mc:ghast_fireball", {
|
||||||
tail = 1,
|
tail = 1,
|
||||||
tail_texture = "mobs_mc_spit.png^[colorize:black:255", --repurpose spit texture
|
tail_texture = "mobs_mc_spit.png^[colorize:black:255", --repurpose spit texture
|
||||||
tail_size = 5,
|
tail_size = 5,
|
||||||
|
_is_fireball = true,
|
||||||
|
|
||||||
hit_player = function(self, player)
|
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, {
|
player:punch(self.object, 1.0, {
|
||||||
full_punch_interval = 1.0,
|
full_punch_interval = 1.0,
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
local S = minetest.get_translator("mobs_mc")
|
local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:guardian", {
|
mobs:register_mob("mobs_mc:guardian", {
|
||||||
|
description = S("Guardian"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
hp_min = 30,
|
hp_min = 30,
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
local S = minetest.get_translator("mobs_mc")
|
local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:guardian_elder", {
|
mobs:register_mob("mobs_mc:guardian_elder", {
|
||||||
|
description = S("Elder Guardian"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
hp_min = 80,
|
hp_min = 80,
|
||||||
|
|
|
@ -83,6 +83,7 @@ end
|
||||||
|
|
||||||
-- Horse
|
-- Horse
|
||||||
local horse = {
|
local horse = {
|
||||||
|
description = S("Horse"),
|
||||||
type = "animal",
|
type = "animal",
|
||||||
spawn_class = "passive",
|
spawn_class = "passive",
|
||||||
visual = "mesh",
|
visual = "mesh",
|
||||||
|
@ -440,6 +441,7 @@ mobs:register_mob("mobs_mc:horse", horse)
|
||||||
|
|
||||||
-- Skeleton horse
|
-- Skeleton horse
|
||||||
local skeleton_horse = table.copy(horse)
|
local skeleton_horse = table.copy(horse)
|
||||||
|
skeleton_horse.description = S("Skeleton Horse")
|
||||||
skeleton_horse.breath_max = -1
|
skeleton_horse.breath_max = -1
|
||||||
skeleton_horse.armor = {undead = 100, fleshy = 100}
|
skeleton_horse.armor = {undead = 100, fleshy = 100}
|
||||||
skeleton_horse.textures = {{"blank.png", "mobs_mc_horse_skeleton.png", "blank.png"}}
|
skeleton_horse.textures = {{"blank.png", "mobs_mc_horse_skeleton.png", "blank.png"}}
|
||||||
|
@ -462,6 +464,7 @@ mobs:register_mob("mobs_mc:skeleton_horse", skeleton_horse)
|
||||||
|
|
||||||
-- Zombie horse
|
-- Zombie horse
|
||||||
local zombie_horse = table.copy(horse)
|
local zombie_horse = table.copy(horse)
|
||||||
|
zombie_horse.description = S("Zombie Horse")
|
||||||
zombie_horse.breath_max = -1
|
zombie_horse.breath_max = -1
|
||||||
zombie_horse.armor = {undead = 100, fleshy = 100}
|
zombie_horse.armor = {undead = 100, fleshy = 100}
|
||||||
zombie_horse.textures = {{"blank.png", "mobs_mc_horse_zombie.png", "blank.png"}}
|
zombie_horse.textures = {{"blank.png", "mobs_mc_horse_zombie.png", "blank.png"}}
|
||||||
|
@ -486,6 +489,7 @@ mobs:register_mob("mobs_mc:zombie_horse", zombie_horse)
|
||||||
-- Donkey
|
-- Donkey
|
||||||
local d = 0.86 -- donkey scale
|
local d = 0.86 -- donkey scale
|
||||||
local donkey = table.copy(horse)
|
local donkey = table.copy(horse)
|
||||||
|
donkey.description = S("Donkey")
|
||||||
donkey.textures = {{"blank.png", "mobs_mc_donkey.png", "blank.png"}}
|
donkey.textures = {{"blank.png", "mobs_mc_donkey.png", "blank.png"}}
|
||||||
donkey.animation = {
|
donkey.animation = {
|
||||||
speed_normal = 25,
|
speed_normal = 25,
|
||||||
|
@ -516,6 +520,7 @@ mobs:register_mob("mobs_mc:donkey", donkey)
|
||||||
-- Mule
|
-- Mule
|
||||||
local m = 0.94
|
local m = 0.94
|
||||||
local mule = table.copy(donkey)
|
local mule = table.copy(donkey)
|
||||||
|
mule.description = S("Mule")
|
||||||
mule.textures = {{"blank.png", "mobs_mc_mule.png", "blank.png"}}
|
mule.textures = {{"blank.png", "mobs_mc_mule.png", "blank.png"}}
|
||||||
mule.visual_size = { x=horse.visual_size.x*m, y=horse.visual_size.y*m }
|
mule.visual_size = { x=horse.visual_size.x*m, y=horse.visual_size.y*m }
|
||||||
mule.sounds = table.copy(donkey.sounds)
|
mule.sounds = table.copy(donkey.sounds)
|
||||||
|
@ -585,18 +590,18 @@ mobs:spawn_specific(
|
||||||
"JungleEdge",
|
"JungleEdge",
|
||||||
"SavannaM",
|
"SavannaM",
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
15000,
|
15000,
|
||||||
4,
|
4,
|
||||||
mobs_mc.spawn_height.water+3,
|
mobs_mc.spawn_height.water+3,
|
||||||
mobs_mc.spawn_height.overworld_max)
|
mobs_mc.spawn_height.overworld_max)
|
||||||
|
|
||||||
|
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:donkey",
|
"mobs_mc:donkey",
|
||||||
"overworld",
|
"overworld",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"Mesa",
|
"Mesa",
|
||||||
|
@ -606,12 +611,12 @@ mobs:spawn_specific(
|
||||||
"MesaPlateauF_grasstop",
|
"MesaPlateauF_grasstop",
|
||||||
"MesaBryce",
|
"MesaBryce",
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
15000,
|
15000,
|
||||||
4,
|
4,
|
||||||
mobs_mc.spawn_height.water+3,
|
mobs_mc.spawn_height.water+3,
|
||||||
mobs_mc.spawn_height.overworld_max)
|
mobs_mc.spawn_height.overworld_max)
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
|
|
|
@ -12,6 +12,7 @@ local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:iron_golem", {
|
mobs:register_mob("mobs_mc:iron_golem", {
|
||||||
|
description = S("Iron Golem"),
|
||||||
type = "npc",
|
type = "npc",
|
||||||
spawn_class = "passive",
|
spawn_class = "passive",
|
||||||
passive = true,
|
passive = true,
|
||||||
|
|
|
@ -25,6 +25,7 @@ local carpets = {
|
||||||
}
|
}
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:llama", {
|
mobs:register_mob("mobs_mc:llama", {
|
||||||
|
description = S("Llama"),
|
||||||
type = "animal",
|
type = "animal",
|
||||||
spawn_class = "passive",
|
spawn_class = "passive",
|
||||||
rotate = 270,
|
rotate = 270,
|
||||||
|
@ -281,12 +282,12 @@ mobs:spawn_specific(
|
||||||
"MesaPlateauF_grasstop",
|
"MesaPlateauF_grasstop",
|
||||||
"MesaBryce",
|
"MesaBryce",
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
15000,
|
15000,
|
||||||
5,
|
5,
|
||||||
mobs_mc.spawn_height.water+15,
|
mobs_mc.spawn_height.water+15,
|
||||||
mobs_mc.spawn_height.overworld_max)
|
mobs_mc.spawn_height.overworld_max)
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
|
|
|
@ -27,6 +27,7 @@ end
|
||||||
|
|
||||||
-- Ocelot
|
-- Ocelot
|
||||||
local ocelot = {
|
local ocelot = {
|
||||||
|
description = S("Ocelot"),
|
||||||
type = "animal",
|
type = "animal",
|
||||||
spawn_class = "passive",
|
spawn_class = "passive",
|
||||||
can_despawn = true,
|
can_despawn = true,
|
||||||
|
@ -104,6 +105,7 @@ mobs:register_mob("mobs_mc:ocelot", ocelot)
|
||||||
|
|
||||||
-- Cat
|
-- Cat
|
||||||
local cat = table.copy(ocelot)
|
local cat = table.copy(ocelot)
|
||||||
|
cat.description = S("Cat")
|
||||||
cat.textures = {{"mobs_mc_cat_black.png"}, {"mobs_mc_cat_red.png"}, {"mobs_mc_cat_siamese.png"}}
|
cat.textures = {{"mobs_mc_cat_black.png"}, {"mobs_mc_cat_red.png"}, {"mobs_mc_cat_siamese.png"}}
|
||||||
cat.can_despawn = false
|
cat.can_despawn = false
|
||||||
cat.owner = ""
|
cat.owner = ""
|
||||||
|
@ -154,8 +156,8 @@ local base_spawn_chance = 5000
|
||||||
-- Spawn ocelot
|
-- Spawn ocelot
|
||||||
--they get the same as the llama because I'm trying to rework so much of this code right now -j4i
|
--they get the same as the llama because I'm trying to rework so much of this code right now -j4i
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:ocelot",
|
"mobs_mc:ocelot",
|
||||||
"overworld",
|
"overworld",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"Jungle",
|
"Jungle",
|
||||||
|
@ -163,12 +165,12 @@ mobs:spawn_specific(
|
||||||
"JungleM",
|
"JungleM",
|
||||||
"JungleEdge",
|
"JungleEdge",
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
15000,
|
15000,
|
||||||
5,
|
5,
|
||||||
mobs_mc.spawn_height.water+15,
|
mobs_mc.spawn_height.water+15,
|
||||||
mobs_mc.spawn_height.overworld_max)
|
mobs_mc.spawn_height.overworld_max)
|
||||||
--[[
|
--[[
|
||||||
mobs:spawn({
|
mobs:spawn({
|
||||||
|
@ -183,7 +185,7 @@ mobs:spawn({
|
||||||
max_height = mobs_mc.spawn_height.overworld_max,
|
max_height = mobs_mc.spawn_height.overworld_max,
|
||||||
on_spawn = function(self, pos)
|
on_spawn = function(self, pos)
|
||||||
Note: Minecraft has a 1/3 spawn failure rate.
|
Note: Minecraft has a 1/3 spawn failure rate.
|
||||||
In this mod it is emulated by reducing the spawn rate accordingly (see above).
|
In this mod it is emulated by reducing the spawn rate accordingly (see above).
|
||||||
|
|
||||||
-- 1/7 chance to spawn 2 ocelot kittens
|
-- 1/7 chance to spawn 2 ocelot kittens
|
||||||
if pr:next(1,7) == 1 then
|
if pr:next(1,7) == 1 then
|
||||||
|
|
|
@ -12,6 +12,7 @@ local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:parrot", {
|
mobs:register_mob("mobs_mc:parrot", {
|
||||||
|
description = S("Parrot"),
|
||||||
type = "npc",
|
type = "npc",
|
||||||
spawn_class = "passive",
|
spawn_class = "passive",
|
||||||
pathfinding = 1,
|
pathfinding = 1,
|
||||||
|
@ -94,7 +95,7 @@ mobs:register_mob("mobs_mc:parrot", {
|
||||||
-- Parrots spawn rarely in jungles. TODO: Also check for jungle *biome* <- I'll get to this eventually -j4i
|
-- Parrots spawn rarely in jungles. TODO: Also check for jungle *biome* <- I'll get to this eventually -j4i
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:parrot",
|
"mobs_mc:parrot",
|
||||||
"overworld",
|
"overworld",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"Jungle",
|
"Jungle",
|
||||||
|
@ -102,12 +103,12 @@ mobs:spawn_specific(
|
||||||
"JungleM",
|
"JungleM",
|
||||||
"JungleEdge",
|
"JungleEdge",
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
7,
|
7,
|
||||||
30000,
|
30000,
|
||||||
1,
|
1,
|
||||||
mobs_mc.spawn_height.water+7,
|
mobs_mc.spawn_height.water+7,
|
||||||
mobs_mc.spawn_height.overworld_max)
|
mobs_mc.spawn_height.overworld_max)
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
local S = minetest.get_translator("mobs_mc")
|
local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:pig", {
|
mobs:register_mob("mobs_mc:pig", {
|
||||||
|
description = S("Pig"),
|
||||||
type = "animal",
|
type = "animal",
|
||||||
spawn_class = "passive",
|
spawn_class = "passive",
|
||||||
skittish = true,
|
skittish = true,
|
||||||
|
@ -206,8 +207,8 @@ mobs:register_mob("mobs_mc:pig", {
|
||||||
})
|
})
|
||||||
|
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:pig",
|
"mobs_mc:pig",
|
||||||
"overworld",
|
"overworld",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"FlowerForest_beach",
|
"FlowerForest_beach",
|
||||||
|
@ -258,12 +259,12 @@ mobs:spawn_specific(
|
||||||
"JungleEdge",
|
"JungleEdge",
|
||||||
"SavannaM",
|
"SavannaM",
|
||||||
},
|
},
|
||||||
9,
|
9,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
15000,
|
15000,
|
||||||
8,
|
8,
|
||||||
mobs_mc.spawn_height.overworld_min,
|
mobs_mc.spawn_height.overworld_min,
|
||||||
mobs_mc.spawn_height.overworld_max)
|
mobs_mc.spawn_height.overworld_max)
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
|
|
|
@ -8,6 +8,7 @@ local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:polar_bear", {
|
mobs:register_mob("mobs_mc:polar_bear", {
|
||||||
|
description = S("Polar Bear"),
|
||||||
type = "animal",
|
type = "animal",
|
||||||
spawn_class = "passive",
|
spawn_class = "passive",
|
||||||
runaway = false,
|
runaway = false,
|
||||||
|
@ -37,7 +38,7 @@ mobs:register_mob("mobs_mc:polar_bear", {
|
||||||
chance = 2,
|
chance = 2,
|
||||||
min = 0,
|
min = 0,
|
||||||
max = 2,
|
max = 2,
|
||||||
looting = "common",},
|
looting = "common",},
|
||||||
-- 1/4 to drop raw salmon
|
-- 1/4 to drop raw salmon
|
||||||
{name = mobs_mc.items.salmon_raw,
|
{name = mobs_mc.items.salmon_raw,
|
||||||
chance = 4,
|
chance = 4,
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
local S = minetest.get_translator("mobs_mc")
|
local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
local rabbit = {
|
local rabbit = {
|
||||||
|
description = S("Rabbit"),
|
||||||
type = "animal",
|
type = "animal",
|
||||||
spawn_class = "passive",
|
spawn_class = "passive",
|
||||||
passive = true,
|
passive = true,
|
||||||
|
@ -81,6 +82,7 @@ mobs:register_mob("mobs_mc:rabbit", rabbit)
|
||||||
|
|
||||||
-- The killer bunny (Only with spawn egg)
|
-- The killer bunny (Only with spawn egg)
|
||||||
local killer_bunny = table.copy(rabbit)
|
local killer_bunny = table.copy(rabbit)
|
||||||
|
killer_bunny.description = S("Killer Bunny")
|
||||||
killer_bunny.type = "monster"
|
killer_bunny.type = "monster"
|
||||||
killer_bunny.spawn_class = "hostile"
|
killer_bunny.spawn_class = "hostile"
|
||||||
killer_bunny.attack_type = "dogfight"
|
killer_bunny.attack_type = "dogfight"
|
||||||
|
@ -108,8 +110,8 @@ mobs:register_mob("mobs_mc:killer_bunny", killer_bunny)
|
||||||
-- Different skins depending on spawn location <- we'll get to this when the spawning algorithm is fleshed out
|
-- Different skins depending on spawn location <- we'll get to this when the spawning algorithm is fleshed out
|
||||||
|
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:rabbit",
|
"mobs_mc:rabbit",
|
||||||
"overworld",
|
"overworld",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"FlowerForest_beach",
|
"FlowerForest_beach",
|
||||||
|
@ -160,12 +162,12 @@ mobs:spawn_specific(
|
||||||
"JungleEdge",
|
"JungleEdge",
|
||||||
"SavannaM",
|
"SavannaM",
|
||||||
},
|
},
|
||||||
9,
|
9,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
15000,
|
15000,
|
||||||
8,
|
8,
|
||||||
mobs_mc.spawn_height.overworld_min,
|
mobs_mc.spawn_height.overworld_min,
|
||||||
mobs_mc.spawn_height.overworld_max)
|
mobs_mc.spawn_height.overworld_max)
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
|
|
|
@ -56,6 +56,7 @@ local gotten_texture = { "blank.png", "mobs_mc_sheep.png" }
|
||||||
|
|
||||||
--mcsheep
|
--mcsheep
|
||||||
mobs:register_mob("mobs_mc:sheep", {
|
mobs:register_mob("mobs_mc:sheep", {
|
||||||
|
description = S("Sheep"),
|
||||||
type = "animal",
|
type = "animal",
|
||||||
spawn_class = "passive",
|
spawn_class = "passive",
|
||||||
hp_min = 8,
|
hp_min = 8,
|
||||||
|
@ -384,12 +385,12 @@ mobs:spawn_specific(
|
||||||
"JungleEdge",
|
"JungleEdge",
|
||||||
"SavannaM",
|
"SavannaM",
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
15000,
|
15000,
|
||||||
3,
|
3,
|
||||||
mobs_mc.spawn_height.overworld_min,
|
mobs_mc.spawn_height.overworld_min,
|
||||||
mobs_mc.spawn_height.overworld_max)
|
mobs_mc.spawn_height.overworld_max)
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
|
|
|
@ -10,8 +10,9 @@ local S = minetest.get_translator("mobs_mc")
|
||||||
--###################
|
--###################
|
||||||
|
|
||||||
-- animation 45-80 is transition between passive and attack stance
|
-- animation 45-80 is transition between passive and attack stance
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:shulker", {
|
mobs:register_mob("mobs_mc:shulker", {
|
||||||
|
description = S("Shulker"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
attack_type = "projectile",
|
attack_type = "projectile",
|
||||||
|
@ -82,16 +83,16 @@ mobs:register_arrow("mobs_mc:shulkerbullet", {
|
||||||
mobs:register_egg("mobs_mc:shulker", S("Shulker"), "mobs_mc_spawn_icon_shulker.png", 0)
|
mobs:register_egg("mobs_mc:shulker", S("Shulker"), "mobs_mc_spawn_icon_shulker.png", 0)
|
||||||
|
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:shulker",
|
"mobs_mc:shulker",
|
||||||
"end",
|
"end",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"End"
|
"End"
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
5000,
|
5000,
|
||||||
2,
|
2,
|
||||||
mobs_mc.spawn_height.end_min,
|
mobs_mc.spawn_height.end_min,
|
||||||
mobs_mc.spawn_height.end_max)
|
mobs_mc.spawn_height.end_max)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
local S = minetest.get_translator("mobs_mc")
|
local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:silverfish", {
|
mobs:register_mob("mobs_mc:silverfish", {
|
||||||
|
description = S("Silverfish"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
passive = false,
|
passive = false,
|
||||||
|
|
|
@ -13,6 +13,7 @@ local mod_bows = minetest.get_modpath("mcl_bows") ~= nil
|
||||||
|
|
||||||
|
|
||||||
local skeleton = {
|
local skeleton = {
|
||||||
|
description = S("Skeleton"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
hostile = true,
|
hostile = true,
|
||||||
|
@ -131,6 +132,7 @@ mobs:register_mob("mobs_mc:skeleton", skeleton)
|
||||||
--###################
|
--###################
|
||||||
|
|
||||||
local stray = table.copy(skeleton)
|
local stray = table.copy(skeleton)
|
||||||
|
stray.description = S("Stray")
|
||||||
stray.mesh = "mobs_mc_skeleton.b3d"
|
stray.mesh = "mobs_mc_skeleton.b3d"
|
||||||
stray.textures = {
|
stray.textures = {
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,6 +10,7 @@ local S = minetest.get_translator("mobs_mc")
|
||||||
--###################
|
--###################
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:witherskeleton", {
|
mobs:register_mob("mobs_mc:witherskeleton", {
|
||||||
|
description = S("Wither Skeleton"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
hp_min = 20,
|
hp_min = 20,
|
||||||
|
|
|
@ -56,6 +56,7 @@ end
|
||||||
|
|
||||||
-- Slime
|
-- Slime
|
||||||
local slime_big = {
|
local slime_big = {
|
||||||
|
description = S("Slime"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
pathfinding = 1,
|
pathfinding = 1,
|
||||||
|
@ -160,8 +161,8 @@ local smin = mobs_mc.spawn_height.overworld_min
|
||||||
local smax = mobs_mc.spawn_height.water - 23
|
local smax = mobs_mc.spawn_height.water - 23
|
||||||
|
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:slime_tiny",
|
"mobs_mc:slime_tiny",
|
||||||
"overworld",
|
"overworld",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"FlowerForest_underground",
|
"FlowerForest_underground",
|
||||||
|
@ -195,17 +196,17 @@ mobs:spawn_specific(
|
||||||
"ExtremeHillsM_underground",
|
"ExtremeHillsM_underground",
|
||||||
"JungleEdgeM_underground",
|
"JungleEdgeM_underground",
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
12000,
|
12000,
|
||||||
4,
|
4,
|
||||||
smin,
|
smin,
|
||||||
smax)
|
smax)
|
||||||
|
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:slime_small",
|
"mobs_mc:slime_small",
|
||||||
"overworld",
|
"overworld",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"FlowerForest_underground",
|
"FlowerForest_underground",
|
||||||
|
@ -238,19 +239,19 @@ mobs:spawn_specific(
|
||||||
"JungleM_underground",
|
"JungleM_underground",
|
||||||
"ExtremeHillsM_underground",
|
"ExtremeHillsM_underground",
|
||||||
"JungleEdgeM_underground",
|
"JungleEdgeM_underground",
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
8500,
|
8500,
|
||||||
4,
|
4,
|
||||||
smin,
|
smin,
|
||||||
smax)
|
smax)
|
||||||
|
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:slime_big",
|
"mobs_mc:slime_big",
|
||||||
"overworld",
|
"overworld",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"FlowerForest_underground",
|
"FlowerForest_underground",
|
||||||
"JungleEdge_underground",
|
"JungleEdge_underground",
|
||||||
|
@ -283,16 +284,17 @@ mobs:spawn_specific(
|
||||||
"ExtremeHillsM_underground",
|
"ExtremeHillsM_underground",
|
||||||
"JungleEdgeM_underground",
|
"JungleEdgeM_underground",
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
10000,
|
10000,
|
||||||
4,
|
4,
|
||||||
smin,
|
smin,
|
||||||
smax)
|
smax)
|
||||||
|
|
||||||
-- Magma cube
|
-- Magma cube
|
||||||
local magma_cube_big = {
|
local magma_cube_big = {
|
||||||
|
description = S("Magma Cube"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
hp_min = 16,
|
hp_min = 16,
|
||||||
|
@ -405,49 +407,49 @@ local mmin = mobs_mc.spawn_height.nether_min
|
||||||
local mmax = mobs_mc.spawn_height.nether_max
|
local mmax = mobs_mc.spawn_height.nether_max
|
||||||
|
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:magma_cube_tiny",
|
"mobs_mc:magma_cube_tiny",
|
||||||
"nether",
|
"nether",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"Nether"
|
"Nether"
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
15000,
|
15000,
|
||||||
4,
|
4,
|
||||||
mmin,
|
mmin,
|
||||||
mmax)
|
mmax)
|
||||||
|
|
||||||
|
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:magma_cube_small",
|
"mobs_mc:magma_cube_small",
|
||||||
"nether",
|
"nether",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"Nether"
|
"Nether"
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
15500,
|
15500,
|
||||||
4,
|
4,
|
||||||
mmin,
|
mmin,
|
||||||
mmax)
|
mmax)
|
||||||
|
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:magma_cube_big",
|
"mobs_mc:magma_cube_big",
|
||||||
"nether",
|
"nether",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"Nether"
|
"Nether"
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
16000,
|
16000,
|
||||||
4,
|
4,
|
||||||
mmin,
|
mmin,
|
||||||
mmax)
|
mmax)
|
||||||
|
|
||||||
--mobs:spawn_specific("mobs_mc:magma_cube_tiny", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11000, 4, mmin, mmax)
|
--mobs:spawn_specific("mobs_mc:magma_cube_tiny", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11000, 4, mmin, mmax)
|
||||||
|
|
|
@ -21,6 +21,7 @@ local gotten_texture = {
|
||||||
}
|
}
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:snowman", {
|
mobs:register_mob("mobs_mc:snowman", {
|
||||||
|
description = S("Snow Golem"),
|
||||||
type = "npc",
|
type = "npc",
|
||||||
spawn_class = "passive",
|
spawn_class = "passive",
|
||||||
passive = true,
|
passive = true,
|
||||||
|
|
|
@ -13,6 +13,7 @@ local S = minetest.get_translator("mobs_mc")
|
||||||
-- Spider by AspireMint (fishyWET (CC-BY-SA 3.0 license for texture)
|
-- Spider by AspireMint (fishyWET (CC-BY-SA 3.0 license for texture)
|
||||||
|
|
||||||
local spider = {
|
local spider = {
|
||||||
|
description = S("Spider"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
passive = false,
|
passive = false,
|
||||||
|
@ -77,6 +78,7 @@ mobs:register_mob("mobs_mc:spider", spider)
|
||||||
|
|
||||||
-- Cave spider
|
-- Cave spider
|
||||||
local cave_spider = table.copy(spider)
|
local cave_spider = table.copy(spider)
|
||||||
|
cave_spider.description = S("Cave Spider")
|
||||||
cave_spider.textures = { {"mobs_mc_cave_spider.png^(mobs_mc_spider_eyes.png^[makealpha:0,0,0)"} }
|
cave_spider.textures = { {"mobs_mc_cave_spider.png^(mobs_mc_spider_eyes.png^[makealpha:0,0,0)"} }
|
||||||
-- TODO: Poison damage
|
-- TODO: Poison damage
|
||||||
-- TODO: Revert damage to 2
|
-- TODO: Revert damage to 2
|
||||||
|
@ -93,8 +95,8 @@ mobs:register_mob("mobs_mc:cave_spider", cave_spider)
|
||||||
|
|
||||||
|
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:spider",
|
"mobs_mc:spider",
|
||||||
"overworld",
|
"overworld",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"Mesa",
|
"Mesa",
|
||||||
|
@ -237,12 +239,12 @@ mobs:spawn_specific(
|
||||||
"ExtremeHillsM_underground",
|
"ExtremeHillsM_underground",
|
||||||
"JungleEdgeM_underground",
|
"JungleEdgeM_underground",
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
7,
|
7,
|
||||||
30,
|
30,
|
||||||
17000,
|
17000,
|
||||||
2,
|
2,
|
||||||
mobs_mc.spawn_height.overworld_min,
|
mobs_mc.spawn_height.overworld_min,
|
||||||
mobs_mc.spawn_height.overworld_max)
|
mobs_mc.spawn_height.overworld_max)
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
local S = minetest.get_translator("mobs_mc")
|
local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:squid", {
|
mobs:register_mob("mobs_mc:squid", {
|
||||||
|
description = S("Squid"),
|
||||||
type = "animal",
|
type = "animal",
|
||||||
spawn_class = "water",
|
spawn_class = "water",
|
||||||
can_despawn = true,
|
can_despawn = true,
|
||||||
|
|
|
@ -10,6 +10,7 @@ local S = minetest.get_translator("mobs_mc")
|
||||||
--###################
|
--###################
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:vex", {
|
mobs:register_mob("mobs_mc:vex", {
|
||||||
|
description = S("Vex"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
pathfinding = 1,
|
pathfinding = 1,
|
||||||
|
|
|
@ -927,6 +927,7 @@ end)
|
||||||
--[=======[ MOB REGISTRATION AND SPAWNING ]=======]
|
--[=======[ MOB REGISTRATION AND SPAWNING ]=======]
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:villager", {
|
mobs:register_mob("mobs_mc:villager", {
|
||||||
|
description = S("Villager"),
|
||||||
type = "npc",
|
type = "npc",
|
||||||
spawn_class = "passive",
|
spawn_class = "passive",
|
||||||
hp_min = 20,
|
hp_min = 20,
|
||||||
|
|
|
@ -12,6 +12,7 @@ local S = minetest.get_translator("mobs_mc")
|
||||||
local pr = PseudoRandom(os.time()*666)
|
local pr = PseudoRandom(os.time()*666)
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:evoker", {
|
mobs:register_mob("mobs_mc:evoker", {
|
||||||
|
description = S("Evoker"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
physical = true,
|
physical = true,
|
||||||
|
|
|
@ -7,6 +7,7 @@ local S = minetest.get_translator("mobs_mc")
|
||||||
local mod_bows = minetest.get_modpath("mcl_bows") ~= nil
|
local mod_bows = minetest.get_modpath("mcl_bows") ~= nil
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:illusioner", {
|
mobs:register_mob("mobs_mc:illusioner", {
|
||||||
|
description = S("Illusioner"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
attack_type = "projectile",
|
attack_type = "projectile",
|
||||||
|
|
|
@ -11,6 +11,7 @@ local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:vindicator", {
|
mobs:register_mob("mobs_mc:vindicator", {
|
||||||
|
description = S("Vindicator"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
physical = false,
|
physical = false,
|
||||||
|
|
|
@ -26,6 +26,7 @@ local professions = {
|
||||||
}
|
}
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:villager_zombie", {
|
mobs:register_mob("mobs_mc:villager_zombie", {
|
||||||
|
description = S("Zombie Villager"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
hostile = true,
|
hostile = true,
|
||||||
|
|
|
@ -13,6 +13,7 @@ local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:witch", {
|
mobs:register_mob("mobs_mc:witch", {
|
||||||
|
description = S("Witch"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
hp_min = 26,
|
hp_min = 26,
|
||||||
|
|
|
@ -10,6 +10,7 @@ local S = minetest.get_translator("mobs_mc")
|
||||||
--###################
|
--###################
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:wither", {
|
mobs:register_mob("mobs_mc:wither", {
|
||||||
|
description = S("Wither"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
hp_max = 300,
|
hp_max = 300,
|
||||||
|
|
|
@ -19,6 +19,7 @@ end
|
||||||
|
|
||||||
-- Wolf
|
-- Wolf
|
||||||
local wolf = {
|
local wolf = {
|
||||||
|
description = S("Wolf"),
|
||||||
type = "animal",
|
type = "animal",
|
||||||
spawn_class = "passive",
|
spawn_class = "passive",
|
||||||
can_despawn = true,
|
can_despawn = true,
|
||||||
|
@ -157,7 +158,7 @@ dog.owner = ""
|
||||||
-- TODO: Start sitting by default
|
-- TODO: Start sitting by default
|
||||||
dog.order = "roam"
|
dog.order = "roam"
|
||||||
dog.owner_loyal = true
|
dog.owner_loyal = true
|
||||||
dog.follow_velocity = 3.2
|
dog.follow_velocity = 3.2
|
||||||
-- Automatically teleport dog to owner
|
-- Automatically teleport dog to owner
|
||||||
dog.do_custom = mobs_mc.make_owner_teleport_function(12)
|
dog.do_custom = mobs_mc.make_owner_teleport_function(12)
|
||||||
dog.attack_animals = nil
|
dog.attack_animals = nil
|
||||||
|
@ -285,12 +286,12 @@ mobs:spawn_specific(
|
||||||
"ExtremeHillsM",
|
"ExtremeHillsM",
|
||||||
"BirchForestM",
|
"BirchForestM",
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
9000,
|
9000,
|
||||||
7,
|
7,
|
||||||
mobs_mc.spawn_height.water+3,
|
mobs_mc.spawn_height.water+3,
|
||||||
mobs_mc.spawn_height.overworld_max)
|
mobs_mc.spawn_height.overworld_max)
|
||||||
|
|
||||||
mobs:register_egg("mobs_mc:wolf", S("Wolf"), "mobs_mc_spawn_icon_wolf.png", 0)
|
mobs:register_egg("mobs_mc:wolf", S("Wolf"), "mobs_mc_spawn_icon_wolf.png", 0)
|
||||||
|
|
|
@ -46,6 +46,7 @@ table.insert(drops_zombie, {
|
||||||
})
|
})
|
||||||
|
|
||||||
local zombie = {
|
local zombie = {
|
||||||
|
description = S("Zombie"),
|
||||||
type = "monster",
|
type = "monster",
|
||||||
spawn_class = "hostile",
|
spawn_class = "hostile",
|
||||||
hostile = true,
|
hostile = true,
|
||||||
|
@ -122,6 +123,7 @@ mobs:register_mob("mobs_mc:zombie", zombie)
|
||||||
-- A smaller and more dangerous variant of the zombie
|
-- A smaller and more dangerous variant of the zombie
|
||||||
|
|
||||||
local baby_zombie = table.copy(zombie)
|
local baby_zombie = table.copy(zombie)
|
||||||
|
baby_zombie.description = S("Baby Zombie")
|
||||||
baby_zombie.collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.94, 0.25}
|
baby_zombie.collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.94, 0.25}
|
||||||
baby_zombie.xp_min = 12
|
baby_zombie.xp_min = 12
|
||||||
baby_zombie.xp_max = 12
|
baby_zombie.xp_max = 12
|
||||||
|
@ -135,6 +137,7 @@ mobs:register_mob("mobs_mc:baby_zombie", baby_zombie)
|
||||||
-- Husk.
|
-- Husk.
|
||||||
-- Desert variant of the zombie
|
-- Desert variant of the zombie
|
||||||
local husk = table.copy(zombie)
|
local husk = table.copy(zombie)
|
||||||
|
husk.description = S("Husk")
|
||||||
husk.textures = {
|
husk.textures = {
|
||||||
{
|
{
|
||||||
"mobs_mc_empty.png", -- armor
|
"mobs_mc_empty.png", -- armor
|
||||||
|
@ -152,6 +155,7 @@ mobs:register_mob("mobs_mc:husk", husk)
|
||||||
-- Baby husk.
|
-- Baby husk.
|
||||||
-- A smaller and more dangerous variant of the husk
|
-- A smaller and more dangerous variant of the husk
|
||||||
local baby_husk = table.copy(husk)
|
local baby_husk = table.copy(husk)
|
||||||
|
baby_husk.description = S("Baby Husk")
|
||||||
baby_husk.collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.94, 0.25}
|
baby_husk.collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.94, 0.25}
|
||||||
baby_husk.xp_min = 12
|
baby_husk.xp_min = 12
|
||||||
baby_husk.xp_max = 12
|
baby_husk.xp_max = 12
|
||||||
|
|
|
@ -11,6 +11,7 @@ local S = minetest.get_translator("mobs_mc")
|
||||||
|
|
||||||
|
|
||||||
local pigman = {
|
local pigman = {
|
||||||
|
description = S("Zombie Pigman"),
|
||||||
-- type="animal", passive=false: This combination is needed for a neutral mob which becomes hostile, if attacked
|
-- type="animal", passive=false: This combination is needed for a neutral mob which becomes hostile, if attacked
|
||||||
type = "animal",
|
type = "animal",
|
||||||
passive = false,
|
passive = false,
|
||||||
|
@ -113,6 +114,7 @@ mobs:register_mob("mobs_mc:pigman", pigman)
|
||||||
-- A smaller and more dangerous variant of the pigman
|
-- A smaller and more dangerous variant of the pigman
|
||||||
|
|
||||||
local baby_pigman = table.copy(pigman)
|
local baby_pigman = table.copy(pigman)
|
||||||
|
baby_pigman.description = S("Baby Zombie Pigman")
|
||||||
baby_pigman.collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.94, 0.25}
|
baby_pigman.collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.94, 0.25}
|
||||||
baby_pigman.xp_min = 13
|
baby_pigman.xp_min = 13
|
||||||
baby_pigman.xp_max = 13
|
baby_pigman.xp_max = 13
|
||||||
|
@ -131,33 +133,33 @@ mobs:register_mob("mobs_mc:baby_pigman", baby_pigman)
|
||||||
|
|
||||||
-- Regular spawning in the Nether
|
-- Regular spawning in the Nether
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:pigman",
|
"mobs_mc:pigman",
|
||||||
"nether",
|
"nether",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"Nether"
|
"Nether"
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
6000,
|
6000,
|
||||||
3,
|
3,
|
||||||
mobs_mc.spawn_height.nether_min,
|
mobs_mc.spawn_height.nether_min,
|
||||||
mobs_mc.spawn_height.nether_max)
|
mobs_mc.spawn_height.nether_max)
|
||||||
-- Baby zombie is 20 times less likely than regular zombies
|
-- Baby zombie is 20 times less likely than regular zombies
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
"mobs_mc:baby_pigman",
|
"mobs_mc:baby_pigman",
|
||||||
"nether",
|
"nether",
|
||||||
"ground",
|
"ground",
|
||||||
{
|
{
|
||||||
"Nether"
|
"Nether"
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
minetest.LIGHT_MAX+1,
|
minetest.LIGHT_MAX+1,
|
||||||
30,
|
30,
|
||||||
100000,
|
100000,
|
||||||
4,
|
4,
|
||||||
mobs_mc.spawn_height.nether_min,
|
mobs_mc.spawn_height.nether_min,
|
||||||
mobs_mc.spawn_height.nether_max)
|
mobs_mc.spawn_height.nether_max)
|
||||||
|
|
||||||
-- Spawning in Nether portals in the Overworld
|
-- Spawning in Nether portals in the Overworld
|
||||||
|
|
|
@ -11,7 +11,6 @@ of the license, or (at your option) any later version.
|
||||||
|
|
||||||
local S = minetest.get_translator("lightning")
|
local S = minetest.get_translator("lightning")
|
||||||
|
|
||||||
local has_mcl_death_msg = minetest.get_modpath("mcl_death_messages")
|
|
||||||
local get_connected_players = minetest.get_connected_players
|
local get_connected_players = minetest.get_connected_players
|
||||||
local line_of_sight = minetest.line_of_sight
|
local line_of_sight = minetest.line_of_sight
|
||||||
local get_node = minetest.get_node
|
local get_node = minetest.get_node
|
||||||
|
@ -139,48 +138,39 @@ lightning.strike = function(pos)
|
||||||
for o=1, #objs do
|
for o=1, #objs do
|
||||||
local obj = objs[o]
|
local obj = objs[o]
|
||||||
local lua = obj:get_luaentity()
|
local lua = obj:get_luaentity()
|
||||||
if obj:is_player() then
|
-- pig → zombie pigman (no damage)
|
||||||
-- Player damage
|
if lua and lua.name == "mobs_mc:pig" then
|
||||||
if has_mcl_death_msg then
|
local rot = obj:get_yaw()
|
||||||
mcl_death_messages.player_damage(obj, S("@1 was struck by lightning.", obj:get_player_name()))
|
obj:remove()
|
||||||
end
|
obj = add_entity(pos2, "mobs_mc:pigman")
|
||||||
obj:set_hp(obj:get_hp()-5, { type = "punch", from = "mod" })
|
obj:set_yaw(rot)
|
||||||
-- 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)
|
-- mooshroom: toggle color red/brown (no damage)
|
||||||
elseif lua.name == "mobs_mc:mooshroom" then
|
elseif lua and lua.name == "mobs_mc:mooshroom" then
|
||||||
if lua.base_texture[1] == "mobs_mc_mooshroom.png" then
|
if lua.base_texture[1] == "mobs_mc_mooshroom.png" then
|
||||||
lua.base_texture = { "mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" }
|
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
|
else
|
||||||
obj:set_hp(obj:get_hp()-5, { type = "punch", from = "mod" })
|
lua.base_texture = { "mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png" }
|
||||||
end
|
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
|
||||||
|
mcl_util.deal_damage(obj, 5, {type = "lightning_bolt"})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,5 +2,4 @@ name = lightning
|
||||||
author = sofar
|
author = sofar
|
||||||
description = A mod that adds thunder and lightning effects.
|
description = A mod that adds thunder and lightning effects.
|
||||||
depends = mcl_fire
|
depends = mcl_fire
|
||||||
optional_depends = mcl_death_messages
|
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ local pos_to_dim = mcl_worlds.pos_to_dimension
|
||||||
local dim_change = mcl_worlds.dimension_change
|
local dim_change = mcl_worlds.dimension_change
|
||||||
local is_in_void = mcl_worlds.is_in_void
|
local is_in_void = mcl_worlds.is_in_void
|
||||||
local get_spawn_pos = mcl_spawn.get_player_spawn_pos
|
local get_spawn_pos = mcl_spawn.get_player_spawn_pos
|
||||||
local death_msg = mcl_death_messages.player_damage
|
|
||||||
local send_chat = minetest.chat_send_player
|
local send_chat = minetest.chat_send_player
|
||||||
local get_connected = minetest.get_connected_players
|
local get_connected = minetest.get_connected_players
|
||||||
|
|
||||||
|
@ -40,7 +39,6 @@ minetest.register_on_mods_loaded(function()
|
||||||
end
|
end
|
||||||
self._void_timer = 0
|
self._void_timer = 0
|
||||||
|
|
||||||
local pos = obj:get_pos()
|
|
||||||
local void, void_deadly = is_in_void(pos)
|
local void, void_deadly = is_in_void(pos)
|
||||||
if void_deadly then
|
if void_deadly then
|
||||||
local ent = obj:get_luaentity()
|
local ent = obj:get_luaentity()
|
||||||
|
@ -80,8 +78,7 @@ minetest.register_globalstep(function(dtime)
|
||||||
elseif enable_damage and not is_immortal then
|
elseif enable_damage and not is_immortal then
|
||||||
-- Damage enabled, not immortal: Deal void damage (4 HP / 0.5 seconds)
|
-- Damage enabled, not immortal: Deal void damage (4 HP / 0.5 seconds)
|
||||||
if player:get_hp() > 0 then
|
if player:get_hp() > 0 then
|
||||||
death_msg(player, S("@1 fell into the endless void.", player:get_player_name()))
|
mcl_util.deal_damage(player, VOID_DAMAGE, {type = "out_of_world"})
|
||||||
player:set_hp(player:get_hp() - VOID_DAMAGE)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
name = mcl_void_damage
|
name = mcl_void_damage
|
||||||
author = Wuzzy
|
author = Wuzzy
|
||||||
description = Deal damage to entities stuck in the deep void
|
description = Deal damage to entities stuck in the deep void
|
||||||
depends = mcl_worlds, mcl_death_messages
|
depends = mcl_worlds
|
||||||
|
|
|
@ -1,307 +1,247 @@
|
||||||
local S = minetest.get_translator("mcl_death_messages")
|
local S = minetest.get_translator("mcl_death_messages")
|
||||||
local N = function(s) return s end
|
|
||||||
local C = minetest.colorize
|
|
||||||
|
|
||||||
local color_skyblue = mcl_colors.AQUA
|
mcl_death_messages = {
|
||||||
|
assist = {},
|
||||||
local function get_tool_name(item)
|
messages = {
|
||||||
local name = item:get_meta():get_string("name")
|
in_fire = {
|
||||||
if name ~= "" then
|
_translator = S,
|
||||||
return name
|
plain = "@1 went up in flames",
|
||||||
end
|
assist = "@1 walked into fire whilst fighting @2",
|
||||||
local def = item:get_definition()
|
},
|
||||||
return def._tt_original_description or def.description
|
lightning_bolt = {
|
||||||
end
|
_translator = S,
|
||||||
|
plain = "@1 was struck by lightning",
|
||||||
mcl_death_messages = {}
|
assist = "@1 was struck by lightning whilst fighting @2",
|
||||||
|
},
|
||||||
-- Death messages
|
on_fire = {
|
||||||
local msgs = {
|
_translator = S,
|
||||||
["arrow"] = {
|
plain = "@1 burned to death",
|
||||||
N("@1 was fatally hit by an arrow."),
|
assist = "@1 was burnt to a crisp whilst fighting @2",
|
||||||
N("@1 has been killed by an arrow."),
|
},
|
||||||
|
lava = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 tried to swim in lava",
|
||||||
|
assist = "@1 tried to swim in lava to escape @2"
|
||||||
|
},
|
||||||
|
hot_floor = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 discovered the floor was lava",
|
||||||
|
assist = "@1 walked into danger zone due to @2",
|
||||||
|
},
|
||||||
|
in_wall = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 suffocated in a wall",
|
||||||
|
assist = "@1 suffocated in a wall whilst fighting @2",
|
||||||
|
},
|
||||||
|
drown = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 drowned",
|
||||||
|
assist = "@1 drowned whilst trying to escape @2",
|
||||||
|
},
|
||||||
|
starve = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 starved to death",
|
||||||
|
assist = "@1 starved to death whilst fighting @2",
|
||||||
|
},
|
||||||
|
cactus = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 was pricked to death",
|
||||||
|
assist = "@1 walked into a cactus whilst trying to escape @2",
|
||||||
|
},
|
||||||
|
fall = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 hit the ground too hard",
|
||||||
|
assist = "@1 hit the ground too hard whilst trying to escape @2",
|
||||||
|
-- "@1 fell from a high place" -- for fall distance > 5 blocks
|
||||||
|
-- "@1 fell while climbing"
|
||||||
|
-- "@1 fell off some twisting vines"
|
||||||
|
-- "@1 fell off some weeping vines"
|
||||||
|
-- "@1 fell off some vines"
|
||||||
|
-- "@1 fell off scaffolding"
|
||||||
|
-- "@1 fell off a ladder"
|
||||||
|
},
|
||||||
|
fly_into_wall = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 experienced kinetic energy",
|
||||||
|
assist = "@1 experienced kinetic energy whilst trying to escape @2",
|
||||||
|
},
|
||||||
|
out_of_world = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 fell out of the world",
|
||||||
|
assist = "@1 didn't want to live in the same world as @2",
|
||||||
|
},
|
||||||
|
generic = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 died",
|
||||||
|
assist = "@1 died because of @2",
|
||||||
|
},
|
||||||
|
magic = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 was killed by magic",
|
||||||
|
assist = "@1 was killed by magic whilst trying to escape @2",
|
||||||
|
killer = "@1 was killed by @2 using magic",
|
||||||
|
item = "@1 was killed by @2 using @3",
|
||||||
|
},
|
||||||
|
dragon_breath = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 was roasted in dragon breath",
|
||||||
|
killer = "@1 was roasted in dragon breath by @2",
|
||||||
|
},
|
||||||
|
wither = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 withered away",
|
||||||
|
escape = "@1 withered away whilst fighting @2",
|
||||||
|
},
|
||||||
|
wither_skull = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 was killed by magic",
|
||||||
|
killer = "@1 was shot by a skull from @2",
|
||||||
|
},
|
||||||
|
anvil = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 was squashed by a falling anvil",
|
||||||
|
escape = "@1 was squashed by a falling anvil whilst fighting @2",
|
||||||
|
},
|
||||||
|
falling_node = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 was squashed by a falling block",
|
||||||
|
assist = "@1 was squashed by a falling block whilst fighting @2",
|
||||||
|
},
|
||||||
|
mob = {
|
||||||
|
_translator = S,
|
||||||
|
killer = "@1 was slain by @2",
|
||||||
|
item = "@1 was slain by @2 using @3",
|
||||||
|
},
|
||||||
|
player = {
|
||||||
|
_translator = S,
|
||||||
|
killer = "@1 was slain by @2",
|
||||||
|
item = "@1 was slain by @2 using @3"
|
||||||
|
},
|
||||||
|
arrow = {
|
||||||
|
_translator = S,
|
||||||
|
killer = "@1 was shot by @2",
|
||||||
|
item = "@1 was shot by @2 using @3",
|
||||||
|
},
|
||||||
|
fireball = {
|
||||||
|
_translator = S,
|
||||||
|
killer = "@1 was fireballed by @2",
|
||||||
|
item = "@1 was fireballed by @2 using @3",
|
||||||
|
},
|
||||||
|
thorns = {
|
||||||
|
_translator = S,
|
||||||
|
killer = "@1 was killed trying to hurt @2",
|
||||||
|
item = "@1 was killed by @3 trying to hurt @2", -- yes, the order is intentional: @1 @3 @2
|
||||||
|
},
|
||||||
|
explosion = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 blew up",
|
||||||
|
killer = "@1 was blown up by @2",
|
||||||
|
item = "@1 was blown up by @2 using @3",
|
||||||
|
-- "@1 was killed by [Intentional Game Design]" -- for exploding bed in nether or end
|
||||||
|
},
|
||||||
|
cramming = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 was squished too much",
|
||||||
|
assist = "@1 was squashed by @2", -- surprisingly "escape" is actually the correct subtype
|
||||||
|
},
|
||||||
|
fireworks = {
|
||||||
|
_translator = S,
|
||||||
|
plain = "@1 went off with a bang",
|
||||||
|
item = "@1 went off with a bang due to a firework fired from @3 by @2", -- order is intentional
|
||||||
|
},
|
||||||
|
-- Missing snowballs: The Minecraft wiki mentions them but the MC source code does not.
|
||||||
},
|
},
|
||||||
["arrow_name"] = {
|
|
||||||
N("@1 was shot by @2 using [@3]"),
|
|
||||||
},
|
|
||||||
["arrow_skeleton"] = {
|
|
||||||
N("@1 was shot by Skeleton."),
|
|
||||||
},
|
|
||||||
["arrow_stray"] = {
|
|
||||||
N("@1 was shot by Stray."),
|
|
||||||
},
|
|
||||||
["arrow_illusioner"] = {
|
|
||||||
N("@1 was shot by Illusioner."),
|
|
||||||
},
|
|
||||||
["arrow_mob"] = {
|
|
||||||
N("@1 was shot."),
|
|
||||||
},
|
|
||||||
["drown"] = {
|
|
||||||
N("@1 forgot to breathe."),
|
|
||||||
N("@1 drowned."),
|
|
||||||
N("@1 ran out of oxygen."),
|
|
||||||
},
|
|
||||||
["murder"] = {
|
|
||||||
N("@1 was slain by @2 using [@3]"),
|
|
||||||
},
|
|
||||||
["murder_hand"] = {
|
|
||||||
N("@1 was slain by @2"),
|
|
||||||
},
|
|
||||||
["murder_any"] = {
|
|
||||||
N("@1 was killed."),
|
|
||||||
},
|
|
||||||
["mob_kill"] = {
|
|
||||||
N("@1 was slain by a mob."),
|
|
||||||
},
|
|
||||||
["blaze_fireball"] = {
|
|
||||||
N("@1 was burned to death by a Blaze's fireball."),
|
|
||||||
N("@1 was fireballed by a Blaze"),
|
|
||||||
},
|
|
||||||
["fire_charge"] = {
|
|
||||||
N("@1 was burned by a fire charge."),
|
|
||||||
},
|
|
||||||
["ghast_fireball"] = {
|
|
||||||
N("A Ghast scared @1 to death."),
|
|
||||||
N("@1 has been fireballed by a Ghast."),
|
|
||||||
},
|
|
||||||
["fall"] = {
|
|
||||||
N("@1 fell from a high cliff."),
|
|
||||||
N("@1 took fatal fall damage."),
|
|
||||||
N("@1 fell victim to gravity."),
|
|
||||||
N("@1 hit the ground too hard.")
|
|
||||||
},
|
|
||||||
|
|
||||||
["other"] = {
|
|
||||||
N("@1 died."),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
local mobkills = {
|
local function get_item_killer_message(obj, messages, reason)
|
||||||
["mobs_mc:zombie"] = N("@1 was slain by Zombie."),
|
if messages.item then
|
||||||
["mobs_mc:baby_zombie"] = N("@1 was slain by Baby Zombie."),
|
local wielded = mcl_util.get_wielded_item(reason.source)
|
||||||
["mobs_mc:blaze"] = N("@1 was burnt to a crisp while fighting Blaze."),
|
local itemname = wielded:get_meta():get_string("name")
|
||||||
["mobs_mc:slime"] = N("@1 was slain by Slime."),
|
if itemname ~= "" then
|
||||||
["mobs_mc:witch"] = N("@1 was slain by Witch using magic."),
|
itemname = "[" .. itemname .. "]"
|
||||||
["mobs_mc:magma_cube_tiny"] = N("@1 was slain by Magma Cube."),
|
if mcl_enchanting.is_enchanted(wielded:get_name()) then
|
||||||
["mobs_mc:magma_cube_small"] = N("@1 was slain by Magma Cube."),
|
itemname = minetest.colorize(mcl_colors.AQUA, itemname)
|
||||||
["mobs_mc:magma_cube_big"] = N("@1 was slain by Magma Cube."),
|
end
|
||||||
["mobs_mc:wolf"] = N("@1 was slain by Wolf."),
|
return messages._translator(messages.item, mcl_util.get_object_name(obj), mcl_util.get_object_name(reason.source), itemname)
|
||||||
["mobs_mc:cat"] = N("@1 was slain by Cat."),
|
end
|
||||||
["mobs_mc:ocelot"] = N("@1 was slain by Ocelot."),
|
|
||||||
["mobs_mc:enderdragon"] = N("@1 was slain by Enderdragon."),
|
|
||||||
["mobs_mc:wither"] = N("@1 was slain by Wither."),
|
|
||||||
["mobs_mc:enderman"] = N("@1 was slain by Enderman."),
|
|
||||||
["mobs_mc:endermite"] = N("@1 was slain by Endermite."),
|
|
||||||
["mobs_mc:ghast"] = N("@1 was fireballed by a Ghast."),
|
|
||||||
["mobs_mc:guardian_elder"] = N("@1 was slain by Elder Guardian."),
|
|
||||||
["mobs_mc:guardian"] = N("@1 was slain by Guardian."),
|
|
||||||
["mobs_mc:iron_golem"] = N("@1 was slain by Iron Golem."),
|
|
||||||
["mobs_mc:polar_bear"] = N("@1 was slain by Polar Bear."),
|
|
||||||
["mobs_mc:killer_bunny"] = N("@1 was slain by Killer Bunny."),
|
|
||||||
["mobs_mc:shulker"] = N("@1 was slain by Shulker."),
|
|
||||||
["mobs_mc:silverfish"] = N("@1 was slain by Silverfish."),
|
|
||||||
["mobs_mc:skeleton"] = N("@1 was shot by Skeleton."),
|
|
||||||
["mobs_mc:stray"] = N("@1 was shot by Stray."),
|
|
||||||
["mobs_mc:slime_tiny"] = N("@1 was slain by Slime."),
|
|
||||||
["mobs_mc:slime_small"] = N("@1 was slain by Slime."),
|
|
||||||
["mobs_mc:slime_big"] = N("@1 was slain by Slime."),
|
|
||||||
["mobs_mc:spider"] = N("@1 was slain by Spider."),
|
|
||||||
["mobs_mc:cave_spider"] = N("@1 was slain by Cave Spider."),
|
|
||||||
["mobs_mc:vex"] = N("@1 was slain by Vex."),
|
|
||||||
["mobs_mc:evoker"] = N("@1 was slain by Evoker."),
|
|
||||||
["mobs_mc:illusioner"] = N("@1 was slain by Illusioner."),
|
|
||||||
["mobs_mc:vindicator"] = N("@1 was slain by Vindicator."),
|
|
||||||
["mobs_mc:villager_zombie"] = N("@1 was slain by Zombie Villager."),
|
|
||||||
["mobs_mc:husk"] = N("@1 was slain by Husk."),
|
|
||||||
["mobs_mc:baby_husk"] = N("@1 was slain by Baby Husk."),
|
|
||||||
["mobs_mc:pigman"] = N("@1 was slain by Zombie Pigman."),
|
|
||||||
["mobs_mc:baby_pigman"] = N("@1 was slain by Baby Zombie Pigman."),
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Select death message
|
|
||||||
local dmsg = function(mtype, ...)
|
|
||||||
local r = math.random(1, #msgs[mtype])
|
|
||||||
return S(msgs[mtype][r], ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Select death message for death by mob
|
|
||||||
local mmsg = function(mtype, ...)
|
|
||||||
if mobkills[mtype] then
|
|
||||||
return S(mobkills[mtype], ...)
|
|
||||||
else
|
|
||||||
return dmsg("mob_kill", ...)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local last_damages = { }
|
local function get_plain_killer_message(obj, messages, reason)
|
||||||
|
return messages.killer and messages._translator(messages.killer, mcl_util.get_object_name(obj), mcl_util.get_object_name(reason.source))
|
||||||
|
end
|
||||||
|
|
||||||
minetest.register_on_dieplayer(function(player, reason)
|
local function get_killer_message(obj, messages, reason)
|
||||||
-- Death message
|
return reason.source and (get_item_killer_message(obj, messages, reason) or get_plain_killer_message(obj, messages, reason))
|
||||||
local message = minetest.settings:get_bool("mcl_showDeathMessages") --Maybe cache the setting?
|
end
|
||||||
if message == nil then
|
|
||||||
message = true
|
local function get_assist_message(obj, messages, reason)
|
||||||
|
if messages.assist and mcl_death_messages.assist[obj] then
|
||||||
|
return messages._translator(messages.assist, mcl_util.get_object_name(obj), mcl_death_messages.assist[obj].name)
|
||||||
end
|
end
|
||||||
if message then
|
end
|
||||||
local name = player:get_player_name()
|
|
||||||
if not name then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local msg
|
|
||||||
if last_damages[name] then
|
|
||||||
-- custom message
|
|
||||||
msg = last_damages[name].message
|
|
||||||
elseif reason.type == "node_damage" then
|
|
||||||
local pos = player:get_pos()
|
|
||||||
-- Check multiple nodes because players occupy multiple nodes
|
|
||||||
-- (we add one additional node because the check may fail if the player was
|
|
||||||
-- just barely touching the node with the head)
|
|
||||||
local posses = { pos, {x=pos.x,y=pos.y+1,z=pos.z}, {x=pos.x,y=pos.y+2,z=pos.z}}
|
|
||||||
local highest_damage = 0
|
|
||||||
local highest_damage_def = nil
|
|
||||||
-- Show message for node that dealt the most damage
|
|
||||||
for p=1, #posses do
|
|
||||||
local def = minetest.registered_nodes[minetest.get_node(posses[p]).name]
|
|
||||||
local dmg = def.damage_per_second
|
|
||||||
if dmg and dmg > highest_damage then
|
|
||||||
highest_damage = dmg
|
|
||||||
highest_damage_def = def
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if highest_damage_def and highest_damage_def._mcl_node_death_message then
|
|
||||||
local field = highest_damage_def._mcl_node_death_message
|
|
||||||
local field_msg
|
|
||||||
if type(field) == "table" then
|
|
||||||
field_msg = field[math.random(1, #field)]
|
|
||||||
else
|
|
||||||
field_msg = field
|
|
||||||
end
|
|
||||||
local textdomain
|
|
||||||
if highest_damage_def.mod_origin then
|
|
||||||
textdomain = highest_damage_def.mod_origin
|
|
||||||
else
|
|
||||||
textdomain = "mcl_death_messages"
|
|
||||||
end
|
|
||||||
-- We assume the textdomain of the death message in the node definition
|
|
||||||
-- equals the modname.
|
|
||||||
msg = minetest.translate(textdomain, field_msg, name)
|
|
||||||
end
|
|
||||||
elseif reason.type == "drown" then
|
|
||||||
msg = dmsg("drown", name)
|
|
||||||
elseif reason.type == "punch" then
|
|
||||||
-- Punches
|
|
||||||
local hitter = reason.object
|
|
||||||
|
|
||||||
-- Player was slain by potions
|
local function get_plain_message(obj, messages, reason)
|
||||||
if not hitter then return end
|
if messages.plain then
|
||||||
|
return messages._translator(messages.plain, mcl_util.get_object_name(obj))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local hittername, hittertype, hittersubtype, shooter
|
local function get_fallback_message(obj, messages, reason)
|
||||||
local hitter_toolname = get_tool_name(hitter:get_wielded_item())
|
return "mcl_death_messages.messages." .. reason.type .. " " .. mcl_util.get_object_name(obj)
|
||||||
|
end
|
||||||
|
|
||||||
-- Custom message
|
local function fallback_translator(s)
|
||||||
if last_damages[name] then
|
return s
|
||||||
msg = last_damages[name].message
|
end
|
||||||
-- Unknown hitter
|
|
||||||
elseif hitter == nil then
|
mcl_damage.register_on_death(function(obj, reason)
|
||||||
msg = dmsg("murder_any", name)
|
if not minetest.settings:get_bool("mcl_showDeathMessages", true) then
|
||||||
-- Player
|
return
|
||||||
elseif hitter:is_player() then
|
end
|
||||||
hittername = hitter:get_player_name()
|
|
||||||
if hittername ~= nil then
|
local send_to
|
||||||
if hitter_toolname == "" then
|
|
||||||
msg = dmsg("murder_hand", name, hittername)
|
if obj:is_player() then
|
||||||
else
|
send_to = true
|
||||||
msg = dmsg("murder", name, hittername, C(color_skyblue, hitter_toolname))
|
end -- ToDo: add mob death messages for owned mobs, only send to owner (sent_to = "player name")
|
||||||
end
|
|
||||||
else
|
|
||||||
msg = dmsg("murder_any", name)
|
if send_to then
|
||||||
end
|
local messages = mcl_death_messages.messages[reason.type] or {}
|
||||||
-- Mob (according to Common Mob Interface)
|
messages._translator = messages._translator or fallback_translator
|
||||||
elseif hitter:get_luaentity()._cmi_is_mob then
|
|
||||||
if hitter:get_luaentity().nametag and hitter:get_luaentity().nametag ~= "" then
|
local message =
|
||||||
hittername = hitter:get_luaentity().nametag
|
get_killer_message(obj, messages, reason) or
|
||||||
end
|
get_assist_message(obj, messages, reason) or
|
||||||
hittersubtype = hitter:get_luaentity().name
|
get_plain_message(obj, messages, reason) or
|
||||||
if hittername then
|
get_fallback_message(obj, messages, reason)
|
||||||
msg = dmsg("murder_hand", name, hittername)
|
|
||||||
elseif hittersubtype ~= nil and hittersubtype ~= "" then
|
if send_to == true then
|
||||||
msg = mmsg(hittersubtype, name)
|
minetest.chat_send_all(message)
|
||||||
else
|
else
|
||||||
msg = dmsg("murder_any", name)
|
minetest.chat_send_player(send_to, message)
|
||||||
end
|
|
||||||
-- Arrow
|
|
||||||
elseif hitter:get_luaentity().name == "mcl_bows:arrow_entity" or hitter:get_luaentity().name == "mobs_mc:arrow_entity" and not killed_by_potion then
|
|
||||||
local shooter
|
|
||||||
if hitter:get_luaentity()._shooter then
|
|
||||||
shooter = hitter:get_luaentity()._shooter
|
|
||||||
end
|
|
||||||
local is_mob = false
|
|
||||||
local s_ent = shooter and shooter:get_luaentity()
|
|
||||||
if shooter == nil then
|
|
||||||
msg = dmsg("arrow", name)
|
|
||||||
elseif shooter:is_player() then
|
|
||||||
msg = dmsg("arrow_name", name, shooter:get_player_name(), C(color_skyblue, get_tool_name(shooter:get_wielded_item())))
|
|
||||||
elseif s_ent and s_ent._cmi_is_mob then
|
|
||||||
if s_ent.nametag ~= "" then
|
|
||||||
msg = dmsg("arrow_name", name, shooter:get_player_name(), get_tool_name(shooter:get_wielded_item()))
|
|
||||||
elseif s_ent.name == "mobs_mc:skeleton" then
|
|
||||||
msg = dmsg("arrow_skeleton", name)
|
|
||||||
elseif s_ent.name == "mobs_mc:stray" then
|
|
||||||
msg = dmsg("arrow_stray", name)
|
|
||||||
elseif s_ent.name == "mobs_mc:illusioner" then
|
|
||||||
msg = dmsg("arrow_illusioner", name)
|
|
||||||
else
|
|
||||||
msg = dmsg("arrow_mob", name)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
msg = dmsg("arrow", name)
|
|
||||||
end
|
|
||||||
-- Blaze fireball
|
|
||||||
elseif hitter:get_luaentity().name == "mobs_mc:blaze_fireball" then
|
|
||||||
if hitter:get_luaentity()._shot_from_dispenser then
|
|
||||||
msg = dmsg("fire_charge", name)
|
|
||||||
else
|
|
||||||
msg = dmsg("blaze_fireball", name)
|
|
||||||
end
|
|
||||||
-- Ghast fireball
|
|
||||||
elseif hitter:get_luaentity().name == "mobs_monster:fireball" then
|
|
||||||
msg = dmsg("ghast_fireball", name)
|
|
||||||
end
|
|
||||||
-- Falling
|
|
||||||
elseif reason.type == "fall" then
|
|
||||||
msg = dmsg("fall", name)
|
|
||||||
-- Other
|
|
||||||
elseif reason.type == "set_hp" then
|
|
||||||
if last_damages[name] then
|
|
||||||
msg = last_damages[name].message
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
if not msg then
|
|
||||||
msg = dmsg("other", name)
|
|
||||||
end
|
|
||||||
minetest.chat_send_all(msg)
|
|
||||||
last_damages[name] = nil
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- dmg_sequence_number is used to discard old damage events
|
mcl_damage.register_on_damage(function(obj, damage, reason)
|
||||||
local dmg_sequence_number = 0
|
if obj:get_hp() - damage > 0 then
|
||||||
local start_damage_reset_countdown = function (player, sequence_number)
|
if reason.source then
|
||||||
minetest.after(1, function(playername, sequence_number)
|
mcl_death_messages.assist[obj] = {name = mcl_util.get_object_name(reason.source), timeout = 5}
|
||||||
if last_damages[playername] and last_damages[playername].sequence_number == sequence_number then
|
else
|
||||||
last_damages[playername] = nil
|
mcl_death_messages.assist[obj] = nil
|
||||||
end
|
end
|
||||||
end, player:get_player_name(), sequence_number)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Send a custom death mesage when damaging a player via set_hp or punch.
|
|
||||||
-- To be called directly BEFORE damaging a player via set_hp or punch.
|
|
||||||
-- The next time the player dies due to a set_hp, the message will be shown.
|
|
||||||
-- The player must die via set_hp within 0.1 seconds, otherwise the message will be discarded.
|
|
||||||
function mcl_death_messages.player_damage(player, message)
|
|
||||||
last_damages[player:get_player_name()] = { message = message, sequence_number = dmg_sequence_number }
|
|
||||||
start_damage_reset_countdown(player, dmg_sequence_number)
|
|
||||||
dmg_sequence_number = dmg_sequence_number + 1
|
|
||||||
if dmg_sequence_number >= 65535 then
|
|
||||||
dmg_sequence_number = 0
|
|
||||||
end
|
end
|
||||||
end
|
end)
|
||||||
|
|
||||||
|
minetest.register_globalstep(function(dtime)
|
||||||
|
local new_assist = {}
|
||||||
|
|
||||||
|
for obj, tbl in pairs(mcl_death_messages.assist) do
|
||||||
|
tbl.timeout = tbl.timeout - dtime
|
||||||
|
if (obj:is_player() or obj:get_luaentity()) and tbl.timeout > 0 then
|
||||||
|
new_assist[obj] = tbl
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
|
@ -1,59 +1,58 @@
|
||||||
# textdomain: mcl_death_messages
|
# textdomain: mcl_death_messages
|
||||||
@1 was fatally hit by an arrow.=@1 wurde tödlich von einem Pfeil getroffen.
|
@1 went up in flames=@1 ging in Flammen auf
|
||||||
@1 has been killed by an arrow.=@1 wurde von einem Pfeil getötet.
|
@1 walked into fire whilst fighting @2=@1 ist während eines Kampfes mit @2 in ein Feuer gelaufen
|
||||||
@1 was shot by an arrow from @2.=@1 wurde mit einem Pfeil von @2 abgeschossen.
|
@1 was struck by lightning=@1 wurde von einem Blitz erschlagen
|
||||||
@1 was shot by an arrow from a skeleton.=@1 wurde von einem Skelett mit Pfeil und Bogen abgeschossen.
|
@1 was struck by lightning whilst fighting @2=@1 wurde während eines Kampfes mit @2 von einem Blitz erschlagen
|
||||||
@1 was shot by an arrow from a stray.=@1 wurde von einem Eiswanderer mit Pfeil und Bogen abgeschossen.
|
@1 burned to death=@1 ist verbrannt
|
||||||
@1 was shot by an arrow from an illusioner.=@1 wurde von einem Illusionisten mit Pfeil und Bogen abgeschossen.
|
@1 was burnt to a crisp whilst fighting @2=@1 ist während eines Kampfes mit @2 verbrannt
|
||||||
@1 was shot by an arrow.=@1 wurde mit einem Pfeil abgeschossen.
|
@1 tried to swim in lava=@1 hat versucht, in Lava zu schwimmen
|
||||||
@1 forgot to breathe.=@1 vergaß, zu atmen.
|
@1 tried to swim in lava to escape @2=@1 hat versucht, in Lava zu schwimmen, um @2 zu entkommen
|
||||||
@1 drowned.=@1 ertrank.
|
@1 discovered the floor was lava=@1 hat festgestellt, dass der Boden Lava ist
|
||||||
@1 ran out of oxygen.=@1 ging die Luft aus.
|
@1 walked into danger zone due to @2=@1 ist wegen @2 in eine Gefahrenzone gelaufen
|
||||||
@1 was killed by @2.=@1 wurde von @2 getötet.
|
@1 suffocated in a wall=@1 ist in einer Mauer erstickt
|
||||||
@1 was killed.=@1 wurde getötet.
|
@1 suffocated in a wall whilst fighting @2=@1 ist während eines Kampfes mit @2 in einer Mauer erstickt
|
||||||
@1 was killed by a mob.=@1 wurde von einem Mob getötet.
|
@1 drowned=@1 ist ertrunken
|
||||||
@1 was burned to death by a blaze's fireball.=@1 wurde von einem Feuerball einer Lohe zu Tode verbrannt.
|
@1 drowned whilst trying to escape @2=@1 ist während dem Versuch, @2 zu entkommen, ertrunken
|
||||||
@1 was killed by a fireball from a blaze.=@1 wurde von einem Feuerball einer Lohe getötet.
|
@1 starved to death=@1 ist verhungert
|
||||||
@1 was burned by a fire charge.=@1 wurde von einer Feuerkugel verbrannt.
|
@1 starved to death whilst fighting @2=@1 ist während eines Kampfes mit @2 verhungert
|
||||||
A ghast scared @1 to death.=Ein Ghast hat @1 zu Tode erschrocken.
|
@1 was pricked to death=@1 wurde zu Tode gestochen
|
||||||
@1 has been fireballed by a ghast.=@1 wurde von einem Ghast mit einer Feuerkugel abgeschossen.
|
@1 walked into a cactus whilst trying to escape @2=@1 ist während dem Versuch, @2 zu entkommen, in einen Kaktus gelaufen
|
||||||
@1 fell from a high cliff.=@1 stürzte von einer hohen Klippe.
|
@1 hit the ground too hard=@1 ist zu hart auf dem Boden aufgetroffen
|
||||||
@1 took fatal fall damage.=@1 nahm tödlichen Fallschaden.
|
@1 hit the ground too hard whilst trying to escape @2=@1 ist während dem Versuch, @2 zu entkommen, zu hart auf dem Boden aufgetroffen
|
||||||
@1 fell victim to gravity.=@1 fiel der Schwerkraft zum Opfer.
|
@1 experienced kinetic energy=@1 hat kinetische Energie erfahren
|
||||||
@1 died.=@1 starb.
|
@1 experienced kinetic energy whilst trying to escape @2=@1 hat während dem Versuch, @2 zu entkommen, kinetische Energie erfahren
|
||||||
@1 was killed by a zombie.=@1 wurde von einem Zombie getötet.
|
@1 fell out of the world=@1 ist aus der Welt gefallen
|
||||||
@1 was killed by a baby zombie.=@1 wurde von einem Zombiebaby getötet.
|
@1 didn't want to live in the same world as @2=@1 wollte nicht in der gleichen Welt wie @2 leben
|
||||||
@1 was killed by a blaze.=@1 wurde von einer Lohe getötet.
|
@1 died=@1 ist gestorben
|
||||||
@1 was killed by a slime.=@1 wurde von einem Schleim getötet.
|
@1 died because of @2=@1 ist wegen @2 gestorben
|
||||||
@1 was killed by a witch.=@1 wurde von einer Hexe getötet.
|
@1 was killed by magic=@1 wurde von Magie getötet
|
||||||
@1 was killed by a magma cube.=@1 wurde von einem Magmakubus getötet.
|
@1 was killed by magic whilst trying to escape @2=@1 wurde während dem Versuch, @2 zu entkommen, von Magie getötet
|
||||||
@1 was killed by a wolf.=@1 wurde von einem Wolf getötet.
|
@1 was killed by @2 using magic=@1 wurde von @2 mit Magie getötet
|
||||||
@1 was killed by a cat.=@1 wurde von einer Katze getötet.
|
@1 was killed by @2 using @3=@1 wurde von @2 mit @3 getötet
|
||||||
@1 was killed by an ocelot.=@1 wurde von einem Ozelot getötet.
|
@1 was roasted in dragon breath=@1 wurde in Drachenatem geröstet
|
||||||
@1 was killed by an ender dragon.=@1 wurde von einem Enderdrachen getötet.
|
@1 was roasted in dragon breath by @2=@1 wurde in Drachenatem von @2 geröstet
|
||||||
@1 was killed by a wither.=@1 wurde von einem Wither getötet.
|
@1 withered away=@1 ist davon gewithert
|
||||||
@1 was killed by an enderman.=@1 wurde von einem Enderman getötet.
|
@1 withered away whilst fighting @2=@1 ist während einem Kampf mit @2 davon gewithert
|
||||||
@1 was killed by an endermite.=@1 wurde von einer Endermilbe getötet.
|
@1 was killed by magic=@1 wurde von Magie getötet
|
||||||
@1 was killed by a ghast.=@1 wurde von einem Ghast getötet.
|
@1 was shot by a skull from @2=@1 wurde von einem Schädel von @2 erschossen
|
||||||
@1 was killed by an elder guardian.=@1 wurde von einem Großen Wächter getötet.
|
@1 was squashed by a falling anvil=@1 wurde von einem fallenden Amboss erquetscht
|
||||||
@1 was killed by a guardian.=@1 wurde von einem Wächter getötet.
|
@1 was squashed by a falling anvil whilst fighting @2=@1 wurde während einem Kampf mit @2 von einem fallenden Amboss erquetscht
|
||||||
@1 was killed by an iron golem.=@1 wurde von einem Eisengolem getötet.
|
@1 was squashed by a falling block=@1 wurde von einem fallenden Block erquetscht
|
||||||
@1 was killed by a polar_bear.=@1 wurde von einem Eisbären getötet.
|
@1 was squashed by a falling block whilst fighting @2=@1 wurde während einem Kampf mit @2 von einem fallenden Block erquetscht
|
||||||
@1 was killed by a killer bunny.=@1 wurde von einem Killerkaninchen getötet.
|
@1 was slain by @2=@1 wurde von @2 erschlagen
|
||||||
@1 was killed by a shulker.=@1 wurde von einem Schulker getötet.
|
@1 was slain by @2 using @3=@1 wurde von @2 mit @3 erschlagen
|
||||||
@1 was killed by a silverfish.=@1 wurde von einem Silberfischchen getötet.
|
@1 was slain by @2=@1 wurde von @2 erschlagen
|
||||||
@1 was killed by a skeleton.=@1 wurde von einem Skelett getötet.
|
@1 was slain by @2 using @3=@1 wurde von @2 mit @3 erschlagen
|
||||||
@1 was killed by a stray.=@1 wurde von einem Eiswanderer getötet.
|
@1 was shot by @2=@1 wurde von @2 erschossen
|
||||||
@1 was killed by a slime.=@1 wurde von einem Schleim getötet.
|
@1 was shot by @2 using @3=@1 wurde von @2 mit @3 erschossen
|
||||||
@1 was killed by a spider.=@1 wurde von einer Spinne getötet.
|
@1 was fireballed by @2=@1 wurde von @2 gefeuerballt
|
||||||
@1 was killed by a cave spider.=@1 wurde von einer Höhlenspinne getötet.
|
@1 was fireballed by @2 using @3=@1 wurde von @2 mit @3 gefeuerballt
|
||||||
@1 was killed by a vex.=@1 wurde von einem Plagegeist getötet.
|
@1 was killed trying to hurt @2=@1 ist bei dem Versuch, @2 zu verletzten gestorben
|
||||||
@1 was killed by an evoker.=@1 wurde von einem Magier getötet.
|
@1 was killed by @3 trying to hurt @2=@1 ist bei dem Versuch, @2 zu verletzten, von @3 getötet worden
|
||||||
@1 was killed by an illusioner.=@1 wurde von einem Illusionisten getötet.
|
@1 blew up=@1 ist gesprengt worden
|
||||||
@1 was killed by a vindicator.=@1 wurde von einem Diener getötet.
|
@1 was blown up by @2=@1 wurde von @2 gesprengt
|
||||||
@1 was killed by a zombie villager.=@1 wurde von einem Dorfbewohnerzombie getötet.
|
@1 was blown up by @2 using @3=@1 wurde von @2 mit @3 gesprengt
|
||||||
@1 was killed by a husk.=@1 wurde von einem Wüstenzombie getötet.
|
@1 was squished too much=@1 war zu gequetscht
|
||||||
@1 was killed by a baby husk.=@1 wurde von einem Wüstenzombiebaby getötet.
|
@1 was squashed by @2=@1 wurde von @2 erquetscht
|
||||||
@1 was killed by a zombie pigman.=@1 wurde von einem Schweinezombie getötet.
|
@1 went off with a bang=@1 ging mit einem Knall ab
|
||||||
@1 was killed by a baby zombie pigman.=@1 wurde von einem Schweinezombiebaby getötet.
|
@1 went off with a bang due to a firework fired from @3 by @2=@1 ging mit einem Knall wegen eines Feuerwerks, das mit @3 von @2 gefeuert wurde, ab
|
||||||
@1 was slain by @2.=
|
|
||||||
|
|
|
@ -1,59 +1,58 @@
|
||||||
# textdomain: mcl_death_messages
|
# textdomain: mcl_death_messages
|
||||||
@1 was fatally hit by an arrow.=
|
@1 went up in flames=
|
||||||
@1 has been killed with an arrow.=
|
@1 walked into fire whilst fighting @2=
|
||||||
@1 was shot by an arrow from @2.=
|
@1 was struck by lightning=
|
||||||
@1 was shot by an arrow from a skeleton.=
|
@1 was struck by lightning whilst fighting @2=
|
||||||
@1 was shot by an arrow from a stray.=
|
@1 burned to death=
|
||||||
@1 was shot by an arrow from an illusioner.=
|
@1 was burnt to a crisp whilst fighting @2=
|
||||||
@1 was shot by an arrow.=
|
@1 tried to swim in lava=
|
||||||
@1 forgot to breathe.=
|
@1 tried to swim in lava to escape @2=
|
||||||
@1 drowned.=
|
@1 discovered the floor was lava=
|
||||||
@1 ran out of oxygen.=
|
@1 walked into danger zone due to @2=
|
||||||
@1 was killed by @2.=
|
@1 suffocated in a wall=
|
||||||
@1 was killed.=
|
@1 suffocated in a wall whilst fighting @2=
|
||||||
@1 was killed by a mob.=
|
@1 drowned=
|
||||||
@1 was burned to death by a blaze's fireball.=
|
@1 drowned whilst trying to escape @2=
|
||||||
@1 was killed by a fireball from a blaze.=
|
@1 starved to death=
|
||||||
@1 was burned by a fire charge.=
|
@1 starved to death whilst fighting @2=
|
||||||
A ghast scared @1 to death.=
|
@1 was pricked to death=
|
||||||
@1 has been fireballed by a ghast.=
|
@1 walked into a cactus whilst trying to escape @2=
|
||||||
@1 fell from a high cliff.=
|
@1 hit the ground too hard=
|
||||||
@1 took fatal fall damage.=
|
@1 hit the ground too hard whilst trying to escape @2=
|
||||||
@1 fell victim to gravity.=
|
@1 experienced kinetic energy=
|
||||||
@1 died.=
|
@1 experienced kinetic energy whilst trying to escape @2=
|
||||||
@1 was killed by a zombie.=
|
@1 fell out of the world=
|
||||||
@1 was killed by a baby zombie.=
|
@1 didn't want to live in the same world as @2=
|
||||||
@1 was killed by a blaze.=
|
@1 died=
|
||||||
@1 was killed by a slime.=
|
@1 died because of @2=
|
||||||
@1 was killed by a witch.=
|
@1 was killed by magic=
|
||||||
@1 was killed by a magma cube.=
|
@1 was killed by magic whilst trying to escape @2=
|
||||||
@1 was killed by a wolf.=
|
@1 was killed by @2 using magic=
|
||||||
@1 was killed by a cat.=
|
@1 was killed by @2 using @3=
|
||||||
@1 was killed by an ocelot.=
|
@1 was roasted in dragon breath=
|
||||||
@1 was killed by an ender dragon.=
|
@1 was roasted in dragon breath by @2=
|
||||||
@1 was killed by a wither.=
|
@1 withered away=
|
||||||
@1 was killed by an enderman.=
|
@1 withered away whilst fighting @2=
|
||||||
@1 was killed by an endermite.=
|
@1 was killed by magic=
|
||||||
@1 was killed by a ghast.=
|
@1 was shot by a skull from @2=
|
||||||
@1 was killed by an elder guardian.=
|
@1 was squashed by a falling anvil=
|
||||||
@1 was killed by a guardian.=
|
@1 was squashed by a falling anvil whilst fighting @2=
|
||||||
@1 was killed by an iron golem.=
|
@1 was squashed by a falling block=
|
||||||
@1 was killed by a polar_bear.=
|
@1 was squashed by a falling block whilst fighting @2=
|
||||||
@1 was killed by a killer bunny.=
|
@1 was slain by @2=
|
||||||
@1 was killed by a shulker.=
|
@1 was slain by @2 using @3=
|
||||||
@1 was killed by a silverfish.=
|
@1 was slain by @2=
|
||||||
@1 was killed by a skeleton.=
|
@1 was slain by @2 using @3=
|
||||||
@1 was killed by a stray.=
|
@1 was shot by @2=
|
||||||
@1 was killed by a slime.=
|
@1 was shot by @2 using @3=
|
||||||
@1 was killed by a spider.=
|
@1 was fireballed by @2=
|
||||||
@1 was killed by a cave spider.=
|
@1 was fireballed by @2 using @3=
|
||||||
@1 was killed by a vex.=
|
@1 was killed trying to hurt @2=
|
||||||
@1 was killed by an evoker.=
|
@1 was killed by @3 trying to hurt @2=
|
||||||
@1 was killed by an illusioner.=
|
@1 blew up=
|
||||||
@1 was killed by a vindicator.=
|
@1 was blown up by @2=
|
||||||
@1 was killed by a zombie villager.=
|
@1 was blown up by @2 using @3=
|
||||||
@1 was killed by a husk.=
|
@1 was squished too much=
|
||||||
@1 was killed by a baby husk.=
|
@1 was squashed by @2=
|
||||||
@1 was killed by a zombie pigman.=
|
@1 went off with a bang=
|
||||||
@1 was killed by a baby zombie pigman.=
|
@1 went off with a bang due to a firework fired from @3 by @2=
|
||||||
@1 was slain by @2.=
|
|
||||||
|
|
|
@ -263,34 +263,7 @@ function mcl_experience.add_experience(player, experience)
|
||||||
local can = final_candidates[math.random(#final_candidates)]
|
local can = final_candidates[math.random(#final_candidates)]
|
||||||
local stack, list, index, wear = can.stack, can.list, can.index, can.wear
|
local stack, list, index, wear = can.stack, can.list, can.index, can.wear
|
||||||
local unbreaking_level = mcl_enchanting.get_enchantment(stack, "unbreaking")
|
local unbreaking_level = mcl_enchanting.get_enchantment(stack, "unbreaking")
|
||||||
local uses
|
local uses = mcl_util.calculate_durability(itemstack)
|
||||||
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 multiplier = 2 * 65535 / uses
|
local multiplier = 2 * 65535 / uses
|
||||||
local repair = experience * multiplier
|
local repair = experience * multiplier
|
||||||
local new_wear = wear - repair
|
local new_wear = wear - repair
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
local S = minetest.get_translator("mcl_hbarmor")
|
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 = {}
|
local mcl_hbarmor = {}
|
||||||
|
|
||||||
-- HUD statbar values
|
-- 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)
|
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)
|
function mcl_hbarmor.get_armor(player)
|
||||||
if not player or not armor.def then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
local name = player:get_player_name()
|
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
|
if not pts then
|
||||||
return false
|
return false
|
||||||
else
|
else
|
||||||
|
|
|
@ -7,7 +7,6 @@ local players = {}
|
||||||
-- Containing all the items for each Creative Mode tab
|
-- Containing all the items for each Creative Mode tab
|
||||||
local inventory_lists = {}
|
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
|
-- Create tables
|
||||||
|
@ -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
|
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, "")
|
player_preview = mcl_player.get_player_formspec_model(player, 3.9, 1.4, 1.2333, 2.4666, "")
|
||||||
else
|
else
|
||||||
local img, img_player
|
player_preview = "image[3.9,1.4;1.2333,2.4666;"..mcl_player.player_get_preview(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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Background images for armor slots (hide if occupied)
|
-- 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]"..
|
main_list = "list[current_player;main;0,3.75;9,3;9]"..
|
||||||
mcl_formspec.get_itemslot_bg(0,3.75,9,3)..
|
mcl_formspec.get_itemslot_bg(0,3.75,9,3)..
|
||||||
-- armor
|
-- armor
|
||||||
"list[detached:"..playername.."_armor;armor;2.5,1.3;1,1;1]"..
|
"list[current_player;armor;2.5,1.3;1,1;1]"..
|
||||||
"list[detached:"..playername.."_armor;armor;2.5,2.75;1,1;2]"..
|
"list[current_player;armor;2.5,2.75;1,1;2]"..
|
||||||
"list[detached:"..playername.."_armor;armor;5.5,1.3;1,1;3]"..
|
"list[current_player;armor;5.5,1.3;1,1;3]"..
|
||||||
"list[detached:"..playername.."_armor;armor;5.5,2.75;1,1;4]"..
|
"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,1.3,1,1)..
|
||||||
mcl_formspec.get_itemslot_bg(2.5,2.75,1,1)..
|
mcl_formspec.get_itemslot_bg(2.5,2.75,1,1)..
|
||||||
mcl_formspec.get_itemslot_bg(5.5,1.3,1,1)..
|
mcl_formspec.get_itemslot_bg(5.5,1.3,1,1)..
|
||||||
|
|
|
@ -3,7 +3,6 @@ local F = minetest.formspec_escape
|
||||||
|
|
||||||
mcl_inventory = {}
|
mcl_inventory = {}
|
||||||
|
|
||||||
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
|
||||||
local mod_craftguide = minetest.get_modpath("mcl_craftguide") ~= 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
|
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, "")
|
player_preview = mcl_player.get_player_formspec_model(player, 1.0, 0.0, 2.25, 4.5, "")
|
||||||
else
|
else
|
||||||
local img, img_player
|
player_preview = "image[1.1,0.2;2,4;"..mcl_player.player_get_preview(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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local armor_slots = {"helmet", "chestplate", "leggings", "boots"}
|
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]"..
|
"background[-0.19,-0.25;9.41,9.49;crafting_formspec_bg.png]"..
|
||||||
player_preview..
|
player_preview..
|
||||||
--armor
|
--armor
|
||||||
"list[detached:"..player_name.."_armor;armor;0,0;1,1;1]"..
|
"list[current_player;armor;0,0;1,1;1]"..
|
||||||
"list[detached:"..player_name.."_armor;armor;0,1;1,1;2]"..
|
"list[current_player;armor;0,1;1,1;2]"..
|
||||||
"list[detached:"..player_name.."_armor;armor;0,2;1,1;3]"..
|
"list[current_player;armor;0,2;1,1;3]"..
|
||||||
"list[detached:"..player_name.."_armor;armor;0,3;1,1;4]"..
|
"list[current_player;armor;0,3;1,1;4]"..
|
||||||
mcl_formspec.get_itemslot_bg(0,0,1,1)..
|
mcl_formspec.get_itemslot_bg(0,0,1,1)..
|
||||||
mcl_formspec.get_itemslot_bg(0,1,1,1)..
|
mcl_formspec.get_itemslot_bg(0,1,1,1)..
|
||||||
mcl_formspec.get_itemslot_bg(0,2,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")).."]"..
|
"tooltip[__mcl_achievements;"..F(S("Achievements")).."]"..
|
||||||
-- for shortcuts
|
-- for shortcuts
|
||||||
"listring[current_player;main]"..
|
"listring[current_player;main]"..
|
||||||
"listring[current_player;craft]"..
|
"listring[current_player;armor]"..
|
||||||
"listring[current_player;main]"..
|
"listring[current_player;main]" ..
|
||||||
"listring[detached:"..player_name.."_armor;armor]"
|
"listring[current_player;craft]" ..
|
||||||
|
"listring[current_player;main]"
|
||||||
player:set_inventory_formspec(form)
|
player:set_inventory_formspec(form)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -176,18 +159,10 @@ minetest.register_on_joinplayer(function(player)
|
||||||
player:hud_set_hotbar_image("mcl_inventory_hotbar.png")
|
player:hud_set_hotbar_image("mcl_inventory_hotbar.png")
|
||||||
player:hud_set_hotbar_selected_image("mcl_inventory_hotbar_selected.png")
|
player:hud_set_hotbar_selected_image("mcl_inventory_hotbar_selected.png")
|
||||||
|
|
||||||
if show_armor then
|
local old_update_player = mcl_armor.update_player
|
||||||
local set_player_armor_original = armor.set_player_armor
|
mcl_armor.update_player = function(player, info)
|
||||||
local update_inventory_original = armor.update_inventory
|
old_update_player(player, info)
|
||||||
armor.set_player_armor = function(self, player)
|
set_inventory(player, true)
|
||||||
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)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- In Creative Mode, the initial inventory setup is handled in creative.lua
|
-- In Creative Mode, the initial inventory setup is handled in creative.lua
|
||||||
|
|
|
@ -136,94 +136,32 @@ local dispenserdef = {
|
||||||
-- Hardcoded dispensions --
|
-- Hardcoded dispensions --
|
||||||
|
|
||||||
-- Armor, mob heads and pumpkins
|
-- Armor, mob heads and pumpkins
|
||||||
if igroups.armor_head or igroups.armor_torso or igroups.armor_legs or igroups.armor_feet then
|
if igroups.armor then
|
||||||
local armor_type, armor_slot
|
local droppos_below = {x = droppos.x, y = droppos.y - 1, z = droppos.z}
|
||||||
local armor_dispensed = false
|
|
||||||
if igroups.armor_head then
|
|
||||||
armor_type = "armor_head"
|
|
||||||
armor_slot = 2
|
|
||||||
elseif igroups.armor_torso then
|
|
||||||
armor_type = "armor_torso"
|
|
||||||
armor_slot = 3
|
|
||||||
elseif igroups.armor_legs then
|
|
||||||
armor_type = "armor_legs"
|
|
||||||
armor_slot = 4
|
|
||||||
elseif igroups.armor_feet then
|
|
||||||
armor_type = "armor_feet"
|
|
||||||
armor_slot = 5
|
|
||||||
end
|
|
||||||
|
|
||||||
local droppos_below = {x=droppos.x, y=droppos.y-1, z=droppos.z}
|
for _, objs in ipairs({minetest.get_objects_inside_radius(droppos, 1), minetest.get_objects_inside_radius(droppos_below, 1)}) do
|
||||||
local dropnode_below = minetest.get_node(droppos_below)
|
for _, obj in ipairs(objs) do
|
||||||
-- Put armor on player or armor stand
|
stack = mcl_armor.equip(stack, obj)
|
||||||
local standpos
|
if stack:is_empty() then
|
||||||
if dropnode.name == "mcl_armor_stand:armor_stand" then
|
|
||||||
standpos = droppos
|
|
||||||
elseif dropnode_below.name == "mcl_armor_stand:armor_stand" then
|
|
||||||
standpos = droppos_below
|
|
||||||
end
|
|
||||||
if standpos then
|
|
||||||
local dropmeta = minetest.get_meta(standpos)
|
|
||||||
local dropinv = dropmeta:get_inventory()
|
|
||||||
if dropinv:room_for_item(armor_type, dropitem) then
|
|
||||||
dropinv:add_item(armor_type, dropitem)
|
|
||||||
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)
|
|
||||||
armor_dispensed = true
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- Put armor on nearby player
|
|
||||||
-- First search for player in front of dispenser (check 2 nodes)
|
|
||||||
local objs1 = minetest.get_objects_inside_radius(droppos, 1)
|
|
||||||
local objs2 = minetest.get_objects_inside_radius(droppos_below, 1)
|
|
||||||
local objs_table = {objs1, objs2}
|
|
||||||
local player
|
|
||||||
for oi=1, #objs_table do
|
|
||||||
local objs_inner = objs_table[oi]
|
|
||||||
for o=1, #objs_inner do
|
|
||||||
--[[ First player in list is the lucky one. The other player get nothing :-(
|
|
||||||
If multiple players are close to the dispenser, it can be a bit
|
|
||||||
-- unpredictable on who gets the armor. ]]
|
|
||||||
if objs_inner[o]:is_player() then
|
|
||||||
player = objs_inner[o]
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if player then
|
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- If player found, add armor
|
if stack:is_empty() then
|
||||||
if player then
|
break
|
||||||
local ainv = minetest.get_inventory({type="detached", name=player:get_player_name().."_armor"})
|
|
||||||
local pinv = player:get_inventory()
|
|
||||||
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)
|
|
||||||
|
|
||||||
stack:take_item()
|
|
||||||
inv:set_stack("main", stack_id, stack)
|
|
||||||
armor_dispensed = true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Place head or pumpkin as node, if equipping it as armor has failed
|
-- Place head or pumpkin as node, if equipping it as armor has failed
|
||||||
if not armor_dispensed then
|
if not stack:is_empty() then
|
||||||
if igroups.head or iname == "mcl_farming:pumpkin_face" then
|
if igroups.head or iname == "mcl_farming:pumpkin_face" then
|
||||||
if dropnodedef.buildable_to then
|
if dropnodedef.buildable_to then
|
||||||
minetest.set_node(droppos, {name = iname, param2 = node.param2})
|
minetest.set_node(droppos, {name = iname, param2 = node.param2})
|
||||||
stack:take_item()
|
stack:take_item()
|
||||||
inv:set_stack("main", stack_id, stack)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
inv:set_stack("main", stack_id, stack)
|
||||||
-- Spawn Egg
|
-- Spawn Egg
|
||||||
elseif igroups.spawn_egg then
|
elseif igroups.spawn_egg then
|
||||||
-- Spawn mob
|
-- Spawn mob
|
||||||
|
|
|
@ -0,0 +1,241 @@
|
||||||
|
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.on_equip(itemstack, obj)
|
||||||
|
local def = itemstack:get_definition()
|
||||||
|
mcl_armor.play_equip_sound(itemstack, obj)
|
||||||
|
if def._on_equip then
|
||||||
|
def._on_equip(obj, itemstack)
|
||||||
|
end
|
||||||
|
mcl_armor.update(obj)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_armor.on_unequip(itemstack, obj)
|
||||||
|
local def = itemstack:get_definition()
|
||||||
|
mcl_armor.play_equip_sound(itemstack, obj, nil, true)
|
||||||
|
if def._on_unequip then
|
||||||
|
def._on_unequip(obj, itemstack)
|
||||||
|
end
|
||||||
|
mcl_armor.update(obj)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_armor.equip(itemstack, obj, swap)
|
||||||
|
local def = itemstack:get_definition()
|
||||||
|
|
||||||
|
if not def then
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
local inv = mcl_util.get_inventory(obj, true)
|
||||||
|
|
||||||
|
if not inv or inv:get_size("armor") == 0 then
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
local element = mcl_armor.elements[def._mcl_armor_element or ""]
|
||||||
|
|
||||||
|
if element then
|
||||||
|
local old_stack = inv:get_stack("armor", element.index)
|
||||||
|
|
||||||
|
if swap or old_stack:is_empty() then
|
||||||
|
local new_stack
|
||||||
|
|
||||||
|
if swap then
|
||||||
|
new_stack = itemstack
|
||||||
|
itemstack = old_stack
|
||||||
|
else
|
||||||
|
new_stack = itemstack:take_item()
|
||||||
|
end
|
||||||
|
|
||||||
|
inv:set_stack("armor", element.index, new_stack)
|
||||||
|
mcl_armor.on_equip(new_stack, 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.update(obj)
|
||||||
|
local info = {points = 0, view_range_factors = {}}
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
local mob_range_mob = def._mcl_armor_mob_range_mob
|
||||||
|
|
||||||
|
if mob_range_mob then
|
||||||
|
local factor = info.view_range_factors[mob_range_mob]
|
||||||
|
|
||||||
|
if factor then
|
||||||
|
if factor > 0 then
|
||||||
|
info.view_range_factors[mob_range_mob] = factor * def._mcl_armor_mob_range_factor
|
||||||
|
end
|
||||||
|
else
|
||||||
|
info.view_range_factors[mob_range_mob] = def._mcl_armor_mob_range_factor
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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
|
||||||
|
|
|
@ -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)
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
mcl_damage.register_modifier(function(obj, damage, reason)
|
||||||
|
local flags = reason.flags
|
||||||
|
|
||||||
|
if flags.bypasses_armor and flags.bypasses_magic then
|
||||||
|
return damage
|
||||||
|
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 and 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 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.type ~= "thorns" and reason.source ~= obj then
|
||||||
|
mcl_util.deal_damage(reason.source, {type = "thorns", direct = obj})
|
||||||
|
|
||||||
|
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, 0)
|
|
@ -1,474 +1,68 @@
|
||||||
local S = minetest.get_translator("mcl_armor")
|
local S = minetest.get_translator("mcl_armor")
|
||||||
|
|
||||||
dofile(minetest.get_modpath(minetest.get_current_modname()).."/armor.lua")
|
mcl_armor = {
|
||||||
dofile(minetest.get_modpath(minetest.get_current_modname()).."/alias.lua")
|
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."),
|
||||||
-- Regisiter Head Armor
|
elements = {
|
||||||
|
head = {
|
||||||
local longdesc = S("This is a piece of equippable armor which reduces the amount of damage you receive.")
|
name = "helmet",
|
||||||
local usage = S("To equip it, put it on the corresponding armor slot in your inventory menu.")
|
description = "Helmet",
|
||||||
|
durability = 0.6857,
|
||||||
minetest.register_tool("mcl_armor:elytra", {
|
index = 2,
|
||||||
description = S("Elytra"),
|
craft = function(m)
|
||||||
_doc_items_longdesc = longdesc,
|
return {
|
||||||
_doc_items_usagehelp = usage,
|
{ m, m, m},
|
||||||
inventory_image = "mcl_armor_inv_elytra.png",
|
{ m, "", m},
|
||||||
groups = {armor_torso=1, mcl_armor_points=0, mcl_armor_uses=10, enchantability=0},
|
{"", "", ""},
|
||||||
_repair_material = "mcl_mobitems:leather",
|
}
|
||||||
sounds = {
|
end,
|
||||||
_mcl_armor_equip = "mcl_armor_equip_leather",
|
},
|
||||||
_mcl_armor_unequip = "mcl_armor_unequip_leather",
|
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,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
on_place = armor.on_armor_use,
|
player_view_range_factors = {},
|
||||||
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,
|
|
||||||
_mcl_upgradeable = true,
|
|
||||||
_mcl_upgrade_item = "mcl_armor:helmet_netherite"
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_tool("mcl_armor:helmet_netherite",{
|
|
||||||
description = S("Netherite Helmet"),
|
|
||||||
_doc_items_longdesc = longdesc,
|
|
||||||
_doc_items_usagehelp = usage,
|
|
||||||
inventory_image = "mcl_armor_inv_helmet_netherite.png",
|
|
||||||
groups = {armor_head=1, mcl_armor_points=3, mcl_armor_uses=407, mcl_armor_toughness=2, enchantability=10 },
|
|
||||||
_repair_material = "mcl_netherite:netherite_ingot",
|
|
||||||
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,
|
|
||||||
_mcl_upgradable = true,
|
|
||||||
_mcl_upgradeitem = "mcl_armor:chestplate_netherite"
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_tool("mcl_armor:chestplate_netherite",{
|
|
||||||
description = S("Netherite Chestplate"),
|
|
||||||
_doc_items_longdesc = longdesc,
|
|
||||||
_doc_items_usagehelp = usage,
|
|
||||||
inventory_image = "mcl_armor_inv_chestplate_netherite.png",
|
|
||||||
groups = {armor_torso=1, mcl_armor_points=8, mcl_armor_uses=592, mcl_armor_toughness=2, enchantability=10 },
|
|
||||||
_repair_material = "mcl_netherite:netherite_ingot",
|
|
||||||
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,
|
|
||||||
_mcl_upgradable = true,
|
|
||||||
_mcl_upgrade_item = "mcl_armor:leggings_netherite"
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_tool("mcl_armor:leggings_netherite",{
|
|
||||||
description = S("Netherite Leggings"),
|
|
||||||
_doc_items_longdesc = longdesc,
|
|
||||||
_doc_items_usagehelp = usage,
|
|
||||||
inventory_image = "mcl_armor_inv_leggings_netherite.png",
|
|
||||||
groups = {armor_legs=1, mcl_armor_points=6, mcl_armor_uses=555, mcl_armor_toughness=2, enchantability=10 },
|
|
||||||
_repair_material = "mcl_netherite:netherite_ingot",
|
|
||||||
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,
|
|
||||||
_mcl_upgradable = true,
|
|
||||||
_mcl_upgrade_item = "mcl_armor:boots_diamond"
|
|
||||||
})
|
|
||||||
|
|
||||||
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,
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_tool("mcl_armor:boots_netherite", {
|
|
||||||
description = S("Netherite Boots"),
|
|
||||||
_doc_items_longdesc = longdesc,
|
|
||||||
_doc_items_usagehelp = usage,
|
|
||||||
inventory_image = "mcl_armor_inv_boots_netherite.png",
|
|
||||||
groups = {armor_feet=1, mcl_armor_points=3, mcl_armor_uses=481, enchantability=1 },
|
|
||||||
_repair_material = "mcl_netherite:netherite_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"} ,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v in pairs(craft_ingreds) do
|
local modpath = minetest.get_modpath("mcl_armor")
|
||||||
-- material
|
|
||||||
local m = v[1]
|
dofile(modpath .. "/api.lua")
|
||||||
-- cooking result
|
dofile(modpath .. "/player.lua")
|
||||||
local c = v[2]
|
dofile(modpath .. "/damage.lua")
|
||||||
if m ~= nil then
|
dofile(modpath .. "/register.lua")
|
||||||
minetest.register_craft({
|
dofile(modpath .. "/alias.lua")
|
||||||
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
|
|
||||||
|
|
|
@ -0,0 +1,169 @@
|
||||||
|
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)
|
||||||
|
|
||||||
|
local meta = player:get_meta()
|
||||||
|
meta:set_int("mcl_armor:armor_points", info.points)
|
||||||
|
|
||||||
|
mcl_armor.player_view_range_factors[player] = info.view_range_factors
|
||||||
|
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
|
||||||
|
|
||||||
|
local element_index = mcl_armor.elements[element].index
|
||||||
|
|
||||||
|
if index ~= 1 and index ~= element_index then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local old_stack = inventory:get_stack("armor", element_index)
|
||||||
|
|
||||||
|
if old_stack:is_empty() or index ~= 1 and 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)
|
||||||
|
|
||||||
|
local function on_put(player, inventory, index, stack)
|
||||||
|
if index == 1 then
|
||||||
|
mcl_armor.equip(stack, player)
|
||||||
|
inventory:set_stack("armor", 1, nil)
|
||||||
|
else
|
||||||
|
mcl_armor.on_equip(stack, player)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_on_player_inventory_action(function(player, action, inventory, inventory_info)
|
||||||
|
if is_armor_action(inventory_info) then
|
||||||
|
if action == "put" then
|
||||||
|
on_put(player, inventory, inventory_info.index, inventory_info.stack)
|
||||||
|
elseif action == "take" then
|
||||||
|
mcl_armor.on_unequip(inventory_info.stack, player)
|
||||||
|
else
|
||||||
|
local stack = inventory:get_stack(inventory_info.to_list, inventory_info.to_index)
|
||||||
|
if inventory_info.to_list == "armor" then
|
||||||
|
on_put(player, inventory, inventory_info.to_index, stack)
|
||||||
|
elseif inventory_info.from_list == "armor" then
|
||||||
|
mcl_armor.on_unequip(stack, player)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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)
|
||||||
|
|
||||||
|
minetest.register_on_leaveplayer(function(player)
|
||||||
|
mcl_armor.player_view_range_factors[player] = nil
|
||||||
|
end)
|
|
@ -0,0 +1,220 @@
|
||||||
|
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_set({
|
||||||
|
name = "netherite",
|
||||||
|
description = "Netherite",
|
||||||
|
durability = 592,
|
||||||
|
enchantability = 15,
|
||||||
|
points = {
|
||||||
|
head = 3,
|
||||||
|
torso = 8,
|
||||||
|
legs = 6,
|
||||||
|
feet = 3,
|
||||||
|
},
|
||||||
|
toughness = 3,
|
||||||
|
craft_material = "mcl_netherite:netherite_ingot",
|
||||||
|
})
|
||||||
|
|
||||||
|
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",
|
||||||
|
_mcl_armor_texture = "mcl_armor_elytra.png"
|
||||||
|
})
|
|
@ -1,84 +1,41 @@
|
||||||
local S = minetest.get_translator("mcl_armor_stand")
|
local S = minetest.get_translator("mcl_armor_stand")
|
||||||
|
|
||||||
local elements = {"head", "torso", "legs", "feet"}
|
-- Spawn a stand entity
|
||||||
|
local function spawn_stand_entity(pos, node)
|
||||||
local function get_stand_object(pos)
|
local luaentity = minetest.add_entity(pos, "mcl_armor_stand:armor_entity"):get_luaentity()
|
||||||
local object = nil
|
luaentity:update_rotation(node or minetest.get_node(pos))
|
||||||
local objects = minetest.get_objects_inside_radius(pos, 0.5) or {}
|
return luaentity
|
||||||
for _, obj in pairs(objects) do
|
|
||||||
local ent = obj:get_luaentity()
|
|
||||||
if ent then
|
|
||||||
if ent.name == "mcl_armor_stand:armor_entity" then
|
|
||||||
-- Remove duplicates
|
|
||||||
if object then
|
|
||||||
obj:remove()
|
|
||||||
else
|
|
||||||
object = obj
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return object
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function update_entity(pos)
|
-- Find a stand entity or spawn one
|
||||||
local node = minetest.get_node(pos)
|
local function get_stand_entity(pos, node)
|
||||||
local object = get_stand_object(pos)
|
for _, obj in ipairs(minetest.get_objects_inside_radius(pos, 0)) do
|
||||||
if object then
|
local luaentity = obj:get_luaentity()
|
||||||
if not string.find(node.name, "mcl_armor_stand:") then
|
if luaentity and luaentity.name == "mcl_armor_stand:armor_entity" then
|
||||||
object:remove()
|
return luaentity
|
||||||
return
|
|
||||||
end
|
end
|
||||||
else
|
|
||||||
object = minetest.add_entity(pos, "mcl_armor_stand:armor_entity")
|
|
||||||
end
|
end
|
||||||
if object then
|
return spawn_stand_entity(pos, node)
|
||||||
local texture = "blank.png"
|
end
|
||||||
local textures = {}
|
|
||||||
local meta = minetest.get_meta(pos)
|
-- Migrate the old inventory format
|
||||||
local inv = meta:get_inventory()
|
local function migrate_inventory(inv)
|
||||||
local yaw = 0
|
inv:set_size("armor", 5)
|
||||||
if inv then
|
local lists = inv:get_lists()
|
||||||
for _, element in pairs(elements) do
|
for name, element in pairs(mcl_armor.elements) do
|
||||||
local stack = inv:get_stack("armor_"..element, 1)
|
local listname = "armor_" .. name
|
||||||
if stack:get_count() == 1 then
|
local list = lists[listname]
|
||||||
local item = stack:get_name() or ""
|
if list then
|
||||||
if minetest.registered_aliases[item] then
|
inv:set_stack("armor", element.index, list[1])
|
||||||
item = minetest.registered_aliases[item]
|
inv:set_size(listname, 0)
|
||||||
end
|
|
||||||
local def = stack:get_definition() or {}
|
|
||||||
local groups = def.groups or {}
|
|
||||||
if groups["armor_"..element] then
|
|
||||||
local texture = def.texture or item:gsub("%:", "_")
|
|
||||||
table.insert(textures, texture..".png")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
if #textures > 0 then
|
|
||||||
texture = table.concat(textures, "^")
|
|
||||||
end
|
|
||||||
if node.param2 then
|
|
||||||
local rot = node.param2 % 4
|
|
||||||
if rot == 1 then
|
|
||||||
yaw = 3 * math.pi / 2
|
|
||||||
elseif rot == 2 then
|
|
||||||
yaw = math.pi
|
|
||||||
elseif rot == 3 then
|
|
||||||
yaw = math.pi / 2
|
|
||||||
end
|
|
||||||
end
|
|
||||||
object:set_yaw(yaw)
|
|
||||||
object:set_properties({textures={texture}})
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Drop all armor of the armor stand on the ground
|
-- Drop all armor on the ground when it got destroyed
|
||||||
local drop_armor = function(pos)
|
local function drop_inventory(pos)
|
||||||
local meta = minetest.get_meta(pos)
|
local inv = minetest.get_meta(pos):get_inventory()
|
||||||
local inv = meta:get_inventory()
|
for _, stack in pairs(inv:get_list("armor")) do
|
||||||
for _, element in pairs(elements) do
|
|
||||||
local stack = inv:get_stack("armor_"..element, 1)
|
|
||||||
if not stack:is_empty() then
|
if not stack:is_empty() then
|
||||||
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
|
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
|
||||||
minetest.add_item(p, stack)
|
minetest.add_item(p, stack)
|
||||||
|
@ -111,136 +68,26 @@ minetest.register_node("mcl_armor_stand:armor_stand", {
|
||||||
_mcl_hardness = 2,
|
_mcl_hardness = 2,
|
||||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||||
on_construct = function(pos)
|
on_construct = function(pos)
|
||||||
local meta = minetest.get_meta(pos)
|
spawn_stand_entity(pos)
|
||||||
local inv = meta:get_inventory()
|
end,
|
||||||
for _, element in pairs(elements) do
|
on_destruct = function(pos)
|
||||||
inv:set_size("armor_"..element, 1)
|
drop_inventory(pos)
|
||||||
end
|
|
||||||
end,
|
end,
|
||||||
-- Drop all armor on the ground when it got destroyed
|
|
||||||
on_destruct = drop_armor,
|
|
||||||
-- Put piece of armor on armor stand, or take one away
|
|
||||||
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||||
local protname = clicker:get_player_name()
|
local protname = clicker:get_player_name()
|
||||||
|
|
||||||
if minetest.is_protected(pos, protname) then
|
if minetest.is_protected(pos, protname) then
|
||||||
minetest.record_protection_violation(pos, protname)
|
minetest.record_protection_violation(pos, protname)
|
||||||
return itemstack
|
return itemstack
|
||||||
end
|
end
|
||||||
|
|
||||||
local inv = minetest.get_inventory({type = "node", pos = pos})
|
return mcl_armor.equip(itemstack, get_stand_entity(pos, node).object, true)
|
||||||
if not inv then
|
|
||||||
return itemstack
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Check if player wields armor
|
|
||||||
local name = itemstack:get_name()
|
|
||||||
local list
|
|
||||||
for e=1, #elements do
|
|
||||||
local g = minetest.get_item_group(name, "armor_" .. elements[e])
|
|
||||||
if g ~= nil and g ~= 0 then
|
|
||||||
list = "armor_" .. elements[e]
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- If player wields armor, put it on armor stand
|
|
||||||
local wielditem = clicker:get_wielded_item()
|
|
||||||
if list then
|
|
||||||
-- ... but only if the slot is free
|
|
||||||
local single_item = ItemStack(itemstack)
|
|
||||||
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)
|
|
||||||
update_entity(pos)
|
|
||||||
itemstack:take_item()
|
|
||||||
return itemstack
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Take armor from stand if player has a free hand or wields the same armor type (if stackable)
|
|
||||||
for e=1, #elements do
|
|
||||||
local stand_armor = inv:get_stack("armor_" .. elements[e], 1)
|
|
||||||
if not stand_armor:is_empty() then
|
|
||||||
local pinv = clicker:get_inventory()
|
|
||||||
local taken = false
|
|
||||||
-- Empty hand
|
|
||||||
if wielditem:get_name() == "" then
|
|
||||||
pinv:set_stack("main", clicker:get_wield_index(), stand_armor)
|
|
||||||
taken = true
|
|
||||||
-- Stackable armor type (if not already full). This is the case for e.g. mob heads.
|
|
||||||
-- This is done purely for convenience.
|
|
||||||
elseif (wielditem:get_name() == stand_armor:get_name() and wielditem:get_count() < wielditem:get_stack_max()) then
|
|
||||||
wielditem:set_count(wielditem:get_count()+1)
|
|
||||||
pinv:set_stack("main", clicker:get_wield_index(), wielditem)
|
|
||||||
taken = true
|
|
||||||
end
|
|
||||||
if taken then
|
|
||||||
armor:play_equip_sound(stand_armor, nil, pos, true)
|
|
||||||
stand_armor:take_item()
|
|
||||||
inv:set_stack("armor_" .. elements[e], 1, stand_armor)
|
|
||||||
end
|
|
||||||
update_entity(pos)
|
|
||||||
return clicker:get_wielded_item()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
update_entity(pos)
|
|
||||||
return itemstack
|
|
||||||
end,
|
|
||||||
after_place_node = function(pos)
|
|
||||||
minetest.add_entity(pos, "mcl_armor_stand:armor_entity")
|
|
||||||
end,
|
|
||||||
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
|
||||||
local name = player:get_player_name()
|
|
||||||
if minetest.is_protected(pos, name) then
|
|
||||||
minetest.record_protection_violation(pos, name)
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
return stack:get_count()
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
|
||||||
local name = player:get_player_name()
|
|
||||||
if minetest.is_protected(pos, name) then
|
|
||||||
minetest.record_protection_violation(pos, name)
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
local def = stack:get_definition() or {}
|
|
||||||
local groups = def.groups or {}
|
|
||||||
if groups[listname] then
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end,
|
|
||||||
allow_metadata_inventory_move = function()
|
|
||||||
return 0
|
|
||||||
end,
|
|
||||||
on_metadata_inventory_put = function(pos)
|
|
||||||
update_entity(pos)
|
|
||||||
end,
|
|
||||||
on_metadata_inventory_take = function(pos)
|
|
||||||
update_entity(pos)
|
|
||||||
end,
|
|
||||||
after_destruct = function(pos)
|
|
||||||
update_entity(pos)
|
|
||||||
end,
|
|
||||||
on_blast = function(pos, _, do_drop)
|
|
||||||
local object = get_stand_object(pos)
|
|
||||||
if object then
|
|
||||||
object:remove()
|
|
||||||
end
|
|
||||||
minetest.after(1, function(pos)
|
|
||||||
update_entity(pos)
|
|
||||||
end, pos)
|
|
||||||
minetest.remove_node(pos)
|
|
||||||
if do_drop then
|
|
||||||
minetest.add_item(pos, "mcl_armor_stand:armor_stand")
|
|
||||||
end
|
|
||||||
end,
|
end,
|
||||||
on_rotate = function(pos, node, user, mode)
|
on_rotate = function(pos, node, user, mode)
|
||||||
if mode == screwdriver.ROTATE_FACE then
|
if mode == screwdriver.ROTATE_FACE then
|
||||||
node.param2 = (node.param2 + 1) % 4
|
node.param2 = (node.param2 + 1) % 4
|
||||||
minetest.swap_node(pos, node)
|
minetest.swap_node(pos, node)
|
||||||
update_entity(pos)
|
get_stand_entity(pos, node):update_rotation(node)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
|
@ -248,50 +95,44 @@ minetest.register_node("mcl_armor_stand:armor_stand", {
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_entity("mcl_armor_stand:armor_entity", {
|
minetest.register_entity("mcl_armor_stand:armor_entity", {
|
||||||
physical = true,
|
initial_properties = {
|
||||||
visual = "mesh",
|
physical = true,
|
||||||
mesh = "3d_armor_entity.obj",
|
visual = "mesh",
|
||||||
visual_size = {x=1, y=1},
|
mesh = "3d_armor_entity.obj",
|
||||||
collisionbox = {-0.1,-0.4,-0.1, 0.1,1.3,0.1},
|
visual_size = {x=1, y=1},
|
||||||
pointable = false,
|
collisionbox = {-0.1,-0.4,-0.1, 0.1,1.3,0.1},
|
||||||
textures = {"blank.png"},
|
pointable = false,
|
||||||
pos = nil,
|
textures = {"blank.png"},
|
||||||
timer = 0,
|
timer = 0,
|
||||||
|
static_save = false,
|
||||||
|
},
|
||||||
on_activate = function(self)
|
on_activate = function(self)
|
||||||
local pos = self.object:get_pos()
|
self.object:set_armor_groups({immortal = 1})
|
||||||
self.object:set_armor_groups({immortal=1})
|
self.node_pos = vector.round(self.object:get_pos())
|
||||||
if pos then
|
self.inventory = minetest.get_meta(self.node_pos):get_inventory()
|
||||||
self.pos = vector.round(pos)
|
migrate_inventory(self.inventory)
|
||||||
update_entity(pos)
|
mcl_armor.update(self.object)
|
||||||
end
|
|
||||||
end,
|
end,
|
||||||
on_step = function(self, dtime)
|
on_step = function(self, dtime)
|
||||||
if not self.pos then
|
if minetest.get_node(self.node_pos).name ~= "mcl_armor_stand:armor_stand" then
|
||||||
return
|
|
||||||
end
|
|
||||||
self.timer = self.timer + dtime
|
|
||||||
if self.timer > 1 then
|
|
||||||
self.timer = 0
|
|
||||||
local pos = self.object:get_pos()
|
|
||||||
if pos then
|
|
||||||
if vector.equals(vector.round(pos), self.pos) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
update_entity(self.pos)
|
|
||||||
self.object:remove()
|
self.object:remove()
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
update_armor = function(self, info)
|
||||||
|
self.object:set_properties({textures = {info.texture}})
|
||||||
|
end,
|
||||||
|
update_rotation = function(self, node)
|
||||||
|
self.object:set_yaw(minetest.dir_to_yaw(minetest.facedir_to_dir(node.param2)))
|
||||||
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
-- FIXME: Armor helper entity can get destroyed by /clearobjects
|
|
||||||
minetest.register_lbm({
|
minetest.register_lbm({
|
||||||
label = "Respawn armor stand entities",
|
label = "Respawn armor stand entities",
|
||||||
name = "mcl_armor_stand:respawn_entities",
|
name = "mcl_armor_stand:respawn_entities",
|
||||||
nodenames = {"mcl_armor_stand:armor_stand"},
|
nodenames = {"mcl_armor_stand:armor_stand"},
|
||||||
run_at_every_load = true,
|
run_at_every_load = true,
|
||||||
action = function(pos, node)
|
action = function(pos, node)
|
||||||
update_entity(pos, node)
|
spawn_stand_entity(pos, node)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -304,7 +145,6 @@ minetest.register_craft({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
-- Legacy handling
|
-- Legacy handling
|
||||||
minetest.register_alias("3d_armor_stand:armor_stand", "mcl_armor_stand:armor_stand")
|
minetest.register_alias("3d_armor_stand:armor_stand", "mcl_armor_stand:armor_stand")
|
||||||
minetest.register_entity(":3d_armor_stand:armor_entity", {
|
minetest.register_entity(":3d_armor_stand:armor_entity", {
|
||||||
|
|
|
@ -69,6 +69,7 @@ local ARROW_ENTITY={
|
||||||
_stuckrechecktimer=nil,-- An additional timer for periodically re-checking the stuck status of an arrow
|
_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.
|
_stuckin=nil, --Position of node in which arow is stuck.
|
||||||
_shooter=nil, -- ObjectRef of player or mob who shot it
|
_shooter=nil, -- ObjectRef of player or mob who shot it
|
||||||
|
_is_arrow = true,
|
||||||
|
|
||||||
_viscosity=0, -- Viscosity of node the arrow is currently in
|
_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
|
_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.
|
-- Punch target object but avoid hurting enderman.
|
||||||
if not lua or lua.name ~= "mobs_mc:enderman" then
|
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
|
if self._in_player == false then
|
||||||
damage_particles(self.object:get_pos(), self._is_critical)
|
damage_particles(self.object:get_pos(), self._is_critical)
|
||||||
end
|
end
|
||||||
|
|
|
@ -59,6 +59,7 @@ mcl_bows.shoot_arrow = function(arrow_item, pos, dir, yaw, shooter, power, damag
|
||||||
obj:set_yaw(yaw-math.pi/2)
|
obj:set_yaw(yaw-math.pi/2)
|
||||||
local le = obj:get_luaentity()
|
local le = obj:get_luaentity()
|
||||||
le._shooter = shooter
|
le._shooter = shooter
|
||||||
|
le._source_object = shooter
|
||||||
le._damage = damage
|
le._damage = damage
|
||||||
le._is_critical = is_critical
|
le._is_critical = is_critical
|
||||||
le._startpos = pos
|
le._startpos = pos
|
||||||
|
|
|
@ -203,7 +203,7 @@ S("• When lava is directly above water, the water turns into stone."),
|
||||||
_mcl_node_death_message = lava_death_messages,
|
_mcl_node_death_message = lava_death_messages,
|
||||||
post_effect_color = {a=245, r=208, g=73, b=10},
|
post_effect_color = {a=245, r=208, g=73, b=10},
|
||||||
stack_max = 64,
|
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,
|
_mcl_blast_resistance = 100,
|
||||||
-- Hardness intentionally set to infinite instead of 100 (Minecraft value) to avoid problems in creative mode
|
-- Hardness intentionally set to infinite instead of 100 (Minecraft value) to avoid problems in creative mode
|
||||||
_mcl_hardness = -1,
|
_mcl_hardness = -1,
|
||||||
|
|
|
@ -10,25 +10,6 @@ local function increase_damage(damage_group, factor)
|
||||||
end
|
end
|
||||||
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
|
-- implemented via on_enchant and additions in mobs_mc; Slowness IV part unimplemented
|
||||||
mcl_enchanting.enchantments.bane_of_arthropods = {
|
mcl_enchanting.enchantments.bane_of_arthropods = {
|
||||||
name = S("Bane of Arthropods"),
|
name = S("Bane of Arthropods"),
|
||||||
|
@ -48,25 +29,6 @@ mcl_enchanting.enchantments.bane_of_arthropods = {
|
||||||
inv_tool_tab = false,
|
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
|
-- requires missing MineClone2 feature
|
||||||
--[[mcl_enchanting.enchantments.channeling = {
|
--[[mcl_enchanting.enchantments.channeling = {
|
||||||
name = S("Channeling"),
|
name = S("Channeling"),
|
||||||
|
@ -86,25 +48,6 @@ mcl_enchanting.enchantments.blast_protection = {
|
||||||
inv_tool_tab = false,
|
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
|
-- implemented in mcl_death_drop
|
||||||
mcl_enchanting.enchantments.curse_of_vanishing = {
|
mcl_enchanting.enchantments.curse_of_vanishing = {
|
||||||
name = S("Curse of Vanishing"),
|
name = S("Curse of Vanishing"),
|
||||||
|
@ -164,24 +107,6 @@ mcl_enchanting.enchantments.efficiency = {
|
||||||
inv_tool_tab = true,
|
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
|
-- implemented in mcl_mobs and via register_on_punchplayer callback
|
||||||
mcl_enchanting.enchantments.fire_aspect = {
|
mcl_enchanting.enchantments.fire_aspect = {
|
||||||
name = S("Fire Aspect"),
|
name = S("Fire Aspect"),
|
||||||
|
@ -207,31 +132,12 @@ minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch,
|
||||||
if wielditem then
|
if wielditem then
|
||||||
local fire_aspect_level = mcl_enchanting.get_enchantment(wielditem, "fire_aspect")
|
local fire_aspect_level = mcl_enchanting.get_enchantment(wielditem, "fire_aspect")
|
||||||
if fire_aspect_level > 0 then
|
if fire_aspect_level > 0 then
|
||||||
mcl_burning.set_on_fire(player, fire_aspect_level * 4, hitter:get_player_name())
|
mcl_burning.set_on_fire(player, fire_aspect_level * 4)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
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 = {
|
mcl_enchanting.enchantments.flame = {
|
||||||
name = S("Flame"),
|
name = S("Flame"),
|
||||||
max_level = 1,
|
max_level = 1,
|
||||||
|
@ -530,44 +436,6 @@ mcl_enchanting.enchantments.power = {
|
||||||
inv_tool_tab = false,
|
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
|
-- implemented via minetest.calculate_knockback (together with the Knockback enchantment) and mcl_bows
|
||||||
mcl_enchanting.enchantments.punch = {
|
mcl_enchanting.enchantments.punch = {
|
||||||
name = S("Punch"),
|
name = S("Punch"),
|
||||||
|
@ -739,25 +607,6 @@ mcl_enchanting.enchantments.soul_speed = {
|
||||||
inv_tool_tab = false,
|
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
|
-- 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 = {
|
mcl_enchanting.enchantments.unbreaking = {
|
||||||
name = S("Unbreaking"),
|
name = S("Unbreaking"),
|
||||||
|
|
|
@ -267,7 +267,8 @@ function mcl_enchanting.initialize()
|
||||||
new_def.groups.not_in_creative_inventory = 1
|
new_def.groups.not_in_creative_inventory = 1
|
||||||
new_def.groups.not_in_craft_guide = 1
|
new_def.groups.not_in_craft_guide = 1
|
||||||
new_def.groups.enchanted = 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._mcl_enchanting_enchanted_tool = new_name
|
||||||
new_def.after_use = get_after_use_callback(itemdef)
|
new_def.after_use = get_after_use_callback(itemdef)
|
||||||
local register_list = register_item_list
|
local register_list = register_item_list
|
||||||
|
|
|
@ -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_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._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.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.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_factor = 0
|
||||||
pumpkin_face_base_def._mcl_armor_mob_range_mob = "mobs_mc:enderman"
|
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
|
pumpkin_face_base_def.groups.non_combat_armor=1
|
||||||
if minetest.get_modpath("mcl_armor") then
|
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
|
end
|
||||||
|
|
||||||
-- Register stem growth
|
-- Register stem growth
|
||||||
|
|
|
@ -5,7 +5,7 @@ local mod_screwdriver = minetest.get_modpath("screwdriver")
|
||||||
|
|
||||||
local equip_armor
|
local equip_armor
|
||||||
if minetest.get_modpath("mcl_armor") then
|
if minetest.get_modpath("mcl_armor") then
|
||||||
equip_armor = armor.on_armor_use
|
equip_armor = mcl_armor.equip_on_use
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Heads system
|
-- Heads system
|
||||||
|
@ -42,7 +42,7 @@ local function addhead(name, texture, desc, longdesc, rangemob, rangefactor)
|
||||||
{ -0.25, -0.5, -0.25, 0.25, 0.0, 0.25, },
|
{ -0.25, -0.5, -0.25, 0.25, 0.0, 0.25, },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
groups = {handy=1, armor_head=1,non_combat_armor=1, head=1, deco_block=1, dig_by_piston=1 },
|
groups = {handy = 1, armor = 1, armor_head = 1, non_combat_armor = 1, non_combat_armor_head = 1, head = 1, deco_block = 1, dig_by_piston = 1},
|
||||||
-- The head textures are based off the textures of an actual mob.
|
-- The head textures are based off the textures of an actual mob.
|
||||||
tiles = {
|
tiles = {
|
||||||
-- Note: bottom texture is overlaid over top texture to get rid of possible transparency.
|
-- Note: bottom texture is overlaid over top texture to get rid of possible transparency.
|
||||||
|
@ -111,6 +111,7 @@ local function addhead(name, texture, desc, longdesc, rangemob, rangefactor)
|
||||||
|
|
||||||
_mcl_armor_mob_range_mob = rangemob,
|
_mcl_armor_mob_range_mob = rangemob,
|
||||||
_mcl_armor_mob_range_factor = rangefactor,
|
_mcl_armor_mob_range_factor = rangefactor,
|
||||||
|
_mcl_armor_element = "head",
|
||||||
_mcl_blast_resistance = 1,
|
_mcl_blast_resistance = 1,
|
||||||
_mcl_hardness = 1,
|
_mcl_hardness = 1,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
local S = minetest.get_translator("mcl_nether")
|
local S = minetest.get_translator("mcl_nether")
|
||||||
|
|
||||||
local mod_death_messages = minetest.get_modpath("mcl_death_messages")
|
|
||||||
local mod_screwdriver = minetest.get_modpath("screwdriver") ~= nil
|
local mod_screwdriver = minetest.get_modpath("screwdriver") ~= nil
|
||||||
local on_rotate
|
local on_rotate
|
||||||
if mod_screwdriver then
|
if mod_screwdriver then
|
||||||
|
@ -141,10 +140,7 @@ minetest.register_node("mcl_nether:magma", {
|
||||||
end
|
end
|
||||||
-- Hurt players standing on top of this block
|
-- Hurt players standing on top of this block
|
||||||
if player:get_hp() > 0 then
|
if player:get_hp() > 0 then
|
||||||
if mod_death_messages then
|
mcl_util.deal_damage(player, 1, {type = "hot_floor"})
|
||||||
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" })
|
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
_mcl_blast_resistance = 0.5,
|
_mcl_blast_resistance = 0.5,
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
name = mcl_nether
|
name = mcl_nether
|
||||||
depends = mcl_core, mcl_sounds, mcl_util, walkover, doc_items, mcl_colors
|
depends = mcl_core, mcl_sounds, mcl_util, walkover, doc_items, mcl_colors
|
||||||
optional_depends = mcl_death_messages, doc, screwdriver
|
optional_depends = doc, screwdriver
|
||||||
|
|
|
@ -132,17 +132,10 @@ minetest.register_globalstep(function(dtime)
|
||||||
if player:get_pos() then mcl_potions._add_spawner(player, "#225533") end
|
if player:get_pos() then mcl_potions._add_spawner(player, "#225533") end
|
||||||
|
|
||||||
if EF.poisoned[player].hit_timer >= EF.poisoned[player].step then
|
if EF.poisoned[player].hit_timer >= EF.poisoned[player].step then
|
||||||
|
if mcl_util.get_hp(player) - 1 > 0 then
|
||||||
if entity and entity._cmi_is_mob then
|
mcl_util.deal_damage(player, 1, {type = "magic"})
|
||||||
entity.health = math.max(entity.health - 1, 1)
|
|
||||||
EF.poisoned[player].hit_timer = 0
|
|
||||||
elseif is_player then
|
|
||||||
player:set_hp( math.max(player:get_hp() - 1, 1), { type = "punch", other = "poison"})
|
|
||||||
EF.poisoned[player].hit_timer = 0
|
|
||||||
else -- if not player or mob then remove
|
|
||||||
EF.poisoned[player] = nil
|
|
||||||
end
|
end
|
||||||
|
EF.poisoned[player].hit_timer = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
if EF.poisoned[player] and EF.poisoned[player].timer >= EF.poisoned[player].dur then
|
if EF.poisoned[player] and EF.poisoned[player].timer >= EF.poisoned[player].dur then
|
||||||
|
@ -351,37 +344,12 @@ minetest.register_globalstep(function(dtime)
|
||||||
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
local is_fire_node = { ["mcl_core:lava_flowing"]=true,
|
|
||||||
["mcl_core:lava_source"]=true,
|
|
||||||
["mcl_fire:eternal_fire"]=true,
|
|
||||||
["mcl_fire:fire"]=true,
|
|
||||||
["mcl_nether:magma"]=true,
|
|
||||||
["mcl_nether:nether_lava_source"]=true,
|
|
||||||
["mcl_nether:nether_lava_flowing"]=true,
|
|
||||||
["mcl_nether:nether_lava_source"]=true
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Prevent damage to player with Fire Resistance enabled
|
-- Prevent damage to player with Fire Resistance enabled
|
||||||
minetest.register_on_player_hpchange(function(player, hp_change, reason)
|
mcl_damage.register_modifier(function(obj, damage, reason)
|
||||||
|
if EF.fire_proof[obj] and not reason.flags.bypasses_magic and reason.flags.is_fire then
|
||||||
if EF.fire_proof[player] and hp_change < 0 then
|
return 0
|
||||||
-- This is a bit forced, but it assumes damage is taken by fire and avoids it
|
|
||||||
-- also assumes any change in hp happens between calls to this function
|
|
||||||
-- it's worth noting that you don't take damage from players in this case...
|
|
||||||
local player_info = mcl_playerinfo[player:get_player_name()]
|
|
||||||
|
|
||||||
if is_fire_node[player_info.node_head] or is_fire_node[player_info.node_feet] or is_fire_node[player_info.node_stand] then
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
return hp_change
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
return hp_change
|
|
||||||
end
|
end
|
||||||
|
end, -50)
|
||||||
end, true)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -603,21 +571,18 @@ function mcl_potions.make_invisible(player, toggle)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if minetest.get_modpath("mcl_armor") and player:is_player() then
|
if player:is_player() then
|
||||||
armor.textures[playername].skin = skin_file
|
mcl_player.player_set_skin(player, "mobs_mc_empty.png")
|
||||||
armor:update_player_visuals(player)
|
elseif not player:is_player() then
|
||||||
elseif not player:is_player() and minetest.get_modpath("mcl_armor") or not player:is_player() and not minetest.get_modpath("mcl_armor") then
|
|
||||||
player:set_properties({visual_size = {x = 0, y = 0}})
|
player:set_properties({visual_size = {x = 0, y = 0}})
|
||||||
end
|
end
|
||||||
player:set_nametag_attributes({color = {a = 0}})
|
player:set_nametag_attributes({color = {a = 0}})
|
||||||
|
|
||||||
elseif EF.invisible[player] then -- show player
|
elseif EF.invisible[player] then -- show player
|
||||||
|
|
||||||
if minetest.get_modpath("mcl_armor") and player:is_player() then
|
if player:is_player() then
|
||||||
skin_file = mcl_skins.skins[playername] .. ".png"
|
mcl_skins.update_player_skin(player)
|
||||||
armor.textures[playername].skin = skin_file
|
elseif not player:is_player() then
|
||||||
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
|
|
||||||
player:set_properties({visual_size = EF.invisible[player].old_size})
|
player:set_properties({visual_size = EF.invisible[player].old_size})
|
||||||
end
|
end
|
||||||
player:set_nametag_attributes({color = {r = 255, g = 255, b = 255, a = 255}})
|
player:set_nametag_attributes({color = {r = 255, g = 255, b = 255, a = 255}})
|
||||||
|
@ -724,12 +689,7 @@ function mcl_potions.healing_func(player, hp)
|
||||||
hp = -1
|
hp = -1
|
||||||
end
|
end
|
||||||
|
|
||||||
if obj and obj._cmi_is_mob then
|
mcl_util.deal_damage(obj, -hp, {type = "magic"})
|
||||||
obj.health = obj.health + hp
|
|
||||||
elseif player:is_player() then
|
|
||||||
player:set_hp(player:get_hp() + hp, { type = "punch", other = "harming" })
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
name = mcl_tnt
|
name = mcl_tnt
|
||||||
depends = mcl_explosions, mcl_particles
|
depends = mcl_explosions, mcl_particles
|
||||||
optional_depends = mcl_sounds, mcl_mobitems, mcl_death_messages, doc_identifier, mesecons
|
optional_depends = mcl_sounds, mcl_mobitems, doc_identifier, mesecons
|
||||||
|
|
|
@ -1,5 +1,58 @@
|
||||||
-- Node is currently defined in mobs_mc.
|
local hud_totem = {}
|
||||||
-- TODO: Add full item definition here when status effects become a thing.
|
|
||||||
|
|
||||||
-- Add group for Creative Mode.
|
minetest.register_on_leaveplayer(function(player)
|
||||||
minetest.override_item("mobs_mc:totem", {groups = { combat_item=1}})
|
hud_totem[player] = nil
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Save the player from death when holding totem of undying in hand
|
||||||
|
mcl_damage.register_modifier(function(obj, damage, reason)
|
||||||
|
if obj:is_player() then
|
||||||
|
local hp = obj:get_hp()
|
||||||
|
if hp - damage <= 0 then
|
||||||
|
local wield = obj:get_wielded_item()
|
||||||
|
if wield:get_name() == "mobs_mc:totem" then
|
||||||
|
local ppos = obj:get_pos()
|
||||||
|
local pnname = minetest.get_node(ppos).name
|
||||||
|
-- Some exceptions when _not_ to save the player
|
||||||
|
for n=1, #mobs_mc.misc.totem_fail_nodes do
|
||||||
|
if pnname == mobs_mc.misc.totem_fail_nodes[n] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Reset breath as well
|
||||||
|
if obj:get_breath() < 11 then
|
||||||
|
obj:set_breath(10)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not minetest.is_creative_enabled(obj:get_player_name()) then
|
||||||
|
wield:take_item()
|
||||||
|
obj:set_wielded_item(wield)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Effects
|
||||||
|
minetest.sound_play({name = "mcl_totems_totem", gain=1}, {pos=ppos, max_hear_distance=16}, true)
|
||||||
|
|
||||||
|
-- Big totem overlay
|
||||||
|
if not hud_totem[obj] then
|
||||||
|
hud_totem[obj] = obj:hud_add({
|
||||||
|
hud_elem_type = "image",
|
||||||
|
text = "mcl_totems_totem.png",
|
||||||
|
position = { x=0.5, y=1 },
|
||||||
|
scale = { x=17, y=17 },
|
||||||
|
offset = { x=0, y=-178 },
|
||||||
|
z_index = 100,
|
||||||
|
})
|
||||||
|
minetest.after(3, function()
|
||||||
|
if obj:is_player() then
|
||||||
|
obj:hud_remove(hud_totem[obj])
|
||||||
|
hud_totem[obj] = nil
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set HP to exactly 1
|
||||||
|
return hp - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end, 1000)
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
name = mcl_totems
|
name = mcl_totems
|
||||||
depends = mobs_mc
|
depends = mobs_mc, mcl_damage
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
local S = minetest.get_translator("mcl_commands")
|
local S = minetest.get_translator("mcl_commands")
|
||||||
local mod_death_messages = minetest.get_modpath("mcl_death_messages")
|
|
||||||
|
|
||||||
local function handle_kill_command(suspect, victim)
|
local function handle_kill_command(suspect, victim)
|
||||||
if minetest.settings:get_bool("enable_damage") == false then
|
if minetest.settings:get_bool("enable_damage") == false then
|
||||||
|
@ -21,17 +20,8 @@ local function handle_kill_command(suspect, victim)
|
||||||
if wield:get_name() == "mobs_mc:totem" then
|
if wield:get_name() == "mobs_mc:totem" then
|
||||||
victimref:set_wielded_item("")
|
victimref:set_wielded_item("")
|
||||||
end
|
end
|
||||||
if mod_death_messages then
|
|
||||||
local msg
|
|
||||||
if suspect == victim then
|
|
||||||
msg = S("@1 committed suicide.", victim)
|
|
||||||
else
|
|
||||||
msg = S("@1 was killed by @2.", victim, suspect)
|
|
||||||
end
|
|
||||||
mcl_death_messages.player_damage(victimref, msg)
|
|
||||||
end
|
|
||||||
-- DIE!
|
-- DIE!
|
||||||
victimref:set_hp(0)
|
victimref:set_hp(0, {_mcl_type = "out_of_world"})
|
||||||
-- Log
|
-- Log
|
||||||
if not suspect == victim then
|
if not suspect == victim then
|
||||||
minetest.log("action", string.format("%s killed %s using /kill", suspect, victim))
|
minetest.log("action", string.format("%s killed %s using /kill", suspect, victim))
|
||||||
|
@ -56,4 +46,4 @@ minetest.register_chatcommand("kill", {
|
||||||
return handle_kill_command(name, param)
|
return handle_kill_command(name, param)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
name = mcl_commands
|
name = mcl_commands
|
||||||
author = Wuzzy
|
author = Wuzzy
|
||||||
description = MCL2 commands
|
description = MCL2 commands
|
||||||
optional_depends = mcl_death_messages
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
mcl_damage.register_modifier(function(obj, damage, reason)
|
||||||
|
if reason.type == "player" then
|
||||||
|
local hitter = reason.direct
|
||||||
|
if mcl_sprint.is_sprinting(hitter) then
|
||||||
|
obj:add_velocity(hitter:get_velocity())
|
||||||
|
elseif (hitter:get_velocity() or hitter:get_player_velocity()).y < 0 then
|
||||||
|
local pos = mcl_util.get_object_center(obj)
|
||||||
|
minetest.add_particlespawner({
|
||||||
|
amount = 15,
|
||||||
|
time = 0.1,
|
||||||
|
minpos = {x=pos.x-0.5, y=pos.y-0.5, z=pos.z-0.5},
|
||||||
|
maxpos = {x=pos.x+0.5, y=pos.y+0.5, z=pos.z+0.5},
|
||||||
|
minvel = {x=-0.1, y=-0.1, z=-0.1},
|
||||||
|
maxvel = {x=0.1, y=0.1, z=0.1},
|
||||||
|
minacc = {x=0, y=0, z=0},
|
||||||
|
maxacc = {x=0, y=0, z=0},
|
||||||
|
minexptime = 1,
|
||||||
|
maxexptime = 2,
|
||||||
|
minsize = 1.5,
|
||||||
|
maxsize = 1.5,
|
||||||
|
collisiondetection = false,
|
||||||
|
vertical = false,
|
||||||
|
texture = "mcl_particles_crit.png^[colorize:#bc7a57:127",
|
||||||
|
})
|
||||||
|
minetest.sound_play("mcl_criticals_hit", {object = obj})
|
||||||
|
-- the minecraft wiki is actually wrong about a crit dealing 150% damage, see minecraft source code
|
||||||
|
return damage + math.random(0, math.floor(damage * 1.5 + 2))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end, -100)
|
|
@ -0,0 +1,2 @@
|
||||||
|
name = mcl_criticals
|
||||||
|
depends = mcl_damage
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -11,7 +11,6 @@ end
|
||||||
mcl_death_drop.register_dropped_list("PLAYER", "main", true)
|
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", "craft", true)
|
||||||
mcl_death_drop.register_dropped_list("PLAYER", "armor", 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)
|
minetest.register_on_dieplayer(function(player)
|
||||||
local keep = minetest.settings:get_bool("mcl_keepInventory", false)
|
local keep = minetest.settings:get_bool("mcl_keepInventory", false)
|
||||||
|
@ -50,7 +49,6 @@ minetest.register_on_dieplayer(function(player)
|
||||||
inv:set_list(listname, {})
|
inv:set_list(listname, {})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
armor:set_player_armor(player)
|
mcl_armor.update(player)
|
||||||
armor:update_inventory(player)
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
local S = minetest.get_translator("mcl_hunger")
|
local S = minetest.get_translator("mcl_hunger")
|
||||||
local mod_death_messages = minetest.get_modpath("mcl_death_messages")
|
|
||||||
|
|
||||||
-- wrapper for minetest.item_eat (this way we make sure other mods can't break this one)
|
-- wrapper for minetest.item_eat (this way we make sure other mods can't break this one)
|
||||||
minetest.do_item_eat = function(hp_change, replace_with_item, itemstack, user, pointed_thing)
|
minetest.do_item_eat = function(hp_change, replace_with_item, itemstack, user, pointed_thing)
|
||||||
|
@ -110,10 +109,7 @@ local function poisonp(tick, time, time_left, damage, exhaustion, name)
|
||||||
-- Deal damage and exhaust player
|
-- Deal damage and exhaust player
|
||||||
-- TODO: Introduce fatal poison at higher difficulties
|
-- TODO: Introduce fatal poison at higher difficulties
|
||||||
if player:get_hp()-damage > 0 then
|
if player:get_hp()-damage > 0 then
|
||||||
if mod_death_messages then
|
mcl_util.deal_damage(player, damage, {type = "hunger"})
|
||||||
mcl_death_messages.player_damage(player, S("@1 succumbed to the poison.", name))
|
|
||||||
end
|
|
||||||
player:set_hp(player:get_hp()-damage)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
mcl_hunger.exhaust(name, exhaustion)
|
mcl_hunger.exhaust(name, exhaustion)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
local S = minetest.get_translator("mcl_hunger")
|
local S = minetest.get_translator("mcl_hunger")
|
||||||
local mod_death_messages = minetest.get_modpath("mcl_death_messages")
|
|
||||||
|
|
||||||
mcl_hunger = {}
|
mcl_hunger = {}
|
||||||
|
|
||||||
|
@ -159,10 +158,7 @@ minetest.register_globalstep(function(dtime)
|
||||||
-- Damage hungry player down to 1 HP
|
-- Damage hungry player down to 1 HP
|
||||||
-- TODO: Allow starvation at higher difficulty levels
|
-- TODO: Allow starvation at higher difficulty levels
|
||||||
if hp-1 > 0 then
|
if hp-1 > 0 then
|
||||||
if mod_death_messages then
|
mcl_util.deal_damage(player, 1, {type = "starve"})
|
||||||
mcl_death_messages.player_damage(player, S("@1 starved to death.", name))
|
|
||||||
end
|
|
||||||
player:set_hp(hp-1)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,4 +2,3 @@ name = mcl_hunger
|
||||||
author = BlockMen
|
author = BlockMen
|
||||||
description = Adds a simple hunger meachanic with satiation, food poisoning and different healing.
|
description = Adds a simple hunger meachanic with satiation, food poisoning and different healing.
|
||||||
depends = hudbars
|
depends = hudbars
|
||||||
optional_depends = mcl_death_messages
|
|
||||||
|
|
|
@ -88,22 +88,41 @@ function mcl_player.player_set_model(player, model_name)
|
||||||
player_model[name] = model_name
|
player_model[name] = model_name
|
||||||
end
|
end
|
||||||
|
|
||||||
function mcl_player.player_set_textures(player, textures, preview)
|
local function set_texture(player, index, texture)
|
||||||
local name = player:get_player_name()
|
local textures = player_textures[player:get_player_name()]
|
||||||
player_textures[name] = textures
|
textures[index] = texture
|
||||||
player:set_properties({textures = textures,})
|
player:set_properties({textures = textures})
|
||||||
if preview then
|
end
|
||||||
player:get_meta():set_string("mcl_player:preview", preview)
|
|
||||||
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
|
end
|
||||||
|
|
||||||
function mcl_player.player_get_preview(player)
|
function mcl_player.player_get_preview(player)
|
||||||
local preview = player:get_meta():get_string("mcl_player:preview")
|
local preview = player:get_meta():get_string("mcl_player:skin_preview")
|
||||||
if preview == nil or preview == "" then
|
if preview == "" then
|
||||||
return "player.png"
|
preview = "player.png"
|
||||||
else
|
|
||||||
return preview
|
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
function mcl_player.get_player_formspec_model(player, x, y, w, h, fsname)
|
function mcl_player.get_player_formspec_model(player, x, y, w, h, fsname)
|
||||||
|
@ -129,8 +148,10 @@ end
|
||||||
|
|
||||||
-- Update appearance when the player joins
|
-- Update appearance when the player joins
|
||||||
minetest.register_on_joinplayer(function(player)
|
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")
|
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_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>>>>
|
player:set_fov(86.1) -- see <https://minecraft.gamepedia.com/Options#Video_settings>>>>
|
||||||
end)
|
end)
|
||||||
|
@ -222,62 +243,3 @@ minetest.register_globalstep(function(dtime)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Don't change HP if the player falls in the water or through End Portal:
|
|
||||||
minetest.register_on_player_hpchange(function(player, hp_change, reason)
|
|
||||||
if reason and reason.type == "fall" and player then
|
|
||||||
local pos = player:get_pos()
|
|
||||||
local node = minetest.get_node(pos)
|
|
||||||
local velocity = player:get_velocity() or player:get_player_velocity() or {x=0,y=-10,z=0}
|
|
||||||
local v_axis_max = math.max(math.abs(velocity.x), math.abs(velocity.y), math.abs(velocity.z))
|
|
||||||
local step = {x = velocity.x / v_axis_max, y = velocity.y / v_axis_max, z = velocity.z / v_axis_max}
|
|
||||||
for i = 1, math.ceil(v_axis_max/5)+1 do -- trace at least 1/5 of the way per second
|
|
||||||
if not node or node.name == "ignore" then
|
|
||||||
minetest.get_voxel_manip():read_from_map(pos, pos)
|
|
||||||
node = minetest.get_node(pos)
|
|
||||||
end
|
|
||||||
if node then
|
|
||||||
if minetest.registered_nodes[node.name].walkable then
|
|
||||||
return hp_change
|
|
||||||
end
|
|
||||||
if minetest.get_item_group(node.name, "water") ~= 0 then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
if node.name == "mcl_portals:portal_end" then
|
|
||||||
if mcl_portals and mcl_portals.end_teleport then
|
|
||||||
mcl_portals.end_teleport(player)
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
pos = vector.add(pos, step)
|
|
||||||
node = minetest.get_node(pos)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return hp_change
|
|
||||||
end, true)
|
|
||||||
|
|
||||||
minetest.register_on_respawnplayer(function(player)
|
|
||||||
local pos = player:get_pos()
|
|
||||||
minetest.add_particlespawner({
|
|
||||||
amount = 50,
|
|
||||||
time = 0.001,
|
|
||||||
minpos = vector.add(pos, 0),
|
|
||||||
maxpos = vector.add(pos, 0),
|
|
||||||
minvel = vector.new(-5,-5,-5),
|
|
||||||
maxvel = vector.new(5,5,5),
|
|
||||||
minexptime = 1.1,
|
|
||||||
maxexptime = 1.5,
|
|
||||||
minsize = 1,
|
|
||||||
maxsize = 2,
|
|
||||||
collisiondetection = false,
|
|
||||||
vertical = false,
|
|
||||||
texture = "mcl_particles_mob_death.png^[colorize:#000000:255",
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.sound_play("mcl_mobs_mob_poof", {
|
|
||||||
pos = pos,
|
|
||||||
gain = 1.0,
|
|
||||||
max_hear_distance = 8,
|
|
||||||
}, true)
|
|
||||||
end)
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
name = mcl_playerinfo
|
name = mcl_playerinfo
|
||||||
author = TenPlus1
|
author = TenPlus1
|
||||||
description = This is a helper mod for other mod to query the nodes around the player.
|
description = This is a helper mod for other mod to query the nodes around the player.
|
||||||
depends = mcl_init, mcl_core, mcl_particles, mcl_death_messages
|
depends = mcl_init, mcl_core, mcl_particles
|
||||||
|
|
|
@ -114,37 +114,6 @@ end
|
||||||
|
|
||||||
local node_stand, node_stand_below, node_head, node_feet
|
local node_stand, node_stand_below, node_head, node_feet
|
||||||
|
|
||||||
|
|
||||||
minetest.register_on_punchplayer(function(player, hitter, damage)
|
|
||||||
if hitter:is_player() then
|
|
||||||
if hitter:get_player_control().aux1 then
|
|
||||||
player:add_velocity(hitter:get_velocity())
|
|
||||||
end
|
|
||||||
if hitter:get_velocity().y < -6 then
|
|
||||||
player:set_hp(player:get_hp() - (damage * math.random(0.50 , 0.75)))
|
|
||||||
local pos = player:get_pos()
|
|
||||||
minetest.add_particlespawner({
|
|
||||||
amount = 15,
|
|
||||||
time = 0.1,
|
|
||||||
minpos = {x=pos.x-0.5, y=pos.y-0.5, z=pos.z-0.5},
|
|
||||||
maxpos = {x=pos.x+0.5, y=pos.y+0.5, z=pos.z+0.5},
|
|
||||||
minvel = {x=-0.1, y=-0.1, z=-0.1},
|
|
||||||
maxvel = {x=0.1, y=0.1, z=0.1},
|
|
||||||
minacc = {x=0, y=0, z=0},
|
|
||||||
maxacc = {x=0, y=0, z=0},
|
|
||||||
minexptime = 1,
|
|
||||||
maxexptime = 2,
|
|
||||||
minsize = 1.5,
|
|
||||||
maxsize = 1.5,
|
|
||||||
collisiondetection = false,
|
|
||||||
vertical = false,
|
|
||||||
texture = "mcl_particles_crit.png^[colorize:#bc7a57:127",
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
|
|
||||||
minetest.register_globalstep(function(dtime)
|
minetest.register_globalstep(function(dtime)
|
||||||
|
|
||||||
time = time + dtime
|
time = time + dtime
|
||||||
|
@ -166,6 +135,7 @@ minetest.register_globalstep(function(dtime)
|
||||||
local parent = player:get_attach()
|
local parent = player:get_attach()
|
||||||
local wielded = player:get_wielded_item()
|
local wielded = player:get_wielded_item()
|
||||||
local player_velocity = player:get_velocity() or player:get_player_velocity()
|
local player_velocity = player:get_velocity() or player:get_player_velocity()
|
||||||
|
local wielded_def = wielded:get_definition()
|
||||||
|
|
||||||
local c_x, c_y = unpack(player_collision(player))
|
local c_x, c_y = unpack(player_collision(player))
|
||||||
|
|
||||||
|
@ -249,7 +219,16 @@ minetest.register_globalstep(function(dtime)
|
||||||
playerphysics.remove_physics_factor(player, "gravity", "mcl_playerplus:elytra")
|
playerphysics.remove_physics_factor(player, "gravity", "mcl_playerplus:elytra")
|
||||||
end
|
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
|
||||||
|
|
||||||
player_velocity_old = player:get_velocity() or player:get_player_velocity()
|
player_velocity_old = player:get_velocity() or player:get_player_velocity()
|
||||||
|
|
||||||
-- controls right and left arms pitch when shooting a bow
|
-- 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
|
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))
|
player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(pitch+90,-30,pitch * -1 * .35))
|
||||||
|
@ -423,8 +402,7 @@ minetest.register_globalstep(function(dtime)
|
||||||
-- Check privilege, too
|
-- Check privilege, too
|
||||||
and (not check_player_privs(name, {noclip = true})) then
|
and (not check_player_privs(name, {noclip = true})) then
|
||||||
if player:get_hp() > 0 then
|
if player:get_hp() > 0 then
|
||||||
mcl_death_messages.player_damage(player, S("@1 suffocated to death.", name))
|
mcl_util.deal_damage(player, 1, {type = "in_wall"})
|
||||||
player:set_hp(player:get_hp() - 1)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -439,8 +417,7 @@ minetest.register_globalstep(function(dtime)
|
||||||
local dist_feet = vector.distance({x=pos.x, y=pos.y-1, z=pos.z}, near)
|
local dist_feet = vector.distance({x=pos.x, y=pos.y-1, z=pos.z}, near)
|
||||||
if dist < 1.1 or dist_feet < 1.1 then
|
if dist < 1.1 or dist_feet < 1.1 then
|
||||||
if player:get_hp() > 0 then
|
if player:get_hp() > 0 then
|
||||||
mcl_death_messages.player_damage(player, S("@1 was prickled to death by a cactus.", name))
|
mcl_util.deal_damage(player, 1, {type = "cactus"})
|
||||||
player:set_hp(player:get_hp() - 1, { type = "punch", from = "mod" })
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -547,3 +524,61 @@ minetest.register_on_leaveplayer(function(player)
|
||||||
mcl_playerplus_internal[name] = nil
|
mcl_playerplus_internal[name] = nil
|
||||||
mcl_playerplus.elytra[player] = nil
|
mcl_playerplus.elytra[player] = nil
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- Don't change HP if the player falls in the water or through End Portal:
|
||||||
|
mcl_damage.register_modifier(function(obj, damage, reason)
|
||||||
|
if reason.type == "fall" then
|
||||||
|
local pos = obj:get_pos()
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
local velocity = obj:get_velocity() or obj:get_player_velocity() or {x=0,y=-10,z=0}
|
||||||
|
local v_axis_max = math.max(math.abs(velocity.x), math.abs(velocity.y), math.abs(velocity.z))
|
||||||
|
local step = {x = velocity.x / v_axis_max, y = velocity.y / v_axis_max, z = velocity.z / v_axis_max}
|
||||||
|
for i = 1, math.ceil(v_axis_max/5)+1 do -- trace at least 1/5 of the way per second
|
||||||
|
if not node or node.name == "ignore" then
|
||||||
|
minetest.get_voxel_manip():read_from_map(pos, pos)
|
||||||
|
node = minetest.get_node(pos)
|
||||||
|
end
|
||||||
|
if node then
|
||||||
|
if minetest.registered_nodes[node.name].walkable then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if minetest.get_item_group(node.name, "water") ~= 0 then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
if node.name == "mcl_portals:portal_end" then
|
||||||
|
if mcl_portals and mcl_portals.end_teleport then
|
||||||
|
mcl_portals.end_teleport(obj)
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
pos = vector.add(pos, step)
|
||||||
|
node = minetest.get_node(pos)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end, -200)
|
||||||
|
|
||||||
|
minetest.register_on_respawnplayer(function(player)
|
||||||
|
local pos = player:get_pos()
|
||||||
|
minetest.add_particlespawner({
|
||||||
|
amount = 50,
|
||||||
|
time = 0.001,
|
||||||
|
minpos = vector.add(pos, 0),
|
||||||
|
maxpos = vector.add(pos, 0),
|
||||||
|
minvel = vector.new(-5,-5,-5),
|
||||||
|
maxvel = vector.new(5,5,5),
|
||||||
|
minexptime = 1.1,
|
||||||
|
maxexptime = 1.5,
|
||||||
|
minsize = 1,
|
||||||
|
maxsize = 2,
|
||||||
|
collisiondetection = false,
|
||||||
|
vertical = false,
|
||||||
|
texture = "mcl_particles_mob_death.png^[colorize:#000000:255",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.sound_play("mcl_mobs_mob_poof", {
|
||||||
|
pos = pos,
|
||||||
|
gain = 1.0,
|
||||||
|
max_hear_distance = 8,
|
||||||
|
}, true)
|
||||||
|
end)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
name = mcl_playerplus
|
name = mcl_playerplus
|
||||||
author = TenPlus1
|
author = TenPlus1
|
||||||
description = Adds some simple player-related gameplay effects: Hurt by touching a cactus, suffocation and more.
|
description = Adds some simple player-related gameplay effects: Hurt by touching a cactus, suffocation and more.
|
||||||
depends = mcl_init, mcl_core, mcl_particles, mcl_hunger, mcl_death_messages, playerphysics, mcl_playerinfo, mcl_weather, mcl_spawn, mcl_enchanting
|
depends = mcl_init, mcl_core, mcl_particles, mcl_hunger, playerphysics, mcl_playerinfo, mcl_weather, mcl_spawn, mcl_enchanting, mcl_damage
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ mcl_skins = {
|
||||||
}
|
}
|
||||||
|
|
||||||
local S = minetest.get_translator("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")
|
local has_mcl_inventory = minetest.get_modpath("mcl_inventory")
|
||||||
|
|
||||||
-- load skin list and metadata
|
-- load skin list and metadata
|
||||||
|
@ -115,10 +114,6 @@ mcl_skins.set_player_skin = function(player, skin_id)
|
||||||
mcl_skins.previews[playername] = preview
|
mcl_skins.previews[playername] = preview
|
||||||
player:get_meta():set_string("mcl_skins:skin_id", tostring(skin_id))
|
player:get_meta():set_string("mcl_skins:skin_id", tostring(skin_id))
|
||||||
mcl_skins.update_player_skin(player)
|
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
|
if has_mcl_inventory then
|
||||||
mcl_inventory.update_inventory_formspec(player)
|
mcl_inventory.update_inventory_formspec(player)
|
||||||
end
|
end
|
||||||
|
@ -134,7 +129,7 @@ mcl_skins.update_player_skin = function(player)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local playername = player:get_player_name()
|
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
|
end
|
||||||
|
|
||||||
-- load player skin on join
|
-- load player skin on join
|
||||||
|
|
|
@ -2,4 +2,4 @@ name = mcl_skins
|
||||||
author = TenPlus1
|
author = TenPlus1
|
||||||
description = Mod that allows players to set their individual skins.
|
description = Mod that allows players to set their individual skins.
|
||||||
depends = mcl_player
|
depends = mcl_player
|
||||||
optional_depends = mcl_inventory, intllib, mcl_armor
|
optional_depends = mcl_inventory, intllib
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
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 itemstack = player:get_wielded_item()
|
||||||
|
local itemname = itemstack:get_name()
|
||||||
|
|
||||||
|
local def = mcl_wieldview.players[player]
|
||||||
|
|
||||||
|
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)
|
||||||
|
mcl_wieldview.players[player] = {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 = player
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
minetest.register_on_leaveplayer(function(player)
|
||||||
|
mcl_wieldview.players[player] = 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)
|
||||||
|
if self.wielder:is_player() then
|
||||||
|
local def = mcl_wieldview.players[self.wielder]
|
||||||
|
local itemstring = def.item
|
||||||
|
|
||||||
|
if self.itemstring ~= itemstring then
|
||||||
|
local itemdef = minetest.registered_items[itemstring]
|
||||||
|
self.object:set_properties({glow = itemdef and itemdef.light_source or 0})
|
||||||
|
|
||||||
|
-- wield item as cubic
|
||||||
|
if def.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,
|
||||||
|
})
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue