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:
mckaygerhard 2023-07-28 22:13:44 -04:00
commit 90292f9af2
8 changed files with 174 additions and 110 deletions

100
api.lua
View File

@ -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

View File

@ -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

View File

@ -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 }
} }
}) })

View File

@ -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")

View File

@ -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({

View File

@ -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.

View File

@ -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