1
0
mirror of https://codeberg.org/tenplus1/mobs_redo.git synced 2025-01-09 09:20:21 +01:00

tidy and tweak code, implement sound check for mineclon*

This commit is contained in:
tenplus1 2024-08-10 13:18:57 +01:00
parent bc6b8931da
commit a8297e6a8e
8 changed files with 492 additions and 621 deletions

278
api.lua
View File

@ -1,25 +1,25 @@
-- Translation support
-- translation and mod checks
local S = minetest.get_translator("mobs") local S = minetest.get_translator("mobs")
local FS = function(...) return minetest.formspec_escape(S(...)) end local FS = function(...) return minetest.formspec_escape(S(...)) end
-- CMI support check
local use_cmi = minetest.global_exists("cmi") local use_cmi = minetest.global_exists("cmi")
local use_mc2 = minetest.get_modpath("mcl_core") -- MineClonia support
-- MineClone2 check
local use_mc2 = minetest.get_modpath("mcl_core")
-- Visual Harm 1ndicator check
local use_vh1 = minetest.get_modpath("visual_harm_1ndicators") local use_vh1 = minetest.get_modpath("visual_harm_1ndicators")
local use_tr = minetest.get_modpath("toolranks")
-- Node check helper -- Node check helper
local function has(nodename) local function has(nodename)
if nodename and minetest.registered_nodes[nodename] then return nodename end if nodename and minetest.registered_nodes[nodename] then return nodename end
end end
-- Global -- Global table
mobs = { mobs = {
mod = "redo", mod = "redo",
version = "20240809", version = "20240810",
spawning_mobs = {},
translate = S, translate = S,
invis = minetest.global_exists("invisibility") and invisibility or {}, invis = minetest.global_exists("invisibility") and invisibility or {},
node_snow = has(minetest.registered_aliases["mapgen_snow"]) node_snow = has(minetest.registered_aliases["mapgen_snow"])
@ -30,6 +30,7 @@ mobs = {
mobs.fallback_node = mobs.node_dirt mobs.fallback_node = mobs.node_dirt
-- localize common functions -- localize common functions
local pi = math.pi local pi = math.pi
local square = math.sqrt local square = math.sqrt
local sin = math.sin local sin = math.sin
@ -54,12 +55,14 @@ local vsubtract = vector.subtract
local settings = minetest.settings local settings = minetest.settings
-- creative check -- creative check
local creative_cache = minetest.settings:get_bool("creative_mode") local creative_cache = minetest.settings:get_bool("creative_mode")
function mobs.is_creative(name) function mobs.is_creative(name)
return creative_cache or minetest.check_player_privs(name, {creative = true}) return creative_cache or minetest.check_player_privs(name, {creative = true})
end end
-- Load settings -- Load settings
local damage_enabled = settings:get_bool("enable_damage") local damage_enabled = settings:get_bool("enable_damage")
local mobs_spawn = settings:get_bool("mobs_spawn") ~= false local mobs_spawn = settings:get_bool("mobs_spawn") ~= false
local peaceful_only = settings:get_bool("only_peaceful_mobs") local peaceful_only = settings:get_bool("only_peaceful_mobs")
@ -82,14 +85,12 @@ local mob_height_fix = settings:get_bool("mob_height_fix") ~= false
local mob_log_spawn = settings:get_bool("mob_log_spawn") == true local mob_log_spawn = settings:get_bool("mob_log_spawn") == true
local active_mobs = 0 local active_mobs = 0
-- get loop timers for node and main functions -- loop interval for node and main functions timers
local node_timer_interval = tonumber(settings:get("mob_node_timer_interval") or 0.25) local node_timer_interval = tonumber(settings:get("mob_node_timer_interval") or 0.25)
local main_timer_interval = tonumber(settings:get("mob_main_timer_interval") or 1.0) local main_timer_interval = tonumber(settings:get("mob_main_timer_interval") or 1.0)
-- pathfinding settings -- pathfinding settings
local pathfinding_enable = settings:get_bool("mob_pathfinding_enable") or true local pathfinding_enable = settings:get_bool("mob_pathfinding_enable") or true
-- Use pathfinder mod if available
local pathfinder_enable = settings:get_bool("mob_pathfinder_enable") or true
-- how long before stuck mobs start searching -- how long before stuck mobs start searching
local pathfinding_stuck_timeout = tonumber( local pathfinding_stuck_timeout = tonumber(
settings:get("mob_pathfinding_stuck_timeout")) or 3.0 settings:get("mob_pathfinding_stuck_timeout")) or 3.0
@ -129,6 +130,7 @@ 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 mob settings
mobs.mob_class = { mobs.mob_class = {
state = "stand", state = "stand",
@ -205,6 +207,7 @@ local mob_class = mobs.mob_class -- Compatibility
local mob_class_meta = {__index = mob_class} local mob_class_meta = {__index = mob_class}
-- return True if number of mobs is at limit -- return True if number of mobs is at limit
local function at_limit() local function at_limit()
if active_limit and active_limit > 0 if active_limit and active_limit > 0
@ -213,17 +216,15 @@ local function at_limit()
end end
end end
-- play sound -- play sound
function mob_class:mob_sound(sound) function mob_class:mob_sound(sound)
if not sound then return end if not sound then return end
-- higher pitch for a child local pitch = self.child and 1.5 or 1.0 -- higher pitch for a child
local pitch = self.child and 1.5 or 1.0
-- a little random pitch to be different pitch = pitch + random(-10, 10) * 0.005 -- little random pitch difference
pitch = pitch + random(-10, 10) * 0.005
minetest.sound_play(sound, { minetest.sound_play(sound, {
object = self.object, object = self.object,
@ -233,8 +234,8 @@ function mob_class:mob_sound(sound)
}, true) }, true)
end end
-- attack player/mob -- attack player/mob
function mob_class:do_attack(player, force) function mob_class:do_attack(player, force)
if self.state == "attack" and not force then return end if self.state == "attack" and not force then return end
@ -245,8 +246,8 @@ function mob_class:do_attack(player, force)
if random(100) < 90 then self:mob_sound(self.sounds.war_cry) end if random(100) < 90 then self:mob_sound(self.sounds.war_cry) end
end end
-- calculate distance -- calculate distance
local get_distance = function(a, b) local get_distance = function(a, b)
if not a or not b then return 50 end -- nil check and default distance if not a or not b then return 50 end -- nil check and default distance
@ -256,8 +257,8 @@ local get_distance = function(a, b)
return square(x * x + y * y + z * z) return square(x * x + y * y + z * z)
end end
-- are we a real player ? -- are we a real player ?
local function is_player(player) local function is_player(player)
if player and type(player) == "userdata" and minetest.is_player(player) then if player and type(player) == "userdata" and minetest.is_player(player) then
@ -265,8 +266,8 @@ local function is_player(player)
end end
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()
local pos = self.object:get_pos() ; if not pos then return {0, 0} end local pos = self.object:get_pos() ; if not pos then return {0, 0} end
@ -294,8 +295,8 @@ function mob_class:collision()
return({x, z}) return({x, z})
end end
-- check if string exists in another string or table -- check if string exists in another string or table
local function check_for(look_for, look_inside) local function check_for(look_for, look_inside)
if type(look_inside) == "string" and look_inside == look_for then return true if type(look_inside) == "string" and look_inside == look_for then return true
@ -316,8 +317,8 @@ local function check_for(look_for, look_inside)
end end
end end
-- move mob in facing direction -- move mob in facing direction
function mob_class:set_velocity(v) function mob_class:set_velocity(v)
-- halt mob if it has been ordered to stay -- halt mob if it has been ordered to stay
@ -356,8 +357,8 @@ function mob_class:set_velocity(v)
x = (sin(yaw) * -v) + c_x, y = vel.y, z = (cos(yaw) * v) + c_y}) x = (sin(yaw) * -v) + c_x, y = vel.y, z = (cos(yaw) * v) + c_y})
end end
-- calculate mob velocity -- calculate mob velocity
function mob_class:get_velocity() function mob_class:get_velocity()
local v = self.object:get_velocity() ; if not v then return 0 end local v = self.object:get_velocity() ; if not v then return 0 end
@ -365,8 +366,8 @@ function mob_class:get_velocity()
return (v.x * v.x + v.z * v.z) ^ 0.5 return (v.x * v.x + v.z * v.z) ^ 0.5
end end
-- set and return valid yaw -- set and return valid yaw
function mob_class:set_yaw(yaw, delay) function mob_class:set_yaw(yaw, delay)
if not yaw or yaw ~= yaw then yaw = 0 end if not yaw or yaw ~= yaw then yaw = 0 end
@ -393,13 +394,12 @@ function mob_class:set_yaw(yaw, delay)
return self.target_yaw return self.target_yaw
end end
-- global function to set mob yaw [deprecated] function mobs:yaw(entity, yaw, delay) -- [deprecated]
function mobs:yaw(entity, yaw, delay)
mob_class.set_yaw(entity, yaw, delay) mob_class.set_yaw(entity, yaw, delay)
end end
-- set defined animation -- set defined animation
function mob_class:set_animation(anim, force) function mob_class:set_animation(anim, force)
if not self.animation or not anim then return end if not self.animation or not anim then return end
@ -444,13 +444,12 @@ function mob_class:set_animation(anim, force)
0, self.animation[anim .. "_loop"] ~= false) 0, self.animation[anim .. "_loop"] ~= false)
end end
-- global function to set mob animation [deprecated] function mobs:set_animation(entity, anim) -- [deprecated]
function mobs:set_animation(entity, anim)
entity.set_animation(entity, anim) entity.set_animation(entity, anim)
end end
-- check line of sight using raycasting (thanks Astrobe) -- check line of sight using raycasting (thanks Astrobe)
function mob_class:line_of_sight(pos1, pos2) function mob_class:line_of_sight(pos1, pos2)
local ray = minetest.raycast(pos1, pos2, true, false) -- ignore entities local ray = minetest.raycast(pos1, pos2, true, false) -- ignore entities
@ -472,18 +471,16 @@ function mob_class:line_of_sight(pos1, pos2)
return true return true
end end
-- global function [deprecated] function mobs:line_of_sight(entity, pos1, pos2) -- [deprecated]
function mobs:line_of_sight(entity, pos1, pos2)
return entity:line_of_sight(pos1, pos2) return entity:line_of_sight(pos1, pos2)
end end
-- if mob not flying in medium it's suppose to, try and find some to return to
function mob_class:attempt_flight_correction(override) function mob_class:attempt_flight_correction(override)
if self:flight_check() and override ~= true then return true end if self:flight_check() and override ~= true then return true end
-- We are not flying in what we are supposed to.
-- See if we can find intended flight medium and return to it
local pos = self.object:get_pos() ; if not pos then return true end local pos = self.object:get_pos() ; if not pos then return true end
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},
@ -508,8 +505,8 @@ function mob_class:attempt_flight_correction(override)
return true return true
end end
-- are we flying in what we are suppose to? (taikedz) -- are we flying in what we are suppose to? (taikedz)
function mob_class:flight_check() function mob_class:flight_check()
local def = minetest.registered_nodes[self.standing_in] local def = minetest.registered_nodes[self.standing_in]
@ -528,8 +525,8 @@ function mob_class:flight_check()
return false return false
end end
-- turn mob to face position -- turn mob to face position
function mob_class:yaw_to_pos(target, rot) function mob_class:yaw_to_pos(target, rot)
rot = rot or 0 rot = rot or 0
@ -545,13 +542,12 @@ function mob_class:yaw_to_pos(target, rot)
return yaw return yaw
end end
-- global [deprecated] function mobs:yaw_to_pos(self, target, rot) -- [deprecated]
function mobs:yaw_to_pos(self, target, rot)
return self:yaw_to_pos(target, rot) return self:yaw_to_pos(target, rot)
end end
-- if stay near set then periodically check for nodes and turn towards them -- if stay near set then periodically check for nodes and turn towards them
function mob_class:do_stay_near() function mob_class:do_stay_near()
if not self.stay_near then return false end if not self.stay_near then return false end
@ -560,13 +556,9 @@ function mob_class:do_stay_near()
local searchnodes = self.stay_near[1] local searchnodes = self.stay_near[1]
local chance = self.stay_near[2] or 10 local chance = self.stay_near[2] or 10
if not pos or random(chance) > 1 then if not pos or random(chance) > 1 then return false end
return false
end
if type(searchnodes) == "string" then if type(searchnodes) == "string" then searchnodes = {self.stay_near[1]} end
searchnodes = {self.stay_near[1]}
end
local r = self.view_range local r = self.view_range
local nearby_nodes = minetest.find_nodes_in_area( local nearby_nodes = minetest.find_nodes_in_area(
@ -584,8 +576,8 @@ function mob_class:do_stay_near()
return true return true
end end
-- custom particle effects -- custom particle effects
local function effect( local function effect(
pos, amount, texture, min_size, max_size, radius, gravity, glow, fall) pos, amount, texture, min_size, max_size, radius, gravity, glow, fall)
@ -618,21 +610,20 @@ local function effect(
}) })
end end
-- global function
function mobs:effect( function mobs:effect(
pos, amount, texture, min_size, max_size, radius, gravity, glow, fall) pos, amount, texture, min_size, max_size, radius, gravity, glow, fall)
effect(pos, amount, texture, min_size, max_size, radius, gravity, glow, fall) effect(pos, amount, texture, min_size, max_size, radius, gravity, glow, fall)
end end
-- Thanks Wuzzy for the editable settings -- Thanks Wuzzy for the editable settings
local HORNY_TIME = 30 local HORNY_TIME = 30
local HORNY_AGAIN_TIME = 60 * 5 -- 5 minutes local HORNY_AGAIN_TIME = 60 * 5 -- 5 minutes
local CHILD_GROW_TIME = 60 * 20 -- 20 minutes local CHILD_GROW_TIME = 60 * 20 -- 20 minutes
-- update nametag and infotext -- update nametag and infotext
function mob_class:update_tag(newname) function mob_class:update_tag(newname)
local col local col
@ -704,8 +695,8 @@ function mob_class:update_tag(newname)
end end
end end
-- drop items -- drop items
function mob_class:item_drop() function mob_class:item_drop()
-- no drops if disabled by setting or mob is child -- no drops if disabled by setting or mob is child
@ -781,8 +772,8 @@ function mob_class:item_drop()
self.drops = {} self.drops = {}
end end
-- remove mob and descrease counter -- remove mob and descrease counter
local function remove_mob(self, decrease) local function remove_mob(self, decrease)
self.object:remove() self.object:remove()
@ -793,13 +784,12 @@ local function remove_mob(self, decrease)
end end
end end
-- global function for removing mobs
function mobs:remove(self, decrease) function mobs:remove(self, decrease)
remove_mob(self, decrease) remove_mob(self, decrease)
end end
-- check if mob is dead or only hurt -- check if mob is dead or only hurt
function mob_class:check_for_death(cmi_cause) function mob_class:check_for_death(cmi_cause)
-- We dead already -- We dead already
@ -916,8 +906,8 @@ function mob_class:check_for_death(cmi_cause)
return true return true
end end
-- get node but use fallback for nil or unknown -- get node but use fallback for nil or unknown
local function node_ok(pos, fallback) local function node_ok(pos, fallback)
local node = minetest.get_node_or_nil(pos) local node = minetest.get_node_or_nil(pos)
@ -931,8 +921,8 @@ function mobs:node_ok(pos, fallback)
return node_ok(pos, fallback) return node_ok(pos, fallback)
end end
-- Returns true if node can deal damage to self -- Returns true if node can deal damage to self
function mobs:is_node_dangerous(mob_object, nodename) function mobs:is_node_dangerous(mob_object, nodename)
if mob_object.water_damage > 0 if mob_object.water_damage > 0
@ -953,8 +943,8 @@ local function is_node_dangerous(mob_object, nodename)
return mobs:is_node_dangerous(mob_object, nodename) return mobs:is_node_dangerous(mob_object, nodename)
end end
-- is mob facing a cliff -- is mob facing a cliff
function mob_class:is_at_cliff() function mob_class:is_at_cliff()
if self.driver or self.fear_height == 0 then -- 0 for no falling protection! if self.driver or self.fear_height == 0 then -- 0 for no falling protection!
@ -986,8 +976,8 @@ function mob_class:is_at_cliff()
return (not def and def.walkable) return (not def and def.walkable)
end end
-- check for nodes or groups inside mob -- check for nodes or groups inside mob
function mob_class:is_inside(itemtable) function mob_class:is_inside(itemtable)
local cb = self.object:get_properties().collisionbox local cb = self.object:get_properties().collisionbox
@ -999,8 +989,8 @@ function mob_class:is_inside(itemtable)
if nn and #nn > 0 then return true end if nn and #nn > 0 then return true end
end end
-- environmental damage (water, lava, fire, light etc.) -- environmental damage (water, lava, fire, light etc.)
function mob_class:do_env_damage() function mob_class:do_env_damage()
local pos = self.object:get_pos() ; if not pos then return end local pos = self.object:get_pos() ; if not pos then return end
@ -1124,8 +1114,8 @@ function mob_class:do_env_damage()
return self:check_for_death({type = "unknown"}) return self:check_for_death({type = "unknown"})
end end
-- jump if facing a solid node that isn't a fences or gate
-- jump if facing a solid node (not fences or gates)
function mob_class:do_jump() function mob_class:do_jump()
local vel = self.object:get_velocity() ; if not vel then return false end local vel = self.object:get_velocity() ; if not vel then return false end
@ -1200,8 +1190,8 @@ function mob_class:do_jump()
return false return false
end end
-- blast damage to entities nearby (modified from TNT mod) -- blast damage to entities nearby (modified from TNT mod)
local function entity_physics(pos, radius) local function entity_physics(pos, radius)
radius = radius * 2 radius = radius * 2
@ -1223,15 +1213,15 @@ local function entity_physics(pos, radius)
end end
end end
-- can mob see player -- can mob see player
local function is_invisible(self, player_name) local function is_invisible(self, player_name)
if mobs.invis[player_name] and not self.ignore_invisibility then return true end if mobs.invis[player_name] and not self.ignore_invisibility then return true end
end end
-- should mob follow what I'm holding ? -- should mob follow what I'm holding ?
function mob_class:follow_holding(clicker) function mob_class:follow_holding(clicker)
if is_invisible(self, clicker:get_player_name()) then return false end if is_invisible(self, clicker:get_player_name()) then return false end
@ -1242,8 +1232,8 @@ function mob_class:follow_holding(clicker)
if check_for(item:get_name(), self.follow) then return true end if check_for(item:get_name(), self.follow) then return true end
end end
-- find two animals of same type and breed if nearby and horny -- find two animals of same type and breed if nearby and horny
function mob_class:breed() function mob_class:breed()
-- child takes a long time before growing into adult -- child takes a long time before growing into adult
@ -1407,17 +1397,14 @@ function mob_class:breed()
end end
end end
-- find and replace what mob is looking for (grass, wheat etc.) -- find and replace what mob is looking for (grass, wheat etc.)
function mob_class:replace(pos) function mob_class:replace(pos)
local vel = self.object:get_velocity() ; if not vel then return end local vel = self.object:get_velocity() ; if not vel then return end
if not mobs_griefing if not mobs_griefing or not self.replace_rate or not self.replace_what
or not self.replace_rate or not self.replace_what or self.child == true or vel.y ~= 0 or random(self.replace_rate) > 1 then
or self.child == true
or vel.y ~= 0
or random(self.replace_rate) > 1 then
return return
end end
@ -1459,19 +1446,16 @@ function mob_class:replace(pos)
end end
end end
-- check if daytime and also if mob is docile during daylight hours -- check if daytime and also if mob is docile during daylight hours
function mob_class:day_docile() function mob_class:day_docile()
if self.docile_by_day == true if self.docile_by_day == true
and self.time_of_day > 0.2 and self.time_of_day < 0.8 then return true end and self.time_of_day > 0.2 and self.time_of_day < 0.8 then return true end
end end
local los_switcher = false
local height_switcher = false
-- are we able to dig this node and add drops? -- are we able to dig this node and add drops?
local function can_dig_drop(pos) local function can_dig_drop(pos)
if minetest.is_protected(pos, "") then return false end if minetest.is_protected(pos, "") then return false end
@ -1500,11 +1484,14 @@ local function can_dig_drop(pos)
end end
end end
-- pathfinder mod check and settings
local pathfinder_mod = minetest.get_modpath("pathfinder") local pathfinder_mod = minetest.get_modpath("pathfinder")
local los_switcher = false
local height_switcher = false
-- path finding and smart mob routine by rnd, line_of_sight and other edits by Elkien3
-- path finding and smart mob routine by rnd,
-- line_of_sight and other edits by Elkien3
function mob_class:smart_mobs(s, p, dist, dtime) function mob_class:smart_mobs(s, p, dist, dtime)
local s1 = self.path.lastpos local s1 = self.path.lastpos
@ -1626,7 +1613,7 @@ function mob_class:smart_mobs(s, p, dist, dtime)
elseif prop.stepheight > 0.5 then jumpheight = 1 end elseif prop.stepheight > 0.5 then jumpheight = 1 end
if pathfinder_mod and pathfinder_enable then if pathfinder_mod then
self.path.way = pathfinder.find_path(s, p1, self, dtime) self.path.way = pathfinder.find_path(s, p1, self, dtime)
else else
self.path.way = minetest.find_path(s, p1, pathfinding_searchdistance, self.path.way = minetest.find_path(s, p1, pathfinding_searchdistance,
@ -1734,8 +1721,8 @@ function mob_class:smart_mobs(s, p, dist, dtime)
end end
end end
-- temporary entity for go_to() function
-- temp entity for go_to() function
minetest.register_entity("mobs:_pos", { minetest.register_entity("mobs:_pos", {
initial_properties = { initial_properties = {
visual = "sprite", texture = "", hp_max = 1, physical = false, visual = "sprite", texture = "", hp_max = 1, physical = false,
@ -1751,6 +1738,7 @@ minetest.register_entity("mobs:_pos", {
}) })
-- add temp entity and make mob go to that entity position -- add temp entity and make mob go to that entity position
function mob_class:go_to(pos) function mob_class:go_to(pos)
local obj = minetest.add_entity(pos, "mobs:_pos") local obj = minetest.add_entity(pos, "mobs:_pos")
@ -1758,8 +1746,8 @@ function mob_class:go_to(pos)
if obj and obj:get_luaentity() then self:do_attack(obj, true) end if obj and obj:get_luaentity() then self:do_attack(obj, true) end
end end
-- peaceful player privilege support -- peaceful player privilege support
local function is_peaceful_player(player) local function is_peaceful_player(player)
-- main setting enabled -- main setting enabled
@ -1773,8 +1761,8 @@ local function is_peaceful_player(player)
end end
end end
-- general attack function for all mobs -- general attack function for all mobs
function mob_class:general_attack() function mob_class:general_attack()
-- return if already attacking, passive or docile during day -- return if already attacking, passive or docile during day
@ -1868,8 +1856,8 @@ function mob_class:general_attack()
end end
end end
-- find someone to runaway from -- find someone to runaway from
function mob_class:do_runaway_from() function mob_class:do_runaway_from()
if not self.runaway_from then return end if not self.runaway_from then return end
@ -1947,8 +1935,8 @@ function mob_class:do_runaway_from()
end end
end end
-- follow player if owner or holding item, if fish outta water then flop -- follow player if owner or holding item, if fish outta water then flop
function mob_class:follow_flop() function mob_class:follow_flop()
-- find player to follow -- find player to follow
@ -2042,8 +2030,8 @@ function mob_class:follow_flop()
end end
end end
-- dogshoot attack switch and counter function -- dogshoot attack switch and counter function
function mob_class:dogswitch(dtime) function mob_class:dogswitch(dtime)
-- switch mode not activated -- switch mode not activated
@ -2066,8 +2054,8 @@ function mob_class:dogswitch(dtime)
return self.dogshoot_switch return self.dogshoot_switch
end end
-- stop attack and reset vars
-- stop attack
function mob_class:stop_attack() function mob_class:stop_attack()
self.attack = nil self.attack = nil
@ -2081,8 +2069,8 @@ function mob_class:stop_attack()
self:set_animation("stand", true) self:set_animation("stand", true)
end end
-- execute current state (stand, walk, run, attacks) -- execute current state (stand, walk, run, attacks)
function mob_class:do_states(dtime) function mob_class:do_states(dtime)
local yaw = self.object:get_yaw() ; if not yaw then return end local yaw = self.object:get_yaw() ; if not yaw then return end
@ -2565,8 +2553,8 @@ function mob_class:do_states(dtime)
end end
end end
-- falling and fall damage -- falling and fall damage
function mob_class:falling(pos) function mob_class:falling(pos)
if self.fly or self.disable_falling then return end if self.fly or self.disable_falling then return end
@ -2609,11 +2597,8 @@ function mob_class:falling(pos)
self.object:set_acceleration({x = 0, y = fall_speed, z = 0}) self.object:set_acceleration({x = 0, y = fall_speed, z = 0})
end end
-- is Took Ranks mod active?
local tr = minetest.get_modpath("toolranks")
-- deal damage and effects when mob punched -- deal damage and effects when mob punched
function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage) function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
-- mob health check -- mob health check
@ -2746,10 +2731,10 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
end end
if mobs.is_creative(hitter:get_player_name()) then if mobs.is_creative(hitter:get_player_name()) then
wear = tr and 1 or 0 wear = use_tr and 1 or 0
end end
if tr and weapon_def.original_description then if use_tr and weapon_def.original_description then
toolranks.new_afteruse(weapon, hitter, nil, {wear = wear}) toolranks.new_afteruse(weapon, hitter, nil, {wear = wear})
else else
weapon:add_wear(wear) weapon:add_wear(wear)
@ -2924,8 +2909,8 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
return true return true
end end
-- helper function to clean mob staticdata -- helper function to clean mob staticdata
local function clean_staticdata(self) local function clean_staticdata(self)
local tmp, t = {} local tmp, t = {}
@ -2943,8 +2928,8 @@ local function clean_staticdata(self)
return tmp return tmp
end end
-- get entity staticdata -- get entity staticdata
function mob_class:mob_staticdata() function mob_class:mob_staticdata()
-- this handles mob count for mobs activated, unloaded, reloaded -- this handles mob count for mobs activated, unloaded, reloaded
@ -3003,6 +2988,7 @@ function mob_class:mob_staticdata()
return minetest.serialize(clean_staticdata(self)) return minetest.serialize(clean_staticdata(self))
end end
-- list of items used in initial_properties
local is_property_name = { local is_property_name = {
hp_max = true, physical = true, collide_with_objects = true, collisionbox = true, hp_max = true, physical = true, collide_with_objects = true, collisionbox = true,
@ -3011,6 +2997,7 @@ local is_property_name = {
} }
-- activate mob and reload settings -- activate mob and reload settings
function mob_class:mob_activate(staticdata, def, dtime) function mob_class:mob_activate(staticdata, def, dtime)
-- if dtime == 0 then entity has just been created -- if dtime == 0 then entity has just been created
@ -3161,8 +3148,8 @@ function mob_class:mob_activate(staticdata, def, dtime)
end end
end end
-- handle mob lifetimer and expiration -- handle mob lifetimer and expiration
function mob_class:mob_expire(pos, dtime) function mob_class:mob_expire(pos, dtime)
-- when lifetimer expires remove mob (except npc and tamed) -- when lifetimer expires remove mob (except npc and tamed)
@ -3193,8 +3180,8 @@ function mob_class:mob_expire(pos, dtime)
end end
end end
-- get nodes mob is standing on, in, facing, facing above
-- get nodes mob is standing on/in, facing/above
function mob_class:get_nodes() function mob_class:get_nodes()
local pos = self.object:get_pos() local pos = self.object:get_pos()
@ -3237,8 +3224,8 @@ print("on: " .. self.standing_on
]] ]]
end end
-- main mob function -- main mob function
function mob_class:on_step(dtime, moveresult) function mob_class:on_step(dtime, moveresult)
if self.state == "die" then return end if self.state == "die" then return end
@ -3379,8 +3366,8 @@ function mob_class:on_step(dtime, moveresult)
end end
end end
-- default function when mobs are blown up with TNT -- default function when mobs are blown up with TNT
function mob_class:on_blast(damage) function mob_class:on_blast(damage)
--print("-- blast damage", damage) --print("-- blast damage", damage)
@ -3392,10 +3379,8 @@ function mob_class:on_blast(damage)
return false, false, {} return false, false, {}
end end
mobs.spawning_mobs = {}
-- register mob entity -- register mob entity
function mobs:register_mob(name, def) function mobs:register_mob(name, def)
mobs.spawning_mobs[name] = {} mobs.spawning_mobs[name] = {}
@ -3547,12 +3532,11 @@ minetest.register_entity(":" .. name, setmetatable({
end end
}, mob_class_meta)) }, mob_class_meta))
end
end -- END mobs:register_mob function
-- count how many mobs of one type are inside an area -- count how many mobs of one type are inside an area
-- will also return true for second value if player is inside area -- will also return true for second value if player is inside area
local function count_mobs(pos, type) local function count_mobs(pos, type)
local total = 0 local total = 0
@ -3575,8 +3559,8 @@ local function count_mobs(pos, type)
return total, players return total, players
end end
-- do we have enough space to spawn mob? (thanks wuzzy) -- do we have enough space to spawn mob? (thanks wuzzy)
local function can_spawn(pos, name) local function can_spawn(pos, name)
local ent = minetest.registered_entities[name] local ent = minetest.registered_entities[name]
@ -3630,7 +3614,6 @@ function mobs:can_spawn(pos, name)
return can_spawn(pos, name) return can_spawn(pos, name)
end end
-- global functions -- global functions
function mobs:add_mob(pos, def) function mobs:add_mob(pos, def)
@ -3698,24 +3681,17 @@ function mobs:add_mob(pos, def)
mob:set_properties({ mob:set_properties({
textures = new_texture, textures = new_texture,
visual_size = { visual_size = {
x = ent.base_size.x * .5, x = ent.base_size.x * .5, y = ent.base_size.y * .5
y = ent.base_size.y * .5
}, },
collisionbox = { collisionbox = {
ent.base_colbox[1] * .5, ent.base_colbox[1] * .5, ent.base_colbox[2] * .5,
ent.base_colbox[2] * .5, ent.base_colbox[3] * .5, ent.base_colbox[4] * .5,
ent.base_colbox[3] * .5, ent.base_colbox[5] * .5, ent.base_colbox[6] * .5
ent.base_colbox[4] * .5,
ent.base_colbox[5] * .5,
ent.base_colbox[6] * .5
}, },
selectionbox = { selectionbox = {
ent.base_selbox[1] * .5, ent.base_selbox[1] * .5, ent.base_selbox[2] * .5,
ent.base_selbox[2] * .5, ent.base_selbox[3] * .5, ent.base_selbox[4] * .5,
ent.base_selbox[3] * .5, ent.base_selbox[5] * .5, ent.base_selbox[6] * .5
ent.base_selbox[4] * .5,
ent.base_selbox[5] * .5,
ent.base_selbox[6] * .5
} }
}) })
@ -3747,12 +3723,13 @@ function mobs:add_mob(pos, def)
return ent return ent
end end
-- global function to add additional spawn checks
function mobs:spawn_abm_check(pos, node, name) function mobs:spawn_abm_check(pos, node, name)
-- global function to add additional spawn checks
-- return true to stop spawning mob -- return true to stop spawning mob
end end
-- older spawning function
function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, interval, function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, interval,
chance, aoc, min_height, max_height, day_toggle, on_spawn, map_load) chance, aoc, min_height, max_height, day_toggle, on_spawn, map_load)
@ -3936,7 +3913,6 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
end end
end end
-- are we registering an abm or lbm? -- are we registering an abm or lbm?
if map_load == true then if map_load == true then
@ -3966,8 +3942,8 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
end end
end end
-- compatibility with older mob registration [DEPRECATED] -- compatibility with older mob registration [DEPRECATED]
function mobs:register_spawn(name, nodes, max_light, min_light, chance, function mobs:register_spawn(name, nodes, max_light, min_light, chance,
active_object_count, max_height, day_toggle) active_object_count, max_height, day_toggle)
@ -3975,8 +3951,8 @@ function mobs:register_spawn(name, nodes, max_light, min_light, chance,
chance, active_object_count, -31000, max_height, day_toggle) chance, active_object_count, -31000, max_height, day_toggle)
end end
-- MarkBu's newer spawn function (USE this one please modders)
-- MarkBu's spawn function (USE this one please)
function mobs:spawn(def) function mobs:spawn(def)
mobs:spawn_specific( mobs:spawn_specific(
@ -3995,8 +3971,8 @@ function mobs:spawn(def)
def.on_map_load) def.on_map_load)
end end
-- register arrow for shoot attack -- register arrow for shoot attack
function mobs:register_arrow(name, def) function mobs:register_arrow(name, def)
if not name or not def then return end if not name or not def then return end
@ -4163,14 +4139,8 @@ function mobs:register_arrow(name, def)
}) })
end end
-- compatibility function (deprecated)
function mobs:explosion(pos, radius)
mobs:boom({sounds = {explode = "tnt_explode"}}, pos, radius, radius, "tnt_smoke.png")
end
-- no damage to nodes explosion -- no damage to nodes explosion
function mobs:safe_boom(self, pos, radius, texture) function mobs:safe_boom(self, pos, radius, texture)
minetest.sound_play(self.sounds and self.sounds.explode or "tnt_explode", { minetest.sound_play(self.sounds and self.sounds.explode or "tnt_explode", {
@ -4184,8 +4154,8 @@ function mobs:safe_boom(self, pos, radius, texture)
effect(pos, 32, texture, radius * 3, radius * 5, radius, 1, 0) effect(pos, 32, texture, radius * 3, radius * 5, radius, 1, 0)
end end
-- make explosion with protection and tnt mod check -- make explosion with protection and tnt mod check
function mobs:boom(self, pos, radius, damage_radius, texture) function mobs:boom(self, pos, radius, damage_radius, texture)
if mobs_griefing and minetest.get_modpath("tnt") and tnt and tnt.boom if mobs_griefing and minetest.get_modpath("tnt") and tnt and tnt.boom
@ -4203,11 +4173,14 @@ function mobs:boom(self, pos, radius, damage_radius, texture)
end end
end end
function mobs:explosion(pos, radius) -- [deprecated] compatibility function
mobs:boom({sounds = {explode = "tnt_explode"}}, pos, radius, radius, "tnt_smoke.png")
end
-- Register spawn eggs - This also introduces the “spawn_egg” group:
-- * spawn_egg=1: generic mob, no metadata
-- * spawn_egg=2: captured/tamed mob, metadata
-- Register spawn eggs
-- Note: This also introduces the “spawn_egg” group:
-- * spawn_egg=1: Spawn egg (generic mob, no metadata)
-- * spawn_egg=2: Spawn egg (captured/tamed mob, metadata)
function mobs:register_egg(mob, desc, background, addegg, no_creative) function mobs:register_egg(mob, desc, background, addegg, no_creative)
local grp = {spawn_egg = 1} local grp = {spawn_egg = 1}
@ -4230,7 +4203,7 @@ function mobs:register_egg(mob, desc, background, addegg, no_creative)
end end
-- register new spawn egg containing mob information (cannot be stacked) -- register new spawn egg containing mob information (cannot be stacked)
-- these are only created for animals and npc mobs, not monsters -- these are only created for animals and npc's, not monsters
if is_mob.type ~= "monster" then if is_mob.type ~= "monster" then
minetest.register_craftitem(":" .. mob .. "_set", { minetest.register_craftitem(":" .. mob .. "_set", {
@ -4346,8 +4319,8 @@ end
}) })
end end
-- force capture a mob if space available in inventory, or drop as spawn egg -- force capture a mob if space available in inventory, or drop as spawn egg
function mobs:force_capture(self, clicker) function mobs:force_capture(self, clicker)
-- add special mob egg with all mob information -- add special mob egg with all mob information
@ -4370,8 +4343,8 @@ function mobs:force_capture(self, clicker)
remove_mob(self, true) remove_mob(self, true)
end end
-- capture critter (thanks to blert2112 for idea) -- capture critter (thanks to blert2112 for idea)
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)
@ -4383,9 +4356,7 @@ function mobs:capture_mob(
local mobname = self.name local mobname = self.name
-- if not nil change what will be added to inventory -- if not nil change what will be added to inventory
if replacewith then if replacewith then mobname = replacewith end
mobname = replacewith
end
local name = clicker:get_player_name() local name = clicker:get_player_name()
local tool = clicker:get_wielded_item() local tool = clicker:get_wielded_item()
@ -4486,8 +4457,8 @@ function mobs:capture_mob(
return true return true
end end
-- protect tamed mob with rune item -- protect tamed mob with rune item
function mobs:protect(self, clicker) function mobs:protect(self, clicker)
local name = clicker:get_player_name() local name = clicker:get_player_name()
@ -4533,11 +4504,10 @@ function mobs:protect(self, clicker)
return true return true
end end
-- feeding, taming, breeding and naming (thanks blert2112)
local mob_obj = {} local mob_obj, mob_sta = {}, {}
local mob_sta = {}
-- feeding, taming and breeding (thanks blert2112)
function mobs:feed_tame(self, clicker, feed_count, breed, tame) function mobs:feed_tame(self, clicker, feed_count, breed, tame)
-- can eat/tame with item in hand -- can eat/tame with item in hand
@ -4649,8 +4619,8 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
return false return false
end end
-- inspired by blockmen's nametag mod -- inspired by blockmen's nametag mod
minetest.register_on_player_receive_fields(function(player, formname, fields) minetest.register_on_player_receive_fields(function(player, formname, fields)
-- right-clicked with nametag and name entered? -- right-clicked with nametag and name entered?
@ -4685,8 +4655,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end end
end) end)
-- compatibility function for old mobs entities to new mobs_redo modpack -- compatibility function for old mobs entities to new mobs_redo modpack
function mobs:alias_mob(old_name, new_name) function mobs:alias_mob(old_name, new_name)
-- check old_name entity doesnt already exist -- check old_name entity doesnt already exist
@ -4718,8 +4688,8 @@ function mobs:alias_mob(old_name, new_name)
}) })
end end
-- admin command to remove untamed mobs around players -- admin command to remove untamed mobs around players
minetest.register_chatcommand("clear_mobs", { minetest.register_chatcommand("clear_mobs", {
params = "<text>", params = "<text>",
description = "Remove untamed mobs from around players.", description = "Remove untamed mobs from around players.",
@ -4758,8 +4728,8 @@ minetest.register_chatcommand("clear_mobs", {
end end
}) })
-- Is mob hearing enabled, if so override minetest.sound_play with custom function -- Is mob hearing enabled, if so override minetest.sound_play with custom function
if settings:get_bool("mobs_can_hear") ~= false then if settings:get_bool("mobs_can_hear") ~= false then
local old_sound_play = minetest.sound_play local old_sound_play = minetest.sound_play
@ -4830,4 +4800,4 @@ minetest.sound_play = function(spec, param, eph)
return old_sound_play(spec, param, eph) return old_sound_play(spec, param, eph)
end end
end -- setting END end

View File

@ -1,9 +1,31 @@
local S = mobs.translate local S = minetest.get_translator("mobs")
local FS = function(...) return minetest.formspec_escape(S(...)) end local FS = function(...) return minetest.formspec_escape(S(...)) end
local mc2 = minetest.get_modpath("mcl_core") local mc2 = minetest.get_modpath("mcl_core")
local mod_def = minetest.get_modpath("default")
-- determine which sounds to use, default or mcl_sounds
local function sound_helper(snd)
mobs[snd] = (mod_def and default[snd]) or (mc2 and mcl_sounds[snd])
or function() return {} end
end
sound_helper("node_sound_defaults")
sound_helper("node_sound_stone_defaults")
sound_helper("node_sound_dirt_defaults")
sound_helper("node_sound_sand_defaults")
sound_helper("node_sound_gravel_defaults")
sound_helper("node_sound_wood_defaults")
sound_helper("node_sound_leaves_defaults")
sound_helper("node_sound_ice_defaults")
sound_helper("node_sound_metal_defaults")
sound_helper("node_sound_water_defaults")
sound_helper("node_sound_snow_defaults")
-- helper function to add {eatable} group to food items -- helper function to add {eatable} group to food items
function mobs.add_eatable(item, hp) function mobs.add_eatable(item, hp)
local def = minetest.registered_items[item] local def = minetest.registered_items[item]
@ -19,6 +41,7 @@ function mobs.add_eatable(item, hp)
end end
-- recipe items -- recipe items
local items = { local items = {
paper = mc2 and "mcl_core:paper" or "default:paper", paper = mc2 and "mcl_core:paper" or "default:paper",
dye_black = mc2 and "mcl_dye:black" or "dye:black", dye_black = mc2 and "mcl_dye:black" or "dye:black",
@ -36,8 +59,8 @@ local items = {
meat_cooked = mc2 and "mcl_mobitems:cooked_beef" or "group:food_meat", 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", {
description = S("Name Tag") .. " " .. S("\nRight-click Mobs Redo mob to apply"), description = S("Name Tag") .. " " .. S("\nRight-click Mobs Redo mob to apply"),
inventory_image = "mobs_nametag.png", inventory_image = "mobs_nametag.png",
@ -52,6 +75,7 @@ minetest.register_craft({
}) })
-- leather -- leather
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",
@ -59,6 +83,7 @@ minetest.register_craftitem("mobs:leather", {
}) })
-- raw meat -- raw meat
minetest.register_craftitem("mobs:meat_raw", { minetest.register_craftitem("mobs:meat_raw", {
description = S("Raw Meat"), description = S("Raw Meat"),
inventory_image = "mobs_meat_raw.png", inventory_image = "mobs_meat_raw.png",
@ -69,6 +94,7 @@ minetest.register_craftitem("mobs:meat_raw", {
mobs.add_eatable("mobs:meat_raw", 3) mobs.add_eatable("mobs:meat_raw", 3)
-- cooked meat -- cooked meat
minetest.register_craftitem("mobs:meat", { minetest.register_craftitem("mobs:meat", {
description = S("Meat"), description = S("Meat"),
inventory_image = "mobs_meat.png", inventory_image = "mobs_meat.png",
@ -86,6 +112,7 @@ minetest.register_craft({
}) })
-- lasso -- lasso
minetest.register_tool("mobs:lasso", { minetest.register_tool("mobs:lasso", {
description = S("Lasso (right-click animal to put in inventory)"), description = S("Lasso (right-click animal to put in inventory)"),
inventory_image = "mobs_magic_lasso.png", inventory_image = "mobs_magic_lasso.png",
@ -104,6 +131,7 @@ minetest.register_craft({
minetest.register_alias("mobs:magic_lasso", "mobs:lasso") minetest.register_alias("mobs:magic_lasso", "mobs:lasso")
-- net -- net
minetest.register_tool("mobs:net", { minetest.register_tool("mobs:net", {
description = S("Net (right-click animal to put in inventory)"), description = S("Net (right-click animal to put in inventory)"),
inventory_image = "mobs_net.png", inventory_image = "mobs_net.png",
@ -120,6 +148,7 @@ minetest.register_craft({
}) })
-- shears (right click to shear animal) -- shears (right click to shear animal)
minetest.register_tool("mobs:shears", { minetest.register_tool("mobs:shears", {
description = S("Steel Shears (right-click to shear)"), description = S("Steel Shears (right-click to shear)"),
inventory_image = "mobs_shears.png", inventory_image = "mobs_shears.png",
@ -135,6 +164,7 @@ minetest.register_craft({
}) })
-- protection rune -- protection rune
minetest.register_craftitem("mobs:protector", { minetest.register_craftitem("mobs:protector", {
description = S("Mob Protection Rune"), description = S("Mob Protection Rune"),
inventory_image = "mobs_protector.png", inventory_image = "mobs_protector.png",
@ -150,7 +180,8 @@ minetest.register_craft({
} }
}) })
-- level 2 protection rune -- protection rune (level 2)
minetest.register_craftitem("mobs:protector2", { minetest.register_craftitem("mobs:protector2", {
description = S("Mob Protection Rune (Level 2)"), description = S("Mob Protection Rune (Level 2)"),
inventory_image = "mobs_protector2.png", inventory_image = "mobs_protector2.png",
@ -167,6 +198,7 @@ minetest.register_craft({
}) })
-- saddle -- saddle
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",
@ -182,9 +214,7 @@ minetest.register_craft({
} }
}) })
-- register mob fence if default found
-- make sure we can register fences
local mod_def = minetest.get_modpath("default")
if mod_def and default.register_fence then if mod_def and default.register_fence then
@ -194,17 +224,15 @@ default.register_fence("mobs:fence_wood", {
texture = "default_wood.png", texture = "default_wood.png",
material = "default:fence_wood", material = "default:fence_wood",
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
sounds = mod_def and default.node_sound_wood_defaults(), sounds = mobs.node_sound_wood_defaults(),
collision_box = { collision_box = {
type = "fixed", type = "fixed", fixed = {{-0.5, -0.5, -0.5, 0.5, 1.9, 0.5}}
fixed = {
{-0.5, -0.5, -0.5, 0.5, 1.9, 0.5},
}
} }
}) })
end end
-- mob fence top (has enlarged collisionbox to stop mobs getting over) -- mob fence top (has enlarged collisionbox to stop mobs getting over)
minetest.register_node("mobs:fence_top", { minetest.register_node("mobs:fence_top", {
description = S("Mob Fence Top"), description = S("Mob Fence Top"),
drawtype = "nodebox", drawtype = "nodebox",
@ -212,19 +240,10 @@ minetest.register_node("mobs:fence_top", {
paramtype = "light", paramtype = "light",
is_ground_content = false, is_ground_content = false,
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, axey = 1}, groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, axey = 1},
sounds = mod_def and default.node_sound_wood_defaults(), sounds = mobs.node_sound_wood_defaults(),
node_box = { node_box = {type = "fixed", fixed = {-0.2, -0.5, -0.2, 0.2, 0, 0.2}},
type = "fixed", collision_box = {type = "fixed", fixed = {-0.4, -1.5, -0.4, 0.4, 0, 0.4}},
fixed = {-0.2, -0.5, -0.2, 0.2, 0, 0.2} selection_box = {type = "fixed", fixed = {-0.4, -1.5, -0.4, 0.4, 0, 0.4}}
},
collision_box = {
type = "fixed",
fixed = {-0.4, -1.5, -0.4, 0.4, 0, 0.4}
},
selection_box = {
type = "fixed",
fixed = {-0.4, -1.5, -0.4, 0.4, 0, 0.4}
}
}) })
minetest.register_craft({ minetest.register_craft({
@ -235,49 +254,15 @@ minetest.register_craft({
} }
}) })
-- items that can be used as fuel -- items that can be used as fuel
minetest.register_craft({
type = "fuel",
recipe = "mobs:nametag",
burntime = 3
})
minetest.register_craft({ minetest.register_craft({type = "fuel", recipe = "mobs:nametag", burntime = 3})
type = "fuel", minetest.register_craft({type = "fuel", recipe = "mobs:lasso", burntime = 7})
recipe = "mobs:lasso", minetest.register_craft({type = "fuel", recipe = "mobs:net", burntime = 8})
burntime = 7 minetest.register_craft({type = "fuel", recipe = "mobs:leather", burntime = 4})
}) minetest.register_craft({type = "fuel", recipe = "mobs:saddle", burntime = 7})
minetest.register_craft({type = "fuel", recipe = "mobs:fence_wood", burntime = 7})
minetest.register_craft({ minetest.register_craft({type = "fuel", recipe = "mobs:fence_top", burntime = 2})
type = "fuel",
recipe = "mobs:net",
burntime = 8
})
minetest.register_craft({
type = "fuel",
recipe = "mobs:leather",
burntime = 4
})
minetest.register_craft({
type = "fuel",
recipe = "mobs:saddle",
burntime = 7
})
minetest.register_craft({
type = "fuel",
recipe = "mobs:fence_wood",
burntime = 7
})
minetest.register_craft({
type = "fuel",
recipe = "mobs:fence_top",
burntime = 2
})
-- this tool spawns same mob and adds owner, protected, nametag info -- this tool spawns same mob and adds owner, protected, nametag info
@ -294,12 +279,9 @@ minetest.register_tool(":mobs:mob_reset_stick", {
on_use = function(itemstack, user, pointed_thing) on_use = function(itemstack, user, pointed_thing)
if pointed_thing.type ~= "object" then if pointed_thing.type ~= "object" then return end
return
end
local obj = pointed_thing.ref local obj = pointed_thing.ref
local control = user:get_player_control() local control = user:get_player_control()
local sneak = control and control.sneak local sneak = control and control.sneak
@ -339,9 +321,7 @@ minetest.register_tool(":mobs:mob_reset_stick", {
-- get base texture -- get base texture
local bt = tex_obj:get_luaentity().base_texture[1] local bt = tex_obj:get_luaentity().base_texture[1]
if type(bt) ~= "string" then if type(bt) ~= "string" then bt = "" end
bt = ""
end
local name = user:get_player_name() local name = user:get_player_name()
@ -357,27 +337,18 @@ minetest.register_tool(":mobs:mob_reset_stick", {
minetest.register_on_player_receive_fields(function(player, formname, fields) minetest.register_on_player_receive_fields(function(player, formname, fields)
-- right-clicked with nametag and name entered? -- right-clicked with nametag and name entered?
if formname == "mobs_texture" if formname == "mobs_texture" and fields.name and fields.name ~= "" then
and fields.name
and fields.name ~= "" then
-- does mob still exist? -- does mob still exist?
if not tex_obj if not tex_obj or not tex_obj:get_luaentity() then return end
or not tex_obj:get_luaentity() then
return
end
-- make sure nametag is being used to name mob -- make sure nametag is being used to name mob
local item = player:get_wielded_item() local item = player:get_wielded_item()
if item:get_name() ~= "mobs:mob_reset_stick" then if item:get_name() ~= "mobs:mob_reset_stick" then return end
return
end
-- limit name entered to 64 characters long -- limit name entered to 64 characters long
if fields.name:len() > 64 then if fields.name:len() > 64 then fields.name = fields.name:sub(1, 64) end
fields.name = fields.name:sub(1, 64)
end
-- update texture -- update texture
local self = tex_obj:get_luaentity() local self = tex_obj:get_luaentity()
@ -391,17 +362,15 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end end
end) end)
-- Meat Block -- Meat Block
minetest.register_node("mobs:meatblock", { minetest.register_node("mobs:meatblock", {
description = S("Meat Block"), description = S("Meat Block"),
tiles = {"mobs_meat_top.png", "mobs_meat_bottom.png", "mobs_meat_side.png"}, tiles = {"mobs_meat_top.png", "mobs_meat_bottom.png", "mobs_meat_side.png"},
paramtype2 = "facedir", paramtype2 = "facedir",
groups = { groups = {choppy = 1, oddly_breakable_by_hand = 1, axey = 1, handy = 1},
choppy = 1, oddly_breakable_by_hand = 1, axey = 1, handy = 1
},
is_ground_content = false, is_ground_content = false,
sounds = mod_def and default.node_sound_leaves_defaults(), sounds = mobs.node_sound_dirt_defaults(),
on_place = minetest.rotate_node, on_place = minetest.rotate_node,
on_use = minetest.item_eat(20), on_use = minetest.item_eat(20),
_mcl_hardness = 0.8, _mcl_hardness = 0.8,
@ -420,15 +389,14 @@ minetest.register_craft({
}) })
-- Meat Block (raw) -- Meat Block (raw)
minetest.register_node("mobs:meatblock_raw", { minetest.register_node("mobs:meatblock_raw", {
description = S("Raw Meat Block"), description = S("Raw Meat Block"),
tiles = {"mobs_meat_raw_top.png", "mobs_meat_raw_bottom.png", "mobs_meat_raw_side.png"}, tiles = {"mobs_meat_raw_top.png", "mobs_meat_raw_bottom.png", "mobs_meat_raw_side.png"},
paramtype2 = "facedir", paramtype2 = "facedir",
groups = { groups = {choppy = 1, oddly_breakable_by_hand = 1, axey = 1, handy = 1},
choppy = 1, oddly_breakable_by_hand = 1, axey = 1, handy = 1
},
is_ground_content = false, is_ground_content = false,
sounds = mod_def and default.node_sound_leaves_defaults(), sounds = mobs.node_sound_dirt_defaults(),
on_place = minetest.rotate_node, on_place = minetest.rotate_node,
on_use = minetest.item_eat(20), on_use = minetest.item_eat(20),
_mcl_hardness = 0.8, _mcl_hardness = 0.8,

View File

@ -1,13 +1,13 @@
local path = minetest.get_modpath("mobs") -- peaceful player privilege
-- Peaceful player privilege
minetest.register_privilege("peaceful_player", { minetest.register_privilege("peaceful_player", {
description = "Prevents Mobs Redo mobs from attacking player", description = "Prevents Mobs Redo mobs from attacking player",
give_to_singleplayer = false give_to_singleplayer = false
}) })
-- Fallback node -- fallback node
minetest.register_node("mobs:fallback_node", { minetest.register_node("mobs:fallback_node", {
description = "Fallback Node", description = "Fallback Node",
tiles = {"mobs_fallback.png"}, tiles = {"mobs_fallback.png"},
@ -16,22 +16,20 @@ minetest.register_node("mobs:fallback_node", {
drop = "" drop = ""
}) })
-- Mob API local path = minetest.get_modpath("mobs")
dofile(path .. "/api.lua")
-- Rideable Mobs dofile(path .. "/api.lua") -- mob API
dofile(path .. "/mount.lua")
-- Mob Items dofile(path .. "/mount.lua") -- rideable mobs
dofile(path .. "/crafts.lua")
-- Mob Spawner dofile(path .. "/crafts.lua") -- items and crafts
dofile(path .. "/spawner.lua")
dofile(path .. "/spawner.lua") -- mob spawner
-- Lucky Blocks -- Lucky Blocks
if minetest.get_modpath("lucky_block") then if minetest.get_modpath("lucky_block") then
dofile(path .. "/lucky_block.lua") dofile(path .. "/lucky_block.lua")
end end
print("[MOD] Mobs Redo loaded") print("[MOD] Mobs Redo loaded")

View File

@ -1,6 +1,7 @@
local S = minetest.get_translator("mobs") local S = minetest.get_translator("mobs")
-- add lucky blocks
lucky_block:add_blocks({ lucky_block:add_blocks({
{"dro", {"mobs:meat_raw"}, 5}, {"dro", {"mobs:meat_raw"}, 5},
@ -17,8 +18,7 @@ lucky_block:add_blocks({
{"lig"} {"lig"}
}) })
-- pint sized rune, use on tamed mob to shrink to half-size
-- pint sized rune
minetest.register_craftitem(":mobs:pint_sized_rune", { minetest.register_craftitem(":mobs:pint_sized_rune", {
description = S("Pint Sized Rune"), description = S("Pint Sized Rune"),
@ -27,17 +27,13 @@ minetest.register_craftitem(":mobs:pint_sized_rune", {
on_use = function(itemstack, user, pointed_thing) on_use = function(itemstack, user, pointed_thing)
if pointed_thing.type ~= "object" then if pointed_thing.type ~= "object" then return end
return
end
local name = user and user:get_player_name() or "" local name = user and user:get_player_name() or ""
local tool = user and user:get_wielded_item() local tool = user and user:get_wielded_item()
local tool_name = tool:get_name() local tool_name = tool:get_name()
if tool_name ~= "mobs:pint_sized_rune" then if tool_name ~= "mobs:pint_sized_rune" then return end
return
end
local self = pointed_thing.ref:get_luaentity() local self = pointed_thing.ref:get_luaentity()
@ -82,11 +78,8 @@ minetest.register_craftitem(":mobs:pint_sized_rune", {
self.base_selbox = selbox self.base_selbox = selbox
self.object:set_properties({ self.object:set_properties(
visual_size = vis_size, {visual_size = vis_size, collisionbox = colbox, selectionbox = selbox})
collisionbox = colbox,
selectionbox = selbox
})
self.pint_size_potion = true self.pint_size_potion = true
@ -102,4 +95,3 @@ minetest.register_craft({
output = "lucky_block:pint_sized_rune", output = "lucky_block:pint_sized_rune",
recipe = {{"lucky_block:pint_sized_potion", "mobs:protector"}} recipe = {{"lucky_block:pint_sized_potion", "mobs:protector"}}
}) })

View File

@ -1,4 +1,4 @@
name = mobs name = mobs
description = Adds a mob api for mods to add animals or monsters etc. description = Adds a mob api for mods to add animals or monsters etc.
optional_depends = default, tnt, invisibility, lucky_block, cmi, toolranks, pathfinder, player_api, mtobjid, visual_harm_1ndicators optional_depends = default, tnt, invisibility, lucky_block, cmi, toolranks, pathfinder, player_api, mtobjid, visual_harm_1ndicators, mcl_sounds
min_minetest_version = 5.0 min_minetest_version = 5.0

108
mount.lua
View File

@ -1,8 +1,10 @@
-- lib_mount by Blert2112 (edited by TenPlus1) -- lib_mount by Blert2112 (edited by TenPlus1)
local is_mc2 = minetest.get_modpath("mcl_mobs") -- MineClone2 check local is_mc2 = minetest.get_modpath("mcl_mobs") -- MineClone2 check
-- one of these is needed to ride mobs, otherwise no riding for you -- one of these is needed to ride mobs, otherwise no riding for you
if not minetest.get_modpath("player_api") and not is_mc2 then if not minetest.get_modpath("player_api") and not is_mc2 then
function mobs.attach() end function mobs.attach() end
@ -14,12 +16,11 @@ if not minetest.get_modpath("player_api") and not is_mc2 then
end end
-- Localise some functions -- Localise some functions
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
-- -- helper functions
-- Helper functions
--
local node_ok = function(pos, fallback) local node_ok = function(pos, fallback)
@ -27,9 +28,7 @@ local node_ok = function(pos, fallback)
local node = minetest.get_node_or_nil(pos) local node = minetest.get_node_or_nil(pos)
if node and minetest.registered_nodes[node.name] then if node and minetest.registered_nodes[node.name] then return node end
return node
end
return {name = fallback} return {name = fallback}
end end
@ -39,9 +38,7 @@ local function node_is(entity)
if not entity.standing_on then return "other" end if not entity.standing_on then return "other" end
if entity.standing_on == "air" then if entity.standing_on == "air" then return "air" end
return "air"
end
if minetest.get_item_group(entity.standing_on, "lava") ~= 0 then if minetest.get_item_group(entity.standing_on, "lava") ~= 0 then
return "lava" return "lava"
@ -61,14 +58,10 @@ end
local function get_sign(i) local function get_sign(i)
i = i or 0 if not i or i == 0 then return 0 end
if i == 0 then
return 0
else
return i / abs(i) return i / abs(i)
end end
end
local function get_velocity(v, yaw, y) local function get_velocity(v, yaw, y)
@ -89,9 +82,7 @@ local function force_detach(player)
local attached_to = player and player:get_attach() local attached_to = player and player:get_attach()
if not attached_to then if not attached_to then return end
return
end
local entity = attached_to:get_luaentity() local entity = attached_to:get_luaentity()
@ -115,11 +106,13 @@ local function force_detach(player)
player:set_properties({visual_size = {x = 1, y = 1}}) player:set_properties({visual_size = {x = 1, y = 1}})
end end
-- detach player on leaving
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
force_detach(player) force_detach(player)
end) end)
-- detatch all players on shutdown
minetest.register_on_shutdown(function() minetest.register_on_shutdown(function()
@ -130,25 +123,21 @@ minetest.register_on_shutdown(function()
end end
end) end)
-- detatch player when dead
minetest.register_on_dieplayer(function(player) minetest.register_on_dieplayer(function(player)
force_detach(player) force_detach(player)
return true return true
end) end)
-- find free position to detach player
-- Just for correct detaching
local function find_free_pos(pos) local function find_free_pos(pos)
local check = { local check = {
{x = 1, y = 0, z = 0}, {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 = -1, y = 1, z = 0}, {x = 0, y = 0, z = 1}, {x = 0, y = 1, z = 1},
{x = -1, y = 0, z = 0}, {x = 0, y = 0, z = -1}, {x = 0, y = 1, z = -1}
{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 for _, c in pairs(check) do
@ -169,8 +158,8 @@ local function find_free_pos(pos)
return pos return pos
end end
-- are we a real player ? -- are we a real player ?
local function is_player(player) local function is_player(player)
if player and type(player) == "userdata" and minetest.is_player(player) then if player and type(player) == "userdata" and minetest.is_player(player) then
@ -178,6 +167,7 @@ local function is_player(player)
end end
end end
-- attach player to mob entity
function mobs.attach(entity, player) function mobs.attach(entity, player)
@ -190,9 +180,7 @@ 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 = pi / 2 end
rot_view = pi / 2
end
local attach_at = entity.driver_attach_at local attach_at = entity.driver_attach_at
local eye_offset = entity.driver_eye_offset local eye_offset = entity.driver_eye_offset
@ -211,10 +199,7 @@ function mobs.attach(entity, player)
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({
visual_size = { visual_size = {x = entity.driver_scale.x, y = entity.driver_scale.y}
x = entity.driver_scale.x,
y = entity.driver_scale.y
}
}) })
minetest.after(0.2, function() minetest.after(0.2, function()
@ -232,6 +217,7 @@ function mobs.attach(entity, player)
player:set_look_horizontal(entity.object:get_yaw() - rot_view) player:set_look_horizontal(entity.object:get_yaw() - rot_view)
end end
-- detatch player from mob
function mobs.detach(player) function mobs.detach(player)
@ -250,15 +236,14 @@ function mobs.detach(player)
end) end)
end end
-- ride mob like car or horse
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 yaw = entity.object:get_yaw() or 0
local rot_view = 0 local rot_view = 0
if entity.player_rotation.y == 90 then if entity.player_rotation.y == 90 then rot_view = pi / 2 end
rot_view = pi / 2
end
local acce_y = 0 local acce_y = 0
local velo = entity.object:get_velocity() ; if not velo then return end local velo = entity.object:get_velocity() ; if not velo then return end
@ -276,9 +261,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
elseif ctrl.down then -- move backwards elseif ctrl.down then -- move backwards
if entity.max_speed_reverse == 0 and entity.v == 0 then if entity.max_speed_reverse == 0 and entity.v == 0 then return end
return
end
entity.v = entity.v - entity.accel * dtime entity.v = entity.v - entity.accel * dtime
end end
@ -290,12 +273,8 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
horz = yaw horz = yaw
if ctrl.left then if ctrl.left then horz = horz + 0.05
horz = horz + 0.05 elseif ctrl.right then horz = horz - 0.05 end
elseif ctrl.right then
horz = horz - 0.05
end
else else
horz = entity.driver:get_look_horizontal() or 0 horz = entity.driver:get_look_horizontal() or 0
end end
@ -333,8 +312,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
if ctrl.jump then -- jump (only when standing on solid surface) if ctrl.jump then -- jump (only when standing on solid surface)
if velo.y == 0 if velo.y == 0
and entity.standing_on ~= "air" and entity.standing_on ~= "air" and entity.standing_on ~= "ignore"
and entity.standing_on ~= "ignore"
and minetest.get_item_group(entity.standing_on, "liquid") == 0 then and minetest.get_item_group(entity.standing_on, "liquid") == 0 then
velo.y = velo.y + entity.jump_height velo.y = velo.y + entity.jump_height
acce_y = acce_y + (acce_y * 3) + 1 acce_y = acce_y + (acce_y * 3) + 1
@ -346,17 +324,13 @@ 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 entity:set_animation(stand_anim) end
entity:set_animation(stand_anim)
end
return return
end end
-- set moving animation -- set moving animation
if moving_anim then if moving_anim then entity:set_animation(moving_anim) end
entity:set_animation(moving_anim)
end
-- Stop! -- Stop!
local s = get_sign(entity.v) local s = get_sign(entity.v)
@ -392,9 +366,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
if ni == "air" then if ni == "air" then
if can_fly == true then if can_fly == true then new_acce.y = 0 end
new_acce.y = 0
end
elseif ni == "liquid" or ni == "lava" then elseif ni == "liquid" or ni == "lava" then
@ -441,8 +413,8 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
entity.v2 = v entity.v2 = v
end end
-- fly mob in facing direction (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, _, 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
@ -454,19 +426,13 @@ function mobs.fly(entity, _, speed, shoots, arrow, moving_anim, stand_anim)
if ctrl.up then if ctrl.up then
entity.object:set_velocity({ entity.object:set_velocity(
x = dir.x * speed, {x = dir.x * speed, y = dir.y * speed + 2, z = dir.z * speed})
y = dir.y * speed + 2,
z = dir.z * speed
})
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, z = -dir.z * speed})
y = dir.y * speed + 2,
z = -dir.z * speed
})
elseif not ctrl.down or ctrl.up or ctrl.jump then elseif not ctrl.down or ctrl.up or ctrl.jump then
entity.object:set_velocity({x = 0, y = -2, z = 0}) entity.object:set_velocity({x = 0, y = -2, z = 0})
@ -501,11 +467,9 @@ function mobs.fly(entity, _, speed, shoots, arrow, moving_anim, stand_anim)
end end
end end
-- 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
entity:set_animation(stand_anim) entity:set_animation(stand_anim) -- stopped animation
else else
-- moving animation entity:set_animation(moving_anim) -- moving animation
entity:set_animation(moving_anim)
end end
end end

View File

@ -66,8 +66,6 @@ mobs_can_hear (Enable Mob hearing) bool true
[Pathfinding] [Pathfinding]
# Enable pathfinding (default Enabled) # Enable pathfinding (default Enabled)
mob_pathfinding_enable (Enable pathfinding) bool true mob_pathfinding_enable (Enable pathfinding) bool true
# Use pathfinder mod if available (default Enabled)
mob_pathfinder_enable (Use pathfinder mod if available) bool true
# How long before stuck mobs starts searching (default 3.0) # How long before stuck mobs starts searching (default 3.0)
mob_pathfinding_stuck_timeout (How long before stuck mobs start searching) float 3.0 mob_pathfinding_stuck_timeout (How long before stuck mobs start searching) float 3.0
# How long will mob follow path before giving up (default 5.0) # How long will mob follow path before giving up (default 5.0)

View File

@ -1,8 +1,9 @@
local S = mobs.translate local S = minetest.get_translator("mobs")
local max_per_block = tonumber(minetest.settings:get("max_objects_per_block") or 99)
-- helper functions
-- are we a real player ?
local function is_player(player) local function is_player(player)
if player and type(player) == "userdata" and minetest.is_player(player) then if player and type(player) == "userdata" and minetest.is_player(player) then
@ -21,8 +22,8 @@ local get_distance = function(a, b)
return square(x * x + y * y + z * z) return square(x * x + y * y + z * z)
end end
-- mob spawner -- 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", {
@ -35,6 +36,7 @@ minetest.register_node("mobs:spawner", {
is_ground_content = false, is_ground_content = false,
_mcl_hardness = 1, _mcl_hardness = 1,
_mcl_blast_resistance = 5, _mcl_blast_resistance = 5,
sounds = mobs.node_sound_stone_defaults(),
on_construct = function(pos) on_construct = function(pos)
@ -56,16 +58,12 @@ minetest.register_node("mobs:spawner", {
on_right_click = function(pos, placer) on_right_click = function(pos, placer)
if minetest.is_protected(pos, placer:get_player_name()) then if minetest.is_protected(pos, placer:get_player_name()) then return end
return
end
end, end,
on_receive_fields = function(pos, formname, fields, sender) on_receive_fields = function(pos, formname, fields, sender)
if not fields.text or fields.text == "" then if not fields.text or fields.text == "" then return end
return
end
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local comm = fields.text:split(" ") local comm = fields.text:split(" ")
@ -76,35 +74,31 @@ minetest.register_node("mobs:spawner", {
return return
end end
local mob = comm[1] -- mob to spawn local mob = comm[1] or "" -- mob to spawn
local mlig = tonumber(comm[2]) -- min light local mlig = tonumber(comm[2]) -- min light
local xlig = tonumber(comm[3]) -- max light local xlig = tonumber(comm[3]) -- max light
local num = tonumber(comm[4]) -- total mobs in area local num = tonumber(comm[4]) -- total mobs in area
local pla = tonumber(comm[5]) -- player distance (0 to disable) local pla = tonumber(comm[5]) -- player distance (0 to disable)
local yof = tonumber(comm[6]) or 0 -- Y offset to spawn mob local yof = tonumber(comm[6]) or 0 -- Y offset to spawn mob
if mob and mob ~= "" and mobs.spawning_mobs[mob] if mob ~= "" and mobs.spawning_mobs[mob] and num and num >= 0 and num <= 10
and num and num >= 0 and num <= 10 and mlig and mlig >= 0 and mlig <= 15 and xlig and xlig >= 0 and xlig <= 15
and mlig and mlig >= 0 and mlig <= 15 and pla and pla >= 0 and pla <= 20 and yof and yof > -10 and yof < 10 then
and xlig and xlig >= 0 and xlig <= 15
and pla and pla >= 0 and pla <= 20
and yof and yof > -10 and yof < 10 then
meta:set_string("command", fields.text) meta:set_string("command", fields.text)
meta:set_string("infotext", S("Spawner Active (@1)", mob)) meta:set_string("infotext", S("Spawner Active (@1)", mob))
else else
minetest.chat_send_player(name, S("Mob Spawner settings failed!")) minetest.chat_send_player(name, S("Mob Spawner settings failed!"))
minetest.chat_send_player(name, minetest.chat_send_player(name,
S("Syntax: “name min_light[0-14] max_light[0-14] max_mobs_in_area[0 to disable] player_distance[1-20] y_offset[-10 to 10]”")) S("Syntax: “name min_light[0-14] max_light[0-14] "
.. "max_mobs_in_area[0 to disable] player_distance[1-20] "
.. "y_offset[-10 to 10]”"))
end end
end end
}) })
local max_per_block = tonumber(minetest.settings:get("max_objects_per_block") or 99)
-- spawner abm -- spawner abm
minetest.register_abm({ minetest.register_abm({
label = "Mob spawner node", label = "Mob spawner node",
nodenames = {"mobs:spawner"}, nodenames = {"mobs:spawner"},
@ -115,9 +109,7 @@ minetest.register_abm({
action = function(pos, node, active_object_count, active_object_count_wider) action = function(pos, node, active_object_count, active_object_count_wider)
-- return if too many entities already -- return if too many entities already
if active_object_count_wider >= max_per_block then if active_object_count_wider >= max_per_block then return end
return
end
-- get meta and command -- get meta and command
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
@ -132,9 +124,7 @@ minetest.register_abm({
local yof = tonumber(comm[6]) or 0 local yof = tonumber(comm[6]) or 0
-- if amount is 0 then do nothing -- if amount is 0 then do nothing
if num == 0 then if num == 0 then return end
return
end
-- are we spawning a registered mob? -- are we spawning a registered mob?
if not mobs.spawning_mobs[mob] then if not mobs.spawning_mobs[mob] then
@ -152,15 +142,11 @@ minetest.register_abm({
ent = obj:get_luaentity() ent = obj:get_luaentity()
if ent and ent.name and ent.name == mob then if ent and ent.name and ent.name == mob then count = count + 1 end
count = count + 1
end
end end
-- is there too many of same type? -- is there too many of same type?
if count >= num then if count >= num then return end
return
end
-- when player distance above 0, spawn mob if player detected and in range -- when player distance above 0, spawn mob if player detected and in range
if pla > 0 then if pla > 0 then
@ -181,17 +167,13 @@ minetest.register_abm({
end end
-- player not found -- player not found
if not in_range then if not in_range then return end
return
end
end end
-- set medium mob usually spawns in (defaults to air) -- set medium mob usually spawns in (defaults to air)
local reg = minetest.registered_entities[mob].fly_in local reg = minetest.registered_entities[mob].fly_in
if not reg or type(reg) == "string" then if not reg or type(reg) == "string" then reg = {(reg or "air")} end
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(
@ -207,8 +189,7 @@ minetest.register_abm({
pos2.y = pos2.y + 0.5 pos2.y = pos2.y + 0.5
-- only if light levels are within range -- only if light levels are within range
if lig >= mlig and lig <= xlig if lig >= mlig and lig <= xlig and minetest.registered_entities[mob] then
and minetest.registered_entities[mob] then
minetest.add_entity(pos2, mob) minetest.add_entity(pos2, mob)
end end
end end