1
0
mirror of https://codeberg.org/tenplus1/mobs_redo.git synced 2025-07-19 16:50:25 +02:00

Compare commits

...

10 Commits

8 changed files with 152 additions and 127 deletions

52
api.lua
View File

@ -8,7 +8,7 @@ local use_cmi = minetest.global_exists("cmi")
mobs = { mobs = {
mod = "redo", mod = "redo",
version = "20201206", version = "20210114",
intllib = S, intllib = S,
invis = minetest.global_exists("invisibility") and invisibility or {} invis = minetest.global_exists("invisibility") and invisibility or {}
} }
@ -65,6 +65,7 @@ local max_per_block = tonumber(settings:get("max_objects_per_block") or 99)
local mob_nospawn_range = tonumber(settings:get("mob_nospawn_range") or 12) local mob_nospawn_range = tonumber(settings:get("mob_nospawn_range") or 12)
local active_limit = tonumber(settings:get("mob_active_limit") or 0) local active_limit = tonumber(settings:get("mob_active_limit") or 0)
local mob_chance_multiplier = tonumber(settings:get("mob_chance_multiplier") or 1) local mob_chance_multiplier = tonumber(settings:get("mob_chance_multiplier") or 1)
local peaceful_player_enabled = settings:get_bool("enable_peaceful_player")
local active_mobs = 0 local active_mobs = 0
@ -562,7 +563,7 @@ function mob_class:attempt_flight_correction(override)
-- We are not flying in what we are supposed to. -- We are not flying in what we are supposed to.
-- See if we can find intended flight medium and return to it -- See if we can find intended flight medium and return to it
local pos = self.object:get_pos() local pos = self.object:get_pos() ; if not pos then return true end
local searchnodes = self.fly_in local searchnodes = self.fly_in
if type(searchnodes) == "string" then if type(searchnodes) == "string" then
@ -571,7 +572,8 @@ function mob_class:attempt_flight_correction(override)
local flyable_nodes = minetest.find_nodes_in_area( local flyable_nodes = minetest.find_nodes_in_area(
{x = pos.x - 1, y = pos.y - 1, z = pos.z - 1}, {x = pos.x - 1, y = pos.y - 1, z = pos.z - 1},
{x = pos.x + 1, y = pos.y + 1, z = pos.z + 1}, searchnodes) {x = pos.x + 1, y = pos.y + 0, z = pos.z + 1}, searchnodes)
-- pos.y + 0 hopefully fixes floating swimmers
if #flyable_nodes < 1 then if #flyable_nodes < 1 then
return false return false
@ -908,6 +910,7 @@ function mob_class:check_for_death(cmi_cause)
local rot = self.animation.die_rotate and 5 local rot = self.animation.die_rotate and 5
self.attack = nil self.attack = nil
self.following = nil
self.v_start = false self.v_start = false
self.timer = 0 self.timer = 0
self.blinktimer = 0 self.blinktimer = 0
@ -915,7 +918,7 @@ function mob_class:check_for_death(cmi_cause)
self.state = "die" self.state = "die"
self.object:set_properties({ self.object:set_properties({
pointable = false, collide_with_objects = false, pointable = false, collide_with_objects = false,
automatic_rotate = rot, automatic_rotate = rot, static_save = false
}) })
self:set_velocity(0) self:set_velocity(0)
self:set_animation("die") self:set_animation("die")
@ -1848,6 +1851,23 @@ function mob_class:smart_mobs(s, p, dist, dtime)
end end
-- peaceful player privilege support
local function is_peaceful_player(player)
if peaceful_player_enabled then
local player_name = player:get_player_name()
if player_name
and minetest.check_player_privs(player_name, "peaceful_player") then
return true
end
end
return false
end
-- general attack function for all mobs -- general attack function for all mobs
function mob_class:general_attack() function mob_class:general_attack()
@ -1920,7 +1940,8 @@ function mob_class:general_attack()
-- choose closest player to attack that isnt self -- choose closest player to attack that isnt self
if dist ~= 0 if dist ~= 0
and dist < min_dist and dist < min_dist
and self:line_of_sight(sp, p, 2) == true then and self:line_of_sight(sp, p, 2) == true
and not is_peaceful_player(player) then
min_dist = dist min_dist = dist
min_player = player min_player = player
end end
@ -3054,6 +3075,7 @@ function mob_class:mob_staticdata()
if t ~= "function" if t ~= "function"
and t ~= "nil" and t ~= "nil"
and t ~= "userdata" and t ~= "userdata"
and _ ~= "object"
and _ ~= "_cmi_components" then and _ ~= "_cmi_components" then
tmp[_] = self[_] tmp[_] = self[_]
end end
@ -3306,6 +3328,8 @@ function mob_class:on_step(dtime, moveresult)
}} }}
}]] }]]
if self.state == "die" then return end ----------------
if use_cmi then if use_cmi then
cmi.notify_step(self.object, dtime) cmi.notify_step(self.object, dtime)
end end
@ -3681,9 +3705,6 @@ local can_spawn = function(pos, name)
end end
end end
-- spawn mob 1/2 node above ground
pos.y = pos.y + 0.5
-- tweak X/Z spawn pos -- tweak X/Z spawn pos
if width_x % 2 == 0 then if width_x % 2 == 0 then
pos.x = pos.x + 0.5 pos.x = pos.x + 0.5
@ -3948,15 +3969,15 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
end end
end end
local ent = minetest.registered_entities[name]
-- should we check mob area for obstructions ? -- should we check mob area for obstructions ?
if mob_area_spawn ~= true then if mob_area_spawn ~= true then
-- do we have enough height clearance to spawn mob? -- do we have enough height clearance to spawn mob?
local ent = minetest.registered_entities[name] local height = max(0, ent.collisionbox[5] - ent.collisionbox[2])
local height = max(1, math.ceil(
(ent.collisionbox[5] or 0.25) - (ent.collisionbox[2] or -0.25) - 1))
for n = 0, height do for n = 0, floor(height) do
local pos2 = {x = pos.x, y = pos.y + n, z = pos.z} local pos2 = {x = pos.x, y = pos.y + n, z = pos.z}
@ -3972,6 +3993,9 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
if pos then if pos then
-- adjust for mob collision box
pos.y = pos.y + (ent.collisionbox[2] * -1) - 0.4
local mob = minetest.add_entity(pos, name) local mob = minetest.add_entity(pos, name)
-- print("[mobs] Spawned " .. name .. " at " -- print("[mobs] Spawned " .. name .. " at "
@ -4503,10 +4527,10 @@ function mobs:capture_mob(self, clicker, chance_hand, chance_net,
minetest.add_item(clicker:get_pos(), new_stack) minetest.add_item(clicker:get_pos(), new_stack)
end end
remove_mob(self, true)
self:mob_sound("default_place_node_hard") self:mob_sound("default_place_node_hard")
remove_mob(self, true)
return new_stack return new_stack
-- when chance above fails or set to 0, miss! -- when chance above fails or set to 0, miss!

View File

@ -5,7 +5,7 @@ local S = mobs.intllib
minetest.register_craftitem("mobs:nametag", { minetest.register_craftitem("mobs:nametag", {
description = S("Name Tag"), description = S("Name Tag"),
inventory_image = "mobs_nametag.png", inventory_image = "mobs_nametag.png",
groups = {flammable = 2} groups = {flammable = 2, nametag = 1}
}) })
if minetest.get_modpath("dye") and minetest.get_modpath("farming") then if minetest.get_modpath("dye") and minetest.get_modpath("farming") then
@ -20,7 +20,7 @@ end
minetest.register_craftitem("mobs:leather", { minetest.register_craftitem("mobs:leather", {
description = S("Leather"), description = S("Leather"),
inventory_image = "mobs_leather.png", inventory_image = "mobs_leather.png",
groups = {flammable = 2} groups = {flammable = 2, leather = 1}
}) })
-- raw meat -- raw meat
@ -119,7 +119,7 @@ minetest.register_craft({
minetest.register_craftitem("mobs:saddle", { minetest.register_craftitem("mobs:saddle", {
description = S("Saddle"), description = S("Saddle"),
inventory_image = "mobs_saddle.png", inventory_image = "mobs_saddle.png",
groups = {flammable = 2} groups = {flammable = 2, saddle = 1}
}) })
minetest.register_craft({ minetest.register_craft({

View File

@ -1,6 +1,12 @@
local path = minetest.get_modpath("mobs") local path = minetest.get_modpath("mobs")
-- Peaceful player privilege
minetest.register_privilege("peaceful_player", {
description = "Prevents Mobs Redo mobs from attacking player",
give_to_singleplayer = false
})
-- Mob API -- Mob API
dofile(path .. "/api.lua") dofile(path .. "/api.lua")

View File

@ -1 +1,4 @@
name = mobs name = mobs
depends = default
optional_depends = tnt, dye, farming, invisibility, intllib, lucky_block, cmi, toolranks
description = Adds a mob api for mods to add animals or monsters etc.

195
mount.lua
View File

@ -1,9 +1,7 @@
-- lib_mount by Blert2112 (edited by TenPlus1) -- lib_mount by Blert2112 (edited by TenPlus1)
local enable_crash = false local abs, cos, floor, sin, sqrt, pi =
local crash_threshold = 6.5 -- ignored if enable_crash=false math.abs, math.cos, math.floor, math.sin, math.sqrt, math.pi
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- --
@ -11,7 +9,6 @@ local crash_threshold = 6.5 -- ignored if enable_crash=false
-- --
local node_ok = function(pos, fallback) local node_ok = function(pos, fallback)
fallback = fallback or mobs.fallback_node fallback = fallback or mobs.fallback_node
local node = minetest.get_node_or_nil(pos) local node = minetest.get_node_or_nil(pos)
@ -25,7 +22,6 @@ end
local function node_is(pos) local function node_is(pos)
local node = node_ok(pos) local node = node_ok(pos)
if node.name == "air" then if node.name == "air" then
@ -49,33 +45,30 @@ end
local function get_sign(i) local function get_sign(i)
i = i or 0 i = i or 0
if i == 0 then if i == 0 then
return 0 return 0
else else
return i / math.abs(i) return i / abs(i)
end end
end end
local function get_velocity(v, yaw, y) local function get_velocity(v, yaw, y)
local x = -sin(yaw) * v
local x = -math.sin(yaw) * v local z = cos(yaw) * v
local z = math.cos(yaw) * v
return {x = x, y = y, z = z} return {x = x, y = y, z = z}
end end
local function get_v(v) local function get_v(v)
return math.sqrt(v.x * v.x + v.z * v.z) return sqrt(v.x * v.x + v.z * v.z)
end end
local function force_detach(player) local function force_detach(player)
local attached_to = player:get_attach() local attached_to = player:get_attach()
if not attached_to then if not attached_to then
@ -86,21 +79,19 @@ local function force_detach(player)
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
player:set_detach() player:set_detach()
default.player_attached[player:get_player_name()] = false player_api.player_attached[player:get_player_name()] = false
player:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0}) player:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
default.player_set_animation(player, "stand" , 30) player_api.set_animation(player, "stand", 30)
player:set_properties({visual_size = {x = 1, y = 1} }) player:set_properties({visual_size = {x = 1, y = 1}})
end end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
force_detach(player) force_detach(player)
end) end)
@ -119,10 +110,37 @@ end)
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- Just for correct detaching
local function find_free_pos(pos)
local check = {
{x = 1, y = 0, z = 0},
{x = 1, y = 1, z = 0},
{x = -1, y = 0, z = 0},
{x = -1, y = 1, z = 0},
{x = 0, y = 0, z = 1},
{x = 0, y = 1, z = 1},
{x = 0, y = 0, z = -1},
{x = 0, y = 1, z = -1}
}
for _, c in pairs(check) do
local npos = {x = pos.x + c.x, y = pos.y + c.y, z = pos.z + c.z}
local node = minetest.get_node_or_nil(npos)
if node and node.name then
local def = minetest.registered_nodes[node.name]
if def and not def.walkable and
def.liquidtype == "none" then
return npos
end
end
end
return pos
end
-------------------------------------------------------------------------------
function mobs.attach(entity, player) function mobs.attach(entity, player)
local attach_at, eye_offset = {}, {}
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}
entity.driver_attach_at = entity.driver_attach_at 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_eye_offset = entity.driver_eye_offset or {x = 0, y = 0, z = 0}
@ -131,17 +149,17 @@ function mobs.attach(entity, player)
local rot_view = 0 local rot_view = 0
if entity.player_rotation.y == 90 then if entity.player_rotation.y == 90 then
rot_view = math.pi / 2 rot_view = pi / 2
end end
attach_at = entity.driver_attach_at local attach_at = entity.driver_attach_at
eye_offset = entity.driver_eye_offset local eye_offset = entity.driver_eye_offset
entity.driver = player entity.driver = player
force_detach(player) force_detach(player)
player:set_attach(entity.object, "", attach_at, entity.player_rotation) player:set_attach(entity.object, "", attach_at, entity.player_rotation)
default.player_attached[player:get_player_name()] = true player_api.player_attached[player:get_player_name()] = true
player:set_eye_offset(eye_offset, {x = 0, y = 0, z = 0}) player:set_eye_offset(eye_offset, {x = 0, y = 0, z = 0})
player:set_properties({ player:set_properties({
@ -151,46 +169,36 @@ function mobs.attach(entity, player)
} }
}) })
minetest.after(0.2, function(name) minetest.after(0.2, function()
local player = minetest.get_player_by_name(name) if player and player:is_player() then
if player then player_api.set_animation(player, "sit", 30)
default.player_set_animation(player, "sit" , 30)
end end
end, player:get_player_name()) end)
player:set_look_horizontal(entity.object:get_yaw() - rot_view) player:set_look_horizontal(entity.object:get_yaw() - rot_view)
end end
function mobs.detach(player, offset) function mobs.detach(player)
force_detach(player) force_detach(player)
default.player_set_animation(player, "stand" , 30) minetest.after(0.1, function()
if player and player:is_player() then
local pos = player:get_pos() local pos = find_free_pos(player:get_pos())
pos.y = pos.y + 0.5
pos = {
x = pos.x + offset.x,
y = pos.y + 0.2 + offset.y,
z = pos.z + offset.z
}
minetest.after(0.1, function(name, pos)
local player = minetest.get_player_by_name(name)
if player then
player:set_pos(pos) player:set_pos(pos)
end end
end, player:get_player_name(), pos) end)
end end
function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime) function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
local yaw = entity.object:get_yaw() or 0
local rot_steer, rot_view = math.pi/2, 0 local rot_view = 0
if entity.player_rotation.y == 90 then if entity.player_rotation.y == 90 then
rot_steer, rot_view = 0, math.pi/2 rot_view = pi / 2
end end
local acce_y = 0 local acce_y = 0
@ -200,19 +208,14 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
-- process controls -- process controls
if entity.driver then if entity.driver then
--print ("---velo", get_v(velo))
local ctrl = entity.driver:get_player_control() local ctrl = entity.driver:get_player_control()
-- move forwards -- move forwards
if ctrl.up then if ctrl.up then
entity.v = entity.v + entity.accel / 10 entity.v = entity.v + entity.accel / 10
-- move backwards -- move backwards
elseif ctrl.down then 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
end end
@ -220,12 +223,24 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
entity.v = entity.v - entity.accel / 10 entity.v = entity.v - entity.accel / 10
end end
-- fix mob rotation -- mob rotation
local horz = entity.driver:get_look_horizontal() or 0 local horz
if entity.alt_turn == true then
horz = yaw
if ctrl.left then
horz = horz + 0.05
elseif ctrl.right then
horz = horz - 0.05
end
else
horz = entity.driver:get_look_horizontal() or 0
end
entity.object:set_yaw(horz - entity.rotate) entity.object:set_yaw(horz - entity.rotate)
if can_fly then if can_fly then
-- fly up -- fly up
if ctrl.jump then if ctrl.jump then
velo.y = velo.y + 1 velo.y = velo.y + 1
@ -245,9 +260,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
velo.y = velo.y + 0.1 velo.y = velo.y + 0.1
if velo.y > 0 then velo.y = 0 end if velo.y > 0 then velo.y = 0 end
end end
else else
-- jump -- jump
if ctrl.jump then if ctrl.jump then
@ -261,7 +274,6 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
-- if not moving then set animation and return -- 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 entity.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then
if stand_anim then if stand_anim then
mobs:set_animation(entity, stand_anim) mobs:set_animation(entity, stand_anim)
end end
@ -280,7 +292,6 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
entity.v = entity.v - 0.02 * s entity.v = entity.v - 0.02 * s
if s ~= get_sign(entity.v) then if s ~= get_sign(entity.v) then
entity.object:set_velocity({x = 0, y = 0, z = 0}) entity.object:set_velocity({x = 0, y = 0, z = 0})
entity.v = 0 entity.v = 0
return return
@ -293,14 +304,15 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
max_spd = entity.max_speed_forward max_spd = entity.max_speed_forward
end end
if math.abs(entity.v) > max_spd then if abs(entity.v) > max_spd then
entity.v = entity.v - get_sign(entity.v) entity.v = entity.v - get_sign(entity.v)
end end
-- Set position, velocity and acceleration -- Set position, velocity and acceleration
local p = entity.object:get_pos() local p = entity.object:get_pos()
local new_velo if not p then return end
local new_acce = {x = 0, y = -9.8, z = 0}
local new_acce = {x = 0, y = -9.81, z = 0}
p.y = p.y - 0.5 p.y = p.y - 0.5
@ -308,23 +320,18 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
local v = entity.v local v = entity.v
if ni == "air" then if ni == "air" then
if can_fly == true then if can_fly == true then
new_acce.y = 0 new_acce.y = 0
end end
elseif ni == "liquid" or ni == "lava" then elseif ni == "liquid" or ni == "lava" then
if ni == "lava" and entity.lava_damage ~= 0 then if ni == "lava" and entity.lava_damage ~= 0 then
entity.lava_counter = (entity.lava_counter or 0) + dtime entity.lava_counter = (entity.lava_counter or 0) + dtime
if entity.lava_counter > 1 then if entity.lava_counter > 1 then
minetest.sound_play("default_punch", { minetest.sound_play("default_punch", {
object = entity.object, object = entity.object,
max_hear_distance = 5 max_hear_distance = 5
}, true) })
entity.object:punch(entity.object, 1.0, { entity.object:punch(entity.object, 1.0, {
full_punch_interval = 1.0, full_punch_interval = 1.0,
@ -335,14 +342,12 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
end end
end end
if entity.terrain_type == 2 local terrain_type = entity.terrain_type
or entity.terrain_type == 3 then if terrain_type == 2 or terrain_type == 3 then
new_acce.y = 0 new_acce.y = 0
p.y = p.y + 1 p.y = p.y + 1
if node_is(p) == "liquid" then if node_is(p) == "liquid" then
if velo.y >= 5 then if velo.y >= 5 then
velo.y = 5 velo.y = 5
elseif velo.y < 0 then elseif velo.y < 0 then
@ -351,9 +356,11 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
new_acce.y = 5 new_acce.y = 5
end end
else else
if math.abs(velo.y) < 1 then if abs(velo.y) < 1 then
local pos = entity.object:get_pos() local pos = entity.object:get_pos()
pos.y = math.floor(pos.y) + 0.5 if not pos then return end
pos.y = floor(pos.y) + 0.5
entity.object:set_pos(pos) entity.object:set_pos(pos)
velo.y = 0 velo.y = 0
end end
@ -363,46 +370,22 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
end end
end end
new_velo = get_velocity(v, entity.object:get_yaw() - rot_view, velo.y) local new_velo = get_velocity(v, yaw - rot_view, velo.y)
new_acce.y = new_acce.y + acce_y new_acce.y = new_acce.y + acce_y
entity.object:set_velocity(new_velo) entity.object:set_velocity(new_velo)
entity.object:set_acceleration(new_acce) entity.object:set_acceleration(new_acce)
-- CRASH!
if enable_crash then
local intensity = entity.v2 - v
if intensity >= crash_threshold then
--print("----------- crash", intensity)
entity.object:punch(entity.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = intensity}
}, nil)
end
end
entity.v2 = v entity.v2 = v
end end
-- directional flying routine by D00Med (edited by TenPlus1) -- directional flying routine by D00Med (edited by TenPlus1)
function mobs.fly(entity, _, speed, shoots, arrow, moving_anim, stand_anim)
function mobs.fly(entity, dtime, speed, shoots, arrow, moving_anim, stand_anim)
local ctrl = entity.driver:get_player_control() local ctrl = entity.driver:get_player_control()
local velo = entity.object:get_velocity() local velo = entity.object:get_velocity()
local dir = entity.driver:get_look_dir() local dir = entity.driver:get_look_dir()
local yaw = entity.driver:get_look_horizontal() + 1.57 -- offset fix between old and new commands local yaw = entity.driver:get_look_horizontal() + 1.57 -- offset fix between old and new commands
local rot_steer, rot_view = math.pi / 2, 0
if entity.player_rotation.y == 90 then
rot_steer, rot_view = 0, math.pi / 2
end
if ctrl.up then if ctrl.up then
entity.object:set_velocity({ entity.object:set_velocity({
@ -414,7 +397,7 @@ function mobs.fly(entity, dtime, speed, shoots, arrow, moving_anim, stand_anim)
elseif ctrl.down then elseif ctrl.down then
entity.object:set_velocity({ entity.object:set_velocity({
x = -dir.x * speed, x = -dir.x * speed,
y = dir.y * speed + 2, y = dir.y * speed + 2,
z = -dir.z * speed z = -dir.z * speed
}) })
@ -422,11 +405,10 @@ function mobs.fly(entity, dtime, speed, shoots, arrow, moving_anim, stand_anim)
entity.object:set_velocity({x = 0, y = -2, z = 0}) entity.object:set_velocity({x = 0, y = -2, z = 0})
end end
entity.object:set_yaw(yaw + math.pi + math.pi / 2 - entity.rotate) entity.object:set_yaw(yaw + pi + pi / 2 - entity.rotate)
-- firing arrows -- firing arrows
if ctrl.LMB and ctrl.sneak and shoots then if ctrl.LMB and ctrl.sneak and shoots then
local pos = entity.object:get_pos() local pos = entity.object:get_pos()
local obj = minetest.add_entity({ local obj = minetest.add_entity({
x = pos.x + 0 + dir.x * 2.5, x = pos.x + 0 + dir.x * 2.5,
@ -438,8 +420,8 @@ function mobs.fly(entity, dtime, speed, shoots, arrow, moving_anim, stand_anim)
ent.switch = 1 -- for mob specific arrows ent.switch = 1 -- for mob specific arrows
ent.owner_id = tostring(entity.object) -- so arrows dont hurt entity you are riding 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 vec = {x = dir.x * 6, y = dir.y * 6, z = dir.z * 6}
local yaw = entity.driver:get_look_horizontal() yaw = entity.driver:get_look_horizontal()
obj:set_yaw(yaw + math.pi / 2) obj:set_yaw(yaw + pi / 2)
obj:set_velocity(vec) obj:set_velocity(vec)
else else
obj:remove() obj:remove()
@ -448,7 +430,6 @@ function mobs.fly(entity, dtime, speed, shoots, arrow, moving_anim, stand_anim)
-- change animation if stopped -- change animation if stopped
if velo.x == 0 and velo.y == 0 and velo.z == 0 then if velo.x == 0 and velo.y == 0 and velo.z == 0 then
mobs:set_animation(entity, stand_anim) mobs:set_animation(entity, stand_anim)
else else
-- moving animation -- moving animation

View File

@ -23,6 +23,7 @@ Lucky Blocks: 9
Changelog: Changelog:
- 1.55 - Add 'peaceful_player' privelage and setting so mobs don't attack specific players (thanks sfence)
- 1.54 - Simplified animal breeding function, added editable settings (thanks Wuzzy), Child mobs now take 20 mins to grow up, reverted to simple mob spawning with setting to use area checks, on_flop added, air_damage added. - 1.54 - Simplified animal breeding function, added editable settings (thanks Wuzzy), Child mobs now take 20 mins to grow up, reverted to simple mob spawning with setting to use area checks, on_flop added, air_damage added.
- 1.53 - Added 'on_map_load' settings to mobs:spawn so that mobs will only spawn when new areas of map are loaded. - 1.53 - Added 'on_map_load' settings to mobs:spawn so that mobs will only spawn when new areas of map are loaded.
- 1.52 - Added 'mob_active_limit' in settings to set number of mobs in game, - 1.52 - Added 'mob_active_limit' in settings to set number of mobs in game,

View File

@ -36,3 +36,6 @@ mob_active_limit (Mob Active Limit) float 0
# Enables area check when spawning mobs # Enables area check when spawning mobs
mob_area_spawn (Mob Area Spawn) bool false mob_area_spawn (Mob Area Spawn) bool false
# Enable peaceful player attack prevention
enable_peaceful_player (Mobs do not attack peaceful player without reason) bool false

View File

@ -23,9 +23,9 @@ minetest.register_node("mobs:spawner", {
-- text entry formspec -- text entry formspec
meta:set_string("formspec", meta:set_string("formspec",
"size[9,3.5]" "size[10,3.5]"
.. "label[0.15,0.5;" .. minetest.formspec_escape(head) .. "]" .. "label[0.15,0.5;" .. minetest.formspec_escape(head) .. "]"
.. "field[1,2.5;7.5,0.8;text;" .. S("Command:") .. "field[1,2.5;8.5,0.8;text;" .. S("Command:")
.. ";${command}]") .. ";${command}]")
meta:set_string("infotext", S("Spawner Not Active (enter settings)")) meta:set_string("infotext", S("Spawner Not Active (enter settings)"))
@ -162,10 +162,17 @@ minetest.register_abm({
end end
end end
-- set medium mob usually spawns in (defaults to air)
local reg = minetest.registered_entities[mob].fly_in
if not reg or type(reg) == "string" then
reg = {(reg or "air")}
end
-- find air blocks within 5 nodes of spawner -- find air blocks within 5 nodes of spawner
local air = minetest.find_nodes_in_area( local air = minetest.find_nodes_in_area(
{x = pos.x - 5, y = pos.y + yof, z = pos.z - 5}, {x = pos.x - 5, y = pos.y + yof, z = pos.z - 5},
{x = pos.x + 5, y = pos.y + yof, z = pos.z + 5}, {"air"}) {x = pos.x + 5, y = pos.y + yof, z = pos.z + 5}, reg)
-- spawn in random air block -- spawn in random air block
if air and #air > 0 then if air and #air > 0 then