Merge master of upstream https://notabug.org/TenPlus1/mobs_redo into main
* can now ride mobs redo mobs in mineclone2 (must be fine tuned) better MineClone2 compatibility for api, items and crafts * harder player checks (must be in better way) add check to see what hit mob, player or entity for immune_to * monsters will always attack creatura mobs, anything else will defend it's owner if attacked * change mobs_swing.ogg to mono * can now add nodes to 'runaway_from' table * add damage_per_second nil check * on_breed spawns child a little higher * remove htimer, tweak update_tag() * add mtobjid mod to optional dependencies, stop mob count going * added check to be sure creatura mod enabled * if max_light_damage is 16 then use natural light value to damage mob * min/max light set to 15, only kill mob with natural light * better way to reset pause_timer with "stand" order * pause timer reset, mobs ordered to "stand", fix knockback * fix group attack anim reset, tidy code * simplify yaw clamping
This commit is contained in:
commit
90292f9af2
100
api.lua
100
api.lua
@ -27,10 +27,14 @@ local use_cmi = minetest.global_exists("cmi")
|
|||||||
|
|
||||||
mobs = {
|
mobs = {
|
||||||
mod = "redo",
|
mod = "redo",
|
||||||
version = "20230613",
|
version = "20230726",
|
||||||
intllib = S,
|
intllib = S,
|
||||||
invis = minetest.global_exists("invisibility") and invisibility or {}
|
invis = minetest.global_exists("invisibility") and invisibility or {},
|
||||||
|
node_snow = minetest.registered_aliases["mapgen_snow"] or "mcl_core:snow",
|
||||||
|
node_dirt = minetest.registered_aliases["mapgen_dirt"] or "mcl_core:dirt"
|
||||||
}
|
}
|
||||||
|
mobs.fallback_node = mobs.node_dirt
|
||||||
|
|
||||||
|
|
||||||
-- localize common functions
|
-- localize common functions
|
||||||
local pi = math.pi
|
local pi = math.pi
|
||||||
@ -135,12 +139,6 @@ local aoc_range = tonumber(settings:get("active_block_range")) * 16
|
|||||||
local creatura = minetest.get_modpath("creatura") and
|
local creatura = minetest.get_modpath("creatura") and
|
||||||
settings:get_bool("mobs_attack_creatura") == true
|
settings:get_bool("mobs_attack_creatura") == true
|
||||||
|
|
||||||
-- default nodes
|
|
||||||
local node_ice = "default:ice"
|
|
||||||
local node_snowblock = "default:snowblock"
|
|
||||||
local node_snow = "default:snow"
|
|
||||||
|
|
||||||
mobs.fallback_node = minetest.registered_aliases["mapgen_dirt"] or "default:dirt"
|
|
||||||
|
|
||||||
mobs.mob_class = {
|
mobs.mob_class = {
|
||||||
stepheight = 1.1,
|
stepheight = 1.1,
|
||||||
@ -265,6 +263,15 @@ local get_distance = function(a, b)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- are we a real player ?
|
||||||
|
local function is_player(player)
|
||||||
|
|
||||||
|
if player and type(player) == "userdata" and minetest.is_player(player) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- collision function based on jordan4ibanez' open_ai mod
|
-- collision function based on jordan4ibanez' open_ai mod
|
||||||
function mob_class:collision()
|
function mob_class:collision()
|
||||||
|
|
||||||
@ -275,7 +282,7 @@ function mob_class:collision()
|
|||||||
|
|
||||||
for _,object in ipairs(minetest.get_objects_inside_radius(pos, width)) do
|
for _,object in ipairs(minetest.get_objects_inside_radius(pos, width)) do
|
||||||
|
|
||||||
if object:is_player() then
|
if is_player(object) then
|
||||||
|
|
||||||
local pos2 = object:get_pos()
|
local pos2 = object:get_pos()
|
||||||
local vec = {x = pos.x - pos2.x, z = pos.z - pos2.z}
|
local vec = {x = pos.x - pos2.x, z = pos.z - pos2.z}
|
||||||
@ -858,7 +865,7 @@ function mob_class:item_drop()
|
|||||||
-- was mob killed by player?
|
-- was mob killed by player?
|
||||||
local death_by_player = self.cause_of_death
|
local death_by_player = self.cause_of_death
|
||||||
and self.cause_of_death.puncher
|
and self.cause_of_death.puncher
|
||||||
and self.cause_of_death.puncher:is_player()
|
and is_player(self.cause_of_death.puncher)
|
||||||
|
|
||||||
-- check for tool 'looting_level' under tool_capabilities as default, or use
|
-- check for tool 'looting_level' under tool_capabilities as default, or use
|
||||||
-- meta string 'looting_level' if found (max looting level is 3).
|
-- meta string 'looting_level' if found (max looting level is 3).
|
||||||
@ -1312,7 +1319,7 @@ function mob_class:do_jump()
|
|||||||
and (self.walk_chance == 0 or minetest.registered_items[self.looking_at].walkable)
|
and (self.walk_chance == 0 or minetest.registered_items[self.looking_at].walkable)
|
||||||
and not blocked
|
and not blocked
|
||||||
and not self.facing_fence
|
and not self.facing_fence
|
||||||
and self.looking_at ~= node_snow then
|
and self.looking_at ~= mobs.node_snow then
|
||||||
|
|
||||||
local v = self.object:get_velocity()
|
local v = self.object:get_velocity()
|
||||||
|
|
||||||
@ -2015,7 +2022,7 @@ function mob_class:general_attack()
|
|||||||
local ent = objs[n]:get_luaentity()
|
local ent = objs[n]:get_luaentity()
|
||||||
|
|
||||||
-- are we a player?
|
-- are we a player?
|
||||||
if objs[n]:is_player() then
|
if is_player(objs[n]) then
|
||||||
|
|
||||||
-- if player invisible or mob cannot attack then remove from list
|
-- if player invisible or mob cannot attack then remove from list
|
||||||
if not damage_enabled
|
if not damage_enabled
|
||||||
@ -2110,9 +2117,10 @@ function mob_class:do_runaway_from()
|
|||||||
local min_dist = self.view_range + 1
|
local min_dist = self.view_range + 1
|
||||||
local objs = minetest.get_objects_inside_radius(s, self.view_range)
|
local objs = minetest.get_objects_inside_radius(s, self.view_range)
|
||||||
|
|
||||||
|
-- loop through entities surrounding mob
|
||||||
for n = 1, #objs do
|
for n = 1, #objs do
|
||||||
|
|
||||||
if objs[n]:is_player() then
|
if is_player(objs[n]) then
|
||||||
|
|
||||||
pname = objs[n]:get_player_name()
|
pname = objs[n]:get_player_name()
|
||||||
|
|
||||||
@ -2161,6 +2169,20 @@ function mob_class:do_runaway_from()
|
|||||||
self.state = "runaway"
|
self.state = "runaway"
|
||||||
self.runaway_timer = 3
|
self.runaway_timer = 3
|
||||||
self.following = nil
|
self.following = nil
|
||||||
|
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- check for nodes to runaway from
|
||||||
|
objs = minetest.find_node_near(s, self.view_range, self.runaway_from, true)
|
||||||
|
|
||||||
|
if objs then
|
||||||
|
|
||||||
|
yaw_to_pos(self, objs, 3)
|
||||||
|
|
||||||
|
self.state = "runaway"
|
||||||
|
self.runaway_timer = 3
|
||||||
|
self.following = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2203,7 +2225,7 @@ function mob_class:follow_flop()
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- stop following player if not holding specific item or mob is horny
|
-- stop following player if not holding specific item or mob is horny
|
||||||
if self.following and self.following:is_player()
|
if self.following and is_player(self.following)
|
||||||
and (self:follow_holding(self.following) == false or self.horny) then
|
and (self:follow_holding(self.following) == false or self.horny) then
|
||||||
self.following = nil
|
self.following = nil
|
||||||
end
|
end
|
||||||
@ -2216,7 +2238,7 @@ function mob_class:follow_flop()
|
|||||||
local s = self.object:get_pos()
|
local s = self.object:get_pos()
|
||||||
local p
|
local p
|
||||||
|
|
||||||
if self.following:is_player() then
|
if is_player(self.following) then
|
||||||
p = self.following:get_pos()
|
p = self.following:get_pos()
|
||||||
elseif self.following.object then
|
elseif self.following.object then
|
||||||
p = self.following.object:get_pos()
|
p = self.following.object:get_pos()
|
||||||
@ -2316,22 +2338,13 @@ function mob_class:do_states(dtime)
|
|||||||
if is_node_dangerous(self, self.standing_in) then
|
if is_node_dangerous(self, self.standing_in) then
|
||||||
|
|
||||||
local s = self.object:get_pos()
|
local s = self.object:get_pos()
|
||||||
local lp
|
local grps = {}
|
||||||
|
|
||||||
-- is there something I need to avoid?
|
if self.water_damage > 0 then table.insert(grps, "group:water") end
|
||||||
if self.water_damage > 0
|
if self.fire_damage > 0 then table.insert(grps, "group:fire") end
|
||||||
and self.lava_damage > 0 then
|
if self.lava_damage > 0 then table.insert(grps, "group:lava") end
|
||||||
|
|
||||||
lp = minetest.find_node_near(s, 1, {"group:water", "group:igniter"})
|
local lp = minetest.find_node_near(s, 1, grps)
|
||||||
|
|
||||||
elseif self.water_damage > 0 then
|
|
||||||
|
|
||||||
lp = minetest.find_node_near(s, 1, {"group:water"})
|
|
||||||
|
|
||||||
elseif self.lava_damage > 0 then
|
|
||||||
|
|
||||||
lp = minetest.find_node_near(s, 1, {"group:igniter"})
|
|
||||||
end
|
|
||||||
|
|
||||||
if lp then
|
if lp then
|
||||||
|
|
||||||
@ -2340,7 +2353,7 @@ function mob_class:do_states(dtime)
|
|||||||
lp = minetest.find_nodes_in_area_under_air(
|
lp = minetest.find_nodes_in_area_under_air(
|
||||||
{x = s.x - 5, y = s.y , z = s.z - 5},
|
{x = s.x - 5, y = s.y , z = s.z - 5},
|
||||||
{x = s.x + 5, y = s.y + 2, z = s.z + 5},
|
{x = s.x + 5, y = s.y + 2, z = s.z + 5},
|
||||||
{"group:soil", "group:stone", "group:sand", node_ice, node_snowblock})
|
{"group:cracky", "group:crumbly", "group:choppy", "group:solid"})
|
||||||
|
|
||||||
-- did we find land?
|
-- did we find land?
|
||||||
if lp and #lp > 0 then
|
if lp and #lp > 0 then
|
||||||
@ -2372,7 +2385,7 @@ function mob_class:do_states(dtime)
|
|||||||
|
|
||||||
for n = 1, #objs do
|
for n = 1, #objs do
|
||||||
|
|
||||||
if objs[n]:is_player() then
|
if is_player(objs[n]) then
|
||||||
lp = objs[n]:get_pos()
|
lp = objs[n]:get_pos()
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@ -2484,7 +2497,7 @@ function mob_class:do_states(dtime)
|
|||||||
or not self.attack
|
or not self.attack
|
||||||
or not self.attack:get_pos()
|
or not self.attack:get_pos()
|
||||||
or self.attack:get_hp() <= 0
|
or self.attack:get_hp() <= 0
|
||||||
or (self.attack:is_player()
|
or (is_player(self.attack)
|
||||||
and is_invisible(self, self.attack:get_player_name())) then
|
and is_invisible(self, self.attack:get_player_name())) then
|
||||||
|
|
||||||
--print(" ** stop attacking **", self.name, self.health, dist, self.view_range)
|
--print(" ** stop attacking **", self.name, self.health, dist, self.view_range)
|
||||||
@ -2875,7 +2888,7 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
|
|||||||
if self.protected then
|
if self.protected then
|
||||||
|
|
||||||
-- did player hit mob and if so is it in protected area
|
-- did player hit mob and if so is it in protected area
|
||||||
if hitter:is_player() then
|
if is_player(hitter) then
|
||||||
|
|
||||||
local player_name = hitter:get_player_name()
|
local player_name = hitter:get_player_name()
|
||||||
|
|
||||||
@ -2933,10 +2946,17 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- check if hit by player item or entity
|
||||||
|
local hit_item = weapon_def.name
|
||||||
|
|
||||||
|
if not is_player(hitter) then
|
||||||
|
hit_item = hitter:get_luaentity().name
|
||||||
|
end
|
||||||
|
|
||||||
-- check for tool immunity or special damage
|
-- check for tool immunity or special damage
|
||||||
for n = 1, #self.immune_to do
|
for n = 1, #self.immune_to do
|
||||||
|
|
||||||
if self.immune_to[n][1] == weapon_def.name then
|
if self.immune_to[n][1] == hit_item then
|
||||||
|
|
||||||
damage = self.immune_to[n][2] or 0
|
damage = self.immune_to[n][2] or 0
|
||||||
|
|
||||||
@ -3036,7 +3056,7 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
|
|||||||
local entity = hitter and hitter:get_luaentity()
|
local entity = hitter and hitter:get_luaentity()
|
||||||
|
|
||||||
-- check if arrow from same mob, if so then do no damage
|
-- check if arrow from same mob, if so then do no damage
|
||||||
if (entity and entity.name ~= self.arrow) or hitter:is_player() then
|
if (entity and entity.name ~= self.arrow) or is_player(hitter) then
|
||||||
self.health = self.health - floor(damage)
|
self.health = self.health - floor(damage)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -3399,7 +3419,7 @@ function mob_class:mob_expire(pos, dtime)
|
|||||||
|
|
||||||
for n = 1, #objs do
|
for n = 1, #objs do
|
||||||
|
|
||||||
if objs[n]:is_player() then
|
if is_player(objs[n]) then
|
||||||
|
|
||||||
self.lifetimer = 20
|
self.lifetimer = 20
|
||||||
|
|
||||||
@ -3779,7 +3799,7 @@ local function count_mobs(pos, type)
|
|||||||
|
|
||||||
for n = 1, #objs do
|
for n = 1, #objs do
|
||||||
|
|
||||||
if not objs[n]:is_player() then
|
if not is_player(objs[n]) then
|
||||||
|
|
||||||
ent = objs[n]:get_luaentity()
|
ent = objs[n]:get_luaentity()
|
||||||
|
|
||||||
@ -4101,7 +4121,7 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
|
|||||||
|
|
||||||
for n = 1, #objs do
|
for n = 1, #objs do
|
||||||
|
|
||||||
if objs[n]:is_player() then
|
if is_player(objs[n]) then
|
||||||
--print("--- player too close", name)
|
--print("--- player too close", name)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -4297,7 +4317,7 @@ function mobs:register_arrow(name, def)
|
|||||||
|
|
||||||
for _,player in pairs(minetest.get_objects_inside_radius(pos, 1.0)) do
|
for _,player in pairs(minetest.get_objects_inside_radius(pos, 1.0)) do
|
||||||
|
|
||||||
if self.hit_player and player:is_player() then
|
if self.hit_player and is_player(player) then
|
||||||
|
|
||||||
self:hit_player(player)
|
self:hit_player(player)
|
||||||
|
|
||||||
@ -4545,7 +4565,7 @@ end
|
|||||||
function mobs:capture_mob(
|
function mobs:capture_mob(
|
||||||
self, clicker, chance_hand, chance_net, chance_lasso, force_take, replacewith)
|
self, clicker, chance_hand, chance_net, chance_lasso, force_take, replacewith)
|
||||||
|
|
||||||
if not self or not clicker:is_player() or not clicker:get_inventory() then
|
if not self or not is_player(clicker) or not clicker:get_inventory() then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
4
api.txt
4
api.txt
@ -154,8 +154,8 @@ functions needed for the mob to work properly which contains the following:
|
|||||||
'friendly_fire` when set to false, mobs will not be able to harm other
|
'friendly_fire` when set to false, mobs will not be able to harm other
|
||||||
mobs of the same type with friendly fire arrows.
|
mobs of the same type with friendly fire arrows.
|
||||||
Defaults to true.
|
Defaults to true.
|
||||||
'runaway_from' contains a table with mob names to run away from, add
|
'runaway_from' contains a table with mob names or nodesto run away
|
||||||
"player" to list to runaway from player also.
|
from, add "player" to list to runaway from player also.
|
||||||
'ignore_invisibility' When true mob will still be able to see and attack
|
'ignore_invisibility' When true mob will still be able to see and attack
|
||||||
player even if invisible (invisibility mod only).
|
player even if invisible (invisibility mod only).
|
||||||
'blood_amount' contains the number of blood droplets to appear when
|
'blood_amount' contains the number of blood droplets to appear when
|
||||||
|
89
crafts.lua
89
crafts.lua
@ -1,5 +1,24 @@
|
|||||||
|
|
||||||
local S = mobs.intllib
|
local S = mobs.intllib
|
||||||
|
local mc2 = minetest.get_modpath("mcl_core")
|
||||||
|
|
||||||
|
-- recipe items
|
||||||
|
local items = {
|
||||||
|
paper = mc2 and "mcl_core:paper" or "default:paper",
|
||||||
|
dye_black = mc2 and "mcl_dye:black" or "dye:black",
|
||||||
|
string = mc2 and "mcl_mobitems:string" or "farming:string",
|
||||||
|
stick = mc2 and "mcl_core:stick" or "default:stick",
|
||||||
|
diamond = mc2 and "mcl_core:diamond" or "default:diamond",
|
||||||
|
steel_ingot = mc2 and "mcl_core:iron_ingot" or "default:steel_ingot",
|
||||||
|
gold_block = mc2 and "mcl_core:goldblock" or "default:goldblock",
|
||||||
|
diamond_block = mc2 and "mcl_core:diamondblock" or "default:diamondblock",
|
||||||
|
stone = mc2 and "mcl_core:stone" or "default:stone",
|
||||||
|
mese_crystal = mc2 and "mcl_core:gold_ingot" or "default:mese_crystal",
|
||||||
|
wood = mc2 and "mcl_core:wood" or "default:wood",
|
||||||
|
fence_wood = mc2 and "group:fence_wood" or "default:fence_wood",
|
||||||
|
meat_raw = mc2 and "mcl_mobitems:beef" or "group:food_meat_raw",
|
||||||
|
meat_cooked = mc2 and "mcl_mobitems:cooked_beef" or "group:food_meat",
|
||||||
|
}
|
||||||
|
|
||||||
-- name tag
|
-- name tag
|
||||||
minetest.register_craftitem("mobs:nametag", {
|
minetest.register_craftitem("mobs:nametag", {
|
||||||
@ -8,12 +27,12 @@ minetest.register_craftitem("mobs:nametag", {
|
|||||||
groups = {flammable = 2, nametag = 1}
|
groups = {flammable = 2, nametag = 1}
|
||||||
})
|
})
|
||||||
|
|
||||||
if minetest.get_modpath("dye") and minetest.get_modpath("farming") then
|
minetest.register_craft({
|
||||||
minetest.register_craft({
|
|
||||||
output = "mobs:nametag",
|
output = "mobs:nametag",
|
||||||
recipe = {{"default:paper", "dye:black", "farming:string"}}
|
recipe = {
|
||||||
})
|
{ items.paper, items.dye_black, items.string }
|
||||||
end
|
}
|
||||||
|
})
|
||||||
|
|
||||||
-- leather
|
-- leather
|
||||||
minetest.register_craftitem("mobs:leather", {
|
minetest.register_craftitem("mobs:leather", {
|
||||||
@ -52,17 +71,14 @@ minetest.register_tool("mobs:lasso", {
|
|||||||
groups = {flammable = 2}
|
groups = {flammable = 2}
|
||||||
})
|
})
|
||||||
|
|
||||||
if minetest.get_modpath("farming") then
|
minetest.register_craft({
|
||||||
|
|
||||||
minetest.register_craft({
|
|
||||||
output = "mobs:lasso",
|
output = "mobs:lasso",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"farming:string", "", "farming:string"},
|
{ items.string, "", items.string},
|
||||||
{"", "default:diamond", ""},
|
{ "", items.diamond, "" },
|
||||||
{"farming:string", "", "farming:string"}
|
{ items.string, "", items.string }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
end
|
|
||||||
|
|
||||||
minetest.register_alias("mobs:magic_lasso", "mobs:lasso")
|
minetest.register_alias("mobs:magic_lasso", "mobs:lasso")
|
||||||
|
|
||||||
@ -73,17 +89,14 @@ minetest.register_tool("mobs:net", {
|
|||||||
groups = {flammable = 2}
|
groups = {flammable = 2}
|
||||||
})
|
})
|
||||||
|
|
||||||
if minetest.get_modpath("farming") then
|
minetest.register_craft({
|
||||||
|
|
||||||
minetest.register_craft({
|
|
||||||
output = "mobs:net",
|
output = "mobs:net",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"group:stick", "", "group:stick"},
|
{ items.stick, "", items.stick },
|
||||||
{"group:stick", "", "group:stick"},
|
{ items.stick, "", items.stick },
|
||||||
{"farming:string", "group:stick", "farming:string"}
|
{ items.string, items.stick, items.string }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
end
|
|
||||||
|
|
||||||
-- shears (right click to shear animal)
|
-- shears (right click to shear animal)
|
||||||
minetest.register_tool("mobs:shears", {
|
minetest.register_tool("mobs:shears", {
|
||||||
@ -95,8 +108,8 @@ minetest.register_tool("mobs:shears", {
|
|||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
output = "mobs:shears",
|
output = "mobs:shears",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"", "default:steel_ingot", ""},
|
{ "", items.steel_ingot, "" },
|
||||||
{"", "group:stick", "default:steel_ingot"}
|
{ "", items.stick, items.steel_ingot }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -110,9 +123,9 @@ minetest.register_craftitem("mobs:protector", {
|
|||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
output = "mobs:protector",
|
output = "mobs:protector",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"default:stone", "default:stone", "default:stone"},
|
{ items.stone, items.stone, items.stone },
|
||||||
{"default:stone", "default:goldblock", "default:stone"},
|
{ items.stone, items.gold_block, items.stone },
|
||||||
{"default:stone", "default:stone", "default:stone"}
|
{ items.stone, items.stone, items.stone }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -126,9 +139,9 @@ minetest.register_craftitem("mobs:protector2", {
|
|||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
output = "mobs:protector2",
|
output = "mobs:protector2",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"mobs:protector", "default:mese_crystal", "mobs:protector"},
|
{ "mobs:protector", items.mese_crystal, "mobs:protector" },
|
||||||
{"default:mese_crystal", "default:diamondblock", "default:mese_crystal"},
|
{ items.mese_crystal, items.diamond_block, items.mese_crystal },
|
||||||
{"mobs:protector", "default:mese_crystal", "mobs:protector"}
|
{ "mobs:protector", items.mese_crystal, "mobs:protector" }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -143,8 +156,8 @@ minetest.register_craft({
|
|||||||
output = "mobs:saddle",
|
output = "mobs:saddle",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"mobs:leather", "mobs:leather", "mobs:leather"},
|
{"mobs:leather", "mobs:leather", "mobs:leather"},
|
||||||
{"mobs:leather", "default:steel_ingot", "mobs:leather"},
|
{"mobs:leather", items.steel_ingot, "mobs:leather"},
|
||||||
{"mobs:leather", "default:steel_ingot", "mobs:leather"}
|
{"mobs:leather", items.steel_ingot, "mobs:leather"}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -197,7 +210,7 @@ minetest.register_craft({
|
|||||||
output = "mobs:fence_top 12",
|
output = "mobs:fence_top 12",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"group:wood", "group:wood", "group:wood"},
|
{"group:wood", "group:wood", "group:wood"},
|
||||||
{"", "default:fence_wood", ""}
|
{"", items.fence_wood, ""}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -372,9 +385,9 @@ minetest.register_node("mobs:meatblock", {
|
|||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
output = "mobs:meatblock",
|
output = "mobs:meatblock",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"group:food_meat", "group:food_meat", "group:food_meat"},
|
{ items.meat_cooked, items.meat_cooked, items.meat_cooked },
|
||||||
{"group:food_meat", "group:food_meat", "group:food_meat"},
|
{ items.meat_cooked, items.meat_cooked, items.meat_cooked },
|
||||||
{"group:food_meat", "group:food_meat", "group:food_meat"}
|
{ items.meat_cooked, items.meat_cooked, items.meat_cooked }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -392,9 +405,9 @@ minetest.register_node("mobs:meatblock_raw", {
|
|||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
output = "mobs:meatblock_raw",
|
output = "mobs:meatblock_raw",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"group:food_meat_raw", "group:food_meat_raw", "group:food_meat_raw"},
|
{ items.meat_raw, items.meat_raw, items.meat_raw },
|
||||||
{"group:food_meat_raw", "group:food_meat_raw", "group:food_meat_raw"},
|
{ items.meat_raw, items.meat_raw, items.meat_raw },
|
||||||
{"group:food_meat_raw", "group:food_meat_raw", "group:food_meat_raw"}
|
{ items.meat_raw, items.meat_raw, items.meat_raw }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
1
init.lua
1
init.lua
@ -7,6 +7,7 @@ minetest.register_privilege("peaceful_player", {
|
|||||||
give_to_singleplayer = false
|
give_to_singleplayer = false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
-- Mob API
|
-- Mob API
|
||||||
dofile(path .. "/api.lua")
|
dofile(path .. "/api.lua")
|
||||||
|
|
||||||
|
61
mount.lua
61
mount.lua
@ -1,6 +1,20 @@
|
|||||||
-- lib_mount by Blert2112 (edited by TenPlus1)
|
-- lib_mount by Blert2112 (edited by TenPlus1)
|
||||||
|
|
||||||
|
--[[ one of these is needed (for now) to ride mobs, otherwise no riding for you
|
||||||
|
if not minetest.get_modpath("default")
|
||||||
|
or not minetest.get_modpath("player_api") then
|
||||||
|
|
||||||
|
function mobs.attach() end
|
||||||
|
function mobs.detach() end
|
||||||
|
function mobs.fly() end
|
||||||
|
function mobs.drive() end
|
||||||
|
|
||||||
|
return
|
||||||
|
end
|
||||||
|
]]
|
||||||
|
|
||||||
local is_50 = minetest.get_modpath("player_api") -- 5.x compatibility
|
local is_50 = minetest.get_modpath("player_api") -- 5.x compatibility
|
||||||
|
local is_mc2 = minetest.get_modpath("mcl_mobs") -- MineClone2 compatibility
|
||||||
|
|
||||||
local abs, cos, floor, sin, sqrt, pi =
|
local abs, cos, floor, sin, sqrt, pi =
|
||||||
math.abs, math.cos, math.floor, math.sin, math.sqrt, math.pi
|
math.abs, math.cos, math.floor, math.sin, math.sqrt, math.pi
|
||||||
@ -75,9 +89,7 @@ end
|
|||||||
|
|
||||||
local function force_detach(player)
|
local function force_detach(player)
|
||||||
|
|
||||||
if not player then return end
|
local attached_to = player and player:get_attach()
|
||||||
|
|
||||||
local attached_to = player:get_attach()
|
|
||||||
|
|
||||||
if not attached_to then
|
if not attached_to then
|
||||||
return
|
return
|
||||||
@ -85,8 +97,7 @@ local function force_detach(player)
|
|||||||
|
|
||||||
local entity = attached_to:get_luaentity()
|
local entity = attached_to:get_luaentity()
|
||||||
|
|
||||||
if entity and entity.driver
|
if entity and entity.driver and entity.driver == player then
|
||||||
and entity.driver == player then
|
|
||||||
entity.driver = nil
|
entity.driver = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -97,6 +108,9 @@ local function force_detach(player)
|
|||||||
if is_50 then
|
if is_50 then
|
||||||
player_api.player_attached[name] = false
|
player_api.player_attached[name] = false
|
||||||
player_api.set_animation(player, "stand", 30)
|
player_api.set_animation(player, "stand", 30)
|
||||||
|
elseif is_mc2 then
|
||||||
|
mcl_player.player_attached[player:get_player_name()] = false
|
||||||
|
mcl_player.player_set_animation(player, "stand", 30)
|
||||||
else
|
else
|
||||||
default.player_attached[name] = false
|
default.player_attached[name] = false
|
||||||
default.player_set_animation(player, "stand", 30)
|
default.player_set_animation(player, "stand", 30)
|
||||||
@ -151,8 +165,7 @@ local function find_free_pos(pos)
|
|||||||
|
|
||||||
local def = minetest.registered_nodes[node.name]
|
local def = minetest.registered_nodes[node.name]
|
||||||
|
|
||||||
if def and not def.walkable and
|
if def and not def.walkable and def.liquidtype == "none" then
|
||||||
def.liquidtype == "none" then
|
|
||||||
return npos
|
return npos
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -162,6 +175,15 @@ local function find_free_pos(pos)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- are we a real player ?
|
||||||
|
local function is_player(player)
|
||||||
|
|
||||||
|
if player and type(player) == "userdata" and minetest.is_player(player) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function mobs.attach(entity, player)
|
function mobs.attach(entity, player)
|
||||||
|
|
||||||
entity.player_rotation = entity.player_rotation or {x = 0, y = 0, z = 0}
|
entity.player_rotation = entity.player_rotation or {x = 0, y = 0, z = 0}
|
||||||
@ -184,6 +206,8 @@ function mobs.attach(entity, player)
|
|||||||
|
|
||||||
if is_50 then
|
if is_50 then
|
||||||
player_api.player_attached[player:get_player_name()] = true
|
player_api.player_attached[player:get_player_name()] = true
|
||||||
|
elseif is_mc2 then
|
||||||
|
mcl_player.player_attached[player:get_player_name()] = true
|
||||||
else
|
else
|
||||||
default.player_attached[player:get_player_name()] = true
|
default.player_attached[player:get_player_name()] = true
|
||||||
end
|
end
|
||||||
@ -200,10 +224,12 @@ function mobs.attach(entity, player)
|
|||||||
|
|
||||||
minetest.after(0.2, function()
|
minetest.after(0.2, function()
|
||||||
|
|
||||||
if player and player:is_player() then
|
if is_player(player) then
|
||||||
|
|
||||||
if is_50 then
|
if is_50 then
|
||||||
player_api.set_animation(player, "sit", 30)
|
player_api.set_animation(player, "sit", 30)
|
||||||
|
elseif is_mc2 then
|
||||||
|
mcl_player.player_set_animation(player, "sit_mount" , 30)
|
||||||
else
|
else
|
||||||
default.player_set_animation(player, "sit", 30)
|
default.player_set_animation(player, "sit", 30)
|
||||||
end
|
end
|
||||||
@ -251,13 +277,11 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
|
|||||||
|
|
||||||
local ctrl = entity.driver:get_player_control()
|
local ctrl = entity.driver:get_player_control()
|
||||||
|
|
||||||
-- move forwards
|
if ctrl.up then -- move forwards
|
||||||
if ctrl.up then
|
|
||||||
|
|
||||||
entity.v = entity.v + entity.accel * dtime
|
entity.v = entity.v + entity.accel * dtime
|
||||||
|
|
||||||
-- move backwards
|
elseif ctrl.down then -- move backwards
|
||||||
elseif ctrl.down then
|
|
||||||
|
|
||||||
if entity.max_speed_reverse == 0 and entity.v == 0 then
|
if entity.max_speed_reverse == 0 and entity.v == 0 then
|
||||||
return
|
return
|
||||||
@ -287,8 +311,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
|
|||||||
|
|
||||||
if can_fly then
|
if can_fly then
|
||||||
|
|
||||||
-- fly up
|
if ctrl.jump then -- fly up
|
||||||
if ctrl.jump then
|
|
||||||
|
|
||||||
velo.y = velo.y + 1
|
velo.y = velo.y + 1
|
||||||
|
|
||||||
@ -301,8 +324,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
|
|||||||
if velo.y < 0 then velo.y = 0 end
|
if velo.y < 0 then velo.y = 0 end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- fly down
|
if ctrl.sneak then -- fly down
|
||||||
if ctrl.sneak then
|
|
||||||
|
|
||||||
velo.y = velo.y - 1
|
velo.y = velo.y - 1
|
||||||
|
|
||||||
@ -315,8 +337,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
|
|||||||
if velo.y > 0 then velo.y = 0 end
|
if velo.y > 0 then velo.y = 0 end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- jump
|
if ctrl.jump then -- jump
|
||||||
if ctrl.jump then
|
|
||||||
|
|
||||||
if velo.y == 0 then
|
if velo.y == 0 then
|
||||||
velo.y = velo.y + entity.jump_height
|
velo.y = velo.y + entity.jump_height
|
||||||
@ -449,12 +470,10 @@ end
|
|||||||
function mobs.fly(entity, _, speed, shoots, arrow, moving_anim, stand_anim)
|
function mobs.fly(entity, _, speed, shoots, arrow, moving_anim, stand_anim)
|
||||||
|
|
||||||
local ctrl = entity.driver:get_player_control() ; if not ctrl then return end
|
local ctrl = entity.driver:get_player_control() ; if not ctrl then return end
|
||||||
local velo = entity.object:get_velocity()
|
local velo = entity.object:get_velocity() ; if not velo then return end
|
||||||
local dir = entity.driver:get_look_dir()
|
local dir = entity.driver:get_look_dir()
|
||||||
local yaw = entity.driver:get_look_horizontal() + 1.57
|
local yaw = entity.driver:get_look_horizontal() + 1.57
|
||||||
|
|
||||||
if not ctrl or not velo then return end
|
|
||||||
|
|
||||||
if ctrl.up then
|
if ctrl.up then
|
||||||
|
|
||||||
entity.object:set_velocity({
|
entity.object:set_velocity({
|
||||||
|
@ -37,6 +37,8 @@ Zeg9, ExeterDad and AspireMint.
|
|||||||
* Refactored do_jump and added get_nodes function
|
* Refactored do_jump and added get_nodes function
|
||||||
* Many bug fixes and tweaks to improve performance
|
* Many bug fixes and tweaks to improve performance
|
||||||
* Added 'mobs_attack_creatura' setting so that monsters can attack Creatura mobs
|
* Added 'mobs_attack_creatura' setting so that monsters can attack Creatura mobs
|
||||||
|
* Nodes can be added to 'runaway_from' table
|
||||||
|
* Better Mineclone2 compatibility with api, items and recipes
|
||||||
|
|
||||||
### Version 1.56
|
### Version 1.56
|
||||||
|
|
||||||
|
Binary file not shown.
13
spawner.lua
13
spawner.lua
@ -1,8 +1,17 @@
|
|||||||
|
|
||||||
local S = mobs.intllib
|
local S = mobs.intllib
|
||||||
|
|
||||||
-- mob spawner
|
|
||||||
|
|
||||||
|
-- are we a real player ?
|
||||||
|
local function is_player(player)
|
||||||
|
|
||||||
|
if player and type(player) == "userdata" and minetest.is_player(player) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- mob spawner
|
||||||
local spawner_default = "mobs_animal:pumba 10 15 0 0 0"
|
local spawner_default = "mobs_animal:pumba 10 15 0 0 0"
|
||||||
|
|
||||||
minetest.register_node("mobs:spawner", {
|
minetest.register_node("mobs:spawner", {
|
||||||
@ -148,7 +157,7 @@ minetest.register_abm({
|
|||||||
|
|
||||||
for _, oir in pairs(objsp) do
|
for _, oir in pairs(objsp) do
|
||||||
|
|
||||||
if oir:is_player() then
|
if is_player(oir) then
|
||||||
|
|
||||||
in_range = 1
|
in_range = 1
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user