Majority of mapgen

This commit is contained in:
Nathan Fritzler 2022-06-06 19:30:58 -06:00
parent 46b8300b57
commit d791930272
Signed by: Lazerbeak12345
GPG Key ID: 736DE8D7C58AD7FE
1462 changed files with 24 additions and 60173 deletions

View File

@ -1,28 +0,0 @@
===ITEM_DROP MOD for MINETEST-C55===
by PilzAdam
Introduction:
This mod adds Minecraft like drop/pick up of items to Minetest.
This mod has been forked from item_drop in the VoxBox game.
License:
Sourcecode: WTFPL (see below)
Sound: WTFPL (see below)
See also:
http://minetest.net/
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

View File

@ -1,833 +0,0 @@
--these are lua locals, used for higher performance
local minetest, math, vector, ipairs, pairs = minetest, math, vector, ipairs, pairs
--this is used for the player pool in the sound buffer
local pool = {}
local tick = false
minetest.register_on_joinplayer(function(player)
local name
name = player:get_player_name()
pool[name] = 0
end)
minetest.register_on_leaveplayer(function(player)
local name
name = player:get_player_name()
pool[name] = nil
end)
local has_awards = minetest.get_modpath("awards")
local mcl_item_entity = {}
--basic settings
local item_drop_settings = {} --settings table
item_drop_settings.dug_buffer = 0.65 -- the warm up period before a dug item can be collected
item_drop_settings.age = 1.0 --how old a dropped item (_insta_collect==false) has to be before collecting
item_drop_settings.radius_magnet = 2.0 --radius of item magnet. MUST BE LARGER THAN radius_collect!
item_drop_settings.xp_radius_magnet = 7.25 --radius of xp magnet. MUST BE LARGER THAN radius_collect!
item_drop_settings.radius_collect = 0.2 --radius of collection
item_drop_settings.player_collect_height = 0.8 --added to their pos y value
item_drop_settings.collection_safety = false --do this to prevent items from flying away on laggy servers
item_drop_settings.random_item_velocity = true --this sets random item velocity if velocity is 0
item_drop_settings.drop_single_item = false --if true, the drop control drops 1 item instead of the entire stack, and sneak+drop drops the stack
-- drop_single_item is disabled by default because it is annoying to throw away items from the intentory screen
item_drop_settings.magnet_time = 0.75 -- how many seconds an item follows the player before giving up
local function get_gravity()
return tonumber(minetest.settings:get("movement_gravity")) or 9.81
end
local registered_pickup_achievement = {}
--TODO: remove limitation of 1 award per itemname
function mcl_item_entity.register_pickup_achievement(itemname, award)
if not has_awards then
minetest.log("warning", "[mcl_item_entity] Trying to register pickup achievement ["..award.."] for ["..itemname.."] while awards missing")
elseif registered_pickup_achievement[itemname] then
minetest.log("error", "[mcl_item_entity] Trying to register already existing pickup achievement ["..award.."] for ["..itemname.."]")
else
registered_pickup_achievement[itemname] = award
end
end
mcl_item_entity.register_pickup_achievement("tree", "mcl:mineWood")
mcl_item_entity.register_pickup_achievement("mcl_mobitems:blaze_rod", "mcl:blazeRod")
mcl_item_entity.register_pickup_achievement("mcl_mobitems:leather", "mcl:killCow")
mcl_item_entity.register_pickup_achievement("mcl_core:diamond", "mcl:diamonds")
local function check_pickup_achievements(object, player)
if has_awards then
local itemname = ItemStack(object:get_luaentity().itemstring):get_name()
local playername = player:get_player_name()
for name,award in pairs(registered_pickup_achievement) do
if itemname == name or minetest.get_item_group(itemname, name) ~= 0 then
awards.unlock(playername, award)
end
end
end
end
local function enable_physics(object, luaentity, ignore_check)
if luaentity.physical_state == false or ignore_check == true then
luaentity.physical_state = true
object:set_properties({
physical = true
})
object:set_acceleration({x=0,y=-get_gravity(),z=0})
end
end
local function disable_physics(object, luaentity, ignore_check, reset_movement)
if luaentity.physical_state == true or ignore_check == true then
luaentity.physical_state = false
object:set_properties({
physical = false
})
if reset_movement ~= false then
object:set_velocity({x=0,y=0,z=0})
object:set_acceleration({x=0,y=0,z=0})
end
end
end
minetest.register_globalstep(function(dtime)
tick = not tick
for _,player in pairs(minetest.get_connected_players()) do
if player:get_hp() > 0 or not minetest.settings:get_bool("enable_damage") then
local name = player:get_player_name()
local pos = player:get_pos()
if tick == true and pool[name] > 0 then
minetest.sound_play("item_drop_pickup", {
pos = pos,
gain = 0.3,
max_hear_distance = 16,
pitch = math.random(70,110)/100
})
if pool[name] > 6 then
pool[name] = 6
else
pool[name] = pool[name] - 1
end
end
local inv = player:get_inventory()
local checkpos = {x=pos.x,y=pos.y + item_drop_settings.player_collect_height,z=pos.z}
--magnet and collection
for _,object in pairs(minetest.get_objects_inside_radius(checkpos, item_drop_settings.xp_radius_magnet)) do
if not object:is_player() and vector.distance(checkpos, object:get_pos()) < item_drop_settings.radius_magnet and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" and object:get_luaentity()._magnet_timer and (object:get_luaentity()._insta_collect or (object:get_luaentity().age > item_drop_settings.age)) then
if object:get_luaentity()._magnet_timer >= 0 and object:get_luaentity()._magnet_timer < item_drop_settings.magnet_time and inv and inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then
-- Collection
if not object:get_luaentity()._removed then
-- Ignore if itemstring is not set yet
if object:get_luaentity().itemstring ~= "" then
inv:add_item("main", ItemStack(object:get_luaentity().itemstring))
check_pickup_achievements(object, player)
-- Destroy entity
-- This just prevents this section to be run again because object:remove() doesn't remove the item immediately.
object:get_luaentity().target = checkpos
object:get_luaentity()._removed = true
object:set_velocity({x=0,y=0,z=0})
object:set_acceleration({x=0,y=0,z=0})
object:move_to(checkpos)
pool[name] = pool[name] + 1
minetest.after(0.25, function()
--safety check
if object and object:get_luaentity() then
object:remove()
end
end)
end
end
end
elseif not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "mcl_experience:orb" then
local entity = object:get_luaentity()
entity.collector = player:get_player_name()
entity.collected = true
end
end
end
end
end)
-- Stupid workaround to get drops from a drop table:
-- Create a temporary table in minetest.registered_nodes that contains the proper drops,
-- because unfortunately minetest.get_node_drops needs the drop table to be inside a registered node definition
-- (very ugly)
local tmp_id = 0
local function get_drops(drop, toolname, param2, paramtype2)
tmp_id = tmp_id + 1
local tmp_node_name = "mcl_item_entity:" .. tmp_id
minetest.registered_nodes[tmp_node_name] = {
name = tmp_node_name,
drop = drop,
paramtype2 = paramtype2
}
local drops = minetest.get_node_drops({name = tmp_node_name, param2 = param2}, toolname)
minetest.registered_nodes[tmp_node_name] = nil
return drops
end
local function discrete_uniform_distribution(drops, min_count, max_count, cap)
local new_drops = table.copy(drops)
for i, item in ipairs(drops) do
local new_item = ItemStack(item)
local multiplier = math.random(min_count, max_count)
if cap then
multiplier = math.min(cap, multiplier)
end
new_item:set_count(multiplier * new_item:get_count())
new_drops[i] = new_item
end
return new_drops
end
local function get_fortune_drops(fortune_drops, fortune_level)
local drop
local i = fortune_level
repeat
drop = fortune_drops[i]
i = i - 1
until drop or i < 1
return drop or {}
end
local doTileDrops = minetest.settings:get_bool("mcl_doTileDrops", true)
function minetest.handle_node_drops(pos, drops, digger)
-- NOTE: This function override allows digger to be nil.
-- This means there is no digger. This is a special case which allows this function to be called
-- by hand. Creative Mode is intentionally ignored in this case.
if (digger and digger:is_player() and minetest.is_creative_enabled(digger:get_player_name())) or doTileDrops == false then
return
end
-- Check if node will yield its useful drop by the digger's tool
local dug_node = minetest.get_node(pos)
local tooldef
local tool
if digger then
tool = digger:get_wielded_item()
tooldef = minetest.registered_tools[tool:get_name()]
if not mcl_autogroup.can_harvest(dug_node.name, tool:get_name()) then
return
end
end
local diggroups = tooldef and tooldef._mcl_diggroups
local shearsy_level = diggroups and diggroups.shearsy and diggroups.shearsy.level
--[[ Special node drops when dug by shears by reading _mcl_shears_drop or with a silk touch tool reading _mcl_silk_touch_drop
from the node definition.
Definition of _mcl_shears_drop / _mcl_silk_touch_drop:
* true: Drop itself when dug by shears / silk touch tool
* table: Drop every itemstring in this table when dug by shears _mcl_silk_touch_drop
]]
local enchantments = tool and mcl_enchanting.get_enchantments(tool, "silk_touch")
local silk_touch_drop = false
local nodedef = minetest.registered_nodes[dug_node.name]
if not nodedef then return end
if shearsy_level and shearsy_level > 0 and nodedef._mcl_shears_drop then
if nodedef._mcl_shears_drop == true then
drops = { dug_node.name }
else
drops = nodedef._mcl_shears_drop
end
elseif tool and enchantments.silk_touch and nodedef._mcl_silk_touch_drop then
silk_touch_drop = true
if nodedef._mcl_silk_touch_drop == true then
drops = { dug_node.name }
else
drops = nodedef._mcl_silk_touch_drop
end
end
if tool and nodedef._mcl_fortune_drop and enchantments.fortune then
local fortune_level = enchantments.fortune
local fortune_drop = nodedef._mcl_fortune_drop
if fortune_drop.discrete_uniform_distribution then
local min_count = fortune_drop.min_count
local max_count = fortune_drop.max_count + fortune_level * (fortune_drop.factor or 1)
local chance = fortune_drop.chance or fortune_drop.get_chance and fortune_drop.get_chance(fortune_level)
if not chance or math.random() < chance then
drops = discrete_uniform_distribution(fortune_drop.multiply and drops or fortune_drop.items, min_count, max_count, fortune_drop.cap)
elseif fortune_drop.override then
drops = {}
end
else
-- Fixed Behavior
local drop = get_fortune_drops(fortune_drop, fortune_level)
drops = get_drops(drop, tool:get_name(), dug_node.param2, nodedef.paramtype2)
end
end
if digger and mcl_experience.throw_xp and not silk_touch_drop then
local experience_amount = minetest.get_item_group(dug_node.name,"xp")
if experience_amount > 0 then
mcl_experience.throw_xp(pos, experience_amount)
end
end
for _,item in ipairs(drops) do
local count
if type(item) == "string" then
count = ItemStack(item):get_count()
else
count = item:get_count()
end
local drop_item = ItemStack(item)
drop_item:set_count(1)
for i=1,count do
local dpos = table.copy(pos)
-- Apply offset for plantlike_rooted nodes because of their special shape
if nodedef and nodedef.drawtype == "plantlike_rooted" and nodedef.walkable then
dpos.y = dpos.y + 1
end
-- Spawn item and apply random speed
local obj = minetest.add_item(dpos, drop_item)
if obj then
local x = math.random(1, 5)
if math.random(1,2) == 1 then
x = -x
end
local z = math.random(1, 5)
if math.random(1,2) == 1 then
z = -z
end
obj:set_velocity({x=1/x, y=obj:get_velocity().y, z=1/z})
obj:get_luaentity().age = item_drop_settings.dug_buffer
obj:get_luaentity()._insta_collect = false
end
end
end
end
-- Drop single items by default
function minetest.item_drop(itemstack, dropper, pos)
if dropper and dropper:is_player() then
local v = dropper:get_look_dir()
local p = {x=pos.x, y=pos.y+1.2, z=pos.z}
local cs = itemstack:get_count()
if dropper:get_player_control().sneak then
cs = 1
end
local item = itemstack:take_item(cs)
local obj = minetest.add_item(p, item)
if obj then
v.x = v.x*4
v.y = v.y*4 + 2
v.z = v.z*4
obj:set_velocity(v)
-- Force collection delay
obj:get_luaentity()._insta_collect = false
return itemstack
end
end
end
--modify builtin:item
local time_to_live = tonumber(minetest.settings:get("item_entity_ttl"))
if not time_to_live then
time_to_live = 300
end
local function cxcz(o, cw, one, zero)
if cw < 0 then
table.insert(o, { [one]=1, y=0, [zero]=0 })
table.insert(o, { [one]=-1, y=0, [zero]=0 })
else
table.insert(o, { [one]=-1, y=0, [zero]=0 })
table.insert(o, { [one]=1, y=0, [zero]=0 })
end
return o
end
minetest.register_entity(":__builtin:item", {
initial_properties = {
hp_max = 1,
physical = true,
collide_with_objects = false,
collisionbox = {-0.3, -0.3, -0.3, 0.3, 0.3, 0.3},
pointable = false,
visual = "wielditem",
visual_size = {x = 0.4, y = 0.4},
textures = {""},
spritediv = {x = 1, y = 1},
initial_sprite_basepos = {x = 0, y = 0},
is_visible = false,
infotext = "",
},
-- Itemstring of dropped item. The empty string is used when the item is not yet initialized yet.
-- The itemstring MUST be set immediately to a non-empty string after creating the entity.
-- The hand is NOT permitted as dropped item. ;-)
-- Item entities will be deleted if they still have an empty itemstring on their first on_step tick.
itemstring = "",
-- If true, item will fall
physical_state = true,
-- If item entity is currently flowing in water
_flowing = false,
-- Number of seconds this item entity has existed so far
age = 0,
-- How old it has become in the collection animation
collection_age = 0,
set_item = function(self, itemstring)
self.itemstring = itemstring
if self.itemstring == "" then
-- item not yet known
return
end
local stack = ItemStack(itemstring)
if minetest.get_item_group(stack:get_name(), "compass") > 0 then
if string.find(stack:get_name(), "_lodestone") then
stack:set_name("mcl_compass:18_lodestone")
else
stack:set_name("mcl_compass:18")
end
itemstring = stack:to_string()
self.itemstring = itemstring
end
if minetest.get_item_group(stack:get_name(), "clock") > 0 then
self.is_clock = true
end
local count = stack:get_count()
local max_count = stack:get_stack_max()
if count > max_count then
count = max_count
self.itemstring = stack:get_name().." "..max_count
end
local itemtable = stack:to_table()
local itemname = nil
local description = ""
if itemtable then
itemname = stack:to_table().name
end
local glow
local def = minetest.registered_items[itemname]
if def then
description = def.description
glow = def.light_source
end
local s = 0.2 + 0.1 * (count / max_count)
local wield_scale = (def and def.wield_scale and def.wield_scale.x) or 1
local c = s
s = s / wield_scale
local prop = {
is_visible = true,
visual = "wielditem",
textures = {itemname},
visual_size = {x = s, y = s},
collisionbox = {-c, -c, -c, c, c, c},
automatic_rotate = math.pi * 0.5,
infotext = description,
glow = glow,
}
self.object:set_properties(prop)
if item_drop_settings.random_item_velocity == true then
minetest.after(0, function(self)
if not self or not self.object or not self.object:get_luaentity() then
return
end
local vel = self.object:get_velocity()
if vel and vel.x == 0 and vel.z == 0 then
local x = math.random(1, 5)
if math.random(1,2) == 1 then
x = -x
end
local z = math.random(1, 5)
if math.random(1,2) == 1 then
z = -z
end
local y = math.random(2,4)
self.object:set_velocity({x=1/x, y=y, z=1/z})
end
end, self)
end
end,
get_staticdata = function(self)
local data = minetest.serialize({
itemstring = self.itemstring,
always_collect = self.always_collect,
age = self.age,
_insta_collect = self._insta_collect,
_flowing = self._flowing,
_removed = self._removed,
})
-- sfan5 guessed that the biggest serializable item
-- entity would have a size of 65530 bytes. This has
-- been experimentally verified to be still too large.
--
-- anon5 has calculated that the biggest serializable
-- item entity has a size of exactly 65487 bytes:
--
-- 1. serializeString16 can handle max. 65535 bytes.
-- 2. The following engine metadata is always saved:
-- • 1 byte (version)
-- • 2 byte (length prefix)
-- • 14 byte “__builtin:item”
-- • 4 byte (length prefix)
-- • 2 byte (health)
-- • 3 × 4 byte = 12 byte (position)
-- • 4 byte (yaw)
-- • 1 byte (version 2)
-- • 2 × 4 byte = 8 byte (pitch and roll)
-- 3. This leaves 65487 bytes for the serialization.
if #data > 65487 then -- would crash the engine
local stack = ItemStack(self.itemstring)
stack:get_meta():from_table(nil)
self.itemstring = stack:to_string()
minetest.log(
"warning",
"Overlong item entity metadata removed: “" ..
self.itemstring ..
"” had serialized length of " ..
#data
)
return self:get_staticdata()
end
return data
end,
on_activate = function(self, staticdata, dtime_s)
if string.sub(staticdata, 1, string.len("return")) == "return" then
local data = minetest.deserialize(staticdata)
if data and type(data) == "table" then
self.itemstring = data.itemstring
self.always_collect = data.always_collect
if data.age then
self.age = data.age + dtime_s
else
self.age = dtime_s
end
--remember collection data
-- If true, can collect item without delay
self._insta_collect = data._insta_collect
self._flowing = data._flowing
self._removed = data._removed
end
else
self.itemstring = staticdata
end
if self._removed then
self._removed = true
self.object:remove()
return
end
if self._insta_collect == nil then
-- Intentionally default, since delayed collection is rare
self._insta_collect = true
end
if self._flowing == nil then
self._flowing = false
end
self._magnet_timer = 0
self._magnet_active = false
-- How long ago the last possible collector was detected. nil = none in this session
self._collector_timer = nil
-- Used to apply additional force
self._force = nil
self._forcestart = nil
self._forcetimer = 0
self.object:set_armor_groups({immortal = 1})
self.object:set_velocity({x = 0, y = 2, z = 0})
self.object:set_acceleration({x = 0, y = -get_gravity(), z = 0})
self:set_item(self.itemstring)
end,
try_merge_with = function(self, own_stack, object, entity)
if self.age == entity.age or entity._removed then
-- Can not merge with itself and remove entity
return false
end
local stack = ItemStack(entity.itemstring)
local name = stack:get_name()
if own_stack:get_name() ~= name or
own_stack:get_meta() ~= stack:get_meta() or
own_stack:get_wear() ~= stack:get_wear() or
own_stack:get_free_space() == 0 then
-- Can not merge different or full stack
return false
end
local count = own_stack:get_count()
local total_count = stack:get_count() + count
local max_count = stack:get_stack_max()
if total_count > max_count then
return false
end
-- Merge the remote stack into this one
local pos = object:get_pos()
pos.y = pos.y + ((total_count - count) / max_count) * 0.15
self.object:move_to(pos)
self.age = 0 -- Handle as new entity
own_stack:set_count(total_count)
self:set_item(own_stack:to_string())
entity._removed = true
object:remove()
return true
end,
on_step = function(self, dtime, moveresult)
if self._removed then
self.object:set_properties({
physical = false
})
self.object:set_velocity({x=0,y=0,z=0})
self.object:set_acceleration({x=0,y=0,z=0})
return
end
self.age = self.age + dtime
if self._collector_timer then
self._collector_timer = self._collector_timer + dtime
end
if time_to_live > 0 and self.age > time_to_live then
self._removed = true
self.object:remove()
return
end
-- Delete corrupted item entities. The itemstring MUST be non-empty on its first step,
-- otherwise there might have some data corruption.
if self.itemstring == "" then
minetest.log("warning", "Item entity with empty itemstring found at "..minetest.pos_to_string(self.object:get_pos()).. "! Deleting it now.")
self._removed = true
self.object:remove()
return
end
local p = self.object:get_pos()
local node = minetest.get_node_or_nil(p)
local in_unloaded = (node == nil)
if self.is_clock then
self.object:set_properties({
textures = {"mcl_clock:clock_" .. (mcl_worlds.clock_works(p) and mcl_clock.old_time or mcl_clock.random_frame)}
})
end
-- If no collector was found for a long enough time, declare the magnet as disabled
if self._magnet_active and (self._collector_timer == nil or (self._collector_timer > item_drop_settings.magnet_time)) then
self._magnet_active = false
enable_physics(self.object, self)
return
end
if in_unloaded then
-- Don't infinetly fall into unloaded map
disable_physics(self.object, self)
return
end
-- Destroy item in lava, fire or special nodes
local nn = node.name
local def = minetest.registered_nodes[nn]
local lg = minetest.get_item_group(nn, "lava")
local fg = minetest.get_item_group(nn, "fire")
local dg = minetest.get_item_group(nn, "destroys_items")
if (def and (lg ~= 0 or fg ~= 0 or dg == 1)) then
--Wait 2 seconds to allow mob drops to be cooked, & picked up instead of instantly destroyed.
if self.age > 2 then
if dg ~= 2 then
minetest.sound_play("builtin_item_lava", {pos = self.object:get_pos(), gain = 0.5})
end
self._removed = true
self.object:remove()
return
end
end
-- Destroy item when it collides with a cactus
if moveresult and moveresult.collides then
for _, collision in pairs(moveresult.collisions) do
local pos = collision.node_pos
if collision.type == "node" and minetest.get_node(pos).name == "mcl_core:cactus" then
self._removed = true
self.object:remove()
return
end
end
end
-- Push item out when stuck inside solid opaque node
if def and def.walkable and def.groups and def.groups.opaque == 1 then
local shootdir
local cx = (p.x % 1) - 0.5
local cz = (p.z % 1) - 0.5
local order = {}
-- First prepare the order in which the 4 sides are to be checked.
-- 1st: closest
-- 2nd: other direction
-- 3rd and 4th: other axis
if math.abs(cx) < math.abs(cz) then
order = cxcz(order, cx, "x", "z")
order = cxcz(order, cz, "z", "x")
else
order = cxcz(order, cz, "z", "x")
order = cxcz(order, cx, "x", "z")
end
-- Check which one of the 4 sides is free
for o=1, #order do
local nn = minetest.get_node(vector.add(p, order[o])).name
local def = minetest.registered_nodes[nn]
if def and def.walkable == false and nn ~= "ignore" then
shootdir = order[o]
break
end
end
-- If none of the 4 sides is free, shoot upwards
if shootdir == nil then
shootdir = { x=0, y=1, z=0 }
local nn = minetest.get_node(vector.add(p, shootdir)).name
if nn == "ignore" then
-- Do not push into ignore
return
end
end
-- Set new item moving speed accordingly
local newv = vector.multiply(shootdir, 3)
self.object:set_acceleration({x = 0, y = 0, z = 0})
self.object:set_velocity(newv)
disable_physics(self.object, self, false, false)
if shootdir.y == 0 then
self._force = newv
p.x = math.floor(p.x)
p.y = math.floor(p.y)
p.z = math.floor(p.z)
self._forcestart = p
self._forcetimer = 1
end
return
end
-- This code is run after the entity got a push from above “push away” code.
-- It is responsible for making sure the entity is entirely outside the solid node
-- (with its full collision box), not just its center.
if self._forcetimer > 0 then
local cbox = self.object:get_properties().collisionbox
local ok = false
if self._force.x > 0 and (p.x > (self._forcestart.x + 0.5 + (cbox[4] - cbox[1])/2)) then ok = true
elseif self._force.x < 0 and (p.x < (self._forcestart.x + 0.5 - (cbox[4] - cbox[1])/2)) then ok = true
elseif self._force.z > 0 and (p.z > (self._forcestart.z + 0.5 + (cbox[6] - cbox[3])/2)) then ok = true
elseif self._force.z < 0 and (p.z < (self._forcestart.z + 0.5 - (cbox[6] - cbox[3])/2)) then ok = true end
-- Item was successfully forced out. No more pushing
if ok then
self._forcetimer = -1
self._force = nil
enable_physics(self.object, self)
else
self._forcetimer = self._forcetimer - dtime
end
return
elseif self._force then
self._force = nil
enable_physics(self.object, self)
return
end
-- Move item around on flowing liquids; add 'source' check to allow items to continue flowing a bit in the source block of flowing water.
if def and def.liquidtype == "flowing" or def.liquidtype == "source" then
--[[ Get flowing direction (function call from flowlib), if there's a liquid.
NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7.
Luckily, this is exactly what we need if we only care about water, which has this flowing distance. ]]
local vec = flowlib.quick_flow(p, node)
-- Just to make sure we don't manipulate the speed for no reason
if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then
-- Minecraft Wiki: Flowing speed is "about 1.39 meters per second"
local f = 1.2
-- Set new item moving speed into the direciton of the liquid
local newv = vector.multiply(vec, f)
-- Swap to acceleration instead of a static speed to better mimic MC mechanics.
self.object:set_acceleration({x = newv.x, y = -0.22, z = newv.z})
self.physical_state = true
self._flowing = true
self.object:set_properties({
physical = true
})
return
end
elseif self._flowing == true then
-- Disable flowing physics if not on/in flowing liquid
self._flowing = false
enable_physics(self.object, self, true)
return
end
-- If node is not registered or node is walkably solid and resting on nodebox
local nn = minetest.get_node({x=p.x, y=p.y-0.5, z=p.z}).name
local v = self.object:get_velocity()
if not minetest.registered_nodes[nn] or minetest.registered_nodes[nn].walkable and not minetest.registered_nodes[nn].groups.slippery and v.y == 0 then
if self.physical_state then
local own_stack = ItemStack(self.object:get_luaentity().itemstring)
-- Merge with close entities of the same item
for _, object in pairs(minetest.get_objects_inside_radius(p, 0.8)) do
local obj = object:get_luaentity()
if obj and obj.name == "__builtin:item"
and obj.physical_state == false then
if self:try_merge_with(own_stack, object, obj) then
return
end
end
end
disable_physics(self.object, self)
end
else
if self._magnet_active == false then
enable_physics(self.object, self)
end
end
end,
-- Note: on_punch intentionally left out. The player should *not* be able to collect items by punching
})

View File

@ -1,4 +0,0 @@
name = mcl_item_entity
author = PilzAdam
description = Dropped items will be attracted to the player like a magnet.
depends = flowlib, mcl_enchanting

View File

@ -1 +0,0 @@
Item_Drop_Pickup - https://freesound.org/people/benniknop/sounds/317848/ (License: CC0)

View File

@ -1,21 +0,0 @@
mcl_minecarts
=============
Based on the mod "boost_carts" by Krock.
Target: Run smoothly and do not use too much CPU.
License of source code:
-----------------------
MIT License
Copyright (C) 2012-2016 PilzAdam
Copyright (C) 2014-2016 SmallJoker
Copyright (C) 2012-2016 Various Minetest developers and contributors
Authors/licenses of media files:
-----------------------
Minecart model:
22i (GPLv3)
Texture files (CC BY-SA 3.0):
XSSheep

View File

@ -1,137 +0,0 @@
local vector = vector
function mcl_minecarts:get_sign(z)
if z == 0 then
return 0
else
return z / math.abs(z)
end
end
function mcl_minecarts:velocity_to_dir(v)
if math.abs(v.x) > math.abs(v.z) then
return {x=mcl_minecarts:get_sign(v.x), y=mcl_minecarts:get_sign(v.y), z=0}
else
return {x=0, y=mcl_minecarts:get_sign(v.y), z=mcl_minecarts:get_sign(v.z)}
end
end
function mcl_minecarts:is_rail(pos, railtype)
local node = minetest.get_node(pos).name
if node == "ignore" then
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map(pos, pos)
local area = VoxelArea:new{
MinEdge = emin,
MaxEdge = emax,
}
local data = vm:get_data()
local vi = area:indexp(pos)
node = minetest.get_name_from_content_id(data[vi])
end
if minetest.get_item_group(node, "rail") == 0 then
return false
end
if not railtype then
return true
end
return minetest.get_item_group(node, "connect_to_raillike") == railtype
end
function mcl_minecarts:check_front_up_down(pos, dir_, check_down, railtype)
local dir = vector.new(dir_)
-- Front
dir.y = 0
local cur = vector.add(pos, dir)
if mcl_minecarts:is_rail(cur, railtype) then
return dir
end
-- Up
if check_down then
dir.y = 1
cur = vector.add(pos, dir)
if mcl_minecarts:is_rail(cur, railtype) then
return dir
end
end
-- Down
dir.y = -1
cur = vector.add(pos, dir)
if mcl_minecarts:is_rail(cur, railtype) then
return dir
end
return nil
end
function mcl_minecarts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
local pos = vector.round(pos_)
local cur
local left_check, right_check = true, true
-- Check left and right
local left = {x=0, y=0, z=0}
local right = {x=0, y=0, z=0}
if dir.z ~= 0 and dir.x == 0 then
left.x = -dir.z
right.x = dir.z
elseif dir.x ~= 0 and dir.z == 0 then
left.z = dir.x
right.z = -dir.x
end
if ctrl then
if old_switch == 1 then
left_check = false
elseif old_switch == 2 then
right_check = false
end
if ctrl.left and left_check then
cur = mcl_minecarts:check_front_up_down(pos, left, false, railtype)
if cur then
return cur, 1
end
left_check = false
end
if ctrl.right and right_check then
cur = mcl_minecarts:check_front_up_down(pos, right, false, railtype)
if cur then
return cur, 2
end
right_check = true
end
end
-- Normal
cur = mcl_minecarts:check_front_up_down(pos, dir, true, railtype)
if cur then
return cur
end
-- Left, if not already checked
if left_check then
cur = mcl_minecarts:check_front_up_down(pos, left, false, railtype)
if cur then
return cur
end
end
-- Right, if not already checked
if right_check then
cur = mcl_minecarts:check_front_up_down(pos, right, false, railtype)
if cur then
return cur
end
end
-- Backwards
if not old_switch then
cur = mcl_minecarts:check_front_up_down(pos, {
x = -dir.x,
y = dir.y,
z = -dir.z
}, true, railtype)
if cur then
return cur
end
end
return {x=0, y=0, z=0}
end

View File

@ -1,864 +0,0 @@
local modname = minetest.get_current_modname()
local S = minetest.get_translator(modname)
local has_mcl_wip = minetest.get_modpath("mcl_wip")
mcl_minecarts = {}
mcl_minecarts.modpath = minetest.get_modpath(modname)
mcl_minecarts.speed_max = 10
mcl_minecarts.check_float_time = 15
dofile(mcl_minecarts.modpath.."/functions.lua")
dofile(mcl_minecarts.modpath.."/rails.lua")
local function detach_driver(self)
if not self._driver then
return
end
mcl_player.player_attached[self._driver] = nil
local player = minetest.get_player_by_name(self._driver)
self._driver = nil
self._start_pos = nil
if player then
player:set_detach()
player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
mcl_player.player_set_animation(player, "stand" , 30)
end
end
local function activate_tnt_minecart(self, timer)
if self._boomtimer then
return
end
self.object:set_armor_groups({immortal=1})
if timer then
self._boomtimer = timer
else
self._boomtimer = tnt.BOOMTIMER
end
self.object:set_properties({textures = {
"mcl_tnt_blink.png",
"mcl_tnt_blink.png",
"mcl_tnt_blink.png",
"mcl_tnt_blink.png",
"mcl_tnt_blink.png",
"mcl_tnt_blink.png",
"mcl_minecarts_minecart.png",
}})
self._blinktimer = tnt.BLINKTIMER
minetest.sound_play("tnt_ignite", {pos = self.object:get_pos(), gain = 1.0, max_hear_distance = 15}, true)
end
local activate_normal_minecart = detach_driver
-- Table for item-to-entity mapping. Keys: itemstring, Values: Corresponding entity ID
local entity_mapping = {}
local function register_entity(entity_id, mesh, textures, drop, on_rightclick, on_activate_by_rail)
local cart = {
physical = false,
collisionbox = {-10/16., -0.5, -10/16, 10/16, 0.25, 10/16},
visual = "mesh",
mesh = mesh,
visual_size = {x=1, y=1},
textures = textures,
on_rightclick = on_rightclick,
_driver = nil, -- player who sits in and controls the minecart (only for minecart!)
_punched = false, -- used to re-send _velocity and position
_velocity = {x=0, y=0, z=0}, -- only used on punch
_start_pos = nil, -- Used to calculate distance for “On A Rail” achievement
_last_float_check = nil, -- timestamp of last time the cart was checked to be still on a rail
_fueltime = nil, -- how many seconds worth of fuel is left. Only used by minecart with furnace
_boomtimer = nil, -- how many seconds are left before exploding
_blinktimer = nil, -- how many seconds are left before TNT blinking
_blink = false, -- is TNT blink texture active?
_old_dir = {x=0, y=0, z=0},
_old_pos = nil,
_old_vel = {x=0, y=0, z=0},
_old_switch = 0,
_railtype = nil,
}
function cart:on_activate(staticdata, dtime_s)
-- Initialize
local data = minetest.deserialize(staticdata)
if type(data) == "table" then
self._railtype = data._railtype
end
self.object:set_armor_groups({immortal=1})
-- Activate cart if on activator rail
if self.on_activate_by_rail then
local pos = self.object:get_pos()
local node = minetest.get_node(vector.floor(pos))
if node.name == "mcl_minecarts:activator_rail_on" then
self:on_activate_by_rail()
end
end
end
function cart:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
local pos = self.object:get_pos()
if not self._railtype then
local node = minetest.get_node(vector.floor(pos)).name
self._railtype = minetest.get_item_group(node, "connect_to_raillike")
end
if not puncher or not puncher:is_player() then
local cart_dir = mcl_minecarts:get_rail_direction(pos, {x=1, y=0, z=0}, nil, nil, self._railtype)
if vector.equals(cart_dir, {x=0, y=0, z=0}) then
return
end
self._velocity = vector.multiply(cart_dir, 3)
self._old_pos = nil
self._punched = true
return
end
-- Punch+sneak: Pick up minecart (unless TNT was ignited)
if puncher:get_player_control().sneak and not self._boomtimer then
if self._driver then
if self._old_pos then
self.object:set_pos(self._old_pos)
end
detach_driver(self)
end
-- Disable detector rail
local rou_pos = vector.round(pos)
local node = minetest.get_node(rou_pos)
if node.name == "mcl_minecarts:detector_rail_on" then
local newnode = {name="mcl_minecarts:detector_rail", param2 = node.param2}
minetest.swap_node(rou_pos, newnode)
mesecon.receptor_off(rou_pos)
end
-- Drop items and remove cart entity
if not minetest.is_creative_enabled(puncher:get_player_name()) then
for d=1, #drop do
minetest.add_item(self.object:get_pos(), drop[d])
end
elseif puncher and puncher:is_player() then
local inv = puncher:get_inventory()
for d=1, #drop do
if not inv:contains_item("main", drop[d]) then
inv:add_item("main", drop[d])
end
end
end
self.object:remove()
return
end
local vel = self.object:get_velocity()
if puncher:get_player_name() == self._driver then
if math.abs(vel.x + vel.z) > 7 then
return
end
end
local punch_dir = mcl_minecarts:velocity_to_dir(puncher:get_look_dir())
punch_dir.y = 0
local cart_dir = mcl_minecarts:get_rail_direction(pos, punch_dir, nil, nil, self._railtype)
if vector.equals(cart_dir, {x=0, y=0, z=0}) then
return
end
time_from_last_punch = math.min(time_from_last_punch, tool_capabilities.full_punch_interval)
local f = 3 * (time_from_last_punch / tool_capabilities.full_punch_interval)
self._velocity = vector.multiply(cart_dir, f)
self._old_pos = nil
self._punched = true
end
cart.on_activate_by_rail = on_activate_by_rail
function cart:on_step(dtime)
local ctrl, player = nil, nil
if self._driver then
player = minetest.get_player_by_name(self._driver)
if player then
ctrl = player:get_player_control()
-- player detach
if ctrl.sneak then
detach_driver(self)
return
end
end
end
local vel = self.object:get_velocity()
local update = {}
if self._last_float_check == nil then
self._last_float_check = 0
else
self._last_float_check = self._last_float_check + dtime
end
local pos, rou_pos, node = self.object:get_pos()
local r = 0.6
for _, node_pos in pairs({{r, 0}, {0, r}, {-r, 0}, {0, -r}}) do
if minetest.get_node(vector.offset(pos, node_pos[1], 0, node_pos[2])).name == "mcl_core:cactus" then
detach_driver(self)
for d = 1, #drop do
minetest.add_item(pos, drop[d])
end
self.object:remove()
return
end
end
-- Drop minecart if it isn't on a rail anymore
if self._last_float_check >= mcl_minecarts.check_float_time then
pos = self.object:get_pos()
rou_pos = vector.round(pos)
node = minetest.get_node(rou_pos)
local g = minetest.get_item_group(node.name, "connect_to_raillike")
if g ~= self._railtype and self._railtype then
-- Detach driver
if player then
if self._old_pos then
self.object:set_pos(self._old_pos)
end
mcl_player.player_attached[self._driver] = nil
player:set_detach()
player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
end
-- Explode if already ignited
if self._boomtimer then
self.object:remove()
mcl_explosions.explode(pos, 4, { drop_chance = 1.0 })
return
end
-- Drop items and remove cart entity
local pname = ""
if player then
pname = player:get_player_name()
end
if not minetest.is_creative_enabled(pname) then
for d=1, #drop do
minetest.add_item(self.object:get_pos(), drop[d])
end
end
self.object:remove()
return
end
self._last_float_check = 0
end
-- Update furnace stuff
if self._fueltime and self._fueltime > 0 then
self._fueltime = self._fueltime - dtime
if self._fueltime <= 0 then
self.object:set_properties({textures =
{
"default_furnace_top.png",
"default_furnace_top.png",
"default_furnace_front.png",
"default_furnace_side.png",
"default_furnace_side.png",
"default_furnace_side.png",
"mcl_minecarts_minecart.png",
}})
self._fueltime = 0
end
end
local has_fuel = self._fueltime and self._fueltime > 0
-- Update TNT stuff
if self._boomtimer then
-- Explode
self._boomtimer = self._boomtimer - dtime
local pos = self.object:get_pos()
if self._boomtimer <= 0 then
self.object:remove()
mcl_explosions.explode(pos, 4, { drop_chance = 1.0 })
return
else
tnt.smoke_step(pos)
end
end
if self._blinktimer then
self._blinktimer = self._blinktimer - dtime
if self._blinktimer <= 0 then
self._blink = not self._blink
if self._blink then
self.object:set_properties({textures =
{
"default_tnt_top.png",
"default_tnt_bottom.png",
"default_tnt_side.png",
"default_tnt_side.png",
"default_tnt_side.png",
"default_tnt_side.png",
"mcl_minecarts_minecart.png",
}})
else
self.object:set_properties({textures =
{
"mcl_tnt_blink.png",
"mcl_tnt_blink.png",
"mcl_tnt_blink.png",
"mcl_tnt_blink.png",
"mcl_tnt_blink.png",
"mcl_tnt_blink.png",
"mcl_minecarts_minecart.png",
}})
end
self._blinktimer = tnt.BLINKTIMER
end
end
if self._punched then
vel = vector.add(vel, self._velocity)
self.object:set_velocity(vel)
self._old_dir.y = 0
elseif vector.equals(vel, {x=0, y=0, z=0}) and (not has_fuel) then
return
end
local dir, last_switch = nil, nil
if not pos then
pos = self.object:get_pos()
end
if self._old_pos and not self._punched then
local flo_pos = vector.floor(pos)
local flo_old = vector.floor(self._old_pos)
if vector.equals(flo_pos, flo_old) and (not has_fuel) then
return
-- Prevent querying the same node over and over again
end
if not rou_pos then
rou_pos = vector.round(pos)
end
local rou_old = vector.round(self._old_pos)
if not node then
node = minetest.get_node(rou_pos)
end
local node_old = minetest.get_node(rou_old)
-- Update detector rails
if node.name == "mcl_minecarts:detector_rail" then
local newnode = {name="mcl_minecarts:detector_rail_on", param2 = node.param2}
minetest.swap_node(rou_pos, newnode)
mesecon.receptor_on(rou_pos)
end
if node_old.name == "mcl_minecarts:detector_rail_on" then
local newnode = {name="mcl_minecarts:detector_rail", param2 = node_old.param2}
minetest.swap_node(rou_old, newnode)
mesecon.receptor_off(rou_old)
end
-- Activate minecart if on activator rail
if node_old.name == "mcl_minecarts:activator_rail_on" and self.on_activate_by_rail then
self:on_activate_by_rail()
end
end
-- Stop cart if velocity vector flips
if self._old_vel and self._old_vel.y == 0 and
(self._old_vel.x * vel.x < 0 or self._old_vel.z * vel.z < 0) then
self._old_vel = {x = 0, y = 0, z = 0}
self._old_pos = pos
self.object:set_velocity(vector.new())
self.object:set_acceleration(vector.new())
return
end
self._old_vel = vector.new(vel)
if self._old_pos then
local diff = vector.subtract(self._old_pos, pos)
for _,v in ipairs({"x","y","z"}) do
if math.abs(diff[v]) > 1.1 then
local expected_pos = vector.add(self._old_pos, self._old_dir)
dir, last_switch = mcl_minecarts:get_rail_direction(pos, self._old_dir, ctrl, self._old_switch, self._railtype)
if vector.equals(dir, {x=0, y=0, z=0}) then
dir = false
pos = vector.new(expected_pos)
update.pos = true
end
break
end
end
end
if vel.y == 0 then
for _,v in ipairs({"x", "z"}) do
if vel[v] ~= 0 and math.abs(vel[v]) < 0.9 then
vel[v] = 0
update.vel = true
end
end
end
local cart_dir = mcl_minecarts:velocity_to_dir(vel)
local max_vel = mcl_minecarts.speed_max
if not dir then
dir, last_switch = mcl_minecarts:get_rail_direction(pos, cart_dir, ctrl, self._old_switch, self._railtype)
end
local new_acc = {x=0, y=0, z=0}
if vector.equals(dir, {x=0, y=0, z=0}) and not has_fuel then
vel = {x=0, y=0, z=0}
update.vel = true
else
-- If the direction changed
if dir.x ~= 0 and self._old_dir.z ~= 0 then
vel.x = dir.x * math.abs(vel.z)
vel.z = 0
pos.z = math.floor(pos.z + 0.5)
update.pos = true
end
if dir.z ~= 0 and self._old_dir.x ~= 0 then
vel.z = dir.z * math.abs(vel.x)
vel.x = 0
pos.x = math.floor(pos.x + 0.5)
update.pos = true
end
-- Up, down?
if dir.y ~= self._old_dir.y then
vel.y = dir.y * math.abs(vel.x + vel.z)
pos = vector.round(pos)
update.pos = true
end
-- Slow down or speed up
local acc = dir.y * -1.8
local friction = 0.4
local ndef = minetest.registered_nodes[minetest.get_node(pos).name]
local speed_mod = ndef and ndef._rail_acceleration
acc = acc - friction
if has_fuel then
acc = acc + 0.6
end
if speed_mod and speed_mod ~= 0 then
acc = acc + speed_mod + friction
end
new_acc = vector.multiply(dir, acc)
end
self.object:set_acceleration(new_acc)
self._old_pos = vector.new(pos)
self._old_dir = vector.new(dir)
self._old_switch = last_switch
-- Limits
for _,v in ipairs({"x","y","z"}) do
if math.abs(vel[v]) > max_vel then
vel[v] = mcl_minecarts:get_sign(vel[v]) * max_vel
new_acc[v] = 0
update.vel = true
end
end
-- Give achievement when player reached a distance of 1000 nodes from the start position
if self._driver and (vector.distance(self._start_pos, pos) >= 1000) then
awards.unlock(self._driver, "mcl:onARail")
end
if update.pos or self._punched then
local yaw = 0
if dir.x < 0 then
yaw = 0.5
elseif dir.x > 0 then
yaw = 1.5
elseif dir.z < 0 then
yaw = 1
end
self.object:set_yaw(yaw * math.pi)
end
if self._punched then
self._punched = false
end
if not (update.vel or update.pos) then
return
end
local anim = {x=0, y=0}
if dir.y == -1 then
anim = {x=1, y=1}
elseif dir.y == 1 then
anim = {x=2, y=2}
end
self.object:set_animation(anim, 1, 0)
self.object:set_velocity(vel)
if update.pos then
self.object:set_pos(pos)
end
end
function cart:get_staticdata()
return minetest.serialize({_railtype = self._railtype})
end
minetest.register_entity(entity_id, cart)
end
-- Place a minecart at pointed_thing
function mcl_minecarts.place_minecart(itemstack, pointed_thing, placer)
if not pointed_thing.type == "node" then
return
end
local railpos, node
if mcl_minecarts:is_rail(pointed_thing.under) then
railpos = pointed_thing.under
node = minetest.get_node(pointed_thing.under)
elseif mcl_minecarts:is_rail(pointed_thing.above) then
railpos = pointed_thing.above
node = minetest.get_node(pointed_thing.above)
else
return
end
-- Activate detector rail
if node.name == "mcl_minecarts:detector_rail" then
local newnode = {name="mcl_minecarts:detector_rail_on", param2 = node.param2}
minetest.swap_node(railpos, newnode)
mesecon.receptor_on(railpos)
end
local entity_id = entity_mapping[itemstack:get_name()]
local cart = minetest.add_entity(railpos, entity_id)
local railtype = minetest.get_item_group(node.name, "connect_to_raillike")
local le = cart:get_luaentity()
if le then
le._railtype = railtype
end
local cart_dir = mcl_minecarts:get_rail_direction(railpos, {x=1, y=0, z=0}, nil, nil, railtype)
cart:set_yaw(minetest.dir_to_yaw(cart_dir))
local pname = ""
if placer then
pname = placer:get_player_name()
end
if not minetest.is_creative_enabled(pname) then
itemstack:take_item()
end
return itemstack
end
local function register_craftitem(itemstring, entity_id, description, tt_help, longdesc, usagehelp, icon, creative)
entity_mapping[itemstring] = entity_id
local groups = { minecart = 1, transport = 1 }
if creative == false then
groups.not_in_creative_inventory = 1
end
local def = {
stack_max = 1,
on_place = function(itemstack, placer, pointed_thing)
if not pointed_thing.type == "node" then
return
end
-- Call on_rightclick if the pointed node defines it
local node = minetest.get_node(pointed_thing.under)
if placer and not placer:get_player_control().sneak then
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack
end
end
return mcl_minecarts.place_minecart(itemstack, pointed_thing, placer)
end,
_on_dispense = function(stack, pos, droppos, dropnode, dropdir)
-- Place minecart as entity on rail. If there's no rail, just drop it.
local placed
if minetest.get_item_group(dropnode.name, "rail") ~= 0 then
-- FIXME: This places minecarts even if the spot is already occupied
local pointed_thing = { under = droppos, above = { x=droppos.x, y=droppos.y+1, z=droppos.z } }
placed = mcl_minecarts.place_minecart(stack, pointed_thing)
end
if placed == nil then
-- Drop item
minetest.add_item(droppos, stack)
end
end,
groups = groups,
}
def.description = description
def._tt_help = tt_help
def._doc_items_longdesc = longdesc
def._doc_items_usagehelp = usagehelp
def.inventory_image = icon
def.wield_image = icon
minetest.register_craftitem(itemstring, def)
end
--[[
Register a minecart
* itemstring: Itemstring of minecart item
* entity_id: ID of minecart entity
* description: Item name / description
* longdesc: Long help text
* usagehelp: Usage help text
* mesh: Minecart mesh
* textures: Minecart textures table
* icon: Item icon
* drop: Dropped items after destroying minecart
* on_rightclick: Called after rightclick
* on_activate_by_rail: Called when above activator rail
* creative: If false, don't show in Creative Inventory
]]
local function register_minecart(itemstring, entity_id, description, tt_help, longdesc, usagehelp, mesh, textures, icon, drop, on_rightclick, on_activate_by_rail, creative)
register_entity(entity_id, mesh, textures, drop, on_rightclick, on_activate_by_rail)
register_craftitem(itemstring, entity_id, description, tt_help, longdesc, usagehelp, icon, creative)
if minetest.get_modpath("doc_identifier") then
doc.sub.identifier.register_object(entity_id, "craftitems", itemstring)
end
end
-- Minecart
register_minecart(
"mcl_minecarts:minecart",
"mcl_minecarts:minecart",
S("Minecart"),
S("Vehicle for fast travel on rails"),
S("Minecarts can be used for a quick transportion on rails.") .. "\n" ..
S("Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type."),
S("You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.") .. "\n" ..
S("To obtain the minecart, punch it while holding down the sneak key.") .. "\n" ..
S("If it moves over a powered activator rail, you'll get ejected."),
"mcl_minecarts_minecart.b3d",
{"mcl_minecarts_minecart.png"},
"mcl_minecarts_minecart_normal.png",
{"mcl_minecarts:minecart"},
function(self, clicker)
local name = clicker:get_player_name()
if not clicker or not clicker:is_player() then
return
end
local player_name = clicker:get_player_name()
if self._driver and player_name == self._driver then
detach_driver(self)
elseif not self._driver then
self._driver = player_name
self._start_pos = self.object:get_pos()
mcl_player.player_attached[player_name] = true
clicker:set_attach(self.object, "", {x=0, y=-1.75, z=-2}, {x=0, y=0, z=0})
mcl_player.player_attached[name] = true
minetest.after(0.2, function(name)
local player = minetest.get_player_by_name(name)
if player then
mcl_player.player_set_animation(player, "sit" , 30)
player:set_eye_offset({x=0, y=-5.5, z=0},{x=0, y=-4, z=0})
mcl_title.set(clicker, "actionbar", {text=S("Sneak to dismount"), color="white", stay=60})
end
end, name)
end
end, activate_normal_minecart
)
-- Minecart with Chest
register_minecart(
"mcl_minecarts:chest_minecart",
"mcl_minecarts:chest_minecart",
S("Minecart with Chest"),
nil, nil, nil,
"mcl_minecarts_minecart_chest.b3d",
{ "mcl_chests_normal.png", "mcl_minecarts_minecart.png" },
"mcl_minecarts_minecart_chest.png",
{"mcl_minecarts:minecart", "mcl_chests:chest"},
nil, nil, false)
-- Minecart with Furnace
register_minecart(
"mcl_minecarts:furnace_minecart",
"mcl_minecarts:furnace_minecart",
S("Minecart with Furnace"),
nil,
S("A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel."),
S("Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.") .. "\n" ..
S("To obtain the minecart and furnace, punch them while holding down the sneak key."),
"mcl_minecarts_minecart_block.b3d",
{
"default_furnace_top.png",
"default_furnace_top.png",
"default_furnace_front.png",
"default_furnace_side.png",
"default_furnace_side.png",
"default_furnace_side.png",
"mcl_minecarts_minecart.png",
},
"mcl_minecarts_minecart_furnace.png",
{"mcl_minecarts:minecart", "mcl_furnaces:furnace"},
-- Feed furnace with coal
function(self, clicker)
if not clicker or not clicker:is_player() then
return
end
if not self._fueltime then
self._fueltime = 0
end
local held = clicker:get_wielded_item()
if minetest.get_item_group(held:get_name(), "coal") == 1 then
self._fueltime = self._fueltime + 180
if not minetest.is_creative_enabled(clicker:get_player_name()) then
held:take_item()
local index = clicker:get_wield_index()
local inv = clicker:get_inventory()
inv:set_stack("main", index, held)
end
self.object:set_properties({textures =
{
"default_furnace_top.png",
"default_furnace_top.png",
"default_furnace_front_active.png",
"default_furnace_side.png",
"default_furnace_side.png",
"default_furnace_side.png",
"mcl_minecarts_minecart.png",
}})
end
end, nil, false
)
-- Minecart with Command Block
register_minecart(
"mcl_minecarts:command_block_minecart",
"mcl_minecarts:command_block_minecart",
S("Minecart with Command Block"),
nil, nil, nil,
"mcl_minecarts_minecart_block.b3d",
{
"jeija_commandblock_off.png^[verticalframe:2:0",
"jeija_commandblock_off.png^[verticalframe:2:0",
"jeija_commandblock_off.png^[verticalframe:2:0",
"jeija_commandblock_off.png^[verticalframe:2:0",
"jeija_commandblock_off.png^[verticalframe:2:0",
"jeija_commandblock_off.png^[verticalframe:2:0",
"mcl_minecarts_minecart.png",
},
"mcl_minecarts_minecart_command_block.png",
{"mcl_minecarts:minecart"},
nil, nil, false
)
-- Minecart with Hopper
register_minecart(
"mcl_minecarts:hopper_minecart",
"mcl_minecarts:hopper_minecart",
S("Minecart with Hopper"),
nil, nil, nil,
"mcl_minecarts_minecart_hopper.b3d",
{
"mcl_hoppers_hopper_inside.png",
"mcl_minecarts_minecart.png",
"mcl_hoppers_hopper_outside.png",
"mcl_hoppers_hopper_top.png",
},
"mcl_minecarts_minecart_hopper.png",
{"mcl_minecarts:minecart", "mcl_hoppers:hopper"},
nil, nil, false
)
-- Minecart with TNT
register_minecart(
"mcl_minecarts:tnt_minecart",
"mcl_minecarts:tnt_minecart",
S("Minecart with TNT"),
S("Vehicle for fast travel on rails").."\n"..S("Can be ignited by tools or powered activator rail"),
S("A minecart with TNT is an explosive vehicle that travels on rail."),
S("Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.") .. "\n" ..
S("To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited."),
"mcl_minecarts_minecart_block.b3d",
{
"default_tnt_top.png",
"default_tnt_bottom.png",
"default_tnt_side.png",
"default_tnt_side.png",
"default_tnt_side.png",
"default_tnt_side.png",
"mcl_minecarts_minecart.png",
},
"mcl_minecarts_minecart_tnt.png",
{"mcl_minecarts:minecart", "mcl_tnt:tnt"},
-- Ingite
function(self, clicker)
if not clicker or not clicker:is_player() then
return
end
if self._boomtimer then
return
end
local held = clicker:get_wielded_item()
if held:get_name() == "mcl_fire:flint_and_steel" then
if not minetest.is_creative_enabled(clicker:get_player_name()) then
held:add_wear(65535/65) -- 65 uses
local index = clicker:get_wield_index()
local inv = clicker:get_inventory()
inv:set_stack("main", index, held)
end
activate_tnt_minecart(self)
end
end, activate_tnt_minecart)
minetest.register_craft({
output = "mcl_minecarts:minecart",
recipe = {
{"mcl_core:iron_ingot", "", "mcl_core:iron_ingot"},
{"mcl_core:iron_ingot", "mcl_core:iron_ingot", "mcl_core:iron_ingot"},
},
})
minetest.register_craft({
output = "mcl_minecarts:tnt_minecart",
recipe = {
{"mcl_tnt:tnt"},
{"mcl_minecarts:minecart"},
},
})
-- TODO: Re-enable crafting of special minecarts when they have been implemented
--[[minetest.register_craft({
output = "mcl_minecarts:furnace_minecart",
recipe = {
{"mcl_furnaces:furnace"},
{"mcl_minecarts:minecart"},
},
})
minetest.register_craft({
output = "mcl_minecarts:hopper_minecart",
recipe = {
{"mcl_hoppers:hopper"},
{"mcl_minecarts:minecart"},
},
})
minetest.register_craft({
output = "mcl_minecarts:chest_minecart",
recipe = {
{"mcl_chests:chest"},
{"mcl_minecarts:minecart"},
},
})]]
if has_mcl_wip then
mcl_wip.register_wip_item("mcl_minecarts:chest_minecart")
mcl_wip.register_wip_item("mcl_minecarts:furnace_minecart")
mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart")
mcl_wip.register_wip_item("mcl_minecarts:hopper_minecart")
end

View File

@ -1,36 +0,0 @@
# textdomain: mcl_minecarts
Minecart=Lore
Minecarts can be used for a quick transportion on rails.=Loren können für eine schnelle Fahrt auf Schienen benutzt werden.
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=Loren fahren nur auf Schienen und bleiben immer auf der Strecke. An einer Einmündung ohne einem Weg nach vorne fahren sie nach links. Die Geschwindigkeit hängt vom Schienentyp ab.
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Sie können die Lore auf Schienen platzieren. Rechtsklicken, um einzusteigen.
To obtain the minecart, punch it while holding down the sneak key.=Um die Lore aufzusammeln, schlagen Sie sie, während Sie die Schleichen-Taste gedrückt halten.
A minecart with TNT is an explosive vehicle that travels on rail.=Eine Lore mit TNT ist ein explosives Fahrzeug, das auf Schienen fährt.
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Auf Schienen platzieren. Zuschlagen zum Bewegen. Das TNT wird mit einem Feuerzeug angezündet, oder, wenn die Lore sich auf einer bestromten Aktivierungsschiene befindet.
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Um die Lore und das TNT zu erhalten, schlagen Sie sie, während Sie die Schleichtaste drücken. Das ist nicht möglich, wenn das TNT bereits gezündet wurde.
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=Eine Lore mit Ofen ist ein Fahrzeug, das auf Rädern fährt. Sie kann mit Brennstoff angetrieben werden.
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=Auf Schienen platzieren. Wird Kohle eingefügt, wird der Ofen für eine lange Zeit brennen und die Lore wird fähig sein, sich selbst anzutreiben. Zuschlagen, um die Bewegung einzuläuten.
To obtain the minecart and furnace, punch them while holding down the sneak key.=Um die Lore und den Ofen zu erhalten, schlagen Sie zu, während Sie die Schleichtaste drücken.
Minecart with Chest=Lore mit Truhe
Minecart with Furnace=Lore mit Ofen
Minecart with Command Block=Lore mit Befehlsblock
Minecart with Hopper=Lore mit Trichter
Minecart with TNT=Lore mit TNT
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Bauen Sie sie auf den Boden, um Ihr Schienennetzwerk zu errichten, die Schienen werden sich automatisch verbinden und sich nach Bedarf in Kurven, Einmündungen, Kreuzungen und Steigungen verwandeln.
Rail=Schiene
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=Schienen können benutzt werden, um Strecken für Loren zu bauen. Normale Schienen werden Loren aufgrund von Reibung leicht verlangsamen.
Powered Rail=Antriebsschiene
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Schienen können benutzt werden, um Strecken für Loren zu bauen. Antriebsschienen können Loren beschleunigen und abbremsen.
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Ohne Redstone-Energie wird die Schiene Loren abbremsen. Mit Redstone-Energie wird sie sie beschleunigen.
Activator Rail=Aktivierungsschiene
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=Schienen können benutzt werden, um Strecken für Loren zu bauen. Aktivierungsschienen werden benutzt, um besondere Loren zu aktivieren.
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=Wenn diese Schiene mit Redstone-Energie versorgt wird, werden alle Loren, die sie passieren, aktiviert.
Detector Rail=Sensorschiene
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=Schienen können benutzt werden, um Strecken für Loren zu bauen. Eine Sensorschiene kann eine Lore erkennen und versorgt Redstone-Mechanismen.
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=Um eine Lore zu erkennen und die Redstone-Energie zu aktivieren, verbinden Sie die Schiene mit Redstonestaub oder Redstone-Mechanismen und schicken Sie eine beliebige Lore über die Schiene.
Track for minecarts=Strecke für Loren
Speed up when powered, slow down when not powered=Beschleunigt, wenn bestromt, sonst verlangsamt es
Activates minecarts when powered=Aktiviert Loren, wenn bestromt
Emits redstone power when a minecart is detected=Gibt ein Redstonesignal aus, wenn eine Lore erfasst wird
Vehicle for fast travel on rails=Fahrzeug zum schnellen Transport auf Schienen
Can be ignited by tools or powered activator rail=Kann mit Werkzeugen oder bestromten Aktivierungsschienen angezündet werden
Sneak to dismount=Zum Aussteigen schleichen

View File

@ -1,23 +0,0 @@
# textdomain: mcl_minecarts
Minecart=Vagoneta
Minecarts can be used for a quick transportion on rails.=Las vagonetas se pueden usar para transportarse rápido en los rieles.
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=Las vagonetas solo viajan en rieles y siempre siguen las pistas. En un cruce en T sin camino recto, giran a la izquierda. La velocidad se ve afectada por el tipo de riel.
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Puedes colocar el vagoneta en los rieles. Haga clic derecho para insertarlo. Golpea para que se mueva.
To obtain the minecart, punch it while holding down the sneak key.=Para obtener el vagoneta, golpéalo mientras mantienes presionada la tecla.
Minecart with Chest=Vagoneta con cofre
Minecart with Furnace=Vagoneta con horno
Minecart with Command Block=Vagoneta con bloque de comandos
Minecart with Hopper=Vagoneta con tolva
Minecart with TNT=Vagoneta con dinamita
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Colóquelos en el suelo para construir su ferrocarril, los rieles se conectarán automáticamente entre sí y se convertirán en curvas, uniones en T, cruces y pendientes según sea necesario.
Rail=Raíl
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=Los rieles se pueden usar para construir vías de transporte para vagonetas. Los rieles normales ralentizan ligeramente las vagonetas debido a la fricción.
Powered Rail=Raíl propulsor
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Los rieles se pueden usar para construir vías de transporte para vagonetas. Los railes propulsores pueden acelerar y frenar las vagonetas.
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Sin energía de redstone, el riel frenará las vagonetas. Para hacer que este riel acelere las vagonetas, aliméntalo con redstone.
Activator Rail=Raíl activador
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=Los rieles se pueden usar para construir vías de transporte para vagonetas. Los railes activador se utilizan para activar una vagoneta especial.
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=Para hacer que este riel active las vagonetas, enciéndelo con energía de redstone y envía una vagoneta sobre este pedazo de riel.
Detector Rail=Raíl detector
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=Los rieles se pueden usar para construir vías de transporte para vagonetas. Un raíl detector puede detectar una vagoneta sobre él y alimenta los mecanismos de redstone.
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=Para detectar una vagoneta y proporcionar energía de redstone, conéctelo a los senderos de redstone o mecanismos de redstone y envíe cualquier vagoneta sobre el riel.

View File

@ -1,36 +0,0 @@
# textdomain: mcl_minecarts
Minecart=Wagonnet
Minecarts can be used for a quick transportion on rails.=Les wagonnets peuvent être utilisés pour un transport rapide sur rails.
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=Les wagonnets roulent uniquement sur des rails et suivent toujours les pistes. À un carrefour en T sans voie directe, ils tournent à gauche. La vitesse dépend du type de rail.
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Vous pouvez placer le wagonnet sur des rails. Faites un clic droit dessus pour entrer dedans. Frappez-le pour le faire bouger.
To obtain the minecart, punch it while holding down the sneak key.=Pour obtenir la wagonnet, frappez-le tout en maintenant la touche furtive enfoncée.
A minecart with TNT is an explosive vehicle that travels on rail.=Un wagonnet avec de la TNT est un véhicule explosif qui se déplace sur rail.
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Placez-le sur des rails. Frappez-le pour le déplacer. Le TNT est allumé avec un briquet ou lorsque le minecart est sur un rail d'activation alimenté.
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Pour obtenir la wagonnet et la TNT, frappez-les tout en maintenant la touche furtive enfoncée. Vous ne pouvez pas faire cela si le TNT a été allumé.
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=Une wagonnet avec un four est un véhicule qui se déplace sur rails. Il peut se propulser avec du carburant.
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=Placez-le sur des rails. Si vous lui donnez du charbon, le four commencera à brûler pendant longtemps et le wagonnet pourra se déplacer. Frappez-le pour le faire bouger.
To obtain the minecart and furnace, punch them while holding down the sneak key.=Pour obtenir le wagonnet et le four, frappez-les tout en maintenant la touche furtive enfoncée.
Minecart with Chest=Wagonnet avec Coffre
Minecart with Furnace=Wagonnet avec Four
Minecart with Command Block=Wagonnet avec Bloc de Commande
Minecart with Hopper=Wagonnet avec Entonoir
Minecart with TNT=Wagonnet avec TNT
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Placez-les sur le sol pour construire votre chemin de fer, les rails se connecteront automatiquement les uns aux autres et se transformeront en courbes, en jonctions en T, en traversées et en pentes au besoin.
Rail=Rail
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=Les rails peuvent être utilisés pour construire des voies de transport pour les wagonnets. Les rails ralentissent légèrement les wagonnets en raison de la friction.
Powered Rail=Rail allimenté
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Les rails peuvent être utilisés pour construire des voies de transport pour les wagonnets. Les rails motorisés sont capables d'accélérer et de freiner les wagonnets.
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Sans énergie de redstone, le rail freinera les wagonnets. Pour que ce rail accélère les minecarts, alimentez-le avec une source d'énergie redstone.
Activator Rail=Rail d'activation
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=Les rails peuvent être utilisés pour construire des voies de transport pour les wagonnets. Des rails activateurs sont utilisés pour activer des wagonnets spéciaux.
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=Pour activer ce rail, activez les wagonnets, alimentez-le avec de l'énergie redstone et envoyez un wagonnet sur ce morceau de rail.
Detector Rail=Rail de détection
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=Les rails peuvent être utilisés pour construire des voies de transport pour les wagonnets. Un rail de détection est capable de détecter un wagonnet au-dessus et alimente les mécanismes de redstone.
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=Pour détecter un wagonnet et fournir une alimentation redstone, connectez-le aux câble redstone ou aux mécanismes redstone et envoyez n'importe quel wagonnet sur le rail.
Track for minecarts=Piste pour wagonnets
Speed up when powered, slow down when not powered=Accélérez lorsqu'il est alimenté, ralentissez lorsqu'il n'est pas alimenté
Activates minecarts when powered=Active les wagonnets lorsqu'il est alimenté
Emits redstone power when a minecart is detected=Émet de l'énergie redstone lorsqu'un wagonnet est détecté
Vehicle for fast travel on rails=Véhicule pour voyager rapidement sur rails
Can be ignited by tools or powered activator rail=Peut être allumé par des outils ou un rail d'activation motorisé
Sneak to dismount=

View File

@ -1,36 +0,0 @@
# textdomain: mcl_minecarts
Minecart=Wagonik
Minecarts can be used for a quick transportion on rails.=Wagoniki mogą być użyte do szybkiego transportu po torach.
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=Wagoniki mogą jeździć tylko po torach i zawsze podążają za wytyczoną ścieżką. W przypadku skrzyżowań typu T, gdzie nie ma prostej ścieżki, skręcają w lew. Ich szybkość zależy od typu torów.
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Możesz postawić wagonik na torach. Kliknij prawym przyciskiem myszy aby do niego wejść. Uderz go by zaczął się poruszać.
To obtain the minecart, punch it while holding down the sneak key.=Aby odzyskać wagonik uderz go podczas skradania.
A minecart with TNT is an explosive vehicle that travels on rail.=Wagonik z TNT jest wybuchowym pojazdem podróżującym po torach.
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Postaw go na torach. Uderz by zaczął się poruszać. TNT zapala się krzesiwem lub gdy wagonik jest na zasilonych torach aktywacyjnych.
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Aby odzyskać wagonik z TNT uderz go podczas skradania. Nie możesz tego zrobić gdy TNT jest zapalone.
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=Wagonik z piecem jest pojazdem podróżującym na torach. Napędza on samego siebie za pomocą paliwa.
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=Postaw go na torach. Jeśli dasz mu nieco węgla piec zacznie palić przez długi czas, a wagonik będzie się sam poruszał. Uderz go by zaczął się poruszać.
To obtain the minecart and furnace, punch them while holding down the sneak key.=Aby odzyskać wagonik z piecem uderz go podczas skradania.
Minecart with Chest=Wagonik ze skrzynią
Minecart with Furnace=Wagonik z piecem
Minecart with Command Block=Wagonik z blokiem poleceń
Minecart with Hopper=Wagonik z lejem
Minecart with TNT=Wagonik z TNT
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Postaw je na ziemi by zbudować ścieżkę z torów. Tory automatycznie połączą się ze sobą i zamienią się w zakręty, skrzyżowania typu T, skrzyżowania i równie w zależności od potrzeb.
Rail=Tor
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=Tory mogą być wykorzystane do zbudowania torów dla wagoników. Zwyczajne tory nieco spowalniają wagoniki ze względu na tarcie.
Powered Rail=Zasilane tory
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Tory mogą być wykorzystane do zbudowania torów dla wagoników. Zasilane tory mogą przyspieszać lub spowalniać wagoniki.
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Bez zasilania czerwienitem tory będą spowalniać wagoniki. Aby sprawić by je przyspieszały zasil je czerwienitem.
Activator Rail=Tory aktywacyjne
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=Tory mogą być wykorzystane do zbudowania torów dla wagoników. Tory aktywacyjne są wykorzystywane do aktywacji specjalnych wagoników.
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=Aby ten tor aktywował wagonik, zasil go czerwienitem i spraw by wagonik po nim przejechał.
Detector Rail=Tory z czujnikiem
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=Tory mogą być wykorzystane do zbudowania torów dla wagoników. Tory z czujnikiem są w stanie wykryć kiedy wagonik po nich przejeżdża i wysłać sygnał do czerwienitowych mechanizmów.
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=Aby wykryć wagonik i dostarczyć zasilanie czerwienitem podłącz go czerwienitem to mechanizmu i spraw by wagonik po nim przejechał.
Track for minecarts=Tor dla wagoników
Speed up when powered, slow down when not powered=Przyspiesza gdy zasilane, spowalnia gdy nie
Activates minecarts when powered=Aktywuje wagoniki gdy zasilane
Emits redstone power when a minecart is detected=Emituje zasilanie czerwienitem gdy wagonik jest wykryty
Vehicle for fast travel on rails=Pojazd do szybkiej podróży na torach
Can be ignited by tools or powered activator rail=Może być zapalony przez narzędzia, lub zasilane tor aktywacyjne
Sneak to dismount=Zacznij się skradać by zejść

View File

@ -1,36 +0,0 @@
# textdomain: mcl_minecarts
Minecart=Вагонетка
Minecarts can be used for a quick transportion on rails.=Вагонетки нужны, чтобы быстро перемещаться по рельсам.
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=Вагонетки едут строго по проложенному железнодорожному пути. На Т-образной развилке они поворачивают налево. Скорость зависит от типа рельсов.
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Вы ставите вагонетку на рельсы. Правым кликом садитесь в неё. Стукаете, чтобы начать движение.
To obtain the minecart, punch it while holding down the sneak key.=Чтобы взять вагонетку, стукните её, удерживая клавишу [Красться].
A minecart with TNT is an explosive vehicle that travels on rail.=Вагон тротила это подрывной железнодорожный транспорт.
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Поместите его на рельсы. Стукните, чтобы он поехал. Тротил воспламеняется, если его поджечь огнивом, либо при попадании на подключенный рельсовый активатор.
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Чтобы взять вагон тротила, стукните его, удерживая клавишу [Красться]. Если тротил воспламенён, сделать это нельзя.
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=Вагон с печью - это железнодорожный транспорт. Он может двигаться за счёт топлива.
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=Поставьте его на рельсы. Если добавить немного угля, то печь зажжётся на продолжительное время и вагон сможет ехать. Стукните вагон для начала движения.
To obtain the minecart and furnace, punch them while holding down the sneak key.=Чтобы взять вагон с печью, стукните его, удерживая клавишу [Красться].
Minecart with Chest=Вагон с сундуком
Minecart with Furnace=Вагон с печью
Minecart with Command Block=Вагон с командным блоком
Minecart with Hopper=Вагон с бункером
Minecart with TNT=Вагон тротила
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Поместите на землю, чтобы сделать железную дорогу, рельсы автоматически соединятся между собой и будут превращаться в плавный повороты, T-образные развилки, перекрёстки и уклоны там, где это потребуется.
Rail=Рельсы
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=Рельсы используются для строительства железной дороги. Обычные рельсы немного замедляют движение вагонеток из-за трения.
Powered Rail=Подключаемые рельсы
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Рельсы используются для строительства железной дороги. Подключённые рельсы могут разгонять и тормозить вагонетки.
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Без энергии редстоуна рельсы будут тормозить вагонетки.
Activator Rail=Рельсовый активатор
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=Рельсы используются для строительства железной дороги. Рельсовый активатор активирует особые вагонетки.
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=Чтобы этот блок рельсов активировал вагонетку, подключите его к энергии редстоуна и направьте вагонетку через него.
Detector Rail=Рельсовый детектор
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=Рельсы используются для строительства железной дороги. Рельсовый детектор может обнаруживать вагонетку у себя наверху и подключать механизмы редстоуна.
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=Чтобы обнаруживать вагонетку и подавать энергию редстоуна, подключите его к дорожке редстоуна или механизму редстоуна, после чего направьте любую вагонетку через него.
Track for minecarts=Железная дорога
Speed up when powered, slow down when not powered=Разгоняет, если подключён, тормозит, если не подключён
Activates minecarts when powered=Активирует особые вагонетки, если подключён
Emits redstone power when a minecart is detected=Испускает энергию редстоуна при обнаружении вагонетки
Vehicle for fast travel on rails=Быстрый железнодорожный транспорт
Can be ignited by tools or powered activator rail=Можно воспламенить с помощью инструмента или подключенного рельсового активатора
Sneak to dismount=Нажмите [Красться] для высадки

View File

@ -1,36 +0,0 @@
# textdomain: mcl_minecarts
Minecart=
Minecarts can be used for a quick transportion on rails.=
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=
To obtain the minecart, punch it while holding down the sneak key.=
A minecart with TNT is an explosive vehicle that travels on rail.=
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=
To obtain the minecart and furnace, punch them while holding down the sneak key.=
Minecart with Chest=
Minecart with Furnace=
Minecart with Command Block=
Minecart with Hopper=
Minecart with TNT=
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=
Rail=
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=
Powered Rail=
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=
Activator Rail=
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=
Detector Rail=
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=
Track for minecarts=
Speed up when powered, slow down when not powered=
Activates minecarts when powered=
Emits redstone power when a minecart is detected=
Vehicle for fast travel on rails=
Can be ignited by tools or powered activator rail=
Sneak to dismount=

View File

@ -1,6 +0,0 @@
name = mcl_minecarts
author = Krock
description = Minecarts are vehicles to move players quickly on rails.
depends = mcl_title, mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons
optional_depends = doc_identifier, mcl_wip

View File

@ -1,249 +0,0 @@
local S = minetest.get_translator(minetest.get_current_modname())
-- Template rail function
local function register_rail(itemstring, tiles, def_extras, creative)
local groups = {handy=1,pickaxey=1, attached_node=1,rail=1,connect_to_raillike=minetest.raillike_group("rail"),dig_by_water=1,destroy_by_lava_flow=1, transport=1}
if creative == false then
groups.not_in_creative_inventory = 1
end
local ndef = {
drawtype = "raillike",
tiles = tiles,
is_ground_content = false,
inventory_image = tiles[1],
wield_image = tiles[1],
paramtype = "light",
walkable = false,
selection_box = {
type = "fixed",
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
},
stack_max = 64,
groups = groups,
sounds = mcl_sounds.node_sound_metal_defaults(),
_mcl_blast_resistance = 3.5,
_mcl_hardness = 0.7,
after_destruct = function(pos)
-- Scan for minecarts in this pos and force them to execute their "floating" check.
-- Normally, this will make them drop.
local objs = minetest.get_objects_inside_radius(pos, 1)
for o=1, #objs do
local le = objs[o]:get_luaentity()
if le then
-- All entities in this mod are minecarts, so this works
if string.sub(le.name, 1, 14) == "mcl_minecarts:" then
le._last_float_check = mcl_minecarts.check_float_time
end
end
end
end,
}
if def_extras then
for k,v in pairs(def_extras) do
ndef[k] = v
end
end
minetest.register_node(itemstring, ndef)
end
-- Redstone rules
local rail_rules_long =
{{x=-1, y= 0, z= 0, spread=true},
{x= 1, y= 0, z= 0, spread=true},
{x= 0, y=-1, z= 0, spread=true},
{x= 0, y= 1, z= 0, spread=true},
{x= 0, y= 0, z=-1, spread=true},
{x= 0, y= 0, z= 1, spread=true},
{x= 1, y= 1, z= 0},
{x= 1, y=-1, z= 0},
{x=-1, y= 1, z= 0},
{x=-1, y=-1, z= 0},
{x= 0, y= 1, z= 1},
{x= 0, y=-1, z= 1},
{x= 0, y= 1, z=-1},
{x= 0, y=-1, z=-1}}
local rail_rules_short = mesecon.rules.pplate
local railuse = S("Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.")
-- Normal rail
register_rail("mcl_minecarts:rail",
{"default_rail.png", "default_rail_curved.png", "default_rail_t_junction.png", "default_rail_crossing.png"},
{
description = S("Rail"),
_tt_help = S("Track for minecarts"),
_doc_items_longdesc = S("Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction."),
_doc_items_usagehelp = railuse,
}
)
-- Powered rail (off = brake mode)
register_rail("mcl_minecarts:golden_rail",
{"mcl_minecarts_rail_golden.png", "mcl_minecarts_rail_golden_curved.png", "mcl_minecarts_rail_golden_t_junction.png", "mcl_minecarts_rail_golden_crossing.png"},
{
description = S("Powered Rail"),
_tt_help = S("Track for minecarts").."\n"..S("Speed up when powered, slow down when not powered"),
_doc_items_longdesc = S("Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts."),
_doc_items_usagehelp = railuse .. "\n" .. S("Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power."),
_rail_acceleration = -3,
mesecons = {
conductor = {
state = mesecon.state.off,
offstate = "mcl_minecarts:golden_rail",
onstate = "mcl_minecarts:golden_rail_on",
rules = rail_rules_long,
},
},
}
)
-- Powered rail (on = acceleration mode)
register_rail("mcl_minecarts:golden_rail_on",
{"mcl_minecarts_rail_golden_powered.png", "mcl_minecarts_rail_golden_curved_powered.png", "mcl_minecarts_rail_golden_t_junction_powered.png", "mcl_minecarts_rail_golden_crossing_powered.png"},
{
_doc_items_create_entry = false,
_rail_acceleration = 4,
mesecons = {
conductor = {
state = mesecon.state.on,
offstate = "mcl_minecarts:golden_rail",
onstate = "mcl_minecarts:golden_rail_on",
rules = rail_rules_long,
},
},
drop = "mcl_minecarts:golden_rail",
},
false
)
-- Activator rail (off)
register_rail("mcl_minecarts:activator_rail",
{"mcl_minecarts_rail_activator.png", "mcl_minecarts_rail_activator_curved.png", "mcl_minecarts_rail_activator_t_junction.png", "mcl_minecarts_rail_activator_crossing.png"},
{
description = S("Activator Rail"),
_tt_help = S("Track for minecarts").."\n"..S("Activates minecarts when powered"),
_doc_items_longdesc = S("Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts."),
_doc_items_usagehelp = railuse .. "\n" .. S("To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail."),
mesecons = {
conductor = {
state = mesecon.state.off,
offstate = "mcl_minecarts:activator_rail",
onstate = "mcl_minecarts:activator_rail_on",
rules = rail_rules_long,
},
},
}
)
-- Activator rail (on)
register_rail("mcl_minecarts:activator_rail_on",
{"mcl_minecarts_rail_activator_powered.png", "mcl_minecarts_rail_activator_curved_powered.png", "mcl_minecarts_rail_activator_t_junction_powered.png", "mcl_minecarts_rail_activator_crossing_powered.png"},
{
_doc_items_create_entry = false,
mesecons = {
conductor = {
state = mesecon.state.on,
offstate = "mcl_minecarts:activator_rail",
onstate = "mcl_minecarts:activator_rail_on",
rules = rail_rules_long,
},
effector = {
-- Activate minecarts
action_on = function(pos, node)
local pos2 = { x = pos.x, y =pos.y + 1, z = pos.z }
local objs = minetest.get_objects_inside_radius(pos2, 1)
for _, o in pairs(objs) do
local l = o:get_luaentity()
if l and string.sub(l.name, 1, 14) == "mcl_minecarts:" and l.on_activate_by_rail then
l:on_activate_by_rail()
end
end
end,
},
},
drop = "mcl_minecarts:activator_rail",
},
false
)
-- Detector rail (off)
register_rail("mcl_minecarts:detector_rail",
{"mcl_minecarts_rail_detector.png", "mcl_minecarts_rail_detector_curved.png", "mcl_minecarts_rail_detector_t_junction.png", "mcl_minecarts_rail_detector_crossing.png"},
{
description = S("Detector Rail"),
_tt_help = S("Track for minecarts").."\n"..S("Emits redstone power when a minecart is detected"),
_doc_items_longdesc = S("Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms."),
_doc_items_usagehelp = railuse .. "\n" .. S("To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail."),
mesecons = {
receptor = {
state = mesecon.state.off,
rules = rail_rules_short,
},
},
}
)
-- Detector rail (on)
register_rail("mcl_minecarts:detector_rail_on",
{"mcl_minecarts_rail_detector_powered.png", "mcl_minecarts_rail_detector_curved_powered.png", "mcl_minecarts_rail_detector_t_junction_powered.png", "mcl_minecarts_rail_detector_crossing_powered.png"},
{
_doc_items_create_entry = false,
mesecons = {
receptor = {
state = mesecon.state.on,
rules = rail_rules_short,
},
},
drop = "mcl_minecarts:detector_rail",
},
false
)
-- Crafting
minetest.register_craft({
output = "mcl_minecarts:rail 16",
recipe = {
{"mcl_core:iron_ingot", "", "mcl_core:iron_ingot"},
{"mcl_core:iron_ingot", "mcl_core:stick", "mcl_core:iron_ingot"},
{"mcl_core:iron_ingot", "", "mcl_core:iron_ingot"},
}
})
minetest.register_craft({
output = "mcl_minecarts:golden_rail 6",
recipe = {
{"mcl_core:gold_ingot", "", "mcl_core:gold_ingot"},
{"mcl_core:gold_ingot", "mcl_core:stick", "mcl_core:gold_ingot"},
{"mcl_core:gold_ingot", "mesecons:redstone", "mcl_core:gold_ingot"},
}
})
minetest.register_craft({
output = "mcl_minecarts:activator_rail 6",
recipe = {
{"mcl_core:iron_ingot", "mcl_core:stick", "mcl_core:iron_ingot"},
{"mcl_core:iron_ingot", "mesecons_torch:mesecon_torch_on", "mcl_core:iron_ingot"},
{"mcl_core:iron_ingot", "mcl_core:stick", "mcl_core:iron_ingot"},
}
})
minetest.register_craft({
output = "mcl_minecarts:detector_rail 6",
recipe = {
{"mcl_core:iron_ingot", "", "mcl_core:iron_ingot"},
{"mcl_core:iron_ingot", "mesecons_pressureplates:pressure_plate_stone_off", "mcl_core:iron_ingot"},
{"mcl_core:iron_ingot", "mesecons:redstone", "mcl_core:iron_ingot"},
}
})
-- Aliases
if minetest.get_modpath("doc") then
doc.add_entry_alias("nodes", "mcl_minecarts:golden_rail", "nodes", "mcl_minecarts:golden_rail_on")
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 624 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 319 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 B

File diff suppressed because it is too large Load Diff

View File

@ -1,796 +0,0 @@
Mobs Redo: MineClone 2 Edition
API documentation
==============================
Welcome to the world of mobs in Minetest and hopefully an easy guide to defining
your own mobs and having them appear in your worlds.
Registering Mobs
----------------
To register a mob and have it ready for use requires the following function:
mobs:register_mob(name, definition)
The 'name' of a mob usually starts with the mod name it's running from followed
by it's own name e.g.
"mobs_monster:sand_monster" or "mymod:totally_awesome_beast"
... and the 'definition' is a table which holds all of the settings and
functions needed for the mob to work properly which contains the following:
'nametag' contains the name which is shown above mob.
'type' holds the type of mob that inhabits your world e.g.
"animal" usually docile and walking around.
"monster" attacks player or npc on sight.
"npc" walk around and will defend themselves if hit first, they
kill monsters.
'hp_min' the minimum health value the mob can spawn with.
'hp_max' the maximum health value the mob can spawn with.
'breath_max' The maximum breath value the mob can spawn with and can have.
If -1 (default), mob does not take drowning damage.
'breathes_in_water' If true, mob loses breath when not in water. Otherwise,
mob loses breath when inside a node with `drowning` attribute
set (default: false).
'armor' entity armor groups (see lua_api.txt). If table, a list of
armor groups like for entities. If number, set value of
'fleshy' armor group only.
Note: The 'immortal=1' armor group will automatically be added
since this mod handles health and damage manually.
Default: 100 (mob will take full dmg from 'fleshy' hits)
'passive' when true allows animals to defend themselves when hit,
otherwise they amble onwards.
'walk_velocity' is the speed that your mob can walk around.
'run_velocity'is the speed your mob can run with, usually when attacking.
'walk_chance' has a 0-100 chance value your mob will walk from standing,
set to 0 for jumping mobs only.
'jump' when true allows your mob to jump updwards.
'jump_height' holds the height your mob can jump, 0 to disable jumping.
'stepheight' height of a block that your mob can easily walk up onto,
defaults to 0.6.
'fly' when true allows your mob to fly around instead of walking.
'fly_in' holds the node name or a table of node names in which the
mob flies (or swims) around in. The special name
'__airlike' stands for all nodes with 'walkable=false'
that are not liquids
'runaway' if true causes animals to turn and run away when hit.
'view_range' how many nodes in distance the mob can see a player.
'damage' how many health points the mob does to a player or another
mob when melee attacking.
'knock_back' when true has mobs falling backwards when hit, the greater
the damage the more they move back.
'fear_height' is how high a cliff or edge has to be before the mob stops
walking, 0 to turn off height fear.
'fall_speed' has the maximum speed the mob can fall at, default is -10.
'fall_damage' when true causes falling to inflict damage.
'water_damage'holds the damage per second infliced to mobs when standing in
water (default: 0).
'lava_damage' holds the damage per second inflicted to mobs when standing
in lava (default: 8).
'fire_damage' holds the damage per second inflicted to mobs when standing
in fire (default: 1).
'light_damage'holds the damage per second inflicted to mobs when it's too
bright (above 13 light).
'suffocation' when true causes mobs to suffocate inside solid blocks (2 damage per second).
'floats' when set to 1 mob will float in water, 0 has them sink.
'follow' mobs follow player when holding any of the items which appear
on this table, the same items can be fed to a mob to tame or
breed e.g. {"farming:wheat", "default:apple"}
'reach' is how far the mob can attack player when standing
nearby, default is 3 nodes.
'docile_by_day' when true has mobs wandering around during daylight
hours and only attacking player at night or when
provoked.
'attacks_monsters' when true has npc's attacking monsters or not.
'attack_animals' when true will have monsters attacking animals.
'owner_loyal' when true will have tamed mobs attack anything player
punches when nearby.
'group_attack' when true has same mob type grouping together to attack
offender.
[MCL2 extension:] When a table, this is a list of
mob types that will get alerted as well (besides same mob type)
'attack_type' tells the api what a mob does when attacking the player
or another mob:
'dogfight' is a melee attack when player is within mob reach.
'shoot' has mob shoot pre-defined arrows at player when inside
view_range.
'dogshoot' has melee attack when inside reach and shoot attack
when inside view_range.
'explode' causes mob to stop and explode when inside reach.
'explosion_radius' the radius of explosion node destruction,
defaults to 1
'explosion_damage_radius' the radius of explosion entity & player damage,
defaults to explosion_radius * 2
'explosion_timer' number of seconds before mob explodes while its target
is still inside reach or explosion_damage_radius,
defaults to 3.
'explosiontimer_reset_radius' The distance you must travel before the timer will be reset.
'allow_fuse_reset' Allow 'explode' attack_type to reset fuse and resume
chasing if target leaves the blast radius or line of
sight. Defaults to true.
'stop_to_explode' When set to true (default), mob must stop and wait for
explosion_timer in order to explode. If false, mob will
continue chasing.
'arrow' holds the pre-defined arrow object to shoot when
attacking.
'dogshoot_switch' allows switching between attack types by using timers
(1 for shoot, 2 for dogfight)
'dogshoot_count_max'contains how many seconds before switching from
dogfight to shoot.
'dogshoot_count2_max' contains how many seconds before switching from shoot
to dogfight.
'shoot_interval' has the number of seconds between shots.
'shoot_offset' holds the y position added as to where the
arrow/fireball appears on mob.
'specific_attack' has a table of entity names that mob can also attack
e.g. {"player", "mobs_animal:chicken"}.
'runaway_from' contains a table with mob names to run away from, add
"player" to list to runaway from player also.
'pathfinding' set to 1 for mobs to use pathfinder feature to locate
player, set to 2 so they can build/break also (only
works with dogfight attack and when 'mobs_griefing'
in minetest.conf is not false).
'immune_to' is a table that holds specific damage when being hit by
certain items e.g.
{"default:sword_wood",0} -- causes no damage.
{"default:gold_lump", -10} -- heals by 10 health points.
{"default:coal_block", 20} -- 20 damage when hit on head with coal blocks.
'makes_footstep_sound' when true you can hear mobs walking.
'sounds' this is a table with sounds of the mob
'distance' maximum distance sounds can be heard, default is 10.
'base_pitch' base pitch to use adult mobs, default is 1.0 (MCL2 extension)
'random' played randomly from time to time.
also played for overfeeding animal.
'eat' played when mob eats something
'war_cry' what you hear when mob starts to attack player. (currently disabled)
'attack' what you hear when being attacked.
'shoot_attack' sound played when mob shoots.
'damage' sound heard when mob is hurt.
'death' played when mob is killed.
'jump' played when mob jumps. There's a built-in cooloff timer to avoid sound spam
'flop' played when mob flops (like a stranded fish)
'fuse' sound played when mob explode timer starts.
'explode' sound played when mob explodes.
Note: For all sounds except fuse and explode, the pitch is slightly randomized from the base pitch
The pitch of children is 50% higher.
'drops' table of items that are dropped when mob is killed, fields are:
'name' name of item to drop.
'chance' chance of drop, 1 for always, 2 for 1-in-2 chance etc.
'min' minimum number of items dropped.
'max' maximum number of items dropped.
'visual' holds the look of the mob you wish to create:
'cube' looks like a normal node
'sprite' sprite which looks same from all angles.
'upright_sprite' flat model standing upright.
'wielditem' how it looks when player holds it in hand.
'mesh' uses separate object file to define mob.
'visual_size' has the size of the mob, defaults to {x = 1, y = 1}
'collisionbox' has the box in which mob can be interacted with the
world e.g. {-0.5, -0.5, -0.5, 0.5, 0.8, 0.5}.
NOTE: Due to a workaround, the upper Y coordinate will be forced
to a minimum value of 0.79.
'selectionbox' has the box in which player can interact with mob
'textures' holds a table list of textures to be used for mob, or you
could use multiple lists inside another table for random
selection e.g. { {"texture1.png"}, {"texture2.png"} }
'child_texture' holds the texture table for when baby mobs are used.
'gotten_texture' holds the texture table for when self.gotten value is
true, used for milking cows or shearing sheep.
'mesh' holds the name of the external object used for mob model
e.g. "mobs_cow.b3d"
'gotten_mesh" holds the name of the external object used for when
self.gotten is true for mobs.
'rotate' custom model rotation, 0 = front, 90 = side, 180 = back,
270 = other side.
'double_melee_attack' when true has the api choose between 'punch' and
'punch2' animations.
'animation' holds a table containing animation names and settings for use with mesh models:
{
'stand_start'start frame for when mob stands still.
'stand_end' end frame of stand animation.
'stand_speed'speed of animation in frames per second.
'walk_start' when mob is walking around.
'walk_end'
'walk_speed'
'run_start' when a mob runs or attacks.
'run_end'
'run_speed'
'fly_start' when a mob is flying.
'fly_end'
'fly_speed'
'punch_start'when a mob melee attacks.
'punch_end'
'punch_speed'
'punch2_start' alternative melee attack animation.
'punch2_end'
'punch2_speed'
'shoot_start'shooting animation.
'shoot_end'
'shoot_speed'
'die_start' death animation
'die_end'
'die_speed'
'die_loop' when set to false stops the animation looping.
}
Using '_loop = false' setting will stop any of the above animations from
looping.
'speed_normal' is used for animation speed for compatibility with some
older mobs.
'pushable' Allows players, & other mobs to push the mob.
MineClone 2 extensions:
'spawn_class' Classification of mod for the spawning algorithm:
"hostile", "passive", "ambient" or "water"
'ignores_nametag' if true, mob cannot be named by nametag
'rain_damage' damage per second if mob is standing in rain (default: 0)
'sunlight_damage' holds the damage per second inflicted to mobs when they
are in direct sunlight
'spawn_small_alternative' name of a smaller mob to use as replacement if
spawning fails due to space requirements
'glow' same as in entity definition
'child' if true, spawn mob as child
'shoot_arrow(self, pos, dir)' function that is called when mob wants to shoot an arrow.
You can spawn your own arrow here. pos is mob position,
dir is mob's aiming direction
'sounds_child' same as sounds, but for childs. If not defined, childs will use same
sound as adults but with higher pitch
'follow_velocity' The speed at which a mob moves toward the player when they're holding the appropriate follow item.
'instant_death' If true, mob dies instantly (no death animation or delay) (default: false)
'xp_min' the minimum XP it drops on death (default: 0)
'xp_max' the maximum XP it drops on death (default: 0)
'fire_resistant' If true, the mob can't burn
'fire_damage_resistant' If true the mob will not take damage when burning
'ignited_by_sunlight' If true the mod will burn at daytime. (Takes sunlight_damage per second)
'nofollow' Do not follow players when they wield the "follow" item. For mobs (like villagers)
that are bred in a different way.
'pick_up' table of itemstrings the mob will pick up (e.g. for breeding)
'on_pick_up' function that will be called on item pickup - return true to not pickup the item
mobs:gopath(self,target,callback_arrived) pathfind a way to target and run callback on arrival
Node Replacement
----------------
Mobs can look around for specific nodes as they walk and replace them to mimic
eating.
'replace_what' group of items to replace e.g.
{"farming:wheat_8", "farming:carrot_8"}
or you can use the specific options of what, with and
y offset by using this instead:
{
{"group:grass", "air", 0},
{"default:dirt_with_grass", "default:dirt", -1}
}
'replace_with' replace with what e.g. "air" or in chickens case "mobs:egg"
'replace_rate' how random should the replace rate be (typically 10)
'replace_offset' +/- value to check specific node to replace
'on_replace(self, pos, oldnode, newnode)'
is called when mob is about to replace a node. Also called
when not actually replacing due to mobs_griefing setting being false.
'self' ObjectRef of mob
'pos' Position of node to replace
'oldnode' Current node
'newnode' What the node will become after replacing
If false is returned, the mob will not replace the node.
By default, replacing sets self.gotten to true and resets the object
properties.
Custom Definition Functions
---------------------------
Along with the above mob registry settings we can also use custom functions to
enhance mob functionality and have them do many interesting things:
'on_die' a function that is called when the mob is killed; the
parameters are (self, pos). Return true to skip the builtin
death animation and death effects
'on_rightclick'its same as in minetest.register_entity()
'on_blast' is called when an explosion happens near mob when using TNT
functions, parameters are (object, damage) and returns
(do_damage, do_knockback, drops)
'on_spawn' is a custom function that runs on mob spawn with 'self' as
variable, return true at end of function to run only once.
'after_activate' is a custom function that runs once mob has been activated
with these paramaters (self, staticdata, def, dtime)
'on_breed' called when two similar mobs breed, paramaters are
(parent1, parent2) objects, return false to stop child from
being resized and owner/tamed flags and child textures being
applied.Function itself must spawn new child mob.
'on_grown' is called when a child mob has grown up, only paramater is
(self).
'do_punch' called when mob is punched with paramaters (self, hitter,
time_from_last_punch, tool_capabilities, direction), return
false to stop punch damage and knockback from taking place.
'custom_attack'when set this function is called instead of the normal mob
melee attack, parameters are (self, to_attack).
'on_die' a function that is called when mob is killed (self, pos)
'do_custom' a custom function that is called every tick while mob is
active and which has access to all of the self.* variables
e.g. (self.health for health or self.standing_in for node
status), return with 'false' to skip remainder of mob API.
Internal Variables
------------------
The mob api also has some preset variables and functions that it will remember
for each mob.
'self.health' contains current health of mob (cannot exceed
self.hp_max)
'self.breath' contains current breath of mob, if mob takes drowning
damage at all (cannot exceed self.breath_max). Breath
decreases by 1 each second while in a node with drowning
damage and increases by 1 each second otherwise.
'self.texture_list'contains list of all mob textures
'self.child_texture' contains mob child texture when growing up
'self.base_texture'contains current skin texture which was randomly
selected from textures list
'self.gotten' this is used to track whether some special item has been
gotten from the mob, for example, wool from sheep.
Initialized as false, and the mob must set this value
manually.
'self.horny' when animal fed enough it is set to true and animal can
breed with same animal
'self.hornytimer' background timer that controls breeding functions and
mob childhood timings
'self.child' used for when breeding animals have child, will use
child_texture and be half size
'self.owner' string used to set owner of npc mobs, typically used for
dogs
'self.order' set to "follow" or "stand" so that npc will follow owner
or stand it's ground
'self.state' Current mob state.
"stand": no movement (except turning around)
"walk": walk or move around aimlessly
"attack": chase and attack enemy
"runaway": flee from target
"flop": bounce around aimlessly
(for swimming mobs that have stranded)
"die": during death
'self.nametag' contains the name of the mob which it can show above
Spawning Mobs in World
----------------------
mobs:register_spawn(name, nodes, max_light, min_light, chance,
active_object_count, max_height, day_toggle)
mobs:spawn_specfic(name, nodes, neighbors, min_light, max_light, interval,
chance, active_object_count, min_height, max_height, day_toggle, on_spawn)
These functions register a spawn algorithm for the mob. Without this function
the call the mobs won't spawn.
'name' is the name of the animal/monster
'nodes' is a list of nodenames on that the animal/monster can
spawn on top of
'neighbors' is a list of nodenames on that the animal/monster will
spawn beside (default is {"air"} for
mobs:register_spawn)
'max_light' is the maximum of light
'min_light' is the minimum of light
'interval' is same as in register_abm() (default is 30 for
mobs:register_spawn)
'chance' is same as in register_abm()
'active_object_count' number of this type of mob to spawn at one time inside
map area
'min_height' is the minimum height the mob can spawn
'max_height' is the maximum height the mob can spawn
'day_toggle' true for day spawning, false for night or nil for
anytime
'on_spawn' is a custom function which runs after mob has spawned
and gives self and pos values.
A simpler way to handle mob spawns has been added with the mobs:spawn(def)
command which uses above names to make settings clearer:
mobs:spawn({name = "mobs_monster:tree_monster",
nodes = {"group:leaves"},
max_light = 7,
})
For each mob that spawns with this function is a field in mobs.spawning_mobs.
It tells if the mob should spawn or not.Default is true.So other mods can
only use the API of this mod by disabling the spawning of the default mobs in
this mod.
mobs:spawn_abm_check(pos, node, name)
This global function can be changed to contain additional checks for mobs to
spawn e.g. mobs that spawn only in specific areas and the like.By returning
true the mob will not spawn.
'pos' holds the position of the spawning mob
'node' contains the node the mob is spawning on top of
'name' is the name of the animal/monster
MineClone 2 extensions
----------------------
mobs:spawn_child(pos, mob_type)
This function spawns a mob as a child. The parameter mob_type is the
entitystring of the new mob.
This function returns the mob on success and nil otherwise.
mobs:death_effect(pos, collisionbox)
Create death particles at pos with the given collisionbox.
Making Arrows
-------------
mobs:register_arrow(name, definition)
This function registers a arrow for mobs with the attack type shoot.
'name' is the name of the arrow
'definition' is a table with the following values:
'visual' same is in minetest.register_entity()
'visual_size'same is in minetest.register_entity()
'textures' same is in minetest.register_entity()
'velocity' the velocity of the arrow
'drop' if set to true any arrows hitting a node will drop as item
'hit_player' a function that is called when the arrow hits a player;
this function should hurt the player, the parameters are
(self, player)
'hit_mob' a function that is called when the arrow hits a mob;
this function should hurt the mob, the parameters are
(self, mob)
'hit_object' a function that is called when the arrow hits an object
that is neither a player nor a mob. this function should
hurt the object, the parameters are (self, object)
'hit_node' a function that is called when the arrow hits a node, the
parameters are (self, pos, node)
'tail' when set to 1 adds a trail or tail to mob arrows
'tail_texture' texture string used for above effect
'tail_size' has size for above texture (defaults to between 5 and 10)
'expire' contains float value for how long tail appears for
(defaults to 0.25)
'glow' has value for how brightly tail glows 1 to 10 (default is
0 for no glow)
'rotate' integer value in degrees to rotate arrow
'on_step' is a custom function when arrow is active, nil for
default.
Spawn Eggs
----------
mobs:register_egg(name, description, background, addegg, no_creative)
This function registers a spawn egg which can be used by admin to properly spawn in a mob.
'name' this is the name of your new mob to spawn e.g. "mob:sheep"
'description' the name of the new egg you are creating e.g. "Spawn Sheep"
'background'the texture displayed for the egg in inventory
'addegg' would you like an egg image in front of your texture (1 = yes,
0 = no)
'no_creative' when set to true this stops spawn egg appearing in creative
mode for destructive mobs like Dungeon Masters.
Explosion Function
------------------
mobs:boom(self, pos, radius)
'self' mob entity
'pos' centre position of explosion
'radius' radius of explosion (typically set to 3)
This function generates an explosion which removes nodes in a specific radius
and damages any entity caught inside the blast radius.Protection will limit
node destruction but not entity damage.
mobs:capture_mob
----------------
mobs:capture_mob(...)
Does nothing and returns false.
This function is provided for compability with Mobs Redo for an attempt to
capture a mob.
Mobs cannot be captured in MineClone 2.
In Mobs Redo, this is generally called inside the on_rightclick section of the mob
api code, it provides a chance of capturing the mob. See Mobs Redo documentation
of parameters.
Feeding and Taming/Breeding
---------------------------
mobs:feed_tame(self, clicker, feed_count, breed, tame)
This function allows the mob to be fed the item inside self.follow be it apple,
wheat or whatever a set number of times and be tamed or bred as a result.
Will return true when mob is fed with item it likes.
'self' mob information
'clicker' player information
'feed_count' number of times mob must be fed to tame or breed
'breed' true or false stating if mob can be bred and a child created
afterwards
'tame' true or false stating if mob can be tamed so player can pick
them up
Protecting Mobs
---------------
mobs:protect(self, clicker)
This function can be used to right-click any tamed mob with mobs:protector item,
this will protect the mob from harm inside of a protected area from other
players.Will return true when mob right-clicked with mobs:protector item.
'self' mob information
'clicker' player information
Riding Mobs
-----------
Mobs can now be ridden by players and the following shows its functions and
usage:
mobs:attach(self, player)
This function attaches a player to the mob so it can be ridden.
'self' mob information
'player' player information
mobs:detach(player, offset)
This function will detach the player currently riding a mob to an offset
position.
'player' player information
'offset' position table containing offset values
mobs:drive(self, move_animation, stand_animation, can_fly, dtime)
This function allows an attached player to move the mob around and animate it at
same time.
'self' mob information
'move_animation'string containing movement animation e.g. "walk"
'stand_animation' string containing standing animation e.g. "stand"
'can_fly' if true then jump and sneak controls will allow mob to fly
up and down
'dtime' tick time used inside drive function
mobs:fly(self, dtime, speed, can_shoot, arrow_entity, move_animation, stand_animation)
This function allows an attached player to fly the mob around using directional
controls.
'self' mob information
'dtime' tick time used inside fly function
'speed' speed of flight
'can_shoot' true if mob can fire arrow (sneak and left mouse button
fires)
'arrow_entity' name of arrow entity used for firing
'move_animation'string containing name of pre-defined animation e.g. "walk"
or "fly" etc.
'stand_animation' string containing name of pre-defined animation e.g.
"stand" or "blink" etc.
Note: animation names above are from the pre-defined animation lists inside mob
registry without extensions.
mobs:set_animation(self, name)
This function sets the current animation for mob, defaulting to "stand" if not
found.
'self' mob information
'name' name of animation
Certain variables need to be set before using the above functions:
'self.v2' toggle switch used to define below values for the
first time
'self.max_speed_forward' max speed mob can move forward
'self.max_speed_reverse' max speed mob can move backwards
'self.accel' acceleration speed
'self.terrain_type' integer containing terrain mob can walk on
(1 = water, 2 or 3 = land)
'self.driver_attach_at'position offset for attaching player to mob
'self.driver_eye_offset' position offset for attached player view
'self.driver_scale' sets driver scale for mobs larger than {x=1, y=1}
External Settings for "minetest.conf"
------------------------------------
'enable_damage' if true monsters will attack players (default is true)
'only_peaceful_mobs' if true only animals will spawn in game (default is
false)
'mobs_disable_blood' if false, damage effects appear when mob is hit (default
is false)
'mobs_spawn_protected' if set to false then mobs will not spawn in protected
areas (default is true)
'mob_difficulty' sets difficulty level (health and hit damage
multiplied by this number), defaults to 1.0.
'mob_spawn_chance' multiplies chance of all mobs spawning and can be set
to 0.5 to have mobs spawn more or 2.0 to spawn less.
e.g.1 in 7000 * 0.5 = 1 in 3500 so better odds of
spawning.
'mobs_spawn' if false then mobs no longer spawn without spawner or
spawn egg.
'mobs_drop_items' when false mobs no longer drop items when they die.
'mobs_griefing' when false mobs cannot break blocks when using either
pathfinding level 2, replace functions or mobs:boom
function.
Players can override the spawn chance for each mob registered by adding a line
to their minetest.conf file with a new value, the lower the value the more each
mob will spawn e.g.
mobs_animal:sheep_chance 11000
mobs_monster:sand_monster_chance 100
Rideable Horse Example Mob
--------------------------
mobs:register_mob("mob_horse:horse", {
type = "animal",
visual = "mesh",
visual_size = {x = 1.20, y = 1.20},
mesh = "mobs_horse.x",
collisionbox = {-0.4, -0.01, -0.4, 0.4, 1.25, 0.4},
animation = {
speed_normal = 15,
speed_run = 30,
stand_start = 25,
stand_end = 75,
walk_start = 75,
walk_end = 100,
run_start = 75,
run_end = 100,
},
textures = {
{"mobs_horse.png"},
{"mobs_horsepeg.png"},
{"mobs_horseara.png"}
},
fear_height = 3,
runaway = true,
fly = false,
walk_chance = 60,
view_range = 5,
follow = {"farming:wheat"},
passive = true,
hp_min = 12,
hp_max = 16,
armor = 200,
lava_damage = 5,
fall_damage = 5,
water_damage = 1,
makes_footstep_sound = true,
drops = {
{name = "mobs:meat_raw", chance = 1, min = 2, max = 3}
},
sounds = {
random = "horse_neigh.ogg",
damage = "horse_whinney.ogg",
},
do_custom = function(self, dtime)
-- set needed values if not already present
if not self.v2 then
self.v2 = 0
self.max_speed_forward = 6
self.max_speed_reverse = 2
self.accel = 6
self.terrain_type = 3
self.driver_attach_at = {x = 0, y = 20, z = -2}
self.driver_eye_offset = {x = 0, y = 3, z = 0}
self.driver_scale = {x = 1, y = 1}
end
-- if driver present allow control of horse
if self.driver then
mobs.drive(self, "walk", "stand", false, dtime)
return false -- skip rest of mob functions
end
return true
end,
on_die = function(self, pos)
-- drop saddle when horse is killed while riding
-- also detach from horse properly
if self.driver then
minetest.add_item(pos, "mobs:saddle")
mobs.detach(self.driver, {x = 1, y = 0, z = 1})
end
end,
on_rightclick = function(self, clicker)
-- make sure player is clicking
if not clicker or not clicker:is_player() then
return
end
-- feed, tame or heal horse
if mobs:feed_tame(self, clicker, 10, true, true) then
return
end
-- make sure tamed horse is being clicked by owner only
if self.tamed and self.owner == clicker:get_player_name() then
local inv = clicker:get_inventory()
-- detatch player already riding horse
if self.driver and clicker == self.driver then
mobs.detach(clicker, {x = 1, y = 0, z = 1})
-- add saddle back to inventory
if inv:room_for_item("main", "mobs:saddle") then
inv:add_item("main", "mobs:saddle")
else
minetest.add_item(clicker.get_pos(), "mobs:saddle")
end
-- attach player to horse
elseif not self.driver
and clicker:get_wielded_item():get_name() == "mobs:saddle" then
self.object:set_properties({stepheight = 1.1})
mobs.attach(self, clicker)
-- take saddle from inventory
inv:remove_item("main", "mobs:saddle")
end
end
-- used to capture horse with magic lasso
mobs:capture_mob(self, clicker, 0, 0, 80, false, nil)
end
})

View File

@ -1,16 +0,0 @@
local S = minetest.get_translator("mcl_mobs")
-- name tag
minetest.register_craftitem("mcl_mobs:nametag", {
description = S("Name Tag"),
_tt_help = S("Give names to mobs").."\n"..S("Set name at anvil"),
_doc_items_longdesc = S("A name tag is an item to name a mob."),
_doc_items_usagehelp = S("Before you use the name tag, you need to set a name at an anvil. Then you can use the name tag to name a mob. This uses up the name tag."),
inventory_image = "mobs_nametag.png",
wield_image = "mobs_nametag.png",
stack_max = 64,
groups = { tool=1 },
})
minetest.register_alias("mobs:nametag", "mcl_mobs:nametag")

View File

@ -1,14 +0,0 @@
local path = minetest.get_modpath(minetest.get_current_modname())
-- Mob API
dofile(path .. "/api.lua")
-- Spawning Algorithm
dofile(path .. "/spawning.lua")
-- Rideable Mobs
dofile(path .. "/mount.lua")
-- Mob Items
dofile(path .. "/crafts.lua")

View File

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2016 TenPlus1
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -1,11 +0,0 @@
# textdomain: mcl_mobs
Peaceful mode active! No monsters will spawn.=Friedlicher Modus aktiv! Es werden keine Monster auftauchen.
This allows you to place a single mob.=Damit kann man einen Mob platzieren.
Just place it where you want the mob to appear. Animals will spawn tamed, unless you hold down the sneak key while placing. If you place this on a mob spawner, you change the mob it spawns.=Platzieren Sie dies einfach dort, wo der Mob auftauchen soll. Tiere werden zahm erscheinen, außer, wenn Sie beim Platzieren die Schlichtaste drücken. Platzieren Sie dies auf einem Mobspawner, um den Mob im Mobspawner zu wechseln.
You need the “maphack” privilege to change the mob spawner.=Sie brauchen das „maphack“-Privileg, um den Mobspawner ändern zu können.
Name Tag=Namensschild
A name tag is an item to name a mob.=Ein Namensschild ist ein Gegenstand, um einen Mob zu benennen.
Before you use the name tag, you need to set a name at an anvil. Then you can use the name tag to name a mob. This uses up the name tag.=Bevor Sie ein Namensschild benutzen können, müssen Sie ihn an einem Amboss benennen. Dann können können Sie das Namensschild benutztn, um einen Mob zu benennen. Das wird das Namensschild verbrauchen.
Only peaceful mobs allowed!=Nur friedliche Mobs erlaubt!
Give names to mobs=Benennt Mobs
Set name at anvil=Namen am Amboss setzen

View File

@ -1,9 +0,0 @@
# textdomain: mcl_mobs
Peaceful mode active! No monsters will spawn.=¡Modo pacífico activo! No aparecerán monstruos.
This allows you to place a single mob.=Esto le permite colocar un solo animal.
Just place it where you want the mob to appear. Animals will spawn tamed, unless you hold down the sneak key while placing. If you place this on a mob spawner, you change the mob it spawns.=Simplemente colóquelo donde desea que aparezcan los animales. Los animales aparecerán domesticados, a menos que mantenga presionada la tecla de sigilo mientras coloca. Si coloca esto en un engendrador de animales, cambia el animal que genera.
You need the “maphack” privilege to change the mob spawner.=Necesita el privilegio "maphack" para cambiar el generador de animales.
Name Tag=Etiqueta
A name tag is an item to name a mob.=Una etiqueta es un elemento para nombrar una animal.
Before you use the name tag, you need to set a name at an anvil. Then you can use the name tag to name a mob. This uses up the name tag.=Antes de usar la etiqueta, debe establecer un nombre en un yunque. Luego puede usar la etiqueta para nombrar un animal. Esto usa la etiqueta.
Only peaceful mobs allowed!=¡Solo se permiten animales pacíficos!

View File

@ -1,11 +0,0 @@
# textdomain: mcl_mobs
Peaceful mode active! No monsters will spawn.=Mode paisible actif! Aucun monstre n'apparaîtra.
This allows you to place a single mob.=Cela vous permet de placer un seul mob.
Just place it where you want the mob to appear. Animals will spawn tamed, unless you hold down the sneak key while placing. If you place this on a mob spawner, you change the mob it spawns.=Placez-le là où vous voulez que le mob apparaisse. Les animaux apparaîtront apprivoisés, sauf si vous maintenez la touche furtive enfoncée pendant le placement. Si vous le placez sur un générateur de mob, vous changez le mob qu'il génère.
You need the “maphack” privilege to change the mob spawner.=Vous avez besoin du privilège "maphack" pour changer le générateur de mob.
Name Tag=Étiquette de nom
A name tag is an item to name a mob.=Une étiquette de nom est un élément pour nommer un mob.
Before you use the name tag, you need to set a name at an anvil. Then you can use the name tag to name a mob. This uses up the name tag.=Avant d'utiliser l'étiquette de nom, vous devez définir un nom sur une enclume. Ensuite, vous pouvez utiliser l'étiquette de nom pour nommer un mob. Cela utilise l'étiquette de nom.
Only peaceful mobs allowed!=Seuls les mobs pacifiques sont autorisées!
Give names to mobs=Donne des noms aux mobs
Set name at anvil=Définir le nom sur l'enclume

View File

@ -1,11 +0,0 @@
# textdomain: mcl_mobs
Peaceful mode active! No monsters will spawn.=Мирный режим включён! Монстры не будут появляться.
This allows you to place a single mob.=Позволяет вам разместить одного моба.
Just place it where you want the mob to appear. Animals will spawn tamed, unless you hold down the sneak key while placing. If you place this on a mob spawner, you change the mob it spawns.=Просто поместите это туда, где хотите, чтобы появился моб. Животные будут появляться уже прирученные, если это не нужно, удерживайте клавишу [Красться] при размещении. Если поместить это на спаунер, появляющийся из него моб будет изменён.
You need the “maphack” privilege to change the mob spawner.=Вам нужно обладать привилегией “maphack”, чтобы изменить спаунер моба.
Name Tag=Именная бирка
A name tag is an item to name a mob.=Именная бирка это предмет, чтобы дать мобу имя.
Before you use the name tag, you need to set a name at an anvil. Then you can use the name tag to name a mob. This uses up the name tag.=Прежде чем использовать именную бирку, нужно задать имя на наковальне. Тогда вы сможете использовать бирку, чтобы дать имя мобу.
Only peaceful mobs allowed!=Разрешены только мирные мобы!
Give names to mobs=Даёт имена мобам
Set name at anvil=Задайте имя при помощи наковальни

View File

@ -1,11 +0,0 @@
# textdomain: mcl_mobs
Peaceful mode active! No monsters will spawn.=和平模式已啓用!不會生成怪物。
This allows you to place a single mob.=允許你放置一個生物。
Just place it where you want the mob to appear. Animals will spawn tamed, unless you hold down the sneak key while placing. If you place this on a mob spawner, you change the mob it spawns.=把它放在你希望生物出現的地方。除非你在放置的時候按住潛行鍵,否則動物會被馴服地產生。如果你把它放在一個生怪磚上,你就會改變它所產的生物。
You need the “maphack” privilege to change the mob spawner.=你要「maphack」權限來修改生怪磚。
Name Tag=命名牌
A name tag is an item to name a mob.=命名牌是一個用於命名生物的物品
Before you use the name tag, you need to set a name at an anvil. Then you can use the name tag to name a mob. This uses up the name tag.=在使用名字標籤之前,你需要在一個鐵砧上設置一個名字。然後你就可以用名字標籤來給生物命名。這會消耗命名牌。
Only peaceful mobs allowed!=只允許和平生物!
Give names to mobs=替生物命名
Set name at anvil=在鐵砧上設置名字

View File

@ -1,11 +0,0 @@
# textdomain: mcl_mobs
Peaceful mode active! No monsters will spawn.=
This allows you to place a single mob.=
Just place it where you want the mob to appear. Animals will spawn tamed, unless you hold down the sneak key while placing. If you place this on a mob spawner, you change the mob it spawns.=
You need the “maphack” privilege to change the mob spawner.=
Name Tag=
A name tag is an item to name a mob.=
Before you use the name tag, you need to set a name at an anvil. Then you can use the name tag to name a mob. This uses up the name tag.=
Only peaceful mobs allowed!=
Give names to mobs=
Set name at anvil=

View File

@ -1,8 +0,0 @@
if minetest.get_modpath("lucky_block") then
lucky_block:add_blocks({
{"dro", {"mcl_mobs:nametag"}, 1},
{"lig"},
})
end

View File

@ -1,5 +0,0 @@
name = mcl_mobs
author = PilzAdam
description = Adds a mob API for mods to add animals or monsters, etc.
depends = mcl_particles
optional_depends = mcl_weather, mcl_explosions, mcl_hunger, mcl_worlds, invisibility, lucky_block, cmi, doc_identifier, mcl_armor, mcl_portals, mcl_experience

View File

@ -1,448 +0,0 @@
-- lib_mount by Blert2112 (edited by TenPlus1)
local enable_crash = false
local crash_threshold = 6.5 -- ignored if enable_crash=false
------------------------------------------------------------------------------
--
-- Helper functions
--
local node_ok = function(pos, fallback)
fallback = fallback or mcl_mobs.fallback_node
local node = minetest.get_node_or_nil(pos)
if node and minetest.registered_nodes[node.name] then
return node
end
return {name = fallback}
end
local function node_is(pos)
local node = node_ok(pos)
if node.name == "air" then
return "air"
end
if minetest.get_item_group(node.name, "lava") ~= 0 then
return "lava"
end
if minetest.get_item_group(node.name, "liquid") ~= 0 then
return "liquid"
end
if minetest.registered_nodes[node.name].walkable == true then
return "walkable"
end
return "other"
end
local function get_sign(i)
i = i or 0
if i == 0 then
return 0
else
return i / math.abs(i)
end
end
local function get_velocity(v, yaw, y)
local x = -math.sin(yaw) * v
local z = math.cos(yaw) * v
return {x = x, y = y, z = z}
end
local function get_v(v)
return math.sqrt(v.x * v.x + v.z * v.z)
end
local function force_detach(player)
local attached_to = player:get_attach()
if not attached_to then
return
end
local entity = attached_to:get_luaentity()
if entity.driver
and entity.driver == player then
entity.driver = nil
end
player:set_detach()
mcl_player.player_attached[player:get_player_name()] = false
player:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
mcl_player.player_set_animation(player, "stand" , 30)
player:set_properties({visual_size = {x = 1, y = 1} })
end
-------------------------------------------------------------------------------
minetest.register_on_leaveplayer(function(player)
force_detach(player)
end)
minetest.register_on_shutdown(function()
local players = minetest.get_connected_players()
for i = 1, #players do
force_detach(players[i])
end
end)
minetest.register_on_dieplayer(function(player)
force_detach(player)
return true
end)
-------------------------------------------------------------------------------
function mcl_mobs.attach(entity, player)
local attach_at, eye_offset
entity.player_rotation = entity.player_rotation or {x = 0, y = 0, z = 0}
entity.driver_attach_at = entity.driver_attach_at or {x = 0, y = 0, z = 0}
entity.driver_eye_offset = entity.driver_eye_offset or {x = 0, y = 0, z = 0}
entity.driver_scale = entity.driver_scale or {x = 1, y = 1}
local rot_view = 0
if entity.player_rotation.y == 90 then
rot_view = math.pi/2
end
attach_at = entity.driver_attach_at
eye_offset = entity.driver_eye_offset
entity.driver = player
force_detach(player)
player:set_attach(entity.object, "", attach_at, entity.player_rotation)
mcl_player.player_attached[player:get_player_name()] = true
player:set_eye_offset(eye_offset, {x = 0, y = 0, z = 0})
player:set_properties({
visual_size = {
x = entity.driver_scale.x,
y = entity.driver_scale.y
}
})
minetest.after(0.2, function(name)
local player = minetest.get_player_by_name(name)
if player then
mcl_player.player_set_animation(player, "sit_mount" , 30)
end
end, player:get_player_name())
player:set_look_horizontal(entity.object:get_yaw() - rot_view)
end
function mcl_mobs.detach(player, offset)
force_detach(player)
mcl_player.player_set_animation(player, "stand" , 30)
--local pos = player:get_pos()
--pos = {x = pos.x + offset.x, y = pos.y + 0.2 + offset.y, z = pos.z + offset.z}
player:add_velocity(vector.new(math.random(-6,6),math.random(5,8),math.random(-6,6))) --throw the rider off
--[[
minetest.after(0.1, function(name, pos)
local player = minetest.get_player_by_name(name)
if player then
player:set_pos(pos)
end
end, player:get_player_name(), pos)
]]--
end
function mcl_mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
local rot_view = 0
if entity.player_rotation.y == 90 then
rot_view = math.pi/2
end
local acce_y = 0
local velo = entity.object:get_velocity()
entity.v = get_v(velo) * get_sign(entity.v)
-- process controls
if entity.driver then
local ctrl = entity.driver:get_player_control()
-- move forwards
if ctrl.up then
entity.v = entity.v + entity.accel / 10
-- move backwards
elseif ctrl.down then
if entity.max_speed_reverse == 0 and entity.v == 0 then
return
end
entity.v = entity.v - entity.accel / 10
end
-- fix mob rotation
entity.object:set_yaw(entity.driver:get_look_horizontal() - entity.rotate)
if can_fly then
-- fly up
if ctrl.jump then
velo.y = velo.y + 1
if velo.y > entity.accel then velo.y = entity.accel end
elseif velo.y > 0 then
velo.y = velo.y - 0.1
if velo.y < 0 then velo.y = 0 end
end
-- fly down
if ctrl.sneak then
velo.y = velo.y - 1
if velo.y < -entity.accel then velo.y = -entity.accel end
elseif velo.y < 0 then
velo.y = velo.y + 0.1
if velo.y > 0 then velo.y = 0 end
end
else
-- jump
if ctrl.jump then
if velo.y == 0 then
velo.y = velo.y + entity.jump_height
acce_y = acce_y + (acce_y * 3) + 1
end
end
end
end
-- if not moving then set animation and return
if entity.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then
if stand_anim then
mcl_mobs:set_animation(entity, stand_anim)
end
return
end
-- set moving animation
if moving_anim then
mcl_mobs:set_animation(entity, moving_anim)
end
-- Stop!
local s = get_sign(entity.v)
entity.v = entity.v - 0.02 * s
if s ~= get_sign(entity.v) then
entity.object:set_velocity({x = 0, y = 0, z = 0})
entity.v = 0
return
end
-- enforce speed limit forward and reverse
local max_spd = entity.max_speed_reverse
if get_sign(entity.v) >= 0 then
max_spd = entity.max_speed_forward
end
if math.abs(entity.v) > max_spd then
entity.v = entity.v - get_sign(entity.v)
end
-- Set position, velocity and acceleration
local p = entity.object:get_pos()
local new_velo
local new_acce = {x = 0, y = -9.8, z = 0}
p.y = p.y - 0.5
local ni = node_is(p)
local v = entity.v
if ni == "air" then
if can_fly == true then
new_acce.y = 0
end
elseif ni == "liquid" or ni == "lava" then
if ni == "lava" and entity.lava_damage ~= 0 then
entity.lava_counter = (entity.lava_counter or 0) + dtime
if entity.lava_counter > 1 then
minetest.sound_play("default_punch", {
object = entity.object,
max_hear_distance = 5
}, true)
entity.object:punch(entity.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = entity.lava_damage}
}, nil)
entity.lava_counter = 0
end
end
if entity.terrain_type == 2
or entity.terrain_type == 3 then
new_acce.y = 0
p.y = p.y + 1
if node_is(p) == "liquid" then
if velo.y >= 5 then
velo.y = 5
elseif velo.y < 0 then
new_acce.y = 20
else
new_acce.y = 5
end
else
if math.abs(velo.y) < 1 then
local pos = entity.object:get_pos()
pos.y = math.floor(pos.y) + 0.5
entity.object:set_pos(pos)
velo.y = 0
end
end
else
v = v * 0.25
end
end
new_velo = get_velocity(v, entity.object:get_yaw() - rot_view, velo.y)
new_acce.y = new_acce.y + acce_y
entity.object:set_velocity(new_velo)
entity.object:set_acceleration(new_acce)
-- CRASH!
if enable_crash then
local intensity = entity.v2 - v
if intensity >= crash_threshold then
entity.object:punch(entity.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = intensity}
}, nil)
end
end
entity.v2 = v
end
-- directional flying routine by D00Med (edited by TenPlus1)
function mcl_mobs.fly(entity, dtime, speed, shoots, arrow, moving_anim, stand_anim)
local ctrl = entity.driver:get_player_control()
local velo = entity.object:get_velocity()
local dir = entity.driver:get_look_dir()
local yaw = entity.driver:get_look_horizontal() + 1.57 -- offset fix between old and new commands
if ctrl.up then
entity.object:set_velocity({
x = dir.x * speed,
y = dir.y * speed + 2,
z = dir.z * speed
})
elseif ctrl.down then
entity.object:set_velocity({
x = -dir.x * speed,
y = dir.y * speed + 2,
z = -dir.z * speed
})
elseif not ctrl.down or ctrl.up or ctrl.jump then
entity.object:set_velocity({x = 0, y = -2, z = 0})
end
entity.object:set_yaw(yaw + math.pi + math.pi / 2 - entity.rotate)
-- firing arrows
if ctrl.LMB and ctrl.sneak and shoots then
local pos = entity.object:get_pos()
local obj = minetest.add_entity({
x = pos.x + 0 + dir.x * 2.5,
y = pos.y + 1.5 + dir.y,
z = pos.z + 0 + dir.z * 2.5}, arrow)
local ent = obj:get_luaentity()
if ent then
ent.switch = 1 -- for mob specific arrows
ent.owner_id = tostring(entity.object) -- so arrows dont hurt entity you are riding
local vec = {x = dir.x * 6, y = dir.y * 6, z = dir.z * 6}
local yaw = entity.driver:get_look_horizontal()
obj:set_yaw(yaw + math.pi / 2)
obj:set_velocity(vec)
else
obj:remove()
end
end
-- change animation if stopped
if velo.x == 0 and velo.y == 0 and velo.z == 0 then
mcl_mobs:set_animation(entity, stand_anim)
else
-- moving animation
mcl_mobs:set_animation(entity, moving_anim)
end
end

View File

@ -1,74 +0,0 @@
Mobs Redo: MineClone 2 Edition
Based on Mobs Redo from TenPlus1
Built from PilzAdam's original Simple Mobs with additional mobs by KrupnoPavel, Zeg9, ExeterDad and AspireMint.
This mod contains the API only for adding your own mobs into the world, so please use the additional modpacks to add animals, monsters etc.
https://forum.minetest.net/viewtopic.php?f=11&t=9917
------------
Credits:
mcl_mobs_mob_poof.ogg:
- by Planman (license: Creative Commons Zero)
- Source: <https://freesound.org/people/Planman/sounds/208111/>
------------
Changelog from original Mobs Redo mod:
- 1.41- Mob pathfinding has been updated thanks to Elkien3
- 1.40- Updated to use newer functions, requires Minetest 0.4.16+ to work.
- 1.39- Added 'on_breed', 'on_grown' and 'do_punch' custom functions per mob
- 1.38- Better entity checking, nametag setting and on_spawn function added to mob registry, tweaked light damage
- 1.37- Added support for Raymoo's CMI (common mob interface) mod: https://forum.minetest.net/viewtopic.php?f=9&t=15448
- 1.36- Death check added, if mob dies in fire/lava/with lava pick then drops are cooked
- 1.35- Added owner_loyal flag for owned mobs to attack player enemies, also fixed group_attack
- 1.34- Added function to fly mob using directional movement (thanks D00Med for flying code)
- 1.33- Added functions to mount ride mobs (mobs.attach, mobs.detach, mobs.drive) many thanks to Blert2112
- 1.32- Added new spawn check to count specific mobs AND new minetest.conf setting to chance spawn chance and numbers, added ability to protect tamed mobs
- 1.31- Added 'attack_animals' and 'specific_attack' flags for custom monster attacks, also 'mob_difficulty' .conf setting to make mobs harder.
- 1.30- Added support for invisibility mod (mobs cant attack what they cant see), tweaked and tidied code
- 1.29- Split original Mobs Redo into a modpack to make it easier to disable mob sets (animal, monster, npc) or simply use the Api itself for your own mod
- 1.28- New damage system added with ability for mob to be immune to weapons or healed by them :)
- 1.27- Added new sheep, lava flan and spawn egg textures. New Lava Pick tool smelts what you dig. New atan checking function.
- 1.26- Pathfinding feature added thanks to rnd, when monsters attack they become scary smart in finding you :) also, beehive produces honey now :)
- 1.25- Mobs no longer spawn within 12 blocks of player or despawn within same range, spawners now have player detection, Code tidy and tweak.
- 1.24- Added feature where certain animals run away when punched (runaway = true in mob definition)
- 1.23- Added mob spawner block for admin to setup spawners in-game (place and right click to enter settings)
- 1.22- Added ability to name tamed animals and npc using nametags, also npc will attack anyone who punches them apart from owner
- 1.21- Added some more error checking to reduce serialize.h error and added height checks for falling off cliffs (thanks cmdskp)
- 1.20- Error checking added to remove bad mobs, out of map limit mobs and stop serialize.h error
- 1.19- Chickens now drop egg items instead of placing the egg, also throwing eggs result in 1/8 chance of spawning chick
- 1.18- Added docile_by_day flag so that monsters will not attack automatically during daylight hours unless hit first
- 1.17- Added 'dogshoot' attack type, shoots when out of reach, melee attack when in reach, also api tweaks and self.reach added
- 1.16- Mobs follow multiple items now, Npc's can breed
- 1.15- Added Feeding/Taming/Breeding function, right-click to pick up any sheep with X mark on them and replace with new one to fix compatibility.
- 1.14- All .self variables saved in staticdata, Fixed self.health bug
- 1.13- Added capture function (thanks blert2112) chance of picking up mob with hand; net; magic lasso, replaced some .x models with newer .b3d one's
- 1.12- Added animal ownership so that players cannot steal your tamed animals
- 1.11- Added flying mobs (and swimming), fly=true and fly_in="air" or "deafult:water_source" for fishy
- 1,10- Footstep removed (use replace), explosion routine added for exploding mobs.
- 1.09- reworked breeding routine, added mob rotation value, added footstep feature, added jumping mobs with sounds feature, added magic lasso for picking up animals
- 1.08- Mob throwing attack has been rehauled so that they can damage one another, also drops and on_die function added
- 1.07- Npc's can now be set to follow player or stand by using self.order and self.owner variables
- beta- Npc mob added, kills monsters, attacks player when punched, right click with food to heal or gold lump for drop
- 1.06- Changed recovery times after breeding, and time taken to grow up (can be sped up by feeding baby animal)
- 1.05- Added ExeterDad's bunny's which can be picked up and tamed with 4 carrots from farming redo or farming_plus, also shears added to get wool from sheep and lastly Jordach/BSD's kitten
- 1.04- Added mating for sheep, cows and hogs... feed animals to make horny and hope for a baby which is half size, will grow up quick though :)
- 1.03- Added mob drop/replace feature so that chickens can drop eggs, cow/sheep can eat grass/wheat etc.
- 1.02- Sheared sheep are remembered and spawn shaven, Warthogs will attack when threatened, Api additions
- 1.01- Mobs that suffer fall damage or die in water/lava/sunlight will now drop items
- 1.0 - more work on Api so that certain mobs can float in water while some sink like a brick :)
- 0.9 - Spawn eggs added for all mobs (admin only, cannot be placed in protected areas)... Api tweaked
- 0.8 - Added sounds to monster mobs (thanks Cyberpangolin for the sfx) and also chicken sound
- 0.7 - mobs.protected switch added to api.lua, when set to 1 mobs no longer spawn in protected areas, also bug fixes
- 0.6 - Api now supports multi-textured mobs, e.g oerkki, dungeon master, rats and chickens have random skins when spawning (sheep fix TODO), also new Honey block
- 0.5 - Mobs now float in water, die from falling, and some code improvements
- 0.4 - Dungeon Masters and Mese Monsters have much better aim due to shoot_offset, also they can both shoot through nodes that aren't walkable (flowers, grass etc) plus new sheep sound :)
- 0.3 - Added LOTT's Spider mob, made Cobwebs, added KPavel's Bee with Honey and Beehives (made texture), Warthogs now have sound and can be tamed, taming of shaved sheep or milked cow with 8 wheat so it will not despawn, many bug fixes :)
- 0.2 - Cooking bucket of milk into cheese now returns empty bucket
- 0.1 - Initial Release

View File

@ -1,484 +0,0 @@
--lua locals
local get_node = minetest.get_node
local get_item_group = minetest.get_item_group
local get_node_light = minetest.get_node_light
local find_nodes_in_area_under_air = minetest.find_nodes_in_area_under_air
local get_biome_name = minetest.get_biome_name
local get_objects_inside_radius = minetest.get_objects_inside_radius
local get_connected_players = minetest.get_connected_players
local minetest_get_perlin = minetest.get_perlin
local math_random = math.random
local math_floor = math.floor
local math_ceil = math.ceil
local math_cos = math.cos
local math_sin = math.sin
local math_round = function(x) return (x > 0) and math_floor(x + 0.5) or math_ceil(x - 0.5) end
--local vector_distance = vector.distance
local vector_new = vector.new
local vector_floor = vector.floor
local table_copy = table.copy
local table_remove = table.remove
local pairs = pairs
-- range for mob count
local aoc_range = 32
--do mobs spawn?
local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false
local noise_params = {
offset = 0,
scale = 3,
spread = {
x = 301,
y = 50,
z = 304,
},
seed = 100,
octaves = 3,
persistence = 0.5,
}
-- THIS IS THE BIG LIST OF ALL BIOMES - used for programming/updating mobs
-- Also used for missing parameter
-- Please update the list when adding new biomes!
local list_of_all_biomes = {
-- underground:
"FlowerForest_underground",
"JungleEdge_underground",
"ColdTaiga_underground",
"IcePlains_underground",
"IcePlainsSpikes_underground",
"MegaTaiga_underground",
"Taiga_underground",
"ExtremeHills+_underground",
"JungleM_underground",
"ExtremeHillsM_underground",
"JungleEdgeM_underground",
-- ocean:
"RoofedForest_ocean",
"JungleEdgeM_ocean",
"BirchForestM_ocean",
"BirchForest_ocean",
"IcePlains_deep_ocean",
"Jungle_deep_ocean",
"Savanna_ocean",
"MesaPlateauF_ocean",
"ExtremeHillsM_deep_ocean",
"Savanna_deep_ocean",
"SunflowerPlains_ocean",
"Swampland_deep_ocean",
"Swampland_ocean",
"MegaSpruceTaiga_deep_ocean",
"ExtremeHillsM_ocean",
"JungleEdgeM_deep_ocean",
"SunflowerPlains_deep_ocean",
"BirchForest_deep_ocean",
"IcePlainsSpikes_ocean",
"Mesa_ocean",
"StoneBeach_ocean",
"Plains_deep_ocean",
"JungleEdge_deep_ocean",
"SavannaM_deep_ocean",
"Desert_deep_ocean",
"Mesa_deep_ocean",
"ColdTaiga_deep_ocean",
"Plains_ocean",
"MesaPlateauFM_ocean",
"Forest_deep_ocean",
"JungleM_deep_ocean",
"FlowerForest_deep_ocean",
"MushroomIsland_ocean",
"MegaTaiga_ocean",
"StoneBeach_deep_ocean",
"IcePlainsSpikes_deep_ocean",
"ColdTaiga_ocean",
"SavannaM_ocean",
"MesaPlateauF_deep_ocean",
"MesaBryce_deep_ocean",
"ExtremeHills+_deep_ocean",
"ExtremeHills_ocean",
"MushroomIsland_deep_ocean",
"Forest_ocean",
"MegaTaiga_deep_ocean",
"JungleEdge_ocean",
"MesaBryce_ocean",
"MegaSpruceTaiga_ocean",
"ExtremeHills+_ocean",
"Jungle_ocean",
"RoofedForest_deep_ocean",
"IcePlains_ocean",
"FlowerForest_ocean",
"ExtremeHills_deep_ocean",
"MesaPlateauFM_deep_ocean",
"Desert_ocean",
"Taiga_ocean",
"BirchForestM_deep_ocean",
"Taiga_deep_ocean",
"JungleM_ocean",
-- water or beach?
"MesaPlateauFM_sandlevel",
"MesaPlateauF_sandlevel",
"MesaBryce_sandlevel",
"Mesa_sandlevel",
-- beach:
"FlowerForest_beach",
"Forest_beach",
"StoneBeach",
"ColdTaiga_beach_water",
"Taiga_beach",
"Savanna_beach",
"Plains_beach",
"ExtremeHills_beach",
"ColdTaiga_beach",
"Swampland_shore",
"MushroomIslandShore",
"JungleM_shore",
"Jungle_shore",
-- dimension biome:
"Nether",
"End",
-- Overworld regular:
"Mesa",
"FlowerForest",
"Swampland",
"Taiga",
"ExtremeHills",
"Jungle",
"Savanna",
"BirchForest",
"MegaSpruceTaiga",
"MegaTaiga",
"ExtremeHills+",
"Forest",
"Plains",
"Desert",
"ColdTaiga",
"MushroomIsland",
"IcePlainsSpikes",
"SunflowerPlains",
"IcePlains",
"RoofedForest",
"ExtremeHills+_snowtop",
"MesaPlateauFM_grasstop",
"JungleEdgeM",
"ExtremeHillsM",
"JungleM",
"BirchForestM",
"MesaPlateauF",
"MesaPlateauFM",
"MesaPlateauF_grasstop",
"MesaBryce",
"JungleEdge",
"SavannaM",
}
-- count how many mobs are in an area
local function count_mobs(pos)
local num = 0
for _,object in pairs(get_objects_inside_radius(pos, aoc_range)) do
if object and object:get_luaentity() and object:get_luaentity().is_mob then
num = num + 1
end
end
return num
end
-- global functions
function mcl_mobs:spawn_abm_check(pos, node, name)
-- global function to add additional spawn checks
-- return true to stop spawning mob
end
--[[
Custom elements changed:
name:
the mobs name
dimension:
"overworld"
"nether"
"end"
types of spawning:
"water"
"ground"
"lava"
biomes: tells the spawner to allow certain mobs to spawn in certain biomes
{"this", "that", "grasslands", "whatever"}
what is aoc??? objects in area
WARNING: BIOME INTEGRATION NEEDED -> How to get biome through lua??
]]--
--this is where all of the spawning information is kept
local spawn_dictionary = {}
local summary_chance = 0
function mcl_mobs:spawn_setup(def)
if not mobs_spawn then return end
if not def then
minetest.log("warning", "Empty mob spawn setup definition")
return
end
local name = def.name
if not name then
minetest.log("warning", "Missing mob name")
return
end
local dimension = def.dimension or "overworld"
local type_of_spawning = def.type_of_spawning or "ground"
local biomes = def.biomes or list_of_all_biomes
local min_light = def.min_light or 0
local max_light = def.max_light or (minetest.LIGHT_MAX + 1)
local chance = def.chance or 1000
local aoc = def.aoc or aoc_range
local min_height = def.min_height or mcl_mapgen.overworld.min
local max_height = def.max_height or mcl_mapgen.overworld.max
local day_toggle = def.day_toggle
local on_spawn = def.on_spawn
local check_position = def.check_position
-- chance/spawn number override in minetest.conf for registered mob
local numbers = minetest.settings:get(name)
if numbers then
numbers = numbers:split(",")
chance = tonumber(numbers[1]) or chance
aoc = tonumber(numbers[2]) or aoc
if chance == 0 then
minetest.log("warning", string.format("[mcl_mobs] %s has spawning disabled", name))
return
end
minetest.log("action", string.format("[mcl_mobs] Chance setting for %s changed to %s (total: %s)", name, chance, aoc))
end
if chance < 1 then
chance = 1
minetest.log("warning", "Chance shouldn't be less than 1 (mob name: " .. name ..")")
end
spawn_dictionary[#spawn_dictionary + 1] = {
name = name,
dimension = dimension,
type_of_spawning = type_of_spawning,
biomes = biomes,
min_light = min_light,
max_light = max_light,
chance = chance,
aoc = aoc,
min_height = min_height,
max_height = max_height,
day_toggle = day_toggle,
check_position = check_position,
on_spawn = on_spawn,
}
summary_chance = summary_chance + chance
end
function mcl_mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_light, max_light, interval, chance, aoc, min_height, max_height, day_toggle, on_spawn)
-- Do mobs spawn at all?
if not mobs_spawn then
return
end
-- chance/spawn number override in minetest.conf for registered mob
local numbers = minetest.settings:get(name)
if numbers then
numbers = numbers:split(",")
chance = tonumber(numbers[1]) or chance
aoc = tonumber(numbers[2]) or aoc
if chance == 0 then
minetest.log("warning", string.format("[mcl_mobs] %s has spawning disabled", name))
return
end
minetest.log("action", string.format("[mcl_mobs] Chance setting for %s changed to %s (total: %s)", name, chance, aoc))
end
--load information into the spawn dictionary
local key = #spawn_dictionary + 1
spawn_dictionary[key] = {}
spawn_dictionary[key]["name"] = name
spawn_dictionary[key]["dimension"] = dimension
spawn_dictionary[key]["type_of_spawning"] = type_of_spawning
spawn_dictionary[key]["biomes"] = biomes
spawn_dictionary[key]["min_light"] = min_light
spawn_dictionary[key]["max_light"] = max_light
spawn_dictionary[key]["chance"] = chance
spawn_dictionary[key]["aoc"] = aoc
spawn_dictionary[key]["min_height"] = min_height
spawn_dictionary[key]["max_height"] = max_height
spawn_dictionary[key]["day_toggle"] = day_toggle
summary_chance = summary_chance + chance
end
local two_pi = 2 * math.pi
local function get_next_mob_spawn_pos(pos)
local distance = math_random(25, 32)
local angle = math_random() * two_pi
return {
x = math_round(pos.x + distance * math_cos(angle)),
y = pos.y,
z = math_round(pos.z + distance * math_sin(angle))
}
end
local function decypher_limits(posy)
posy = math_floor(posy)
return posy - 32, posy + 32
end
--a simple helper function for mob_spawn
local function biome_check(biome_list, biome_goal)
for _, data in pairs(biome_list) do
if data == biome_goal then
return true
end
end
return false
end
local function is_farm_animal(n)
return n == "mobs_mc:pig" or n == "mobs_mc:cow" or n == "mobs_mc:sheep" or n == "mobs_mc:chicken" or n == "mobs_mc:horse" or n == "mobs_mc:donkey"
end
if mobs_spawn then
local perlin_noise
local function spawn_a_mob(pos, dimension, y_min, y_max)
local dimension = dimension or mcl_worlds.pos_to_dimension(pos)
local goal_pos = get_next_mob_spawn_pos(pos)
local spawning_position_list = find_nodes_in_area_under_air(
{x = goal_pos.x, y = y_min, z = goal_pos.z},
{x = goal_pos.x, y = y_max, z = goal_pos.z},
{"group:solid", "group:water", "group:lava"}
)
if #spawning_position_list <= 0 then return end
local spawning_position = spawning_position_list[math_random(1, #spawning_position_list)]
--hard code mob limit in area to 5 for now
if count_mobs(spawning_position) >= 5 then return end
local gotten_node = get_node(spawning_position).name
local gotten_biome = minetest.get_biome_data(spawning_position)
if not gotten_node or not gotten_biome then return end
gotten_biome = get_biome_name(gotten_biome.biome) --makes it easier to work with
--add this so mobs don't spawn inside nodes
spawning_position.y = spawning_position.y + 1
--only need to poll for node light if everything else worked
local gotten_light = get_node_light(spawning_position)
local is_water = get_item_group(gotten_node, "water") ~= 0
local is_lava = get_item_group(gotten_node, "lava") ~= 0
local is_ground = not (is_water or is_lava)
local is_grass = minetest.get_item_group(gotten_node,"grass_block") ~= 0
local has_bed = minetest.find_node_near(pos,25,{"group:bed"})
if not is_ground then
spawning_position.y = spawning_position.y - 1
end
local mob_def
--create a disconnected clone of the spawn dictionary
--prevents memory leak
local mob_library_worker_table = table_copy(spawn_dictionary)
--grab mob that fits into the spawning location
--randomly grab a mob, don't exclude any possibilities
perlin_noise = perlin_noise or minetest_get_perlin(noise_params)
local noise = perlin_noise:get_3d(spawning_position)
local current_summary_chance = summary_chance
while #mob_library_worker_table > 0 do
local mob_chance_offset = (math_round(noise * current_summary_chance + 12345) % current_summary_chance) + 1
local mob_index = 1
local mob_chance = mob_library_worker_table[mob_index].chance
local step_chance = mob_chance
while step_chance < mob_chance_offset do
mob_index = mob_index + 1
mob_chance = mob_library_worker_table[mob_index].chance
step_chance = step_chance + mob_chance
end
local mob_def = mob_library_worker_table[mob_index]
local mob_type = minetest.registered_entities[mob_def.name].type
if mob_def
and spawning_position.y >= mob_def.min_height
and spawning_position.y <= mob_def.max_height
and mob_def.dimension == dimension
and biome_check(mob_def.biomes, gotten_biome)
and gotten_light >= mob_def.min_light
and gotten_light <= mob_def.max_light
and (is_ground or mob_def.type_of_spawning ~= "ground")
and (mob_def.check_position and mob_def.check_position(spawning_position) or true)
and (not is_farm_animal(mob_def.name) or is_grass)
and (mob_type ~= "npc" or has_bed)
then
--everything is correct, spawn mob
local object = minetest.add_entity(spawning_position, mob_def.name)
if object then
return mob_def.on_spawn and mob_def.on_spawn(object, pos)
end
end
current_summary_chance = current_summary_chance - mob_chance
table_remove(mob_library_worker_table, mob_index)
end
end
--MAIN LOOP
local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime
if timer < 10 then return end
timer = 0
for _, player in pairs(get_connected_players()) do
local pos = player:get_pos()
local dimension = mcl_worlds.pos_to_dimension(pos)
-- ignore void and unloaded area
if dimension ~= "void" and dimension ~= "default" then
local y_min, y_max = decypher_limits(pos.y)
for i = 1, math_random(1, 4) do
spawn_a_mob(pos, dimension, y_min, y_max)
end
end
end
end)
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 895 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 B

View File

@ -1,51 +0,0 @@
local dim = {"x", "z"}
local modpath = minetest.get_modpath(minetest.get_current_modname())
local function load_schem(filename)
local file = io.open(modpath .. "/schems/" .. filename, "r")
local data = minetest.deserialize(file:read())
file:close()
return data
end
local wither_spawn_schems = {}
for _, d in pairs(dim) do
wither_spawn_schems[d] = load_schem("wither_spawn_" .. d .. ".we")
end
local function check_schem(pos, schem)
for _, n in pairs(schem) do
if minetest.get_node(vector.add(pos, n)).name ~= n.name then
return false
end
end
return true
end
local function remove_schem(pos, schem)
for _, n in pairs(schem) do
minetest.remove_node(vector.add(pos, n))
end
end
local function wither_spawn(pos)
for _, d in pairs(dim) do
for i = 0, 2 do
local p = vector.add(pos, {x = 0, y = -2, z = 0, [d] = -i})
local schem = wither_spawn_schems[d]
if check_schem(p, schem) then
remove_schem(p, schem)
minetest.add_entity(vector.add(p, {x = 0, y = 1, z = 0, [d] = 1}), "mobs_mc:wither")
end
end
end
end
local wither_head = minetest.registered_nodes["mcl_heads:wither_skeleton"]
local old_on_place = wither_head.on_place
function wither_head.on_place(itemstack, placer, pointed)
minetest.after(0, wither_spawn, pointed.above)
old_on_place(itemstack, placer, pointed)
end

View File

@ -1,4 +0,0 @@
name = mcl_wither_spawning
description = Wither Spawning for MineClone2
author = Fleckenstein
depends = mobs_mc, mcl_heads

View File

@ -1 +0,0 @@
return {{["y"] = 1, ["x"] = 0, ["name"] = "mcl_nether:soul_sand", ["z"] = 0}, {["y"] = 2, ["x"] = 0, ["name"] = "mcl_heads:wither_skeleton", ["z"] = 0, ["param2"] = 2, ["param1"] = 15}, {["y"] = 0, ["x"] = 1, ["name"] = "mcl_nether:soul_sand", ["z"] = 0}, {["y"] = 1, ["x"] = 1, ["name"] = "mcl_nether:soul_sand", ["z"] = 0}, {["y"] = 2, ["x"] = 1, ["name"] = "mcl_heads:wither_skeleton", ["z"] = 0, ["param2"] = 2, ["param1"] = 15}, {["y"] = 1, ["x"] = 2, ["name"] = "mcl_nether:soul_sand", ["z"] = 0}, {["y"] = 2, ["x"] = 2, ["name"] = "mcl_heads:wither_skeleton", ["z"] = 0, ["param2"] = 2, ["param1"] = 15}}

View File

@ -1 +0,0 @@
return {{["y"] = 0, ["x"] = 0, ["name"] = "mcl_nether:soul_sand", ["z"] = 1}, {["y"] = 1, ["x"] = 0, ["name"] = "mcl_nether:soul_sand", ["z"] = 0}, {["y"] = 1, ["x"] = 0, ["name"] = "mcl_nether:soul_sand", ["z"] = 1}, {["y"] = 1, ["x"] = 0, ["name"] = "mcl_nether:soul_sand", ["z"] = 2}, {["y"] = 2, ["x"] = 0, ["name"] = "mcl_heads:wither_skeleton", ["z"] = 0, ["param2"] = 1, ["param1"] = 15}, {["y"] = 2, ["x"] = 0, ["name"] = "mcl_heads:wither_skeleton", ["z"] = 1, ["param2"] = 1, ["param1"] = 15}, {["y"] = 2, ["x"] = 0, ["name"] = "mcl_heads:wither_skeleton", ["z"] = 2, ["param2"] = 1, ["param1"] = 15}}

View File

@ -1,674 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{one line to give the program's name and a brief idea of what it does.}
Copyright (C) {year} {name of author}
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
{project} Copyright (C) {year} {fullname}
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

View File

@ -1,310 +0,0 @@
# Credits licensing for media files in `mobs_mc`
## Licenses used
The following media licenses are used:
* [CC0](https://creativecommons.org/choose/zero/)
* [CC BY 3.0](https://creativecommons.org/licenses/by/3.0/)
* [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)
* [GPL v3](https://www.gnu.org/licenses/gpl-3.0.html])
* [MIT License](https://opensource.org/licenses/MIT)
* [LGPL v2.1](https://www.gnu.org/licenses/lgpl-2.1.html)
Note: A “`*`” in a file name below is a placeholder which can stand for any text.
## Models
All models were done by [22i](https://github.com/22i) and are licensed under GPLv3.
Origin of those models:
* [Mod “amc”](https://github.com/22i/amc/)
* [Repository with Blender source files for models](https://github.com/22i/minecraft-voxel-blender-models)
## Textures
* Mob and item textures are heavily based on [Pixel Perfection](https://www.planetminecraft.com/texture_pack/131pixel-perfection/), a texture pack for Minecraft.
* Original author: [XSSheep](https://www.planetminecraft.com/member/xssheep/)
* License (if not mentioned otherwise): CC BY-SA 4.0
* Some textures have been modified or added
* Modifications and additions by MysticTempest:
* `mobs_mc_cave_spider.png`
* `mobs_mc_enderman_eyes.png`
* `mobs_mc_enderman.png`
* `mobs_mc_ghast.png`
* `mobs_mc_skeleton.png`
* `mobs_mc_slime.png`
* `mobs_mc_spider_eyes.png`
* `mobs_mc_spider.png`
* `mobs_mc_squid.png`
* `mobs_mc_zombie.png`
* `mobs_mc_villager_butcher.png`
* `mobs_mc_villager_farmer.png`
* `mobs_mc_villager_librarian.png`
* `mobs_mc_villager.png`
* `mobs_mc_villager_priest.png`
* `mobs_mc_villager_smith.png`
* `mobs_mc_parrot_blue.png`
* `mobs_mc_parrot_green.png`
* `mobs_mc_parrot_grey.png`
* `mobs_mc_parrot_red_blue.png`
* `mobs_mc_parrot_yellow_blue.png`
* `mobs_mc_evoker_base.png` (modified by kingoscargames)
* `mobs_mc_illusionist_bow.png`
* `mobs_mc_illusionist.png`
* `mobs_mc_vindicator_axe.png`
* `mobs_mc_vindicator_base.png`
* `mobs_mc_horse_skeleton.png`
* Additions by kingoscargames:
* `mobs_mc_vex.png`
* `mobs_mc_vex_charging.png`
* `mobs_mc_llama.png`
* `mobs_mc_llama_creamy.png`
* `mobs_mc_llama_brown.png`
* `mobs_mc_llama_white.png`
* `mobs_mc_llama_gray.png`
* `mobs_mc_llama_chest.png`
* `mobs_mc_endermite.png`
* `mobs_mc_magmacube.png`
* `mobs_mc_chicken.png`
* `mobs_mc_wither.png`
* `mobs_mc_wither_skeleton.png`
* `mobs_mc_TEMP_wither_projectile.png`
* Gerold55
* `mobs_mc_mooshroom_brown.png` (CC0)
* `mobs_mc_mushroom_brown.png` (CC0)
* “Spawn egg” textures (`mobs_mc_spawn_icon_*`) by 22i
* Llama decor (carpet) textures (`mobs_mc_llama_decor_*`) by erlehmann and rudzik8
* Any other texture not mentioned here are licensed under the MIT License
## Sounds
* PilzAdam and Wuzzy (CC0)
* `mobs_mc_chicken_lay_egg.ogg`
* [AGFX](http://www.freesound.org/people/DrMinky/sounds/) (CC0)
* `mobs_mc_chicken_child.ogg`
* Source: <https://freesound.org/people/AGFX/sounds/43380/>
* [evsecrets](https://freesound.org/people/evsecrets/sounds/) (CC0)
* `mobs_mc_chicken_*.ogg`
* Source: <https://freesound.org/people/evsecrets/sounds/346961/>
* [contramundum](https://freesound.org/people/contramundum/sounds/)
* `mobs_mc_parrot_*.ogg`
* Source: <https://freesound.org/people/contramundum/sounds/388417/>
* Randomation (CC0)
* `green_slime_damage.ogg`
* `green_slime_attack.ogg`
* Source: <http://www.freesound.org/people/RandomationPictures/sounds/138481/>
* [Dr. Minky](http://www.freesound.org/people/DrMinky/sounds/) (CC BY 3.0)
* `green_slime_jump.ogg`
* `green_slime_land.ogg`
* `green_slime_death.ogg`
* Zozzy from Freesound.org (CC0)
* `mobs_mc_cow.ogg`
* Source: <https://www.freesound.org/people/Zozzy/sounds/59245/>
* [Bird\_man](https://freesound.org/people/Bird_man/packs/16972/)
* `mobs_mc_cow_hurt.ogg` (CC0)
* Heavily modified
* Source: <https://freesound.org/people/Bird_man/packs/16972/>
* [Klaraschick](https://freesound.org/people/Klaraschick/)
* `mobs_mc_cow_milk.ogg` (CC0)
* shortened
* Source: <https://freesound.org/people/Klaraschick/sounds/415312/>
* [Hitrison](https://freesound.org/people/Hitrison/)
* `mobs_mc_cow_mushroom_stew.ogg` (CC BY 3.0)
* sound was modified
* Source: <https://freesound.org/people/Hitrison/sounds/251411/>
* [NPXcoot](https://github.com/NPXcoot1) (CC BY-SA 4.0)
* `mobs_mc_ender_dragon_*`
* [bevibeldesign](https://freesound.org/people/bevibeldesign/)
* `mobs_mc_wither_spawn.ogg` (CC0)
* Source: <https://freesound.org/people/bevibeldesign/sounds/366095/>
* [rubberduck](https://opengameart.org/users/rubberduck)
* `mobs_mc_endermite_*.ogg` (CC0)
* `mobs_mc_zombiepig_*.ogg` (CC0)
* `mobs_mc_enderman_teleport_*.ogg` (CC0)
* Source 1: <https://opengameart.org/content/80-cc0-creature-sfx>
* Source 2: <https://opengameart.org/content/80-cc0-creture-sfx-2>
* [Soundscapes55](https://freesound.org/people/Soundscapes55/)
* `mobs_mc_enderman_random.1.ogg` (CC0)
* Source: <https://freesound.org/people/Soundscapes55/sounds/434973/>
* [griffinjennings](https://freesound.org/people/griffinjennings/)
* `mobs_mc_enderman_death.*.ogg` (CC BY 3.0)
* `mobs_mc_enderman_hurt.*.ogg` (CC BY 3.0)
* Sounds were heavily modified
* Source: <https://freesound.org/people/griffinjennings/sounds/463972/>
* [pointparkcinema](https://freesound.org/people/pointparkcinema/)
* `mobs_mc_guardian_random.1.ogg` (CC0)
* Source: <https://freesound.org/people/pointparkcinema/sounds/407252/>
* [nornalbion](https://freesound.org/people/nornalbion/)
* `mobs_mc_guardian_random.2.ogg` (CC BY 3.0)
* `mobs_mc_guardian_random.3.ogg` (CC BY 3.0)
* `mobs_mc_guardian_hurt.*.ogg` (CC BY 3.0)
* Sounds were modified
* Source: <https://freesound.org/people/nornalbion/sounds/195733/>
* [TheBuilder15](https://freesound.org/people/TheBuilder15/)
* `mobs_mc_guardian_death.ogg` (CC0)
* Source: <https://freesound.org/people/pointparkcinema/sounds/407252/>
* Blender Foundation (CC BY 3.0)
* `mobs_sheep.ogg`,
* daufinsyd (MIT License)
* `mobs_mc_blaze_breath.ogg`
* `mobs_mc_blaze_died.ogg`
* [qubodup](https://opengameart.org/content/slime-monster)
* `mobs_mc_squid_hurt.*.ogg` (CC BY 3.0)
* `mobs_mc_squid_death.*.ogg` (CC BY 3.0)
* Changes were made
* Source: <https://opengameart.org/content/slime-monster>
* [kyles](https://freesound.org/people/kyles/)
* `mobs_mc_squid_flop.*.ogg` (CC0)
* Source: <https://freesound.org/people/kyles/sounds/450830/>
* `mobs_mc_snowman_hurt.1.ogg` (CC0)
* Source: <https://freesound.org/people/kyles/sounds/450848/>
* [thefilmbakery](https://freesound.org/people/thefilmbakery/) (CC0)
* `mobs_mc_blaze_hurt.ogg`
* Source: <https://freesound.org/people/thefilmbakery/sounds/137836/>
* TenPlus1, from `mobs_monster` or `mobs_animal` mod (MIT License)
* `mobs_fireball.ogg`
* `mobs_mc_cat_idle.1.ogg`
* `mobs_mc_llama.ogg`
* `mobs_pig.ogg`
* `mobs_pig_angry.ogg`
* `mobs_sandmonster.ogg`
* [Daysycho](https://freesound.org/people/Darsycho/)
* `mobs_mc_spider_hurt.*.ogg` (CC0)
* Source: <https://freesound.org/people/Darsycho/sounds/505185/>
* [columbia23](https://freesound.org/people/columbia23/)
* `mobs_mc_spider_death.ogg` (CC BY 3.0)
* `mobs_mc_spider_random.*.ogg` (CC BY 3.0)
* `mobs_mc_spider_attack.*.ogg` (CC BY 3.0)
* Source: <https://freesound.org/people/columbia23/sounds/395395/>
* BrandonReese (LGPL v2.1)
* `mobs_eerie.ogg`
* [Under7dude](https://freesound.org/people/Under7dude/) (CC0)
* `mobs_mc_zombie_growl.ogg`
* Source: <https://freesound.org/people/Under7dude/sounds/163445/>
* [haratman](https://freesound.org/people/haratman/) (CC0)
* `mobs_mc_zombie_death.ogg`
* Source: <https://freesound.org/people/haratman/sounds/393749/>
* `mobs_mc_zombie_hurt.ogg`
* Source: <https://freesound.org/people/haratman/sounds/393749/>
* [Spennnyyy](https://freesound.org/people/Spennnyyy/) (CC0)
* `mcl_totems_totem.ogg`
* Source: <https://freesound.org/people/Spennnyyy/sounds/323502/>
* [Baŝto](https://opengameart.org/users/ba%C5%9Dto)
* `mobs_mc_skeleton_random.*.ogg` (CC BY 3.0)
* Source: <https://opengameart.org/content/walking-skeleton>
* [spookymodem](https://freesound.org/people/spookymodem/)
* `mobs_mc_skeleton_death.ogg` (CC0)
* <https://freesound.org/people/spookymodem/sounds/202091/>
* [Cribbler](https://freesound.org/people/Cribbler/)
* `mobs_mc_skeleton_hurt.ogg` (CC0)
* Source: <https://freesound.org/people/Cribbler/sounds/381859/>
* [GoodListener](https://freesound.org/people/GoodListener/)
* `mobs_mc_horse_random.1.ogg` (CC BY 3.0)
* Source: <https://freesound.org/people/GoodListener/sounds/322454/>
* `mobs_mc_horse_death.ogg` (CC BY 3.0)
* Source: <https://freesound.org/people/GoodListener/sounds/322445/>
* [Garuda1982](https://freesound.org/people/Garuda1982/)
* `mobs_mc_donkey_random.1.ogg` (CC BY 3.0)
* `mobs_mc_donkey_hurt.ogg` (CC BY 3.0)
* `mobs_mc_donkey_death.ogg` (CC BY 3.0)
* Source: <https://freesound.org/people/Garuda1982/sounds/539505/>
* [JarredGibb](https://freesound.org/people/JarredGibb/sounds/233131/)
* `mobs_mc_donkey_random.2.ogg` (CC0)
* [ERH](https://freesound.org/people/ERH/)
* `mobs_mc_horse_random.2.ogg` (CC BY 3.0)
* Source: <https://freesound.org/people/ERH/sounds/32043/>
* [j1987](https://freesound.org/people/j1987/)
* `mobs_mc_creeper_death.ogg` (CC0)
* Source: <https://freesound.org/people/j1987/sounds/111325>
* [themightyglider](https://opengameart.org/users/themightyglider)
* `mobs_mc_creeper_hurt.ogg` (CC0)
* Source: <https://opengameart.org/content/simple-fuse-sound>
* [pauliw](https://opengameart.org/users/pauliw)
* `mobs_mc_vex_hurt.ogg` (CC0)
* Source: <https://opengameart.org/content/some-kind-of-beings-soundsx>
* `mobs_mc_vex_death.ogg` (CC0)
* Source: <https://opengameart.org/content/some-kind-of-beings-sounds7>
* [suonho](https://freesound.org/people/suonho/)
* `mobs_mc_bat_idle.ogg` (CC BY 3.0)
* Source: <https://freesound.org/people/suonho/sounds/59344/>
* [toefur](https://freesound.org/people/toefur/)
* `mobs_mc_bat_hurt.*.ogg` (CC0)
* `mobs_mc_bat_death.ogg` (CC0)
* Source: <https://freesound.org/people/toefur/sounds/288941/>
* [cmusounddesign](https://freesound.org/people/cmusounddesign/)
* `mobs_mc_cat_hiss.ogg` (CC BY 3.0)
* Source: <https://freesound.org/people/cmusounddesign/sounds/71899/>
* [SelsRoyalNavy](https://freesound.org/people/SelsRoyalNavy/)
* `mobs_mc_cat_idle.2.ogg` (CC0)
* Source: <https://freesound.org/people/SelsRoyalNavy/sounds/427081/>
* [ebcrosby](https://freesound.org/people/ebcrosby/)
* `mobs_mc_ocelot_hurt.ogg` (CC BY 3.0)
* Source: <https://freesound.org/people/ebcrosby/sounds/332979/>
* Hybrid Dog (forum.minetest.net)
* `mobs_mc_wolf_hurt.*.ogg` (CC0)
* `mobs_mc_wolf_bark.*.ogg` (CC0)
* `mobs_mc_wolf_death.*.ogg` (CC0)
* `mobs_mc_wolf_growl.*.ogg` (CC0)
* Sounds modified and simplified
* Source: "dogblocks" mod by Hybrid Dog <https://github.com/HybridDog/dogblocks/>
* [cliftoncarlson](https://freesound.org/people/cliftonmcarlson/)
* `mobs_mc_wolf_take_bone.ogg` (CC0)
* Source: <https://freesound.org/people/cliftonmcarlson/sounds/392883/>
* [Inocodum](https://forum.minetest.net/memberlist.php?mode=viewprofile&u=3115)
* `mobs_mc_silverfish_hurt.ogg` (CC BY-SA 4.0)
* `mobs_mc_silverfish_death.ogg` (CC BY-SA 4.0)
* `mobs_mc_silverfish_idle.ogg` (CC BY-SA 4.0)
* Source: <https://forum.minetest.net/viewtopic.php?f=17&t=10013>
* [LukeIRL](https://freesound.org/people/LukeIRL/)
* `mobs_mc_magma_cube_small.ogg` (CC BY 4.0)
* Derived from: <https://freesound.org/people/LukeIRL/sounds/176123/>
* `mobs_mc_magma_cube_big.ogg` (CC BY 4.0)
* Derived from: <https://freesound.org/people/LukeIRL/sounds/176123/>
* [kbnevel](https://freesound.org/people/kbnevel/)
* `mobs_mc_magma_cube_attack.ogg` (CC0)
* Derived from: <https://freesound.org/people/kbnevel/sounds/119863/>
* [InspectorJ](https://freesound.org/people/InspectorJ/sounds/429591/)
* `mobs_mc_animal_eat_generic.ogg` (CC BY 3.0)
* Source: <https://freesound.org/people/InspectorJ/>
* [tbsounddesigns](https://freesound.org/people/tbsounddesigns/)
* `mobs_mc_bear_random.*.ogg` (CC BY 3.0)
* Source 1: <https://freesound.org/people/tbsounddesigns/sounds/416853/>
* Source 2: <https://freesound.org/people/tbsounddesigns/sounds/416857/>
* Source 3: <https://freesound.org/people/tbsounddesigns/sounds/416855/>
* `mobs_mc_bear_growl.*.ogg` (CC BY 3.0)
* Source 1: <https://freesound.org/people/tbsounddesigns/sounds/416861/>
* Source 2: <https://freesound.org/people/tbsounddesigns/sounds/416859/>
* Source 3: <https://freesound.org/people/tbsounddesigns/sounds/416862/>
* [YleArkisto](https://freesound.org/people/YleArkisto/)
* `mobs_mc_bear_attack.*.ogg` (CC BY 3.0)
* `mobs_mc_bear_death.*.ogg` (CC BY 3.0)
* `mobs_mc_bear_hurt.1.ogg` (CC BY 3.0)
* Changes were made
* Source: <https://freesound.org/people/YleArkisto/sounds/249441/>
* [alexo400](https://freesound.org/people/alexo400/)
* `mobs_mc_snowman_death.*.ogg` (CC0)
* Source: <https://freesound.org/people/alexo400/sounds/543385/>
* [cabled\_mess](https://freesound.org/people/cabled_mess/)
* `mobs_mc_snowman_hurt.2.ogg` (CC0)
* Source: <https://freesound.org/people/cabled_mess/sounds/384424/>
* `mobs_mc_snowman_hurt.3.ogg` (CC0)
* Source: <https://freesound.org/people/cabled_mess/sounds/384421/>
* [kessir](https://freesound.org/people/kessir/sounds/)
* `mobs_mc_rabbit_hurt.*.ogg` (CC0)
* `mobs_mc_rabbit_death.2.ogg` (CC0)
* `mobs_mc_rabbit_death.3.ogg` (CC0)
* Source: <https://freesound.org/people/kessir/sounds/372075/>
* `mobs_mc_rabbit_attack.*.ogg` (CC0)
* Source: <https://freesound.org/people/kessir/sounds/372076/>
* `mobs_mc_rabbit_death.1.ogg` (CC0)
* Source: <https://freesound.org/people/kessir/sounds/385850/>
* [Alshred](https://freesound.org/people/Alshred/sounds/403773/)
* `mobs_mc_rabbit_random.*.ogg` (CC0)
* Changes were made.
* Source: <https://freesound.org/people/Alshred/>
Note: Many of these sounds have been more or less modified to fit the game.
Sounds not mentioned hre are licensed under CC0.

View File

@ -1,84 +0,0 @@
# MC-like mobs [`mobs_mc`]
This mod adds mobs which closely resemble the mobs from the game Minecraft, version 1.12.
## Credits
* [maikerumine](https://github.com/maikerumine): Coding behaviour, spawning, drops, and misc.
* [Wuzzy2](https://github.com/Wuzzy2): Zombies, husks, item textures, and code
* [toby109tt](https://github.com/tobyplowy): Mapping fixes - better 2D planes
* [22i](https://github.com/22i): Models (done in Blender) and mob icons for spawn eggs
* [XSSheep](https://www.planetminecraft.com/member/xssheep/): Mob and item textures (from [Pixel Perfection](https://www.planetminecraft.com/texture_pack/131pixel-perfection/))
* MysticTempest: More mob textures
* See `LICENSE_media.md` for detailed credits about each file
## Licensing
* Code: GNU General Public License, version 3 (see `LICENSE`)
* Media: MIT, CC0, CC BY 3.0 CC BY-SA 4.0, LGPLv2.1, GPLv3. See `LICENSE_media.md` for details
### Links
* [`mobs_mc`](https://github.com/maikerumine/mobs_mc)
* [Blender models](https://github.com/22i/minecraft-voxel-blender-models)
* [How to recreate mobs from textures with Blender and Gimp](http://imgur.com/a/Iqg88)
## List of mobs
**Note**: Many of these are incomplete.
### Monsters
* Zombie
* Husk
* Skeleton
* Stray
* Creeper
* Slime
* Spider
* Cave Spider
* Enderman
* Zombie Villager
* Zombie Pigman
* Wither Skeleton
* Magma Cube
* Blaze
* Ghast
* Evoker
* Vex
* Vindicator
* Witch
* Guardian
* Silverfish
* Endermite
* Shulker
* Ender Dragon
* Wither
* Elder Guardian
### Peaceful mobs
* Chicken
* Cow
* Pig
* Rabbit
* Sheep
* Squid
* Polar Bear
* Bat
* Mooshroom
* Horse
* Donkey
* Llama
* Mule
* Skeleton Horse
* Zombie Horse
### Helpful mobs
* Wolf
* Villager
* Iron golem
* Snow golem
* Ocelot/Cat
* Parrot

View File

@ -1,146 +0,0 @@
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator("mobs_mc")
mcl_mobs:register_mob("mobs_mc:bat", {
description = S("Bat"),
type = "animal",
spawn_class = "ambient",
can_despawn = true,
passive = true,
hp_min = 6,
hp_max = 6,
collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.89, 0.25},
visual = "mesh",
mesh = "mobs_mc_bat.b3d",
textures = {
{"mobs_mc_bat.png"},
},
visual_size = {x=1, y=1},
sounds = {
random = "mobs_mc_bat_idle",
damage = "mobs_mc_bat_hurt",
death = "mobs_mc_bat_death",
distance = 16,
},
walk_velocity = 4.5,
run_velocity = 6.0,
-- TODO: Hang upside down
animation = {
stand_speed = 80,
stand_start = 0,
stand_end = 40,
walk_speed = 80,
walk_start = 0,
walk_end = 40,
run_speed = 80,
run_start = 0,
run_end = 40,
die_speed = 60,
die_start = 40,
die_end = 80,
die_loop = false,
},
walk_chance = 100,
fall_damage = 0,
view_range = 16,
fear_height = 0,
jump = false,
fly = true,
makes_footstep_sound = false,
})
-- Spawning
--[[ If the game has been launched between the 20th of October and the 3rd of November system time,
-- the maximum spawn light level is increased. ]]
local date = os.date("*t")
local maxlight
if (date.month == 10 and date.day >= 20) or (date.month == 11 and date.day <= 3) then
maxlight = 6
else
maxlight = 3
end
-- Spawn on solid blocks at or below Sea level and the selected light level
mcl_mobs:spawn_specific(
"mobs_mc:bat",
"overworld",
"ground",
{
"FlowerForest_underground",
"JungleEdge_underground",
"StoneBeach_underground",
"MesaBryce_underground",
"Mesa_underground",
"RoofedForest_underground",
"Jungle_underground",
"Swampland_underground",
"MushroomIsland_underground",
"BirchForest_underground",
"Plains_underground",
"MesaPlateauF_underground",
"ExtremeHills_underground",
"MegaSpruceTaiga_underground",
"BirchForestM_underground",
"SavannaM_underground",
"MesaPlateauFM_underground",
"Desert_underground",
"Savanna_underground",
"Forest_underground",
"SunflowerPlains_underground",
"ColdTaiga_underground",
"IcePlains_underground",
"IcePlainsSpikes_underground",
"MegaTaiga_underground",
"Taiga_underground",
"ExtremeHills+_underground",
"JungleM_underground",
"ExtremeHillsM_underground",
"JungleEdgeM_underground",
"Mesa",
"FlowerForest",
"Swampland",
"Taiga",
"ExtremeHills",
"Jungle",
"Savanna",
"BirchForest",
"MegaSpruceTaiga",
"MegaTaiga",
"ExtremeHills+",
"Forest",
"Plains",
"Desert",
"ColdTaiga",
"MushroomIsland",
"IcePlainsSpikes",
"SunflowerPlains",
"IcePlains",
"RoofedForest",
"ExtremeHills+_snowtop",
"MesaPlateauFM_grasstop",
"JungleEdgeM",
"ExtremeHillsM",
"JungleM",
"BirchForestM",
"MesaPlateauF",
"MesaPlateauFM",
"MesaPlateauF_grasstop",
"MesaBryce",
"JungleEdge",
"SavannaM",
},
0,
maxlight,
20,
5000,
2,
mcl_vars.mg_overworld_min,
mobs_mc.water_level-1)
-- spawn eggs
mcl_mobs:register_egg("mobs_mc:bat", S("Bat"), "mobs_mc_spawn_icon_bat.png", 0)

View File

@ -1,203 +0,0 @@
-- daufinsyd
-- My work is under the LGPL terms
-- Model and mobs_blaze.png see https://github.com/22i/minecraft-voxel-blender-models -hi 22i ~jordan4ibanez
-- blaze.lua partial copy of mobs_mc/ghast.lua
local S = minetest.get_translator("mobs_mc")
local mod_target = minetest.get_modpath("mcl_target")
--###################
--################### BLAZE
--###################
mcl_mobs:register_mob("mobs_mc:blaze", {
description = S("Blaze"),
type = "monster",
spawn_class = "hostile",
hp_min = 20,
hp_max = 20,
xp_min = 10,
xp_max = 10,
collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.79, 0.3},
rotate = -180,
visual = "mesh",
mesh = "mobs_mc_blaze.b3d",
textures = {
{"mobs_mc_blaze.png"},
},
armor = { fleshy = 100, snowball_vulnerable = 100, water_vulnerable = 100 },
visual_size = {x=3, y=3},
sounds = {
random = "mobs_mc_blaze_breath",
death = "mobs_mc_blaze_died",
damage = "mobs_mc_blaze_hurt",
distance = 16,
},
walk_velocity = .8,
run_velocity = 1.6,
damage = 6,
reach = 2,
pathfinding = 1,
drops = {
{name = "mcl_mobitems:blaze_rod",
chance = 1,
min = 0,
max = 1,
looting = "common",},
},
animation = {
stand_speed = 25,
stand_start = 0,
stand_end = 100,
walk_speed = 25,
walk_start = 0,
walk_end = 100,
run_speed = 50,
run_start = 0,
run_end = 100,
},
-- MC Wiki: takes 1 damage every half second while in water
water_damage = 2,
lava_damage = 0,
fire_damage = 0,
fall_damage = 0,
fall_speed = -2.25,
light_damage = 0,
view_range = 16,
attack_type = "dogshoot",
arrow = "mobs_mc:blaze_fireball",
shoot_interval = 3.5,
shoot_offset = 1.0,
passive = false,
jump = true,
jump_height = 4,
fly = true,
makes_footstep_sound = false,
fear_height = 0,
glow = 14,
fire_resistant = true,
do_custom = function(self)
if self.state == "attack" and self.attack:get_pos() and vector.distance(self.object:get_pos(), self.attack:get_pos()) < 1.2 then
mcl_burning.set_on_fire(self.attack, 5)
end
local pos = self.object:get_pos()
minetest.add_particle({
pos = {x=pos.x+math.random(-0.7,0.7)*math.random()/2,y=pos.y+math.random(0.7,1.2),z=pos.z+math.random(-0.7,0.7)*math.random()/2},
velocity = {x=0, y=math.random(1,1), z=0},
expirationtime = math.random(),
size = math.random(1, 4),
collisiondetection = true,
vertical = false,
texture = "mcl_particles_smoke_anim.png^[colorize:#2c2c2c:255",
animation = {
type = "vertical_frames",
aspect_w = 8,
aspect_h = 8,
length = 2.05,
},
})
minetest.add_particle({
pos = {x=pos.x+math.random(-0.7,0.7)*math.random()/2,y=pos.y+math.random(0.7,1.2),z=pos.z+math.random(-0.7,0.7)*math.random()/2},
velocity = {x=0, y=math.random(1,1), z=0},
expirationtime = math.random(),
size = math.random(1, 4),
collisiondetection = true,
vertical = false,
texture = "mcl_particles_smoke_anim.png^[colorize:#424242:255",
animation = {
type = "vertical_frames",
aspect_w = 8,
aspect_h = 8,
length = 2.05,
},
})
minetest.add_particle({
pos = {x=pos.x+math.random(-0.7,0.7)*math.random()/2,y=pos.y+math.random(0.7,1.2),z=pos.z+math.random(-0.7,0.7)*math.random()/2},
velocity = {x=0, y=math.random(1,1), z=0},
expirationtime = math.random(),
size = math.random(1, 4),
collisiondetection = true,
vertical = false,
texture = "mcl_particles_smoke_anim.png^[colorize:#0f0f0f:255",
animation = {
type = "vertical_frames",
aspect_w = 8,
aspect_h = 8,
length = 2.05,
},
})
end,
})
mcl_mobs:spawn_specific(
"mobs_mc:blaze",
"nether",
"ground",
{"Nether"},
0,
minetest.LIGHT_MAX+1,
30,
5000,
3,
mcl_vars.mg_nether_min,
mcl_vars.mg_nether_max)
-- Blaze fireball
mcl_mobs:register_arrow("mobs_mc:blaze_fireball", {
visual = "sprite",
visual_size = {x = 0.3, y = 0.3},
textures = {"mcl_fire_fire_charge.png"},
velocity = 15,
_is_fireball = true,
-- Direct hit, no fire... just plenty of pain
hit_player = function(self, player)
mcl_burning.set_on_fire(player, 5)
player:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = 5},
}, nil)
end,
hit_mob = function(self, mob)
mcl_burning.set_on_fire(mob, 5)
mob:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = 5},
}, nil)
end,
hit_object = function(self, object)
local lua = object:get_luaentity()
if lua then
if lua.name == "mcl_minecarts:tnt_minecart" then
lua:on_activate_by_rail(2)
end
end
end,
-- Node hit, make fire
hit_node = function(self, pos, node)
if node == "air" then
minetest.set_node(pos, {name = "mcl_fire:fire"})
else
if self._shot_from_dispenser and mod_target and node == "mcl_target:target_off" then
mcl_target.hit(vector.round(pos), 0.4) --4 redstone ticks
end
local v = vector.normalize(self.object:get_velocity())
local crashpos = vector.subtract(pos, v)
local crashnode = minetest.get_node(crashpos)
local cndef = minetest.registered_nodes[crashnode.name]
-- Set fire if node is air, or a replacable flammable node (e.g. a plant)
if crashnode.name == "air" or
(cndef and cndef.buildable_to and minetest.get_item_group(crashnode.name, "flammable") >= 1) then
minetest.set_node(crashpos, {name = "mcl_fire:fire"})
end
end
end
})
-- spawn eggs
mcl_mobs:register_egg("mobs_mc:blaze", S("Blaze"), "mobs_mc_spawn_icon_blaze.png", 0)

View File

@ -1,159 +0,0 @@
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator("mobs_mc")
--###################
--################### CHICKEN
--###################
mcl_mobs:register_mob("mobs_mc:chicken", {
description = S("Chicken"),
type = "animal",
spawn_class = "passive",
hp_min = 4,
hp_max = 4,
xp_min = 1,
xp_max = 3,
collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.69, 0.2},
runaway = true,
floats = 1,
visual = "mesh",
mesh = "mobs_mc_chicken.b3d",
textures = {
{"mobs_mc_chicken.png"},
},
visual_size = {x=2.2, y=2.2},
makes_footstep_sound = true,
walk_velocity = 1,
drops = {
{name = "mcl_mobitems:chicken",
chance = 1,
min = 1,
max = 1,
looting = "common",},
{name = "mcl_mobitems:feather",
chance = 1,
min = 0,
max = 2,
looting = "common",},
},
fall_damage = 0,
fall_speed = -2.25,
sounds = {
random = "mobs_mc_chicken_buck",
damage = "mobs_mc_chicken_hurt",
death = "mobs_mc_chicken_hurt",
eat = "mobs_mc_animal_eat_generic",
distance = 16,
},
sounds_child = {
random = "mobs_mc_chicken_child",
damage = "mobs_mc_chicken_child",
death = "mobs_mc_chicken_child",
eat = "mobs_mc_animal_eat_generic",
distance = 16,
},
animation = {
stand_speed = 25, walk_speed = 25, run_speed = 50,
stand_start = 0, stand_end = 0,
walk_start = 0, walk_end = 40,
run_start = 0, run_end = 40,
},
follow = {
"mcl_farming:wheat_seeds",
"mcl_farming:melon_seeds",
"mcl_farming:pumpkin_seeds",
"mcl_farming:beetroot_seeds",
},
view_range = 16,
fear_height = 4,
on_rightclick = function(self, clicker)
if mcl_mobs:feed_tame(self, clicker, 1, true, true) then return end
if mcl_mobs:protect(self, clicker) then return end
if mcl_mobs:capture_mob(self, clicker, 0, 60, 5, false, nil) then return end
end,
do_custom = function(self, dtime)
self.egg_timer = (self.egg_timer or 0) + dtime
if self.egg_timer < 10 then
return
end
self.egg_timer = 0
if self.child
or math.random(1, 100) > 1 then
return
end
local pos = self.object:get_pos()
minetest.add_item(pos, "mcl_throwing:egg")
minetest.sound_play("mobs_mc_chicken_lay_egg", {
pos = pos,
gain = 1.0,
max_hear_distance = 16,
}, true)
end,
})
--spawn
mcl_mobs:spawn_specific(
"mobs_mc:chicken",
"overworld",
"ground",
{
"flat",
"IcePlainsSpikes",
"ColdTaiga",
"ColdTaiga_beach",
"ColdTaiga_beach_water",
"MegaTaiga",
"MegaSpruceTaiga",
"ExtremeHills",
"ExtremeHills_beach",
"ExtremeHillsM",
"ExtremeHills+",
"ExtremeHills+_snowtop",
"StoneBeach",
"Plains",
"Plains_beach",
"SunflowerPlains",
"Taiga",
"Taiga_beach",
"Forest",
"Forest_beach",
"FlowerForest",
"FlowerForest_beach",
"BirchForest",
"BirchForestM",
"RoofedForest",
"Savanna",
"Savanna_beach",
"SavannaM",
"Jungle",
"Jungle_shore",
"JungleM",
"JungleM_shore",
"JungleEdge",
"JungleEdgeM",
"Swampland",
"Swampland_shore"
},
9,
minetest.LIGHT_MAX+1,
30, 17000,
3,
mobs_mc.water_level,
mcl_vars.mg_overworld_max)
-- spawn eggs
mcl_mobs:register_egg("mobs_mc:chicken", S("Chicken"), "mobs_mc_spawn_icon_chicken.png", 0)

View File

@ -1,218 +0,0 @@
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator("mobs_mc")
local cow_def = {
description = S("Cow"),
type = "animal",
spawn_class = "passive",
hp_min = 10,
hp_max = 10,
xp_min = 1,
xp_max = 3,
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.39, 0.45},
visual = "mesh",
mesh = "mobs_mc_cow.b3d",
textures = { {
"mobs_mc_cow.png",
"blank.png",
}, },
visual_size = {x=2.8, y=2.8},
makes_footstep_sound = true,
walk_velocity = 1,
drops = {
{name = "mcl_mobitems:beef",
chance = 1,
min = 1,
max = 3,
looting = "common",},
{name = "mcl_mobitems:leather",
chance = 1,
min = 0,
max = 2,
looting = "common",},
},
runaway = true,
sounds = {
random = "mobs_mc_cow",
damage = "mobs_mc_cow_hurt",
death = "mobs_mc_cow_hurt",
eat = "mobs_mc_animal_eat_generic",
distance = 16,
},
animation = {
stand_speed = 25, walk_speed = 40,
run_speed = 60, stand_start = 0,
stand_end = 0, walk_start = 0,
walk_end = 40, run_start = 0,
run_end = 40,
},
on_rightclick = function(self, clicker)
if mcl_mobs:feed_tame(self, clicker, 1, true, true) then return end
if mcl_mobs:protect(self, clicker) then return end
if self.child then
return
end
local item = clicker:get_wielded_item()
if item:get_name() == "mcl_buckets:bucket_empty" and clicker:get_inventory() then
local inv = clicker:get_inventory()
inv:remove_item("main", "mcl_buckets:bucket_empty")
minetest.sound_play("mobs_mc_cow_milk", {pos=self.object:get_pos(), gain=0.6})
-- if room add bucket of milk to inventory, otherwise drop as item
if inv:room_for_item("main", {name = "mcl_mobitems:milk_bucket"}) then
clicker:get_inventory():add_item("main", "mcl_mobitems:milk_bucket")
else
local pos = self.object:get_pos()
pos.y = pos.y + 0.5
minetest.add_item(pos, {name = "mcl_mobitems:milk_bucket"})
end
return
end
mcl_mobs:capture_mob(self, clicker, 0, 5, 60, false, nil)
end,
follow = "mcl_farming:wheat_item",
view_range = 10,
fear_height = 4,
}
mcl_mobs:register_mob("mobs_mc:cow", cow_def)
-- Mooshroom
local mooshroom_def = table.copy(cow_def)
mooshroom_def.description = S("Mooshroom")
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.on_rightclick = function(self, clicker)
if mcl_mobs:feed_tame(self, clicker, 1, true, true) then return end
if mcl_mobs:protect(self, clicker) then return end
if self.child then
return
end
local item = clicker:get_wielded_item()
-- Use shears to get mushrooms and turn mooshroom into cow
if item:get_name() == "mcl_tools:shears" then
local pos = self.object:get_pos()
minetest.sound_play("mcl_tools_shears_cut", {pos = pos}, true)
if self.base_texture[1] == "mobs_mc_mooshroom_brown.png" then
minetest.add_item({x=pos.x, y=pos.y+1.4, z=pos.z}, "mcl_mushrooms:mushroom_brown 5")
else
minetest.add_item({x=pos.x, y=pos.y+1.4, z=pos.z}, "mcl_mushrooms:mushroom_red 5")
end
local oldyaw = self.object:get_yaw()
self.object:remove()
local cow = minetest.add_entity(pos, "mobs_mc:cow")
cow:set_yaw(oldyaw)
if not minetest.is_creative_enabled(clicker:get_player_name()) then
item:add_wear(mobs_mc.shears_wear)
clicker:get_inventory():set_stack("main", clicker:get_wield_index(), item)
end
-- Use bucket to milk
elseif item:get_name() == "mcl_buckets:bucket_empty" and clicker:get_inventory() then
local inv = clicker:get_inventory()
inv:remove_item("main", "mcl_buckets:bucket_empty")
minetest.sound_play("mobs_mc_cow_milk", {pos=self.object:get_pos(), gain=0.6})
-- If room, add milk to inventory, otherwise drop as item
if inv:room_for_item("main", {name="mcl_mobitems:milk_bucket"}) then
clicker:get_inventory():add_item("main", "mcl_mobitems:milk_bucket")
else
local pos = self.object:get_pos()
pos.y = pos.y + 0.5
minetest.add_item(pos, {name = "mcl_mobitems:milk_bucket"})
end
-- Use bowl to get mushroom stew
elseif item:get_name() == "mcl_core:bowl" and clicker:get_inventory() then
local inv = clicker:get_inventory()
inv:remove_item("main", "mcl_core:bowl")
minetest.sound_play("mobs_mc_cow_mushroom_stew", {pos=self.object:get_pos(), gain=0.6})
-- If room, add mushroom stew to inventory, otherwise drop as item
if inv:room_for_item("main", {name="mcl_mushrooms:mushroom_stew"}) then
clicker:get_inventory():add_item("main", "mcl_mushrooms:mushroom_stew")
else
local pos = self.object:get_pos()
pos.y = pos.y + 0.5
minetest.add_item(pos, {name = "mcl_mushrooms:mushroom_stew"})
end
end
mcl_mobs:capture_mob(self, clicker, 0, 5, 60, false, nil)
end
mcl_mobs:register_mob("mobs_mc:mooshroom", mooshroom_def)
-- Spawning
mcl_mobs:spawn_specific(
"mobs_mc:cow",
"overworld",
"ground",
{
"flat",
"IcePlainsSpikes",
"ColdTaiga",
"ColdTaiga_beach",
"ColdTaiga_beach_water",
"MegaTaiga",
"MegaSpruceTaiga",
"ExtremeHills",
"ExtremeHills_beach",
"ExtremeHillsM",
"ExtremeHills+",
"ExtremeHills+_snowtop",
"StoneBeach",
"Plains",
"Plains_beach",
"SunflowerPlains",
"Taiga",
"Taiga_beach",
"Forest",
"Forest_beach",
"FlowerForest",
"FlowerForest_beach",
"BirchForest",
"BirchForestM",
"RoofedForest",
"Savanna",
"Savanna_beach",
"SavannaM",
"Jungle",
"Jungle_shore",
"JungleM",
"JungleM_shore",
"JungleEdge",
"JungleEdgeM",
"Swampland",
"Swampland_shore"
},
9,
minetest.LIGHT_MAX+1,
30,
17000,
10,
mobs_mc.water_level,
mcl_vars.mg_overworld_max)
mcl_mobs:spawn_specific(
"mobs_mc:mooshroom",
"overworld",
"ground",
{
"MushroomIslandShore",
"MushroomIsland"
},
9,
minetest.LIGHT_MAX+1,
30,
17000,
5,
mcl_vars.mg_overworld_min,
mcl_vars.mg_overworld_max)
-- spawn egg
mcl_mobs:register_egg("mobs_mc:cow", S("Cow"), "mobs_mc_spawn_icon_cow.png", 0)
mcl_mobs:register_egg("mobs_mc:mooshroom", S("Mooshroom"), "mobs_mc_spawn_icon_mooshroom.png", 0)

View File

@ -1,411 +0,0 @@
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator("mobs_mc")
--###################
--################### CREEPER
--###################
mcl_mobs:register_mob("mobs_mc:creeper", {
type = "monster",
spawn_class = "hostile",
hp_min = 20,
hp_max = 20,
xp_min = 5,
xp_max = 5,
collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.69, 0.3},
pathfinding = 1,
visual = "mesh",
mesh = "mobs_mc_creeper.b3d",
textures = {
{"mobs_mc_creeper.png",
"mobs_mc_empty.png"},
},
visual_size = {x=3, y=3},
sounds = {
attack = "tnt_ignite",
death = "mobs_mc_creeper_death",
damage = "mobs_mc_creeper_hurt",
fuse = "tnt_ignite",
explode = "tnt_explode",
distance = 16,
},
makes_footstep_sound = true,
walk_velocity = 1.05,
run_velocity = 2.1,
runaway_from = { "mobs_mc:ocelot", "mobs_mc:cat" },
attack_type = "explode",
--hssssssssssss
explosion_strength = 3,
explosion_radius = 3.5,
explosion_damage_radius = 3.5,
explosiontimer_reset_radius = 6,
reach = 3,
explosion_timer = 1.5,
allow_fuse_reset = true,
stop_to_explode = true,
-- Force-ignite creeper with flint and steel and explode after 1.5 seconds.
-- TODO: Make creeper flash after doing this as well.
-- TODO: Test and debug this code.
on_rightclick = function(self, clicker)
if self._forced_explosion_countdown_timer ~= nil then
return
end
local item = clicker:get_wielded_item()
if item:get_name() == "mcl_fire:flint_and_steel" then
if not minetest.is_creative_enabled(clicker:get_player_name()) then
-- Wear tool
local wdef = item:get_definition()
item:add_wear(1000)
-- Tool break sound
if item:get_count() == 0 and wdef.sound and wdef.sound.breaks then
minetest.sound_play(wdef.sound.breaks, {pos = clicker:get_pos(), gain = 0.5}, true)
end
clicker:set_wielded_item(item)
end
self._forced_explosion_countdown_timer = self.explosion_timer
minetest.sound_play(self.sounds.attack, {pos = self.object:get_pos(), gain = 1, max_hear_distance = 16}, true)
end
end,
do_custom = function(self, dtime)
if self._forced_explosion_countdown_timer ~= nil then
self._forced_explosion_countdown_timer = self._forced_explosion_countdown_timer - dtime
if self._forced_explosion_countdown_timer <= 0 then
mcl_mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength)
end
end
end,
on_die = function(self, pos, cmi_cause)
-- Drop a random music disc when killed by skeleton or stray
if cmi_cause and cmi_cause.type == "punch" then
local luaentity = cmi_cause.puncher and cmi_cause.puncher:get_luaentity()
if luaentity and luaentity.name:find("arrow") then
local shooter_luaentity = luaentity._shooter and luaentity._shooter:get_luaentity()
if shooter_luaentity and (shooter_luaentity.name == "mobs_mc:skeleton" or shooter_luaentity.name == "mobs_mc:stray") then
minetest.add_item({x=pos.x, y=pos.y+1, z=pos.z}, "mcl_jukebox:record_" .. math.random(9))
end
end
end
end,
maxdrops = 2,
drops = {
{name = "mcl_mobitems:gunpowder",
chance = 1,
min = 0,
max = 2,
looting = "common",},
-- Head
-- TODO: Only drop if killed by charged creeper
{name = "mcl_heads:creeper",
chance = 200, -- 0.5%
min = 1,
max = 1,},
},
animation = {
speed_normal = 24,
speed_run = 48,
stand_start = 0,
stand_end = 23,
walk_start = 24,
walk_end = 49,
run_start = 24,
run_end = 49,
hurt_start = 110,
hurt_end = 139,
death_start = 140,
death_end = 189,
look_start = 50,
look_end = 108,
},
floats = 1,
fear_height = 4,
view_range = 16,
})
mcl_mobs:register_mob("mobs_mc:creeper_charged", {
description = S("Creeper"),
type = "monster",
spawn_class = "hostile",
hp_min = 20,
hp_max = 20,
xp_min = 5,
xp_max = 5,
collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.69, 0.3},
pathfinding = 1,
visual = "mesh",
mesh = "mobs_mc_creeper.b3d",
--BOOM
textures = {
{"mobs_mc_creeper.png",
"mobs_mc_creeper_charge.png"},
},
visual_size = {x=3, y=3},
sounds = {
attack = "tnt_ignite",
death = "mobs_mc_creeper_death",
damage = "mobs_mc_creeper_hurt",
fuse = "tnt_ignite",
explode = "tnt_explode",
distance = 16,
},
makes_footstep_sound = true,
walk_velocity = 1.05,
run_velocity = 2.1,
runaway_from = { "mobs_mc:ocelot", "mobs_mc:cat" },
attack_type = "explode",
explosion_strength = 6,
explosion_radius = 8,
explosion_damage_radius = 8,
explosiontimer_reset_radius = 6,
reach = 3,
explosion_timer = 1.5,
allow_fuse_reset = true,
stop_to_explode = true,
-- Force-ignite creeper with flint and steel and explode after 1.5 seconds.
-- TODO: Make creeper flash after doing this as well.
-- TODO: Test and debug this code.
on_rightclick = function(self, clicker)
if self._forced_explosion_countdown_timer ~= nil then
return
end
local item = clicker:get_wielded_item()
if item:get_name() == "mcl_fire:flint_and_steel" then
if not minetest.is_creative_enabled(clicker:get_player_name()) then
-- Wear tool
local wdef = item:get_definition()
item:add_wear(1000)
-- Tool break sound
if item:get_count() == 0 and wdef.sound and wdef.sound.breaks then
minetest.sound_play(wdef.sound.breaks, {pos = clicker:get_pos(), gain = 0.5}, true)
end
clicker:set_wielded_item(item)
end
self._forced_explosion_countdown_timer = self.explosion_timer
minetest.sound_play(self.sounds.attack, {pos = self.object:get_pos(), gain = 1, max_hear_distance = 16}, true)
end
end,
do_custom = function(self, dtime)
if self._forced_explosion_countdown_timer ~= nil then
self._forced_explosion_countdown_timer = self._forced_explosion_countdown_timer - dtime
if self._forced_explosion_countdown_timer <= 0 then
mcl_mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength)
end
end
end,
on_die = function(self, pos, cmi_cause)
-- Drop a random music disc when killed by skeleton or stray
if cmi_cause and cmi_cause.type == "punch" then
local luaentity = cmi_cause.puncher and cmi_cause.puncher:get_luaentity()
if luaentity and luaentity.name:find("arrow") then
local shooter_luaentity = luaentity._shooter and luaentity._shooter:get_luaentity()
if shooter_luaentity and (shooter_luaentity.name == "mobs_mc:skeleton" or shooter_luaentity.name == "mobs_mc:stray") then
minetest.add_item({x=pos.x, y=pos.y+1, z=pos.z}, "mcl_jukebox:record_" .. math.random(9))
end
end
end
end,
maxdrops = 2,
drops = {
{name = "mcl_mobitems:gunpowder",
chance = 1,
min = 0,
max = 2,
looting = "common",},
-- Head
-- TODO: Only drop if killed by charged creeper
{name = "mcl_heads:creeper",
chance = 200, -- 0.5%
min = 1,
max = 1,},
},
animation = {
speed_normal = 24,
speed_run = 48,
stand_start = 0,
stand_end = 23,
walk_start = 24,
walk_end = 49,
run_start = 24,
run_end = 49,
hurt_start = 110,
hurt_end = 139,
death_start = 140,
death_end = 189,
look_start = 50,
look_end = 108,
},
floats = 1,
fear_height = 4,
view_range = 16,
--Having trouble when fire is placed with lightning
fire_resistant = true,
glow = 3,
})
mcl_mobs:spawn_specific(
"mobs_mc:creeper",
"overworld",
"ground",
{
"Mesa",
"FlowerForest",
"Swampland",
"Taiga",
"ExtremeHills",
"Jungle",
"Savanna",
"BirchForest",
"MegaSpruceTaiga",
"MegaTaiga",
"ExtremeHills+",
"Forest",
"Plains",
"Desert",
"ColdTaiga",
"MushroomIsland",
"IcePlainsSpikes",
"SunflowerPlains",
"IcePlains",
"RoofedForest",
"ExtremeHills+_snowtop",
"MesaPlateauFM_grasstop",
"JungleEdgeM",
"ExtremeHillsM",
"JungleM",
"BirchForestM",
"MesaPlateauF",
"MesaPlateauFM",
"MesaPlateauF_grasstop",
"MesaBryce",
"JungleEdge",
"SavannaM",
"FlowerForest_beach",
"Forest_beach",
"StoneBeach",
"ColdTaiga_beach_water",
"Taiga_beach",
"Savanna_beach",
"Plains_beach",
"ExtremeHills_beach",
"ColdTaiga_beach",
"Swampland_shore",
"MushroomIslandShore",
"JungleM_shore",
"Jungle_shore",
"MesaPlateauFM_sandlevel",
"MesaPlateauF_sandlevel",
"MesaBryce_sandlevel",
"Mesa_sandlevel",
"RoofedForest_ocean",
"JungleEdgeM_ocean",
"BirchForestM_ocean",
"BirchForest_ocean",
"IcePlains_deep_ocean",
"Jungle_deep_ocean",
"Savanna_ocean",
"MesaPlateauF_ocean",
"ExtremeHillsM_deep_ocean",
"Savanna_deep_ocean",
"SunflowerPlains_ocean",
"Swampland_deep_ocean",
"Swampland_ocean",
"MegaSpruceTaiga_deep_ocean",
"ExtremeHillsM_ocean",
"JungleEdgeM_deep_ocean",
"SunflowerPlains_deep_ocean",
"BirchForest_deep_ocean",
"IcePlainsSpikes_ocean",
"Mesa_ocean",
"StoneBeach_ocean",
"Plains_deep_ocean",
"JungleEdge_deep_ocean",
"SavannaM_deep_ocean",
"Desert_deep_ocean",
"Mesa_deep_ocean",
"ColdTaiga_deep_ocean",
"Plains_ocean",
"MesaPlateauFM_ocean",
"Forest_deep_ocean",
"JungleM_deep_ocean",
"FlowerForest_deep_ocean",
"MushroomIsland_ocean",
"MegaTaiga_ocean",
"StoneBeach_deep_ocean",
"IcePlainsSpikes_deep_ocean",
"ColdTaiga_ocean",
"SavannaM_ocean",
"MesaPlateauF_deep_ocean",
"MesaBryce_deep_ocean",
"ExtremeHills+_deep_ocean",
"ExtremeHills_ocean",
"MushroomIsland_deep_ocean",
"Forest_ocean",
"MegaTaiga_deep_ocean",
"JungleEdge_ocean",
"MesaBryce_ocean",
"MegaSpruceTaiga_ocean",
"ExtremeHills+_ocean",
"Jungle_ocean",
"RoofedForest_deep_ocean",
"IcePlains_ocean",
"FlowerForest_ocean",
"ExtremeHills_deep_ocean",
"MesaPlateauFM_deep_ocean",
"Desert_ocean",
"Taiga_ocean",
"BirchForestM_deep_ocean",
"Taiga_deep_ocean",
"JungleM_ocean",
"FlowerForest_underground",
"JungleEdge_underground",
"StoneBeach_underground",
"MesaBryce_underground",
"Mesa_underground",
"RoofedForest_underground",
"Jungle_underground",
"Swampland_underground",
"MushroomIsland_underground",
"BirchForest_underground",
"Plains_underground",
"MesaPlateauF_underground",
"ExtremeHills_underground",
"MegaSpruceTaiga_underground",
"BirchForestM_underground",
"SavannaM_underground",
"MesaPlateauFM_underground",
"Desert_underground",
"Savanna_underground",
"Forest_underground",
"SunflowerPlains_underground",
"ColdTaiga_underground",
"IcePlains_underground",
"IcePlainsSpikes_underground",
"MegaTaiga_underground",
"Taiga_underground",
"ExtremeHills+_underground",
"JungleM_underground",
"ExtremeHillsM_underground",
"JungleEdgeM_underground",
},
0,
7,
20,
16500,
2,
mcl_vars.mg_overworld_min,
mcl_vars.mg_overworld_max)
-- spawn eggs
mcl_mobs:register_egg("mobs_mc:creeper", S("Creeper"), "mobs_mc_spawn_icon_creeper.png", 0)

View File

@ -1 +0,0 @@
mcl_mobs

View File

@ -1,142 +0,0 @@
--###################
--################### ENDERDRAGON
--###################
local S = minetest.get_translator("mobs_mc")
mcl_mobs:register_mob("mobs_mc:enderdragon", {
description = S("Ender Dragon"),
type = "monster",
spawn_class = "hostile",
pathfinding = 1,
attacks_animals = true,
walk_chance = 100,
hp_max = 200,
hp_min = 200,
xp_min = 500,
xp_max = 500,
collisionbox = {-2, 3, -2, 2, 5, 2},
physical = false,
visual = "mesh",
mesh = "mobs_mc_dragon.b3d",
textures = {
{"mobs_mc_dragon.png"},
},
visual_size = {x=3, y=3},
view_range = 35,
walk_velocity = 6,
run_velocity = 6,
can_despawn = false,
sounds = {
-- TODO: more sounds
shoot_attack = "mobs_mc_ender_dragon_shoot",
attack = "mobs_mc_ender_dragon_attack",
distance = 60,
},
physical = true,
damage = 10,
jump = true,
jump_height = 14,
fly = true,
makes_footstep_sound = false,
dogshoot_switch = 1,
dogshoot_count_max =5,
dogshoot_count2_max = 5,
passive = false,
attack_animals = true,
lava_damage = 0,
fire_damage = 0,
on_rightclick = nil,
attack_type = "dogshoot",
arrow = "mobs_mc:dragon_fireball",
shoot_interval = 0.5,
shoot_offset = -1.0,
xp_min = 500,
xp_max = 500,
animation = {
fly_speed = 8, stand_speed = 8,
stand_start = 0, stand_end = 20,
walk_start = 0, walk_end = 20,
run_start = 0, run_end = 20,
},
ignores_nametag = true,
do_custom = function(self)
mcl_bossbars.update_boss(self.object, "Ender Dragon", "light_purple")
for _, obj in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 80)) do
local luaentity = obj:get_luaentity()
if luaentity and luaentity.name == "mcl_end:crystal" then
if luaentity.beam then
if luaentity.beam == self.beam then
break
end
else
if self.beam then
self.beam:remove()
end
minetest.add_entity(self.object:get_pos(), "mcl_end:crystal_beam"):get_luaentity():init(self.object, obj)
break
end
end
end
if self._portal_pos then
-- migrate old format
if type(self._portal_pos) == "string" then
self._portal_pos = minetest.string_to_pos(self._portal_pos)
end
local portal_center = vector.add(self._portal_pos, vector.new(3, 11, 3))
local pos = self.object:get_pos()
if vector.distance(pos, portal_center) > 50 then
self.object:set_pos(self._last_good_pos or portal_center)
else
self._last_good_pos = pos
end
end
end,
on_die = function(self, pos)
if self._portal_pos then
mcl_portals.spawn_gateway_portal()
mcl_structures.call_struct(self._portal_pos, "end_exit_portal_open")
if self._initial then
mcl_experience.throw_xp(pos, 11500) -- 500 + 11500 = 12000
minetest.set_node(vector.add(self._portal_pos, vector.new(3, 5, 3)), {name = "mcl_end:dragon_egg"})
end
end
end,
fire_resistant = true,
})
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
-- dragon fireball (projectile)
mcl_mobs:register_arrow("mobs_mc:dragon_fireball", {
visual = "sprite",
visual_size = {x = 1.25, y = 1.25},
textures = {"mobs_mc_dragon_fireball.png"},
velocity = 6,
-- direct hit, no fire... just plenty of pain
hit_player = function(self, player)
player:punch(self.object, 1.0, {
full_punch_interval = 0.5,
damage_groups = {fleshy = 12},
}, nil)
end,
hit_mob = function(self, mob)
minetest.sound_play("tnt_explode", {pos = mob:get_pos(), gain = 1.5, max_hear_distance = 2*64}, true)
mob:punch(self.object, 1.0, {
full_punch_interval = 0.5,
damage_groups = {fleshy = 12},
}, nil)
end,
-- node hit, explode
hit_node = function(self, pos, node)
mcl_mobs:boom(self, pos, 2)
end
})
mcl_mobs:register_egg("mobs_mc:enderdragon", S("Ender Dragon"), "mobs_mc_spawn_icon_dragon.png", 0, true)
mcl_wip.register_wip_item("mobs_mc:enderdragon")

View File

@ -1,780 +0,0 @@
--MCmobs v0.4
--maikerumine
--made for MC like Survival game
--License for code WTFPL and otherwise stated in readmes
-- ENDERMAN BEHAVIOUR (OLD):
-- In this game, endermen attack the player on sight, like other monsters do.
-- However, they have a reduced viewing range to make them less dangerous.
-- This differs from MC, in which endermen only become hostile when provoked,
-- and they are provoked by looking directly at them.
-- Rootyjr
-----------------------------
-- implemented ability to detect when seen / break eye contact and aggressive response
-- implemented teleport to avoid arrows.
-- implemented teleport to avoid rain.
-- implemented teleport to chase.
-- added enderman particles.
-- drew mcl_portal_particle1.png
-- drew mcl_portal_particle2.png
-- drew mcl_portal_particle3.png
-- drew mcl_portal_particle4.png
-- drew mcl_portal_particle5.png
-- added rain damage.
-- fixed the grass_with_dirt issue.
local S = minetest.get_translator("mobs_mc")
local telesound = function(pos, is_source)
local snd
if is_source then
snd = "mobs_mc_enderman_teleport_src"
else
snd = "mobs_mc_enderman_teleport_dst"
end
minetest.sound_play(snd, {pos=pos, max_hear_distance=16}, true)
end
--###################
--################### ENDERMAN
--###################
local pr = PseudoRandom(os.time()*(-334))
-- How freqeuntly to take and place blocks, in seconds
local take_frequency_min = 235
local take_frequency_max = 245
local place_frequency_min = 235
local place_frequency_max = 245
-- Texuture overrides for enderman block. Required for cactus because it's original is a nodebox
-- and the textures have tranparent pixels.
local block_texture_overrides
do
local cbackground = "mobs_mc_enderman_cactus_background.png"
local ctiles = minetest.registered_nodes["mcl_core:cactus"].tiles
local ctable = {}
local last
for i=1, 6 do
if ctiles[i] then
last = ctiles[i]
end
table.insert(ctable, cbackground .. "^" .. last)
end
block_texture_overrides = {
["mcl_core:cactus"] = ctable,
-- FIXME: replace colorize colors with colors from palette
["mcl_core:dirt_with_grass"] =
{
"mcl_core_grass_block_top.png^[colorize:green:90",
"default_dirt.png",
"default_dirt.png^(mcl_core_grass_block_side_overlay.png^[colorize:green:90)",
"default_dirt.png^(mcl_core_grass_block_side_overlay.png^[colorize:green:90)",
"default_dirt.png^(mcl_core_grass_block_side_overlay.png^[colorize:green:90)",
"default_dirt.png^(mcl_core_grass_block_side_overlay.png^[colorize:green:90)"}
}
end
-- Create the textures table for the enderman, depending on which kind of block
-- the enderman holds (if any).
local create_enderman_textures = function(block_type, itemstring)
local base = "mobs_mc_enderman.png^mobs_mc_enderman_eyes.png"
--[[ Order of the textures in the texture table:
Flower, 90 degrees
Flower, 45 degrees
Held block, backside
Held block, bottom
Held block, front
Held block, left
Held block, right
Held block, top
Enderman texture (base)
]]
-- Regular cube
if block_type == "cube" then
local tiles = minetest.registered_nodes[itemstring].tiles
local textures = {}
local last
if block_texture_overrides[itemstring] then
-- Texture override available? Use these instead!
textures = block_texture_overrides[itemstring]
else
-- Extract the texture names
for i = 1, 6 do
if type(tiles[i]) == "string" then
last = tiles[i]
elseif type(tiles[i]) == "table" then
if tiles[i].name then
last = tiles[i].name
end
end
table.insert(textures, last)
end
end
return {
"blank.png",
"blank.png",
textures[5],
textures[2],
textures[6],
textures[3],
textures[4],
textures[1],
base, -- Enderman texture
}
-- Node of plantlike drawtype, 45° (recommended)
elseif block_type == "plantlike45" then
local textures = minetest.registered_nodes[itemstring].tiles
return {
"blank.png",
textures[1],
"blank.png",
"blank.png",
"blank.png",
"blank.png",
"blank.png",
"blank.png",
base,
}
-- Node of plantlike drawtype, 90°
elseif block_type == "plantlike90" then
local textures = minetest.registered_nodes[itemstring].tiles
return {
textures[1],
"blank.png",
"blank.png",
"blank.png",
"blank.png",
"blank.png",
"blank.png",
"blank.png",
base,
}
elseif block_type == "unknown" then
return {
"blank.png",
"blank.png",
"unknown_node.png",
"unknown_node.png",
"unknown_node.png",
"unknown_node.png",
"unknown_node.png",
"unknown_node.png",
base, -- Enderman texture
}
-- No block held (for initial texture)
elseif block_type == "nothing" or block_type == nil then
return {
"blank.png",
"blank.png",
"blank.png",
"blank.png",
"blank.png",
"blank.png",
"blank.png",
"blank.png",
base, -- Enderman texture
}
end
end
-- Select a new animation definition.
local select_enderman_animation = function(animation_type)
-- Enderman holds a block
if animation_type == "block" then
return {
walk_speed = 25,
run_speed = 50,
stand_speed = 25,
stand_start = 200,
stand_end = 200,
walk_start = 161,
walk_end = 200,
run_start = 161,
run_end = 200,
punch_start = 121,
punch_end = 160,
}
-- Enderman doesn't hold a block
elseif animation_type == "normal" or animation_type == nil then
return {
walk_speed = 25,
run_speed = 50,
stand_speed = 25,
stand_start = 40,
stand_end = 80,
walk_start = 0,
walk_end = 40,
run_start = 0,
run_end = 40,
punch_start = 81,
punch_end = 120,
}
end
end
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
mcl_mobs:register_mob("mobs_mc:enderman", {
description = S("Enderman"),
type = "monster",
spawn_class = "passive",
passive = true,
pathfinding = 1,
hp_min = 40,
hp_max = 40,
xp_min = 5,
xp_max = 5,
collisionbox = {-0.3, -0.01, -0.3, 0.3, 2.89, 0.3},
visual = "mesh",
mesh = "mobs_mc_enderman.b3d",
textures = create_enderman_textures(),
visual_size = {x=3, y=3},
makes_footstep_sound = true,
sounds = {
-- TODO: Custom war cry sound
war_cry = "mobs_sandmonster",
death = {name="mobs_mc_enderman_death", gain=0.7},
damage = {name="mobs_mc_enderman_hurt", gain=0.5},
random = {name="mobs_mc_enderman_random", gain=0.5},
distance = 16,
},
walk_velocity = 0.2,
run_velocity = 3.4,
damage = 7,
reach = 2,
drops = {
{name = "mcl_throwing:ender_pearl",
chance = 1,
min = 0,
max = 1,
looting = "common"},
},
animation = select_enderman_animation("normal"),
_taken_node = "",
do_custom = function(self, dtime)
-- PARTICLE BEHAVIOUR HERE.
local enderpos = self.object:get_pos()
local chanceOfParticle = math.random(0, 1)
if chanceOfParticle == 1 then
minetest.add_particle({
pos = {x=enderpos.x+math.random(-1,1)*math.random()/2,y=enderpos.y+math.random(0,3),z=enderpos.z+math.random(-1,1)*math.random()/2},
velocity = {x=math.random(-.25,.25), y=math.random(-.25,.25), z=math.random(-.25,.25)},
acceleration = {x=math.random(-.5,.5), y=math.random(-.5,.5), z=math.random(-.5,.5)},
expirationtime = math.random(),
size = math.random(),
collisiondetection = true,
vertical = false,
texture = "mcl_portals_particle"..math.random(1, 5)..".png",
})
end
-- RAIN DAMAGE / EVASIVE WARP BEHAVIOUR HERE.
local dim = mcl_worlds.pos_to_dimension(enderpos)
if dim == "overworld" then
if mcl_weather.state == "rain" or mcl_weather.state == "lightning" then
local damage = true
local enderpos = self.object:get_pos()
enderpos.y = enderpos.y+2.89
local height = {x=enderpos.x, y=enderpos.y+512,z=enderpos.z}
local ray = minetest.raycast(enderpos, height, true)
-- Check for blocks above enderman.
for pointed_thing in ray do
if pointed_thing.type == "node" then
local nn = minetest.get_node(minetest.get_pointed_thing_position(pointed_thing)).name
local def = minetest.registered_nodes[nn]
if (not def) or def.walkable then
-- There's a node in the way. Delete arrow without damage
damage = false
break
end
end
end
if damage == true then
self.state = ""
--rain hurts enderman
self.object:punch(self.object, 1.0, {
full_punch_interval=1.0,
damage_groups={fleshy=self._damage},
}, nil)
--randomly teleport hopefully under something.
self:teleport(nil)
end
end
else return end
-- AGRESSIVELY WARP/CHASE PLAYER BEHAVIOUR HERE.
if self.state == "attack" then
--if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
--self:teleport(nil)
--self.state = ""
--else
if self.attack then
local target = self.attack
local pos = target:get_pos()
if pos ~= nil then
if vector.distance(self.object:get_pos(), target:get_pos()) > 10 then
self:teleport(target)
end
end
end
--end
end
-- ARROW / DAYTIME PEOPLE AVOIDANCE BEHAVIOUR HERE.
-- Check for arrows and people nearby.
local enderpos = self.object:get_pos()
enderpos.y = enderpos.y + 1.5
local objs = minetest.get_objects_inside_radius(enderpos, 2)
for n = 1, #objs do
local obj = objs[n]
if obj then
if minetest.is_player(obj) then
-- Warp from players during day.
--if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
-- self:teleport(nil)
--end
else
local lua = obj:get_luaentity()
if lua then
if lua.name == "mcl_bows:arrow_entity" or lua.name == "mcl_throwing:snowball_entity" then
self:teleport(nil)
end
end
end
end
end
-- PROVOKED BEHAVIOUR HERE.
local enderpos = self.object:get_pos()
if self.provoked == "broke_contact" then
self.provoked = "false"
--if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
-- self:teleport(nil)
-- self.state = ""
--else
if self.attack ~= nil and not minetest.settings:get_bool("creative_mode") then
self.state = 'attack'
end
--end
end
-- Check to see if people are near by enough to look at us.
for _,obj in pairs(minetest.get_connected_players()) do
--check if they are within radius
local player_pos = obj:get_pos()
if player_pos then -- prevent crashing in 1 in a million scenario
local ender_distance = vector.distance(enderpos, player_pos)
if ender_distance <= 64 then
-- Check if they are looking at us.
local look_dir_not_normalized = obj:get_look_dir()
local look_dir = vector.normalize(look_dir_not_normalized)
local player_eye_height = obj:get_properties().eye_height
--skip player if they have no data - log it
if not player_eye_height then
minetest.log("error", "Enderman at location: ".. dump(enderpos).." has indexed a null player!")
else
--calculate very quickly the exact location the player is looking
--within the distance between the two "heads" (player and enderman)
local look_pos = vector.new(player_pos.x, player_pos.y + player_eye_height, player_pos.z)
local look_pos_base = look_pos
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)
look_pos = vector.add(look_pos, vector.multiply(look_dir, eye_distance_from_player))
--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
self.provoked = "staring"
self.attack = minetest.get_player_by_name(obj:get_player_name())
break
else -- I'm not sure what this part does, but I don't want to break anything - jordan4ibanez
if self.provoked == "staring" then
self.provoked = "broke_contact"
end
end
end
end
end
end
-- TAKE AND PLACE STUFF BEHAVIOUR BELOW.
if not mobs_griefing then
return
end
-- Take and put nodes
if not self._take_place_timer or not self._next_take_place_time then
self._take_place_timer = 0
self._next_take_place_time = math.random(take_frequency_min, take_frequency_max)
return
end
self._take_place_timer = self._take_place_timer + dtime
if (self._taken_node == nil or self._taken_node == "") and self._take_place_timer >= self._next_take_place_time then
-- Take random node
self._take_place_timer = 0
self._next_take_place_time = math.random(place_frequency_min, place_frequency_max)
local pos = self.object:get_pos()
local takable_nodes = minetest.find_nodes_in_area_under_air({x=pos.x-2, y=pos.y-1, z=pos.z-2}, {x=pos.x+2, y=pos.y+1, z=pos.z+2}, "group:enderman_takable")
if #takable_nodes >= 1 then
local r = pr:next(1, #takable_nodes)
local take_pos = takable_nodes[r]
local node = minetest.get_node(take_pos)
-- Don't destroy protected stuff.
if not minetest.is_protected(take_pos, "") then
minetest.remove_node(take_pos)
local dug = minetest.get_node_or_nil(take_pos)
if dug and dug.name == "air" then
self._taken_node = node.name
local def = minetest.registered_nodes[self._taken_node]
-- Update animation and texture accordingly (adds visibly carried block)
local block_type
-- Cube-shaped
if def.drawtype == "normal" or
def.drawtype == "nodebox" or
def.drawtype == "liquid" or
def.drawtype == "flowingliquid" or
def.drawtype == "glasslike" or
def.drawtype == "glasslike_framed" or
def.drawtype == "glasslike_framed_optional" or
def.drawtype == "allfaces" or
def.drawtype == "allfaces_optional" or
def.drawtype == nil then
block_type = "cube"
elseif def.drawtype == "plantlike" then
-- Flowers and stuff
block_type = "plantlike45"
elseif def.drawtype == "airlike" then
-- Just air
block_type = nil
else
-- Fallback for complex drawtypes
block_type = "unknown"
end
self.base_texture = create_enderman_textures(block_type, self._taken_node)
self.object:set_properties({ textures = self.base_texture })
self.animation = select_enderman_animation("block")
mcl_mobs:set_animation(self, self.animation.current)
if def.sounds and def.sounds.dug then
minetest.sound_play(def.sounds.dug, {pos = take_pos, max_hear_distance = 16}, true)
end
end
end
end
elseif self._taken_node ~= nil and self._taken_node ~= "" and self._take_place_timer >= self._next_take_place_time then
-- Place taken node
self._take_place_timer = 0
self._next_take_place_time = math.random(take_frequency_min, take_frequency_max)
local pos = self.object:get_pos()
local yaw = self.object:get_yaw()
-- Place node at looking direction
local place_pos = vector.subtract(pos, minetest.facedir_to_dir(minetest.dir_to_facedir(minetest.yaw_to_dir(yaw))))
-- Also check to see if protected.
if minetest.get_node(place_pos).name == "air" and not minetest.is_protected(place_pos, "") then
-- ... but only if there's a free space
local success = minetest.place_node(place_pos, {name = self._taken_node})
if success then
local def = minetest.registered_nodes[self._taken_node]
-- Update animation accordingly (removes visible block)
self.animation = select_enderman_animation("normal")
mcl_mobs:set_animation(self, self.animation.current)
if def.sounds and def.sounds.place then
minetest.sound_play(def.sounds.place, {pos = place_pos, max_hear_distance = 16}, true)
end
self._taken_node = ""
end
end
end
end,
do_teleport = function(self, target)
if target ~= nil then
local target_pos = target:get_pos()
-- Find all solid nodes below air in a 10×10×10 cuboid centered on the target
local nodes = minetest.find_nodes_in_area_under_air(vector.subtract(target_pos, 5), vector.add(target_pos, 5), {"group:solid", "group:cracky", "group:crumbly"})
local telepos
if nodes ~= nil then
if #nodes > 0 then
-- Up to 64 attempts to teleport
for n=1, math.min(64, #nodes) do
local r = pr:next(1, #nodes)
local nodepos = nodes[r]
local node_ok = true
-- Selected node needs to have 3 nodes of free space above
for u=1, 3 do
local node = minetest.get_node({x=nodepos.x, y=nodepos.y+u, z=nodepos.z})
local ndef = minetest.registered_nodes[node.name]
if ndef and ndef.walkable then
node_ok = false
break
end
end
if node_ok then
telepos = {x=nodepos.x, y=nodepos.y+1, z=nodepos.z}
end
end
if telepos then
telesound(self.object:get_pos(), false)
self.object:set_pos(telepos)
telesound(telepos, true)
end
end
end
else
-- Attempt to randomly teleport enderman
local pos = self.object:get_pos()
-- Up to 8 top-level attempts to teleport
for n=1, 8 do
local node_ok = false
-- We need to add (or subtract) different random numbers to each vector component, so it couldn't be done with a nice single vector.add() or .subtract():
local randomCube = vector.new( pos.x + 8*(pr:next(0,16)-8), pos.y + 8*(pr:next(0,16)-8), pos.z + 8*(pr:next(0,16)-8) )
local nodes = minetest.find_nodes_in_area_under_air(vector.subtract(randomCube, 4), vector.add(randomCube, 4), {"group:solid", "group:cracky", "group:crumbly"})
if nodes ~= nil then
if #nodes > 0 then
-- Up to 8 low-level (in total up to 8*8 = 64) attempts to teleport
for n=1, math.min(8, #nodes) do
local r = pr:next(1, #nodes)
local nodepos = nodes[r]
node_ok = true
for u=1, 3 do
local node = minetest.get_node({x=nodepos.x, y=nodepos.y+u, z=nodepos.z})
local ndef = minetest.registered_nodes[node.name]
if ndef and ndef.walkable then
node_ok = false
break
end
end
if node_ok then
telesound(self.object:get_pos(), false)
local telepos = {x=nodepos.x, y=nodepos.y+1, z=nodepos.z}
self.object:set_pos(telepos)
telesound(telepos, true)
break
end
end
end
end
if node_ok then
break
end
end
end
end,
on_die = function(self, pos)
-- Drop carried node on death
if self._taken_node ~= nil and self._taken_node ~= "" then
minetest.add_item(pos, self._taken_node)
end
end,
do_punch = function(self, hitter, tflp, tool_caps, dir)
-- damage from rain caused by itself so we don't want it to attack itself.
if hitter ~= self.object and hitter ~= nil then
--if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
-- self:teleport(nil)
--else
if pr:next(1, 8) == 8 then --FIXME: real mc rate
self:teleport(hitter)
end
self.attack=hitter
self.state="attack"
--end
end
end,
armor = { fleshy = 100, water_vulnerable = 100 },
water_damage = 8,
view_range = 64,
fear_height = 4,
attack_type = "dogfight",
})
-- End spawn
mcl_mobs:spawn_specific(
"mobs_mc:enderman",
"end",
"ground",
{
"End"
},
0,
minetest.LIGHT_MAX+1,
30,
3000,
12,
mcl_vars.mg_end_min,
mcl_vars.mg_end_max)
-- Overworld spawn
mcl_mobs:spawn_specific(
"mobs_mc:enderman",
"overworld",
"ground",
{
"Mesa",
"FlowerForest",
"Swampland",
"Taiga",
"ExtremeHills",
"Jungle",
"Savanna",
"BirchForest",
"MegaSpruceTaiga",
"MegaTaiga",
"ExtremeHills+",
"Forest",
"Plains",
"Desert",
"ColdTaiga",
"MushroomIsland",
"IcePlainsSpikes",
"SunflowerPlains",
"IcePlains",
"RoofedForest",
"ExtremeHills+_snowtop",
"MesaPlateauFM_grasstop",
"JungleEdgeM",
"ExtremeHillsM",
"JungleM",
"BirchForestM",
"MesaPlateauF",
"MesaPlateauFM",
"MesaPlateauF_grasstop",
"MesaBryce",
"JungleEdge",
"SavannaM",
"FlowerForest_beach",
"Forest_beach",
"StoneBeach",
"ColdTaiga_beach_water",
"Taiga_beach",
"Savanna_beach",
"Plains_beach",
"ExtremeHills_beach",
"ColdTaiga_beach",
"Swampland_shore",
"MushroomIslandShore",
"JungleM_shore",
"Jungle_shore",
"MesaPlateauFM_sandlevel",
"MesaPlateauF_sandlevel",
"MesaBryce_sandlevel",
"Mesa_sandlevel",
"RoofedForest_ocean",
"JungleEdgeM_ocean",
"BirchForestM_ocean",
"BirchForest_ocean",
"IcePlains_deep_ocean",
"Jungle_deep_ocean",
"Savanna_ocean",
"MesaPlateauF_ocean",
"ExtremeHillsM_deep_ocean",
"Savanna_deep_ocean",
"SunflowerPlains_ocean",
"Swampland_deep_ocean",
"Swampland_ocean",
"MegaSpruceTaiga_deep_ocean",
"ExtremeHillsM_ocean",
"JungleEdgeM_deep_ocean",
"SunflowerPlains_deep_ocean",
"BirchForest_deep_ocean",
"IcePlainsSpikes_ocean",
"Mesa_ocean",
"StoneBeach_ocean",
"Plains_deep_ocean",
"JungleEdge_deep_ocean",
"SavannaM_deep_ocean",
"Desert_deep_ocean",
"Mesa_deep_ocean",
"ColdTaiga_deep_ocean",
"Plains_ocean",
"MesaPlateauFM_ocean",
"Forest_deep_ocean",
"JungleM_deep_ocean",
"FlowerForest_deep_ocean",
"MushroomIsland_ocean",
"MegaTaiga_ocean",
"StoneBeach_deep_ocean",
"IcePlainsSpikes_deep_ocean",
"ColdTaiga_ocean",
"SavannaM_ocean",
"MesaPlateauF_deep_ocean",
"MesaBryce_deep_ocean",
"ExtremeHills+_deep_ocean",
"ExtremeHills_ocean",
"MushroomIsland_deep_ocean",
"Forest_ocean",
"MegaTaiga_deep_ocean",
"JungleEdge_ocean",
"MesaBryce_ocean",
"MegaSpruceTaiga_ocean",
"ExtremeHills+_ocean",
"Jungle_ocean",
"RoofedForest_deep_ocean",
"IcePlains_ocean",
"FlowerForest_ocean",
"ExtremeHills_deep_ocean",
"MesaPlateauFM_deep_ocean",
"Desert_ocean",
"Taiga_ocean",
"BirchForestM_deep_ocean",
"Taiga_deep_ocean",
"JungleM_ocean",
"FlowerForest_underground",
"JungleEdge_underground",
"StoneBeach_underground",
"MesaBryce_underground",
"Mesa_underground",
"RoofedForest_underground",
"Jungle_underground",
"Swampland_underground",
"MushroomIsland_underground",
"BirchForest_underground",
"Plains_underground",
"MesaPlateauF_underground",
"ExtremeHills_underground",
"MegaSpruceTaiga_underground",
"BirchForestM_underground",
"SavannaM_underground",
"MesaPlateauFM_underground",
"Desert_underground",
"Savanna_underground",
"Forest_underground",
"SunflowerPlains_underground",
"ColdTaiga_underground",
"IcePlains_underground",
"IcePlainsSpikes_underground",
"MegaTaiga_underground",
"Taiga_underground",
"ExtremeHills+_underground",
"JungleM_underground",
"ExtremeHillsM_underground",
"JungleEdgeM_underground",
},
0,
7,
30,
19000,
2,
mcl_vars.mg_overworld_min,
mcl_vars.mg_overworld_max)
-- Nether spawn (rare)
mcl_mobs:spawn_specific(
"mobs_mc:enderman",
"nether",
"ground",
{
"Nether"
},
0,
7,
30,
27500,
4,
mcl_vars.mg_nether_min,
mcl_vars.mg_nether_max)
-- spawn eggs
mcl_mobs:register_egg("mobs_mc:enderman", S("Enderman"), "mobs_mc_spawn_icon_enderman.png", 0)

View File

@ -1,41 +0,0 @@
--###################
--################### ENDERMITE
--###################
local S = minetest.get_translator("mobs_mc")
mcl_mobs:register_mob("mobs_mc:endermite", {
description = S("Endermite"),
type = "monster",
spawn_class = "hostile",
passive = false,
hp_min = 8,
hp_max = 8,
xp_min = 3,
xp_max = 3,
armor = {fleshy = 100, arthropod = 100},
group_attack = true,
collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.29, 0.2},
visual = "mesh",
mesh = "mobs_mc_endermite.b3d",
textures = {
{"mobs_mc_endermite.png"},
},
visual_size = {x=3, y=3},
makes_footstep_sound = false,
sounds = {
random = "mobs_mc_endermite_random",
damage = "mobs_mc_endermite_hurt",
death = "mobs_mc_endermite_death",
distance = 16,
},
walk_velocity = 1,
run_velocity = 2,
jump = true,
fear_height = 4,
view_range = 16,
damage = 2,
reach = 1,
})
mcl_mobs:register_egg("mobs_mc:endermite", S("Endermite"), "mobs_mc_spawn_icon_endermite.png", 0)

View File

@ -1,128 +0,0 @@
--MCmobs v0.4
--maikerumine
--made for MC like Survival game
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator("mobs_mc")
--###################
--################### GHAST
--###################
mcl_mobs:register_mob("mobs_mc:ghast", {
description = S("Ghast"),
type = "monster",
spawn_class = "hostile",
pathfinding = 1,
group_attack = true,
hp_min = 10,
hp_max = 10,
xp_min = 5,
xp_max = 5,
collisionbox = {-2, 5, -2, 2, 9, 2},
visual = "mesh",
mesh = "mobs_mc_ghast.b3d",
textures = {
{"mobs_mc_ghast.png"},
},
visual_size = {x=12, y=12},
sounds = {
shoot_attack = "mobs_fireball",
death = "mobs_mc_zombie_death",
attack = "mobs_fireball",
random = "mobs_eerie",
distance = 16,
-- TODO: damage
-- TODO: better death
},
walk_velocity = 1.6,
run_velocity = 3.2,
drops = {
{name = "mcl_mobitems:gunpowder", chance = 1, min = 0, max = 2, looting = "common"},
{name = "mcl_mobitems:ghast_tear", chance = 10/6, min = 0, max = 1, looting = "common", looting_ignore_chance = true},
},
animation = {
stand_speed = 50, walk_speed = 50, run_speed = 50,
stand_start = 0, stand_end = 40,
walk_start = 0, walk_end = 40,
run_start = 0, run_end = 40,
},
fall_damage = 0,
view_range = 100,
attack_type = "dogshoot",
arrow = "mobs_mc:fireball",
shoot_interval = 3.5,
shoot_offset = -5,
dogshoot_switch = 1,
dogshoot_count_max =1,
passive = false,
jump = true,
jump_height = 4,
floats=1,
fly = true,
makes_footstep_sound = false,
instant_death = true,
fire_resistant = true,
do_custom = function(self)
if self.firing == true then
self.base_texture = {"mobs_mc_ghast_firing.png"}
self.object:set_properties({textures=self.base_texture})
else
self.base_texture = {"mobs_mc_ghast.png"}
self.object:set_properties({textures=self.base_texture})
end
end,
})
mcl_mobs:spawn_specific(
"mobs_mc:ghast",
"nether",
"ground",
{
"Nether"
},
0,
minetest.LIGHT_MAX+1,
30,
18000,
2,
mcl_vars.mg_nether_min,
mcl_vars.mg_nether_max)
-- fireball (projectile)
mcl_mobs:register_arrow("mobs_mc:fireball", {
visual = "sprite",
visual_size = {x = 1, y = 1},
textures = {"mcl_fire_fire_charge.png"},
velocity = 15,
collisionbox = {-.5, -.5, -.5, .5, .5, .5},
_is_fireball = true,
hit_player = function(self, player)
player:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = 6},
}, nil)
mcl_mobs:boom(self, self.object:get_pos(), 1, true)
end,
hit_mob = function(self, mob)
mob:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = 6},
}, nil)
mcl_mobs:boom(self, self.object:get_pos(), 1, true)
end,
hit_node = function(self, pos, node)
mcl_mobs:boom(self, pos, 1, true)
end
})
-- spawn eggs
mcl_mobs:register_egg("mobs_mc:ghast", S("Ghast"), "mobs_mc_spawn_icon_ghast.png", 0)

View File

@ -1,105 +0,0 @@
--###################
--################### GUARDIAN
--###################
local S = minetest.get_translator("mobs_mc")
mcl_mobs:register_mob("mobs_mc:guardian", {
description = S("Guardian"),
type = "monster",
spawn_class = "hostile",
hp_min = 30,
hp_max = 30,
xp_min = 10,
xp_max = 10,
breath_max = -1,
passive = false,
attack_type = "dogfight",
pathfinding = 1,
view_range = 16,
walk_velocity = 2,
run_velocity = 4,
damage = 6,
reach = 3,
collisionbox = {-0.425, 0.25, -0.425, 0.425, 1.1, 0.425},
visual = "mesh",
mesh = "mobs_mc_guardian.b3d",
textures = {
{"mobs_mc_guardian.png"},
},
visual_size = {x=3, y=3},
sounds = {
random = "mobs_mc_guardian_random",
war_cry = "mobs_mc_guardian_random",
damage = {name="mobs_mc_guardian_hurt", gain=0.3},
death = "mobs_mc_guardian_death",
flop = "mobs_mc_squid_flop",
distance = 16,
},
animation = {
stand_speed = 25, walk_speed = 25, run_speed = 50,
stand_start = 0, stand_end = 20,
walk_start = 0, walk_end = 20,
run_start = 0, run_end = 20,
},
drops = {
-- Greatly increased amounts of prismarine
{name = "mcl_ocean:prismarine_shard",
chance = 1,
min = 0,
max = 32,
looting = "common",},
-- TODO: Reduce of drops when ocean monument is ready.
-- The following drops are approximations
-- Fish / prismarine crystal
{name = "mcl_fishing:fish_raw",
chance = 4,
min = 1,
max = 1,
looting = "common",},
{name = "mcl_ocean:prismarine_crystals",
chance = 4,
min = 1,
max = 2,
looting = "common",},
-- Rare drop: fish
{name = "mcl_fishing:fish_raw",
chance = 160, -- 2.5% / 4
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.0025,},
{name = "mcl_fishing:salmon_raw",
chance = 160,
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.0025,},
{name = "mcl_fishing:clownfish_raw",
chance = 160,
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.0025,},
{name = "mcl_fishing:pufferfish_raw",
chance = 160,
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.0025,},
},
fly = true,
makes_footstep_sound = false,
fly_in = { "mcl_core:water_source", "mclx_core:river_water_source" },
jump = false,
view_range = 16,
})
-- Spawning disabled due to size issues
-- TODO: Re-enable spawning
--mcl_mobs:spawn_specific("mobs_mc:guardian", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 25000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level - 10)
-- spawn eggs
mcl_mobs:register_egg("mobs_mc:guardian", S("Guardian"), "mobs_mc_spawn_icon_guardian.png", 0)

View File

@ -1,116 +0,0 @@
-- v1.4
--###################
--################### GUARDIAN
--###################
local S = minetest.get_translator("mobs_mc")
mcl_mobs:register_mob("mobs_mc:guardian_elder", {
description = S("Elder Guardian"),
type = "monster",
spawn_class = "hostile",
hp_min = 80,
hp_max = 80,
xp_min = 10,
xp_max = 10,
breath_max = -1,
passive = false,
attack_type = "dogfight",
pathfinding = 1,
view_range = 16,
walk_velocity = 2,
run_velocity = 4,
damage = 8,
reach = 3,
collisionbox = {-0.99875, 0.5, -0.99875, 0.99875, 2.4975, 0.99875},
visual = "mesh",
mesh = "mobs_mc_guardian.b3d",
textures = {
{"mobs_mc_guardian_elder.png"},
},
visual_size = {x=7, y=7},
sounds = {
random = "mobs_mc_guardian_random",
war_cry = "mobs_mc_guardian_random",
damage = {name="mobs_mc_guardian_hurt", gain=0.3},
death = "mobs_mc_guardian_death",
flop = "mobs_mc_squid_flop",
base_pitch = 0.6,
distance = 16,
},
animation = {
stand_speed = 25, walk_speed = 25, run_speed = 50,
stand_start = 0, stand_end = 20,
walk_start = 0, walk_end = 20,
run_start = 0, run_end = 20,
},
drops = {
-- TODO: Reduce # of drops when ocean monument is ready.
-- Greatly increased amounts of prismarine
{name = "mcl_ocean:prismarine_shard",
chance = 1,
min = 1,
max = 64,
looting = "common",},
-- TODO: Only drop if killed by player
{name = "mcl_sponges:sponge_wet",
chance = 1,
min = 1,
max = 1,},
-- The following drops are approximations
-- Fish / prismarine crystal
{name = "mcl_fishing:fish_raw",
chance = 4,
min = 1,
max = 1,
looting = "common",},
{name = "mcl_ocean:prismarine_crystals",
chance = 1,
min = 1,
max = 10,
looting = "common",},
-- Rare drop: fish
{name = "mcl_fishing:fish_raw",
chance = 160, -- 2.5% / 4
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.01 / 4,},
{name = "mcl_fishing:salmon_raw",
chance = 160,
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.01 / 4,},
{name = "mcl_fishing:clownfish_raw",
chance = 160,
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.01 / 4,},
{name = "mcl_fishing:pufferfish_raw",
chance = 160,
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.01 / 4,},
},
fly = true,
makes_footstep_sound = false,
fly_in = { "mcl_core:water_source", "mclx_core:river_water_source" },
jump = false,
view_range = 16,
})
-- Spawning disabled due to size issues <- what do you mean? -j4i
-- TODO: Re-enable spawning
-- mcl_mobs:spawn_specific("mobs_mc:guardian_elder", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 40000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level-18)
-- spawn eggs
mcl_mobs:register_egg("mobs_mc:guardian_elder", S("Elder Guardian"), "mobs_mc_spawn_icon_guardian_elder.png", 0)

View File

@ -1,615 +0,0 @@
--MCmobs v0.4
--maikerumine
--made for MC like Survival game
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator("mobs_mc")
--###################
--################### HORSE
--###################
-- Return overlay texture for horse/donkey/mule, e.g. chest, saddle or horse armor
local horse_extra_texture = function(horse)
local base = horse._naked_texture
local saddle = horse._saddle
local chest = horse._chest
local armor = horse._horse_armor
local textures = {}
if armor and minetest.get_item_group(armor, "horse_armor") > 0 then
textures[2] = base .. "^" .. minetest.registered_items[armor]._horse_overlay_image
else
textures[2] = base
end
if saddle then
textures[3] = base
else
textures[3] = "blank.png"
end
if chest then
textures[1] = base
else
textures[1] = "blank.png"
end
return textures
end
-- Helper functions to determine equipment rules
local can_equip_horse_armor = function(entity_id)
return entity_id == "mobs_mc:horse" or entity_id == "mobs_mc:skeleton_horse" or entity_id == "mobs_mc:zombie_horse"
end
local can_equip_chest = function(entity_id)
return entity_id == "mobs_mc:mule" or entity_id == "mobs_mc:donkey"
end
local can_breed = function(entity_id)
return entity_id == "mobs_mc:horse" or "mobs_mc:mule" or entity_id == "mobs_mc:donkey"
end
--[[ Generate all possible horse textures.
Horse textures are a combination of a base texture and an optional marking overlay. ]]
-- The base horse textures (fur) (fur)
local horse_base = {
"mobs_mc_horse_brown.png",
"mobs_mc_horse_darkbrown.png",
"mobs_mc_horse_white.png",
"mobs_mc_horse_gray.png",
"mobs_mc_horse_black.png",
"mobs_mc_horse_chestnut.png",
"mobs_mc_horse_creamy.png",
}
-- Horse marking texture overlay, to be appended to the base texture string
local horse_markings = {
"", -- no markings
"mobs_mc_horse_markings_whitedots.png", -- snowflake appaloosa
"mobs_mc_horse_markings_blackdots.png", -- sooty
"mobs_mc_horse_markings_whitefield.png", -- paint
"mobs_mc_horse_markings_white.png", -- stockings and blaze
}
local horse_textures = {}
for b=1, #horse_base do
for m=1, #horse_markings do
local fur = horse_base[b]
if horse_markings[m] ~= "" then
fur = fur .. "^" .. horse_markings[m]
end
table.insert(horse_textures, {
"blank.png", -- chest
fur, -- base texture + markings and optional armor
"blank.png", -- saddle
})
end
end
-- in e7898352d890c2414af653eba624939df9c0b8b4 (0.76-dev) all items from mobs_mc were moved to mcl_mobitems
-- this results in existing horses wearing armor would still have the old texture filename in their
-- properties this function updates them. It should be removed some time in the future when we can be
-- reasonably sure all horses that want it get the new nexture.
local function update_textures(self)
local old = "mobs_mc_horse_armor_"
local txt = self.object:get_properties().textures
if txt[2]:find(old) then
txt[2] = txt[2]:gsub(old,"mcl_mobitems_horse_armor_")
self.object:set_properties({textures=txt})
return
end
end
-- Horse
local horse = {
description = S("Horse"),
type = "animal",
spawn_class = "passive",
visual = "mesh",
mesh = "mobs_mc_horse.b3d",
visual_size = {x=3.0, y=3.0},
collisionbox = {-0.69825, -0.01, -0.69825, 0.69825, 1.59, 0.69825},
animation = {
stand_speed = 25,
stand_start = 0,
stand_end = 0,
walk_speed = 25,
walk_start = 0,
walk_end = 40,
run_speed = 60,
run_start = 0,
run_end = 40,
},
textures = horse_textures,
sounds = {
random = "mobs_mc_horse_random",
-- TODO: Separate damage sound
damage = "mobs_mc_horse_death",
death = "mobs_mc_horse_death",
eat = "mobs_mc_animal_eat_generic",
distance = 16,
},
fear_height = 4,
fly = false,
walk_chance = 60,
view_range = 16,
follow = {
"mcl_core:apple",
"mcl_core:sugar",
"mcl_farming:wheat_item",
"mcl_farming:hay_block",
"mcl_core:apple_gold",
"mcl_farming:carrot_item_gold",
},
passive = true,
hp_min = 15,
hp_max = 30,
xp_min = 1,
xp_max = 3,
floats = 1,
makes_footstep_sound = true,
jump = true,
jump_height = 5.75, -- can clear 2.5 blocks
drops = {
{name = "mcl_mobitems:leather",
chance = 1,
min = 0,
max = 2,
looting = "common",},
},
on_spawn = update_textures,
do_custom = function(self, dtime)
-- set needed values if not already present
if not self._regentimer then
self._regentimer = 0
end
if not self.v2 then
self.v2 = 0
self.max_speed_forward = 7
self.max_speed_reverse = 2
self.accel = 6
self.terrain_type = 3
self.driver_attach_at = {x = 0, y = 4.17, z = -1.75}
self.driver_eye_offset = {x = 0, y = 3, z = 0}
self.driver_scale = {x = 1/self.visual_size.x, y = 1/self.visual_size.y}
end
-- Slowly regenerate health
self._regentimer = self._regentimer + dtime
if self._regentimer >= 4 then
if self.health < self.hp_max then
self.health = self.health + 1
end
self._regentimer = 0
end
-- Some weird human is riding. Buck them off?
if self.driver and not self.tamed and self.buck_off_time <= 0 then
if math.random() < 0.2 then
mcl_mobs.detach(self.driver, {x = 1, y = 0, z = 1})
-- TODO bucking animation
else
-- Nah, can't be bothered. Think about it again in one second
self.buck_off_time = 20
end
end
-- Tick the timer for trying to buck the player off
if self.buck_off_time then
if self.driver then
self.buck_off_time = self.buck_off_time - 1
else
-- Player isn't riding anymore so no need to count
self.buck_off_time = nil
end
end
-- if driver present and horse has a saddle allow control of horse
if self.driver and self._saddle then
mcl_mobs.drive(self, "walk", "stand", false, dtime)
return false -- skip rest of mob functions
end
return true
end,
on_die = function(self, pos)
-- drop saddle when horse is killed while riding
if self._saddle then
minetest.add_item(pos, "mcl_mobitems:saddle")
end
-- also detach from horse properly
if self.driver then
mcl_mobs.detach(self.driver, {x = 1, y = 0, z = 1})
end
end,
on_rightclick = function(self, clicker)
-- make sure player is clicking
if not clicker or not clicker:is_player() then
return
end
local item = clicker:get_wielded_item()
local iname = item:get_name()
local heal = 0
-- Taming
self.temper = self.temper or (math.random(1,100))
if not self.tamed then
local temper_increase = 0
-- Feeding, intentionally not using mobs:feed_tame because horse taming is
-- different and more complicated
if (iname == "mcl_core:sugar") then
temper_increase = 3
elseif (iname == "mcl_farming:wheat_item") then
temper_increase = 3
elseif (iname == "mcl_core:apple") then
temper_increase = 3
elseif (iname == "mcl_farming:carrot_item_gold") then
temper_increase = 5
elseif (iname == "mcl_core:apple_gold") then
temper_increase = 10
-- Trying to ride
elseif not self.driver then
self.object:set_properties({stepheight = 1.1})
mcl_mobs.attach(self, clicker)
self.buck_off_time = 40 -- TODO how long does it take in minecraft?
if self.temper > 100 then
self.tamed = true -- NOTE taming can only be finished by riding the horse
if not self.owner or self.owner == "" then
self.owner = clicker:get_player_name()
end
end
temper_increase = 5
-- Clicking on the horse while riding ==> unmount
elseif self.driver and self.driver == clicker then
mcl_mobs.detach(clicker, {x = 1, y = 0, z = 1})
end
-- If nothing happened temper_increase = 0 and addition does nothing
self.temper = self.temper + temper_increase
return
end
if can_breed(self.name) then
-- Breed horse with golden apple or golden carrot
if (iname == "mcl_core:apple_gold") then
heal = 10
elseif (iname == "mcl_farming:carrot_item_gold") then
heal = 4
end
if heal > 0 and mcl_mobs:feed_tame(self, clicker, heal, true, false) then
return
end
end
-- Feed with anything else
-- TODO heal amounts don't work
if (iname == "mcl_core:sugar") then
heal = 1
elseif (iname == "mcl_farming:wheat_item") then
heal = 2
elseif (iname == "mcl_core:apple") then
heal = 3
elseif (iname == "mcl_farming:hay_block") then
heal = 20
end
if heal > 0 and mcl_mobs:feed_tame(self, clicker, heal, false, false) then
return
end
if mcl_mobs:protect(self, clicker) then
return
end
-- Make sure tamed horse is mature and being clicked by owner only
if self.tamed and not self.child and self.owner == clicker:get_player_name() then
local inv = clicker:get_inventory()
-- detatch player already riding horse
if self.driver and clicker == self.driver then
mcl_mobs.detach(clicker, {x = 1, y = 0, z = 1})
-- Put on saddle if tamed
elseif not self.driver and not self._saddle
and iname == "mcl_mobitems:saddle" then
-- Put on saddle and take saddle from player's inventory
local w = clicker:get_wielded_item()
self._saddle = true
if not minetest.is_creative_enabled(clicker:get_player_name()) then
w:take_item()
clicker:set_wielded_item(w)
end
-- Update texture
if not self._naked_texture then
-- Base horse texture without chest or saddle
self._naked_texture = self.base_texture[2]
end
local tex = horse_extra_texture(self)
self.base_texture = tex
self.object:set_properties({textures = self.base_texture})
minetest.sound_play({name = "mcl_armor_equip_leather"}, {gain=0.5, max_hear_distance=12, pos=self.object:get_pos()}, true)
-- Put on horse armor if tamed
elseif can_equip_horse_armor(self.name) and not self.driver and not self._horse_armor
and minetest.get_item_group(iname, "horse_armor") > 0 then
-- Put on armor and take armor from player's inventory
local armor = minetest.get_item_group(iname, "horse_armor")
self._horse_armor = iname
local w = clicker:get_wielded_item()
if not minetest.is_creative_enabled(clicker:get_player_name()) then
w:take_item()
clicker:set_wielded_item(w)
end
-- Set horse armor strength
self.armor = armor
local agroups = self.object:get_armor_groups()
agroups.fleshy = self.armor
self.object:set_armor_groups(agroups)
-- Update texture
if not self._naked_texture then
-- Base horse texture without chest or saddle
self._naked_texture = self.base_texture[2]
end
local tex = horse_extra_texture(self)
self.base_texture = tex
self.object:set_properties({textures = self.base_texture})
local def = w:get_definition()
if def.sounds and def.sounds._mcl_armor_equip then
minetest.sound_play({name = def.sounds._mcl_armor_equip}, {gain=0.5, max_hear_distance=12, pos=self.object:get_pos()}, true)
end
-- Mount horse
elseif not self.driver and self._saddle then
self.object:set_properties({stepheight = 1.1})
mcl_mobs.attach(self, clicker)
-- Used to capture horse
elseif not self.driver and iname ~= "" then
mcl_mobs:capture_mob(self, clicker, 0, 5, 60, false, nil)
end
end
end,
on_breed = function(parent1, parent2)
local pos = parent1.object:get_pos()
local child = mcl_mobs:spawn_child(pos, parent1.name)
if child then
local ent_c = child:get_luaentity()
local p = math.random(1, 2)
local child_texture
-- Randomly pick one of the parents for the child texture
if p == 1 then
if parent1._naked_texture then
child_texture = parent1._naked_texture
else
child_texture = parent1.base_texture[2]
end
else
if parent2._naked_texture then
child_texture = parent2._naked_texture
else
child_texture = parent2.base_texture[2]
end
end
local splt = string.split(child_texture, "^")
if #splt >= 2 then
-- Randomly mutate base texture (fur) and markings
-- with chance of 1/9 each
local base = splt[1]
local markings = splt[2]
local mutate_base = math.random(1, 9)
local mutate_markings = math.random(1, 9)
if mutate_base == 1 then
local b = math.random(1, #horse_base)
base = horse_base[b]
end
if mutate_markings == 1 then
local m = math.random(1, #horse_markings)
markings = horse_markings[m]
end
child_texture = base
if markings ~= "" then
child_texture = child_texture .. "^" .. markings
end
end
ent_c.base_texture = { "blank.png", child_texture, "blank.png" }
ent_c._naked_texture = child_texture
child:set_properties({textures = ent_c.base_texture})
return false
end
end,
}
mcl_mobs:register_mob("mobs_mc:horse", horse)
-- Skeleton horse
local skeleton_horse = table.copy(horse)
skeleton_horse.description = S("Skeleton Horse")
skeleton_horse.breath_max = -1
skeleton_horse.armor = {undead = 100, fleshy = 100}
skeleton_horse.textures = {{"blank.png", "mobs_mc_horse_skeleton.png", "blank.png"}}
skeleton_horse.drops = {
{name = "mcl_mobitems:bone",
chance = 1,
min = 0,
max = 2,},
}
skeleton_horse.sounds = {
random = "mobs_mc_skeleton_random",
death = "mobs_mc_skeleton_death",
damage = "mobs_mc_skeleton_hurt",
eat = "mobs_mc_animal_eat_generic",
base_pitch = 0.95,
distance = 16,
}
skeleton_horse.harmed_by_heal = true
mcl_mobs:register_mob("mobs_mc:skeleton_horse", skeleton_horse)
-- Zombie horse
local zombie_horse = table.copy(horse)
zombie_horse.description = S("Zombie Horse")
zombie_horse.breath_max = -1
zombie_horse.armor = {undead = 100, fleshy = 100}
zombie_horse.textures = {{"blank.png", "mobs_mc_horse_zombie.png", "blank.png"}}
zombie_horse.drops = {
{name = "mcl_mobitems:rotten_flesh",
chance = 1,
min = 0,
max = 2,},
}
zombie_horse.sounds = {
random = "mobs_mc_horse_random",
-- TODO: Separate damage sound
damage = "mobs_mc_horse_death",
death = "mobs_mc_horse_death",
eat = "mobs_mc_animal_eat_generic",
base_pitch = 0.5,
distance = 16,
}
zombie_horse.harmed_by_heal = true
mcl_mobs:register_mob("mobs_mc:zombie_horse", zombie_horse)
-- Donkey
local d = 0.86 -- donkey scale
local donkey = table.copy(horse)
donkey.description = S("Donkey")
donkey.textures = {{"blank.png", "mobs_mc_donkey.png", "blank.png"}}
donkey.animation = {
speed_normal = 25,
stand_start = 0, stand_end = 0,
walk_start = 0, walk_end = 40,
}
donkey.sounds = {
random = "mobs_mc_donkey_random",
damage = "mobs_mc_donkey_hurt",
death = "mobs_mc_donkey_death",
eat = "mobs_mc_animal_eat_generic",
distance = 16,
}
donkey.visual_size = { x=horse.visual_size.x*d, y=horse.visual_size.y*d }
donkey.collisionbox = {
horse.collisionbox[1] * d,
horse.collisionbox[2] * d,
horse.collisionbox[3] * d,
horse.collisionbox[4] * d,
horse.collisionbox[5] * d,
horse.collisionbox[6] * d,
}
donkey.jump = true
donkey.jump_height = 3.75 -- can clear 1 block height
mcl_mobs:register_mob("mobs_mc:donkey", donkey)
-- Mule
local m = 0.94
local mule = table.copy(donkey)
mule.description = S("Mule")
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.sounds = table.copy(donkey.sounds)
mule.sounds.base_pitch = 1.15
mule.collisionbox = {
horse.collisionbox[1] * m,
horse.collisionbox[2] * m,
horse.collisionbox[3] * m,
horse.collisionbox[4] * m,
horse.collisionbox[5] * m,
horse.collisionbox[6] * m,
}
mcl_mobs:register_mob("mobs_mc:mule", mule)
--===========================
--Spawn Function
mcl_mobs:spawn_specific(
"mobs_mc:horse",
"overworld",
"ground",
{
"flat",
"IcePlainsSpikes",
"ColdTaiga",
"ColdTaiga_beach",
"ColdTaiga_beach_water",
"MegaTaiga",
"MegaSpruceTaiga",
"ExtremeHills",
"ExtremeHills_beach",
"ExtremeHillsM",
"ExtremeHills+",
"ExtremeHills+_snowtop",
"StoneBeach",
"Plains",
"Plains_beach",
"SunflowerPlains",
"Taiga",
"Taiga_beach",
"Forest",
"Forest_beach",
"FlowerForest",
"FlowerForest_beach",
"BirchForest",
"BirchForestM",
"RoofedForest",
"Savanna",
"Savanna_beach",
"SavannaM",
"Jungle",
"Jungle_shore",
"JungleM",
"JungleM_shore",
"JungleEdge",
"JungleEdgeM",
"Swampland",
"Swampland_shore"
},
0,
minetest.LIGHT_MAX+1,
30,
15000,
4,
mobs_mc.water_level+3,
mcl_vars.mg_overworld_max)
mcl_mobs:spawn_specific(
"mobs_mc:donkey",
"overworld",
"ground",
{
"Mesa",
"MesaPlateauFM_grasstop",
"MesaPlateauF",
"MesaPlateauFM",
"MesaPlateauF_grasstop",
"MesaBryce",
},
0,
minetest.LIGHT_MAX+1,
30,
15000,
4,
mobs_mc.water_level+3,
mcl_vars.mg_overworld_max)
-- spawn eggs
mcl_mobs:register_egg("mobs_mc:horse", S("Horse"), "mobs_mc_spawn_icon_horse.png", 0)
mcl_mobs:register_egg("mobs_mc:skeleton_horse", S("Skeleton Horse"), "mobs_mc_spawn_icon_horse_skeleton.png", 0)
--mobs:register_egg("mobs_mc:zombie_horse", S("Zombie Horse"), "mobs_mc_spawn_icon_horse_zombie.png", 0)
mcl_mobs:register_egg("mobs_mc:donkey", S("Donkey"), "mobs_mc_spawn_icon_donkey.png", 0)
mcl_mobs:register_egg("mobs_mc:mule", S("Mule"), "mobs_mc_spawn_icon_mule.png", 0)

View File

@ -1,144 +0,0 @@
--MCmobs v0.4
--maikerumine
--made for MC like Survival game
--License for code WTFPL and otherwise stated in readmes
mobs_mc = {}
local pr = PseudoRandom(os.time()*5)
local offsets = {}
for x=-2, 2 do
for z=-2, 2 do
table.insert(offsets, {x=x, y=0, z=z})
end
end
--[[ Periodically check and teleport mob to owner if not sitting (order ~= "sit") and
the owner is too far away. To be used with do_custom. Note: Optimized for mobs smaller than 1×1×1.
Larger mobs might have space problems after teleportation.
* dist: Minimum required distance from owner to teleport. Default: 12
* teleport_check_interval: Optional. Interval in seconds to check the mob teleportation. Default: 4 ]]
mobs_mc.make_owner_teleport_function = function(dist, teleport_check_interval)
return function(self, dtime)
-- No teleportation if no owner or if sitting
if not self.owner or self.order == "sit" then
return
end
if not teleport_check_interval then
teleport_check_interval = 4
end
if not dist then
dist = 12
end
if self._teleport_timer == nil then
self._teleport_timer = teleport_check_interval
return
end
self._teleport_timer = self._teleport_timer - dtime
if self._teleport_timer <= 0 then
self._teleport_timer = teleport_check_interval
local mob_pos = self.object:get_pos()
local owner = minetest.get_player_by_name(self.owner)
if not owner then
-- No owner found, no teleportation
return
end
local owner_pos = owner:get_pos()
local dist_from_owner = vector.distance(owner_pos, mob_pos)
if dist_from_owner > dist then
-- Check for nodes below air in a 5×1×5 area around the owner position
local check_offsets = table.copy(offsets)
-- Attempt to place mob near player. Must be placed on walkable node below a non-walkable one. Place inside that air node.
while #check_offsets > 0 do
local r = pr:next(1, #check_offsets)
local telepos = vector.add(owner_pos, check_offsets[r])
local telepos_below = {x=telepos.x, y=telepos.y-1, z=telepos.z}
table.remove(check_offsets, r)
-- Long story short, spawn on a platform
local trynode = minetest.registered_nodes[minetest.get_node(telepos).name]
local trybelownode = minetest.registered_nodes[minetest.get_node(telepos_below).name]
if trynode and not trynode.walkable and
trybelownode and trybelownode.walkable then
-- Correct position found! Let's teleport.
self.object:set_pos(telepos)
return
end
end
end
end
end
end
local function is_forbidden_node(pos, node)
node = node or minetest.get_node(pos)
return minetest.get_item_group(node.name, "stair") > 0 or minetest.get_item_group(node.name, "slab") > 0 or minetest.get_item_group(node.name, "carpet") > 0
end
function mcl_mobs:spawn_abm_check(pos, node, name)
-- Don't spawn monsters on mycelium
if (node.name == "mcl_core:mycelium" or node.name == "mcl_core:mycelium_snow") and minetest.registered_entities[name].type == "monster" then
return true
--Don't Spawn mobs on stairs, slabs, or carpets
elseif is_forbidden_node(pos, node) or is_forbidden_node(vector.add(pos, vector.new(0, 1, 0))) then
return true
-- Spawn on opaque or liquid nodes
elseif minetest.get_item_group(node.name, "opaque") ~= 0 or minetest.registered_nodes[node.name].liquidtype ~= "none" or node.name == "mcl_core:grass_path" then
return false
end
-- Reject everything else
return true
end
mobs_mc.shears_wear = 276
mobs_mc.water_level = tonumber(minetest.settings:get("water_level")) or 0
-- Animals
local path = minetest.get_modpath("mobs_mc")
dofile(path .. "/bat.lua") -- Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/rabbit.lua") -- Mesh and animation byExeterDad
dofile(path .. "/chicken.lua") -- Mesh and animation by Pavel_S
dofile(path .. "/cow+mooshroom.lua") -- Mesh by Morn76 Animation by Pavel_S
dofile(path .. "/horse.lua") -- KrupnoPavel; Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/llama.lua") -- Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/ocelot.lua") -- Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/parrot.lua") -- Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/pig.lua") -- Mesh and animation by Pavel_S
dofile(path .. "/polar_bear.lua") -- Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/sheep.lua") -- Mesh and animation by Pavel_S
dofile(path .. "/wolf.lua") -- KrupnoPavel
dofile(path .. "/squid.lua") -- Animation, sound and egg texture by daufinsyd
-- NPCs
dofile(path .. "/villager.lua") -- KrupnoPavel Mesh and animation by toby109tt / https://github.com/22i
-- Illagers and witch
dofile(path .. "/villager_evoker.lua") -- Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/villager_vindicator.lua") -- Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/villager_zombie.lua") -- Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/witch.lua") -- Mesh and animation by toby109tt / https://github.com/22i
--Monsters
dofile(path .. "/blaze.lua") -- Animation by daufinsyd
dofile(path .. "/creeper.lua") -- Mesh by Morn76 Animation by Pavel_S
dofile(path .. "/ender_dragon.lua") -- Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/enderman.lua") -- Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/endermite.lua") -- Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/villager_illusioner.lua") -- Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/ghast.lua") -- maikerumine
dofile(path .. "/guardian.lua") -- maikerumine Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/guardian_elder.lua") -- maikerumine Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/snowman.lua")
dofile(path .. "/iron_golem.lua") -- maikerumine Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/shulker.lua") -- maikerumine Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/silverfish.lua") -- maikerumine Mesh and animation by toby109tt / https://github.com/22i
dofile(path .. "/skeleton+stray.lua") -- Mesh by Morn76 Animation by Pavel_S
dofile(path .. "/skeleton_wither.lua") -- Mesh by Morn76 Animation by Pavel_S
dofile(path .. "/zombie.lua") -- Mesh by Morn76 Animation by Pavel_S
dofile(path .. "/zombiepig.lua") -- Mesh by Morn76 Animation by Pavel_S
dofile(path .. "/slime+magma_cube.lua") -- Wuzzy
dofile(path .. "/spider.lua") -- Spider by AspireMint (fishyWET (CC-BY-SA 3.0 license for texture)
dofile(path .. "/vex.lua") -- KrupnoPavel
dofile(path .. "/wither.lua") -- Mesh and animation by toby109tt / https://github.com/22i

View File

@ -1,204 +0,0 @@
--MCmobs v0.4
--maikerumine
--made for MC like Survival game
--License for code WTFPL and otherwise stated in readmes
local S = minetest.get_translator("mobs_mc")
--###################
--################### IRON GOLEM
--###################
local etime = 0
mcl_mobs:register_mob("mobs_mc:iron_golem", {
description = S("Iron Golem"),
type = "npc",
spawn_class = "passive",
passive = true,
hp_min = 100,
hp_max = 100,
breath_max = -1,
collisionbox = {-0.7, -0.01, -0.7, 0.7, 2.69, 0.7},
visual = "mesh",
mesh = "mobs_mc_iron_golem.b3d",
textures = {
{"mobs_mc_iron_golem.png"},
},
visual_size = {x=3, y=3},
makes_footstep_sound = true,
-- TODO: sounds
view_range = 16,
stepheight = 1.1,
owner = "",
order = "follow",
floats = 0,
walk_velocity = 0.6,
run_velocity = 1.2,
-- Approximation
damage = 14,
reach = 3,
group_attack = true,
attacks_monsters = true,
attack_type = "dogfight",
_got_poppy = false,
pick_up = {"mcl_flowers:poppy"},
on_pick_up = function(self,n)
if n.itemstring:find("mcl_flowers:poppy") then
if not self._got_poppy then
self._got_poppy=true
return
end
return true
end
end,
replace_what = {"mcl_flowers:poppy"},
replace_with = {"air"},
on_replace = function(self, pos, oldnode, newnode)
if not self.got_poppy and oldnode.name == "mcl_flowers:poppy" then
self._got_poppy=true
return
end
return false
end,
drops = {
{name = "mcl_core:iron_ingot",
chance = 1,
min = 3,
max = 5,},
{name = "mcl_flowers:poppy",
chance = 1,
min = 0,
max = 2,},
},
fall_damage = 0,
animation = {
stand_speed = 15, walk_speed = 15, run_speed = 25, punch_speed = 15,
stand_start = 0, stand_end = 0,
walk_start = 0, walk_end = 40,
run_start = 0, run_end = 40,
punch_start = 40, punch_end = 50,
},
jump = true,
on_step = function(self,dtime)
etime = etime + dtime
if etime > 10 then
if self._home and vector.distance(self._home,self.object:get_pos()) > 50 then
mcl_mobs:gopath(self,self._home)
end
end
end,
})
-- spawn eggs
mcl_mobs:register_egg("mobs_mc:iron_golem", S("Iron Golem"), "mobs_mc_spawn_icon_iron_golem.png", 0)
--[[ This is to be called when a pumpkin or jack'o lantern has been placed. Recommended: In the on_construct function of the node.
This summons an iron golen if placing the pumpkin created an iron golem summon pattern:
.P.
III
.I.
P = Pumpkin or jack'o lantern
I = Iron block
. = Air
]]
function mobs_mc.check_iron_golem_summon(pos)
local checks = {
-- These are the possible placement patterns, with offset from the pumpkin block.
-- These tables include the positions of the iron blocks (1-4) and air blocks (5-8)
-- 4th element is used to determine spawn position.
-- If a 9th element is present, that one is used for the spawn position instead.
-- Standing (x axis)
{
{x=-1, y=-1, z=0}, {x=1, y=-1, z=0}, {x=0, y=-1, z=0}, {x=0, y=-2, z=0}, -- iron blocks
{x=-1, y=0, z=0}, {x=1, y=0, z=0}, {x=-1, y=-2, z=0}, {x=1, y=-2, z=0}, -- air
},
-- Upside down standing (x axis)
{
{x=-1, y=1, z=0}, {x=1, y=1, z=0}, {x=0, y=1, z=0}, {x=0, y=2, z=0},
{x=-1, y=0, z=0}, {x=1, y=0, z=0}, {x=-1, y=2, z=0}, {x=1, y=2, z=0},
{x=0, y=0, z=0}, -- Different offset for upside down pattern
},
-- Standing (z axis)
{
{x=0, y=-1, z=-1}, {x=0, y=-1, z=1}, {x=0, y=-1, z=0}, {x=0, y=-2, z=0},
{x=0, y=0, z=-1}, {x=0, y=0, z=1}, {x=0, y=-2, z=-1}, {x=0, y=-2, z=1},
},
-- Upside down standing (z axis)
{
{x=0, y=1, z=-1}, {x=0, y=1, z=1}, {x=0, y=1, z=0}, {x=0, y=2, z=0},
{x=0, y=0, z=-1}, {x=0, y=0, z=1}, {x=0, y=2, z=-1}, {x=0, y=2, z=1},
{x=0, y=0, z=0},
},
-- Lying
{
{x=-1, y=0, z=-1}, {x=0, y=0, z=-1}, {x=1, y=0, z=-1}, {x=0, y=0, z=-2},
{x=-1, y=0, z=0}, {x=1, y=0, z=0}, {x=-1, y=0, z=-2}, {x=1, y=0, z=-2},
},
{
{x=-1, y=0, z=1}, {x=0, y=0, z=1}, {x=1, y=0, z=1}, {x=0, y=0, z=2},
{x=-1, y=0, z=0}, {x=1, y=0, z=0}, {x=-1, y=0, z=2}, {x=1, y=0, z=2},
},
{
{x=-1, y=0, z=-1}, {x=-1, y=0, z=0}, {x=-1, y=0, z=1}, {x=-2, y=0, z=0},
{x=0, y=0, z=-1}, {x=0, y=0, z=1}, {x=-2, y=0, z=-1}, {x=-2, y=0, z=1},
},
{
{x=1, y=0, z=-1}, {x=1, y=0, z=0}, {x=1, y=0, z=1}, {x=2, y=0, z=0},
{x=0, y=0, z=-1}, {x=0, y=0, z=1}, {x=2, y=0, z=-1}, {x=2, y=0, z=1},
},
}
for c=1, #checks do
-- Check all possible patterns
local ok = true
-- Check iron block nodes
for i=1, 4 do
local cpos = vector.add(pos, checks[c][i])
local node = minetest.get_node(cpos)
if node.name ~= "mcl_core:ironblock" then
ok = false
break
end
end
-- Check air nodes
for a=5, 8 do
local cpos = vector.add(pos, checks[c][a])
local node = minetest.get_node(cpos)
if node.name ~= "air" then
ok = false
break
end
end
-- Pattern found!
if ok then
-- Remove the nodes
minetest.remove_node(pos)
core.check_for_falling(pos)
for i=1, 4 do
local cpos = vector.add(pos, checks[c][i])
minetest.remove_node(cpos)
core.check_for_falling(cpos)
end
-- Summon iron golem
local place
if checks[c][9] then
place = vector.add(pos, checks[c][9])
else
place = vector.add(pos, checks[c][4])
end
place.y = place.y - 0.5
minetest.add_entity(place, "mobs_mc:iron_golem")
break
end
end
end

View File

@ -1,242 +0,0 @@
local S = minetest.get_translator("mobs_mc")
--###################
--################### LLAMA
--###################
local carpets = {
-- group = { carpet , short_texture_name }
unicolor_white = { "mcl_wool:white_carpet", "white" },
unicolor_dark_orange = { "mcl_wool:brown_carpet", "brown" },
unicolor_grey = { "mcl_wool:silver_carpet", "light_gray" },
unicolor_darkgrey = { "mcl_wool:grey_carpet", "gray" },
unicolor_blue = { "mcl_wool:blue_carpet", "blue" },
unicolor_dark_green = { "mcl_wool:green_carpet", "green" },
unicolor_green = { "mcl_wool:lime_carpet", "lime" },
unicolor_violet = { "mcl_wool:purple_carpet", "purple" },
unicolor_light_red = { "mcl_wool:pink_carpet", "pink" },
unicolor_yellow = { "mcl_wool:yellow_carpet", "yellow" },
unicolor_orange = { "mcl_wool:orange_carpet", "orange" },
unicolor_red = { "mcl_wool:red_carpet", "red" },
unicolor_cyan = { "mcl_wool:cyan_carpet", "cyan" },
unicolor_red_violet = { "mcl_wool:magenta_carpet", "magenta" },
unicolor_black = { "mcl_wool:black_carpet", "black" },
unicolor_light_blue = { "mcl_wool:light_blue_carpet", "light_blue" },
}
mcl_mobs:register_mob("mobs_mc:llama", {
description = S("Llama"),
type = "animal",
spawn_class = "passive",
hp_min = 15,
hp_max = 30,
xp_min = 1,
xp_max = 3,
passive = false,
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.86, 0.45},
visual = "mesh",
mesh = "mobs_mc_llama.b3d",
textures = { -- 1: chest -- 2: decor (carpet) -- 3: llama base texture
{"blank.png", "blank.png", "mobs_mc_llama_brown.png"},
{"blank.png", "blank.png", "mobs_mc_llama_creamy.png"},
{"blank.png", "blank.png", "mobs_mc_llama_gray.png"},
{"blank.png", "blank.png", "mobs_mc_llama_white.png"},
{"blank.png", "blank.png", "mobs_mc_llama.png"},
},
visual_size = {x=3, y=3},
makes_footstep_sound = true,
runaway = true,
walk_velocity = 1,
run_velocity = 4.4,
follow_velocity = 4.4,
floats = 1,
drops = {
{name = "mcl_mobitems:leather",
chance = 1,
min = 0,
max = 2,
looting = "common",},
},
fear_height = 4,
sounds = {
random = "mobs_mc_llama",
eat = "mobs_mc_animal_eat_generic",
-- TODO: Death and damage sounds
distance = 16,
},
animation = {
speed_normal = 24,
run_speed = 60,
run_start = 0,
run_end = 40,
stand_start = 0,
stand_end = 0,
walk_start = 0,
walk_end = 40,
hurt_start = 118,
hurt_end = 154,
death_start = 154,
death_end = 179,
eat_start = 49,
eat_end = 78,
look_start = 78,
look_end = 108,
},
follow = { "mcl_farming:wheat_item", "mcl_farming:hay_block" },
view_range = 16,
do_custom = function(self, dtime)
-- set needed values if not already present
if not self.v2 then
self.v2 = 0
self.max_speed_forward = 4
self.max_speed_reverse = 2
self.accel = 4
self.terrain_type = 3
self.driver_attach_at = {x = 0, y = 4.17, z = -1.5}
self.driver_eye_offset = {x = 0, y = 3, z = 0}
self.driver_scale = {x = 1/self.visual_size.x, y = 1/self.visual_size.y}
end
-- if driver present allow control of llama
if self.driver then
mcl_mobs.drive(self, "walk", "stand", false, dtime)
return false -- skip rest of mob functions
end
return true
end,
on_die = function(self, pos)
-- detach from llama properly
if self.driver then
mcl_mobs.detach(self.driver, {x = 1, y = 0, z = 1})
end
end,
on_rightclick = function(self, clicker)
-- Make sure player is clicking
if not clicker or not clicker:is_player() then
return
end
local item = clicker:get_wielded_item()
if item:get_name() == "mcl_farming:hay_block" then
-- Breed with hay bale
if mcl_mobs:feed_tame(self, clicker, 1, true, false) then return end
else
-- Feed with anything else
if mcl_mobs:feed_tame(self, clicker, 1, false, true) then return end
end
if mcl_mobs:protect(self, clicker) then return end
-- Make sure tamed llama is mature and being clicked by owner only
if self.tamed and not self.child and self.owner == clicker:get_player_name() then
-- Place carpet
if minetest.get_item_group(item:get_name(), "carpet") == 1 and not self.carpet then
for group, carpetdata in pairs(carpets) do
if minetest.get_item_group(item:get_name(), group) == 1 then
if not minetest.is_creative_enabled(clicker:get_player_name()) then
item:take_item()
clicker:set_wielded_item(item)
end
local substr = carpetdata[2]
local tex_carpet = "mobs_mc_llama_decor_"..substr..".png"
self.base_texture = table.copy(self.base_texture)
self.base_texture[2] = tex_carpet
self.object:set_properties({
textures = self.base_texture,
})
self.carpet = item:get_name()
self.drops = {
{name = "mcl_mobitems:leather",
chance = 1,
min = 0,
max = 2,},
{name = item:get_name(),
chance = 1,
min = 1,
max = 1,},
}
return
end
end
end
-- detatch player already riding llama
if self.driver and clicker == self.driver then
mcl_mobs.detach(clicker, {x = 1, y = 0, z = 1})
-- attach player to llama
elseif not self.driver then
self.object:set_properties({stepheight = 1.1})
mcl_mobs.attach(self, clicker)
end
-- Used to capture llama
elseif not self.driver and clicker:get_wielded_item():get_name() ~= "" then
mcl_mobs:capture_mob(self, clicker, 0, 5, 60, false, nil)
end
end,
on_breed = function(parent1, parent2)
-- When breeding, make sure the child has no carpet
local pos = parent1.object:get_pos()
local child, parent
if math.random(1,2) == 1 then
parent = parent1
else
parent = parent2
end
child = mcl_mobs:spawn_child(pos, parent.name)
if child then
local ent_c = child:get_luaentity()
ent_c.base_texture = table.copy(ent_c.base_texture)
ent_c.base_texture[2] = "blank.png"
child:set_properties({textures = ent_c.base_texture})
ent_c.tamed = true
ent_c.carpet = nil
ent_c.owner = parent.owner
return false
end
end,
})
--spawn
mcl_mobs:spawn_specific(
"mobs_mc:llama",
"overworld",
"ground",
{
"Mesa",
"MesaPlateauFM_grasstop",
"MesaPlateauF",
"MesaPlateauFM",
"MesaPlateauF_grasstop",
"MesaBryce",
"Jungle",
"Jungle_shore",
"JungleM",
"JungleM_shore",
"JungleEdge",
"JungleEdgeM",
},
0,
minetest.LIGHT_MAX+1,
30,
15000,
5,
mobs_mc.water_level+15,
mcl_vars.mg_overworld_max)
-- spawn eggs
mcl_mobs:register_egg("mobs_mc:llama", S("Llama"), "mobs_mc_spawn_icon_llama.png", 0)

Some files were not shown because too many files have changed in this diff Show More