1
0
mirror of https://codeberg.org/tenplus1/mobs_redo.git synced 2025-01-08 08:50:20 +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

290
api.lua
View File

@ -1,25 +1,25 @@
-- Translation support
-- translation and mod checks
local S = minetest.get_translator("mobs")
local FS = function(...) return minetest.formspec_escape(S(...)) end
-- CMI support check
local use_cmi = minetest.global_exists("cmi")
-- MineClone2 check
local use_mc2 = minetest.get_modpath("mcl_core")
-- Visual Harm 1ndicator check
local use_mc2 = minetest.get_modpath("mcl_core") -- MineClonia support
local use_vh1 = minetest.get_modpath("visual_harm_1ndicators")
local use_tr = minetest.get_modpath("toolranks")
-- Node check helper
local function has(nodename)
if nodename and minetest.registered_nodes[nodename] then return nodename end
end
-- Global
-- Global table
mobs = {
mod = "redo",
version = "20240809",
version = "20240810",
spawning_mobs = {},
translate = S,
invis = minetest.global_exists("invisibility") and invisibility or {},
node_snow = has(minetest.registered_aliases["mapgen_snow"])
@ -30,6 +30,7 @@ mobs = {
mobs.fallback_node = mobs.node_dirt
-- localize common functions
local pi = math.pi
local square = math.sqrt
local sin = math.sin
@ -54,12 +55,14 @@ local vsubtract = vector.subtract
local settings = minetest.settings
-- creative check
local creative_cache = minetest.settings:get_bool("creative_mode")
function mobs.is_creative(name)
return creative_cache or minetest.check_player_privs(name, {creative = true})
end
-- Load settings
local damage_enabled = settings:get_bool("enable_damage")
local mobs_spawn = settings:get_bool("mobs_spawn") ~= false
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 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 main_timer_interval = tonumber(settings:get("mob_main_timer_interval") or 1.0)
-- pathfinding settings
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
local pathfinding_stuck_timeout = tonumber(
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
settings:get_bool("mobs_attack_creatura") == true
-- default mob settings
mobs.mob_class = {
state = "stand",
@ -205,6 +207,7 @@ local mob_class = mobs.mob_class -- Compatibility
local mob_class_meta = {__index = mob_class}
-- return True if number of mobs is at limit
local function at_limit()
if active_limit and active_limit > 0
@ -213,17 +216,15 @@ local function at_limit()
end
end
-- play sound
function mob_class:mob_sound(sound)
if not sound then return end
-- higher pitch for a child
local pitch = self.child and 1.5 or 1.0
local pitch = self.child and 1.5 or 1.0 -- higher pitch for a child
-- a little random pitch to be different
pitch = pitch + random(-10, 10) * 0.005
pitch = pitch + random(-10, 10) * 0.005 -- little random pitch difference
minetest.sound_play(sound, {
object = self.object,
@ -233,8 +234,8 @@ function mob_class:mob_sound(sound)
}, true)
end
-- attack player/mob
function mob_class:do_attack(player, force)
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
end
-- calculate distance
local get_distance = function(a, b)
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)
end
-- are we a real player ?
local function is_player(player)
if player and type(player) == "userdata" and minetest.is_player(player) then
@ -265,8 +266,8 @@ local function is_player(player)
end
end
-- collision function based on jordan4ibanez' open_ai mod
function mob_class:collision()
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})
end
-- check if string exists in another string or table
local function check_for(look_for, look_inside)
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
-- move mob in facing direction
function mob_class:set_velocity(v)
-- 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})
end
-- calculate mob velocity
function mob_class:get_velocity()
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
end
-- set and return valid yaw
function mob_class:set_yaw(yaw, delay)
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
end
-- global function to set mob yaw [deprecated]
function mobs:yaw(entity, yaw, delay)
function mobs:yaw(entity, yaw, delay) -- [deprecated]
mob_class.set_yaw(entity, yaw, delay)
end
-- set defined animation
function mob_class:set_animation(anim, force)
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)
end
-- global function to set mob animation [deprecated]
function mobs:set_animation(entity, anim)
function mobs:set_animation(entity, anim) -- [deprecated]
entity.set_animation(entity, anim)
end
-- check line of sight using raycasting (thanks Astrobe)
function mob_class:line_of_sight(pos1, pos2)
local ray = minetest.raycast(pos1, pos2, true, false) -- ignore entities
@ -472,18 +471,16 @@ function mob_class:line_of_sight(pos1, pos2)
return true
end
-- global function [deprecated]
function mobs:line_of_sight(entity, pos1, pos2)
function mobs:line_of_sight(entity, pos1, pos2) -- [deprecated]
return entity:line_of_sight(pos1, pos2)
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)
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 flyable_nodes = minetest.find_nodes_in_area(
{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
end
-- are we flying in what we are suppose to? (taikedz)
function mob_class:flight_check()
local def = minetest.registered_nodes[self.standing_in]
@ -528,8 +525,8 @@ function mob_class:flight_check()
return false
end
-- turn mob to face position
function mob_class:yaw_to_pos(target, rot)
rot = rot or 0
@ -545,13 +542,12 @@ function mob_class:yaw_to_pos(target, rot)
return yaw
end
-- global [deprecated]
function mobs:yaw_to_pos(self, target, rot)
function mobs:yaw_to_pos(self, target, rot) -- [deprecated]
return self:yaw_to_pos(target, rot)
end
-- if stay near set then periodically check for nodes and turn towards them
function mob_class:do_stay_near()
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 chance = self.stay_near[2] or 10
if not pos or random(chance) > 1 then
return false
end
if not pos or random(chance) > 1 then return false end
if type(searchnodes) == "string" then
searchnodes = {self.stay_near[1]}
end
if type(searchnodes) == "string" then searchnodes = {self.stay_near[1]} end
local r = self.view_range
local nearby_nodes = minetest.find_nodes_in_area(
@ -584,8 +576,8 @@ function mob_class:do_stay_near()
return true
end
-- custom particle effects
local function effect(
pos, amount, texture, min_size, max_size, radius, gravity, glow, fall)
@ -618,21 +610,20 @@ local function effect(
})
end
-- global function
function mobs: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
-- Thanks Wuzzy for the editable settings
local HORNY_TIME = 30
local HORNY_AGAIN_TIME = 60 * 5 -- 5 minutes
local CHILD_GROW_TIME = 60 * 20 -- 20 minutes
-- update nametag and infotext
function mob_class:update_tag(newname)
local col
@ -704,8 +695,8 @@ function mob_class:update_tag(newname)
end
end
-- drop items
function mob_class:item_drop()
-- no drops if disabled by setting or mob is child
@ -781,8 +772,8 @@ function mob_class:item_drop()
self.drops = {}
end
-- remove mob and descrease counter
local function remove_mob(self, decrease)
self.object:remove()
@ -793,13 +784,12 @@ local function remove_mob(self, decrease)
end
end
-- global function for removing mobs
function mobs:remove(self, decrease)
remove_mob(self, decrease)
end
-- check if mob is dead or only hurt
function mob_class:check_for_death(cmi_cause)
-- We dead already
@ -916,8 +906,8 @@ function mob_class:check_for_death(cmi_cause)
return true
end
-- get node but use fallback for nil or unknown
local function node_ok(pos, fallback)
local node = minetest.get_node_or_nil(pos)
@ -931,8 +921,8 @@ function mobs:node_ok(pos, fallback)
return node_ok(pos, fallback)
end
-- Returns true if node can deal damage to self
function mobs:is_node_dangerous(mob_object, nodename)
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)
end
-- is mob facing a cliff
function mob_class:is_at_cliff()
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)
end
-- check for nodes or groups inside mob
function mob_class:is_inside(itemtable)
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
end
-- environmental damage (water, lava, fire, light etc.)
function mob_class:do_env_damage()
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"})
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()
local vel = self.object:get_velocity() ; if not vel then return false end
@ -1200,8 +1190,8 @@ function mob_class:do_jump()
return false
end
-- blast damage to entities nearby (modified from TNT mod)
local function entity_physics(pos, radius)
radius = radius * 2
@ -1223,15 +1213,15 @@ local function entity_physics(pos, radius)
end
end
-- can mob see player
local function is_invisible(self, player_name)
if mobs.invis[player_name] and not self.ignore_invisibility then return true end
end
-- should mob follow what I'm holding ?
function mob_class:follow_holding(clicker)
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
end
-- find two animals of same type and breed if nearby and horny
function mob_class:breed()
-- child takes a long time before growing into adult
@ -1407,17 +1397,14 @@ function mob_class:breed()
end
end
-- find and replace what mob is looking for (grass, wheat etc.)
function mob_class:replace(pos)
local vel = self.object:get_velocity() ; if not vel then return end
if not mobs_griefing
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
if not mobs_griefing 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
return
end
@ -1459,19 +1446,16 @@ function mob_class:replace(pos)
end
end
-- check if daytime and also if mob is docile during daylight hours
function mob_class:day_docile()
if self.docile_by_day == true
and self.time_of_day > 0.2 and self.time_of_day < 0.8 then return true end
end
local los_switcher = false
local height_switcher = false
-- are we able to dig this node and add drops?
local function can_dig_drop(pos)
if minetest.is_protected(pos, "") then return false end
@ -1500,11 +1484,14 @@ local function can_dig_drop(pos)
end
end
-- pathfinder mod check and settings
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)
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
if pathfinder_mod and pathfinder_enable then
if pathfinder_mod then
self.path.way = pathfinder.find_path(s, p1, self, dtime)
else
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
-- temporary entity for go_to() function
-- temp entity for go_to() function
minetest.register_entity("mobs:_pos", {
initial_properties = {
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
function mob_class:go_to(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
end
-- peaceful player privilege support
local function is_peaceful_player(player)
-- main setting enabled
@ -1773,8 +1761,8 @@ local function is_peaceful_player(player)
end
end
-- general attack function for all mobs
function mob_class:general_attack()
-- return if already attacking, passive or docile during day
@ -1868,8 +1856,8 @@ function mob_class:general_attack()
end
end
-- find someone to runaway from
function mob_class:do_runaway_from()
if not self.runaway_from then return end
@ -1947,8 +1935,8 @@ function mob_class:do_runaway_from()
end
end
-- follow player if owner or holding item, if fish outta water then flop
function mob_class:follow_flop()
-- find player to follow
@ -2042,8 +2030,8 @@ function mob_class:follow_flop()
end
end
-- dogshoot attack switch and counter function
function mob_class:dogswitch(dtime)
-- switch mode not activated
@ -2066,8 +2054,8 @@ function mob_class:dogswitch(dtime)
return self.dogshoot_switch
end
-- stop attack and reset vars
-- stop attack
function mob_class:stop_attack()
self.attack = nil
@ -2081,8 +2069,8 @@ function mob_class:stop_attack()
self:set_animation("stand", true)
end
-- execute current state (stand, walk, run, attacks)
function mob_class:do_states(dtime)
local yaw = self.object:get_yaw() ; if not yaw then return end
@ -2565,8 +2553,8 @@ function mob_class:do_states(dtime)
end
end
-- falling and fall damage
function mob_class:falling(pos)
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})
end
-- is Took Ranks mod active?
local tr = minetest.get_modpath("toolranks")
-- deal damage and effects when mob punched
function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
-- mob health check
@ -2746,10 +2731,10 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
end
if mobs.is_creative(hitter:get_player_name()) then
wear = tr and 1 or 0
wear = use_tr and 1 or 0
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})
else
weapon:add_wear(wear)
@ -2924,8 +2909,8 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
return true
end
-- helper function to clean mob staticdata
local function clean_staticdata(self)
local tmp, t = {}
@ -2943,8 +2928,8 @@ local function clean_staticdata(self)
return tmp
end
-- get entity staticdata
function mob_class:mob_staticdata()
-- this handles mob count for mobs activated, unloaded, reloaded
@ -3003,6 +2988,7 @@ function mob_class:mob_staticdata()
return minetest.serialize(clean_staticdata(self))
end
-- list of items used in initial_properties
local is_property_name = {
hp_max = true, physical = true, collide_with_objects = true, collisionbox = true,
@ -3011,6 +2997,7 @@ local is_property_name = {
}
-- activate mob and reload settings
function mob_class:mob_activate(staticdata, def, dtime)
-- if dtime == 0 then entity has just been created
@ -3161,8 +3148,8 @@ function mob_class:mob_activate(staticdata, def, dtime)
end
end
-- handle mob lifetimer and expiration
function mob_class:mob_expire(pos, dtime)
-- when lifetimer expires remove mob (except npc and tamed)
@ -3193,8 +3180,8 @@ function mob_class:mob_expire(pos, dtime)
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()
local pos = self.object:get_pos()
@ -3237,8 +3224,8 @@ print("on: " .. self.standing_on
]]
end
-- main mob function
function mob_class:on_step(dtime, moveresult)
if self.state == "die" then return end
@ -3379,8 +3366,8 @@ function mob_class:on_step(dtime, moveresult)
end
end
-- default function when mobs are blown up with TNT
function mob_class:on_blast(damage)
--print("-- blast damage", damage)
@ -3392,10 +3379,8 @@ function mob_class:on_blast(damage)
return false, false, {}
end
mobs.spawning_mobs = {}
-- register mob entity
function mobs:register_mob(name, def)
mobs.spawning_mobs[name] = {}
@ -3407,7 +3392,7 @@ function mobs:register_mob(name, def)
collisionbox[5] = collisionbox[2] + 0.99
end
minetest.register_entity(":" .. name, setmetatable({
minetest.register_entity(":" .. name, setmetatable({
initial_properties = {
hp_max = max(1, (def.hp_max or 10) * difficulty),
@ -3546,13 +3531,12 @@ minetest.register_entity(":" .. name, setmetatable({
return self:mob_staticdata(self)
end
}, mob_class_meta))
end -- END mobs:register_mob function
}, mob_class_meta))
end
-- count how many mobs of one type are inside an area
-- will also return true for second value if player is inside area
local function count_mobs(pos, type)
local total = 0
@ -3575,8 +3559,8 @@ local function count_mobs(pos, type)
return total, players
end
-- do we have enough space to spawn mob? (thanks wuzzy)
local function can_spawn(pos, name)
local ent = minetest.registered_entities[name]
@ -3630,7 +3614,6 @@ function mobs:can_spawn(pos, name)
return can_spawn(pos, name)
end
-- global functions
function mobs:add_mob(pos, def)
@ -3698,24 +3681,17 @@ function mobs:add_mob(pos, def)
mob:set_properties({
textures = new_texture,
visual_size = {
x = ent.base_size.x * .5,
y = ent.base_size.y * .5
x = ent.base_size.x * .5, y = ent.base_size.y * .5
},
collisionbox = {
ent.base_colbox[1] * .5,
ent.base_colbox[2] * .5,
ent.base_colbox[3] * .5,
ent.base_colbox[4] * .5,
ent.base_colbox[5] * .5,
ent.base_colbox[6] * .5
ent.base_colbox[1] * .5, ent.base_colbox[2] * .5,
ent.base_colbox[3] * .5, ent.base_colbox[4] * .5,
ent.base_colbox[5] * .5, ent.base_colbox[6] * .5
},
selectionbox = {
ent.base_selbox[1] * .5,
ent.base_selbox[2] * .5,
ent.base_selbox[3] * .5,
ent.base_selbox[4] * .5,
ent.base_selbox[5] * .5,
ent.base_selbox[6] * .5
ent.base_selbox[1] * .5, ent.base_selbox[2] * .5,
ent.base_selbox[3] * .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
end
-- global function to add additional spawn checks
function mobs:spawn_abm_check(pos, node, name)
-- global function to add additional spawn checks
-- return true to stop spawning mob
end
-- older spawning function
function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, interval,
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
-- are we registering an abm or lbm?
if map_load == true then
@ -3966,8 +3942,8 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
end
end
-- compatibility with older mob registration [DEPRECATED]
function mobs:register_spawn(name, nodes, max_light, min_light, chance,
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)
end
-- MarkBu's newer spawn function (USE this one please modders)
-- MarkBu's spawn function (USE this one please)
function mobs:spawn(def)
mobs:spawn_specific(
@ -3995,8 +3971,8 @@ function mobs:spawn(def)
def.on_map_load)
end
-- register arrow for shoot attack
function mobs:register_arrow(name, def)
if not name or not def then return end
@ -4163,14 +4139,8 @@ function mobs:register_arrow(name, def)
})
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
function mobs:safe_boom(self, pos, radius, texture)
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)
end
-- make explosion with protection and tnt mod check
function mobs:boom(self, pos, radius, damage_radius, texture)
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
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)
local grp = {spawn_egg = 1}
@ -4230,8 +4203,8 @@ function mobs:register_egg(mob, desc, background, addegg, no_creative)
end
-- register new spawn egg containing mob information (cannot be stacked)
-- these are only created for animals and npc mobs, not monsters
if is_mob.type ~= "monster" then
-- these are only created for animals and npc's, not monsters
if is_mob.type ~= "monster" then
minetest.register_craftitem(":" .. mob .. "_set", {
@ -4287,7 +4260,7 @@ if is_mob.type ~= "monster" then
return itemstack
end
})
end
end
-- register old stackable mob egg
minetest.register_craftitem(":" .. mob, {
@ -4346,8 +4319,8 @@ end
})
end
-- force capture a mob if space available in inventory, or drop as spawn egg
function mobs:force_capture(self, clicker)
-- add special mob egg with all mob information
@ -4370,8 +4343,8 @@ function mobs:force_capture(self, clicker)
remove_mob(self, true)
end
-- capture critter (thanks to blert2112 for idea)
function mobs:capture_mob(
self, clicker, chance_hand, chance_net, chance_lasso, force_take, replacewith)
@ -4383,9 +4356,7 @@ function mobs:capture_mob(
local mobname = self.name
-- if not nil change what will be added to inventory
if replacewith then
mobname = replacewith
end
if replacewith then mobname = replacewith end
local name = clicker:get_player_name()
local tool = clicker:get_wielded_item()
@ -4486,8 +4457,8 @@ function mobs:capture_mob(
return true
end
-- protect tamed mob with rune item
function mobs:protect(self, clicker)
local name = clicker:get_player_name()
@ -4533,11 +4504,10 @@ function mobs:protect(self, clicker)
return true
end
-- feeding, taming, breeding and naming (thanks blert2112)
local mob_obj = {}
local mob_sta = {}
local mob_obj, mob_sta = {}, {}
-- feeding, taming and breeding (thanks blert2112)
function mobs:feed_tame(self, clicker, feed_count, breed, tame)
-- can eat/tame with item in hand
@ -4649,8 +4619,8 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
return false
end
-- inspired by blockmen's nametag mod
minetest.register_on_player_receive_fields(function(player, formname, fields)
-- right-clicked with nametag and name entered?
@ -4685,8 +4655,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
end)
-- compatibility function for old mobs entities to new mobs_redo modpack
function mobs:alias_mob(old_name, new_name)
-- check old_name entity doesnt already exist
@ -4718,8 +4688,8 @@ function mobs:alias_mob(old_name, new_name)
})
end
-- admin command to remove untamed mobs around players
minetest.register_chatcommand("clear_mobs", {
params = "<text>",
description = "Remove untamed mobs from around players.",
@ -4758,13 +4728,13 @@ minetest.register_chatcommand("clear_mobs", {
end
})
-- Is mob hearing enabled, if so override minetest.sound_play with custom function
if settings:get_bool("mobs_can_hear") ~= false then
local old_sound_play = minetest.sound_play
local old_sound_play = minetest.sound_play
minetest.sound_play = function(spec, param, eph)
minetest.sound_play = function(spec, param, eph)
local def = {} ; param = param or {}
@ -4829,5 +4799,5 @@ minetest.sound_play = function(spec, param, eph)
end
return old_sound_play(spec, param, eph)
end
end
end -- setting 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 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
function mobs.add_eatable(item, hp)
local def = minetest.registered_items[item]
@ -19,6 +41,7 @@ function mobs.add_eatable(item, hp)
end
-- recipe items
local items = {
paper = mc2 and "mcl_core:paper" or "default:paper",
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",
}
-- name tag
minetest.register_craftitem("mobs:nametag", {
description = S("Name Tag") .. " " .. S("\nRight-click Mobs Redo mob to apply"),
inventory_image = "mobs_nametag.png",
@ -52,6 +75,7 @@ minetest.register_craft({
})
-- leather
minetest.register_craftitem("mobs:leather", {
description = S("Leather"),
inventory_image = "mobs_leather.png",
@ -59,6 +83,7 @@ minetest.register_craftitem("mobs:leather", {
})
-- raw meat
minetest.register_craftitem("mobs:meat_raw", {
description = S("Raw Meat"),
inventory_image = "mobs_meat_raw.png",
@ -69,6 +94,7 @@ minetest.register_craftitem("mobs:meat_raw", {
mobs.add_eatable("mobs:meat_raw", 3)
-- cooked meat
minetest.register_craftitem("mobs:meat", {
description = S("Meat"),
inventory_image = "mobs_meat.png",
@ -86,6 +112,7 @@ minetest.register_craft({
})
-- lasso
minetest.register_tool("mobs:lasso", {
description = S("Lasso (right-click animal to put in inventory)"),
inventory_image = "mobs_magic_lasso.png",
@ -104,6 +131,7 @@ minetest.register_craft({
minetest.register_alias("mobs:magic_lasso", "mobs:lasso")
-- net
minetest.register_tool("mobs:net", {
description = S("Net (right-click animal to put in inventory)"),
inventory_image = "mobs_net.png",
@ -120,6 +148,7 @@ minetest.register_craft({
})
-- shears (right click to shear animal)
minetest.register_tool("mobs:shears", {
description = S("Steel Shears (right-click to shear)"),
inventory_image = "mobs_shears.png",
@ -135,6 +164,7 @@ minetest.register_craft({
})
-- protection rune
minetest.register_craftitem("mobs:protector", {
description = S("Mob Protection Rune"),
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", {
description = S("Mob Protection Rune (Level 2)"),
inventory_image = "mobs_protector2.png",
@ -167,6 +198,7 @@ minetest.register_craft({
})
-- saddle
minetest.register_craftitem("mobs:saddle", {
description = S("Saddle"),
inventory_image = "mobs_saddle.png",
@ -182,29 +214,25 @@ minetest.register_craft({
}
})
-- make sure we can register fences
local mod_def = minetest.get_modpath("default")
-- register mob fence if default found
if mod_def and default.register_fence then
-- mob fence (looks like normal fence but collision is 2 high)
default.register_fence("mobs:fence_wood", {
-- mob fence (looks like normal fence but collision is 2 high)
default.register_fence("mobs:fence_wood", {
description = S("Mob Fence"),
texture = "default_wood.png",
material = "default:fence_wood",
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 = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, 1.9, 0.5},
type = "fixed", fixed = {{-0.5, -0.5, -0.5, 0.5, 1.9, 0.5}}
}
}
})
})
end
-- mob fence top (has enlarged collisionbox to stop mobs getting over)
minetest.register_node("mobs:fence_top", {
description = S("Mob Fence Top"),
drawtype = "nodebox",
@ -212,19 +240,10 @@ minetest.register_node("mobs:fence_top", {
paramtype = "light",
is_ground_content = false,
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, axey = 1},
sounds = mod_def and default.node_sound_wood_defaults(),
node_box = {
type = "fixed",
fixed = {-0.2, -0.5, -0.2, 0.2, 0, 0.2}
},
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}
}
sounds = mobs.node_sound_wood_defaults(),
node_box = {type = "fixed", fixed = {-0.2, -0.5, -0.2, 0.2, 0, 0.2}},
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({
@ -235,49 +254,15 @@ minetest.register_craft({
}
})
-- items that can be used as fuel
minetest.register_craft({
type = "fuel",
recipe = "mobs:nametag",
burntime = 3
})
minetest.register_craft({
type = "fuel",
recipe = "mobs:lasso",
burntime = 7
})
minetest.register_craft({
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
})
minetest.register_craft({type = "fuel", recipe = "mobs:nametag", burntime = 3})
minetest.register_craft({type = "fuel", recipe = "mobs:lasso", burntime = 7})
minetest.register_craft({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
@ -294,12 +279,9 @@ minetest.register_tool(":mobs:mob_reset_stick", {
on_use = function(itemstack, user, pointed_thing)
if pointed_thing.type ~= "object" then
return
end
if pointed_thing.type ~= "object" then return end
local obj = pointed_thing.ref
local control = user:get_player_control()
local sneak = control and control.sneak
@ -339,9 +321,7 @@ minetest.register_tool(":mobs:mob_reset_stick", {
-- get base texture
local bt = tex_obj:get_luaentity().base_texture[1]
if type(bt) ~= "string" then
bt = ""
end
if type(bt) ~= "string" then bt = "" end
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)
-- right-clicked with nametag and name entered?
if formname == "mobs_texture"
and fields.name
and fields.name ~= "" then
if formname == "mobs_texture" and fields.name and fields.name ~= "" then
-- does mob still exist?
if not tex_obj
or not tex_obj:get_luaentity() then
return
end
if not tex_obj or not tex_obj:get_luaentity() then return end
-- make sure nametag is being used to name mob
local item = player:get_wielded_item()
if item:get_name() ~= "mobs:mob_reset_stick" then
return
end
if item:get_name() ~= "mobs:mob_reset_stick" then return end
-- limit name entered to 64 characters long
if fields.name:len() > 64 then
fields.name = fields.name:sub(1, 64)
end
if fields.name:len() > 64 then fields.name = fields.name:sub(1, 64) end
-- update texture
local self = tex_obj:get_luaentity()
@ -391,17 +362,15 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
end)
-- Meat Block
minetest.register_node("mobs:meatblock", {
description = S("Meat Block"),
tiles = {"mobs_meat_top.png", "mobs_meat_bottom.png", "mobs_meat_side.png"},
paramtype2 = "facedir",
groups = {
choppy = 1, oddly_breakable_by_hand = 1, axey = 1, handy = 1
},
groups = {choppy = 1, oddly_breakable_by_hand = 1, axey = 1, handy = 1},
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_use = minetest.item_eat(20),
_mcl_hardness = 0.8,
@ -420,15 +389,14 @@ minetest.register_craft({
})
-- Meat Block (raw)
minetest.register_node("mobs:meatblock_raw", {
description = S("Raw Meat Block"),
tiles = {"mobs_meat_raw_top.png", "mobs_meat_raw_bottom.png", "mobs_meat_raw_side.png"},
paramtype2 = "facedir",
groups = {
choppy = 1, oddly_breakable_by_hand = 1, axey = 1, handy = 1
},
groups = {choppy = 1, oddly_breakable_by_hand = 1, axey = 1, handy = 1},
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_use = minetest.item_eat(20),
_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", {
description = "Prevents Mobs Redo mobs from attacking player",
give_to_singleplayer = false
})
-- Fallback node
-- fallback node
minetest.register_node("mobs:fallback_node", {
description = "Fallback Node",
tiles = {"mobs_fallback.png"},
@ -16,22 +16,20 @@ minetest.register_node("mobs:fallback_node", {
drop = ""
})
-- Mob API
dofile(path .. "/api.lua")
local path = minetest.get_modpath("mobs")
-- Rideable Mobs
dofile(path .. "/mount.lua")
dofile(path .. "/api.lua") -- mob API
-- Mob Items
dofile(path .. "/crafts.lua")
dofile(path .. "/mount.lua") -- rideable mobs
-- Mob Spawner
dofile(path .. "/spawner.lua")
dofile(path .. "/crafts.lua") -- items and crafts
dofile(path .. "/spawner.lua") -- mob spawner
-- Lucky Blocks
if minetest.get_modpath("lucky_block") then
dofile(path .. "/lucky_block.lua")
end
print("[MOD] Mobs Redo loaded")

View File

@ -1,6 +1,7 @@
local S = minetest.get_translator("mobs")
-- add lucky blocks
lucky_block:add_blocks({
{"dro", {"mobs:meat_raw"}, 5},
@ -17,8 +18,7 @@ lucky_block:add_blocks({
{"lig"}
})
-- pint sized rune
-- pint sized rune, use on tamed mob to shrink to half-size
minetest.register_craftitem(":mobs: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)
if pointed_thing.type ~= "object" then
return
end
if pointed_thing.type ~= "object" then return end
local name = user and user:get_player_name() or ""
local tool = user and user:get_wielded_item()
local tool_name = tool:get_name()
if tool_name ~= "mobs:pint_sized_rune" then
return
end
if tool_name ~= "mobs:pint_sized_rune" then return end
local self = pointed_thing.ref:get_luaentity()
@ -82,11 +78,8 @@ minetest.register_craftitem(":mobs:pint_sized_rune", {
self.base_selbox = selbox
self.object:set_properties({
visual_size = vis_size,
collisionbox = colbox,
selectionbox = selbox
})
self.object:set_properties(
{visual_size = vis_size, collisionbox = colbox, selectionbox = selbox})
self.pint_size_potion = true
@ -100,6 +93,5 @@ minetest.register_craftitem(":mobs:pint_sized_rune", {
minetest.register_craft({
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
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

108
mount.lua
View File

@ -1,8 +1,10 @@
-- lib_mount by Blert2112 (edited by TenPlus1)
local is_mc2 = minetest.get_modpath("mcl_mobs") -- MineClone2 check
-- 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
function mobs.attach() end
@ -14,12 +16,11 @@ if not minetest.get_modpath("player_api") and not is_mc2 then
end
-- Localise some functions
local abs, cos, floor, sin, sqrt, pi =
math.abs, math.cos, math.floor, math.sin, math.sqrt, math.pi
--
-- Helper functions
--
-- helper functions
local node_ok = function(pos, fallback)
@ -27,9 +28,7 @@ local node_ok = function(pos, fallback)
local node = minetest.get_node_or_nil(pos)
if node and minetest.registered_nodes[node.name] then
return node
end
if node and minetest.registered_nodes[node.name] then return node end
return {name = fallback}
end
@ -39,9 +38,7 @@ local function node_is(entity)
if not entity.standing_on then return "other" end
if entity.standing_on == "air" then
return "air"
end
if entity.standing_on == "air" then return "air" end
if minetest.get_item_group(entity.standing_on, "lava") ~= 0 then
return "lava"
@ -61,13 +58,9 @@ end
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)
end
end
@ -89,9 +82,7 @@ local function force_detach(player)
local attached_to = player and player:get_attach()
if not attached_to then
return
end
if not attached_to then return end
local entity = attached_to:get_luaentity()
@ -115,11 +106,13 @@ local function force_detach(player)
player:set_properties({visual_size = {x = 1, y = 1}})
end
-- detach player on leaving
minetest.register_on_leaveplayer(function(player)
force_detach(player)
end)
-- detatch all players on shutdown
minetest.register_on_shutdown(function()
@ -130,25 +123,21 @@ minetest.register_on_shutdown(function()
end
end)
-- detatch player when dead
minetest.register_on_dieplayer(function(player)
force_detach(player)
return true
end)
-- find free position to detach player
-- 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}
{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
@ -169,8 +158,8 @@ local function find_free_pos(pos)
return pos
end
-- are we a real player ?
local function is_player(player)
if player and type(player) == "userdata" and minetest.is_player(player) then
@ -178,6 +167,7 @@ local function is_player(player)
end
end
-- attach player to mob entity
function mobs.attach(entity, player)
@ -190,9 +180,7 @@ function mobs.attach(entity, player)
local rot_view = 0
if entity.player_rotation.y == 90 then
rot_view = pi / 2
end
if entity.player_rotation.y == 90 then rot_view = pi / 2 end
local attach_at = entity.driver_attach_at
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_properties({
visual_size = {
x = entity.driver_scale.x,
y = entity.driver_scale.y
}
visual_size = {x = entity.driver_scale.x, y = entity.driver_scale.y}
})
minetest.after(0.2, function()
@ -232,6 +217,7 @@ function mobs.attach(entity, player)
player:set_look_horizontal(entity.object:get_yaw() - rot_view)
end
-- detatch player from mob
function mobs.detach(player)
@ -250,15 +236,14 @@ function mobs.detach(player)
end)
end
-- ride mob like car or horse
function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
local yaw = entity.object:get_yaw() or 0
local rot_view = 0
if entity.player_rotation.y == 90 then
rot_view = pi / 2
end
if entity.player_rotation.y == 90 then rot_view = pi / 2 end
local acce_y = 0
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
if entity.max_speed_reverse == 0 and entity.v == 0 then
return
end
if entity.max_speed_reverse == 0 and entity.v == 0 then return end
entity.v = entity.v - entity.accel * dtime
end
@ -290,12 +273,8 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
horz = yaw
if ctrl.left then
horz = horz + 0.05
elseif ctrl.right then
horz = horz - 0.05
end
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
@ -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 velo.y == 0
and entity.standing_on ~= "air"
and entity.standing_on ~= "ignore"
and entity.standing_on ~= "air" and entity.standing_on ~= "ignore"
and minetest.get_item_group(entity.standing_on, "liquid") == 0 then
velo.y = velo.y + entity.jump_height
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 entity.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then
if stand_anim then
entity:set_animation(stand_anim)
end
if stand_anim then entity:set_animation(stand_anim) end
return
end
-- set moving animation
if moving_anim then
entity:set_animation(moving_anim)
end
if moving_anim then entity:set_animation(moving_anim) end
-- Stop!
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 can_fly == true then
new_acce.y = 0
end
if can_fly == true then new_acce.y = 0 end
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
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)
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
entity.object:set_velocity({
x = dir.x * speed,
y = dir.y * speed + 2,
z = dir.z * speed
})
entity.object:set_velocity(
{x = dir.x * speed, y = dir.y * speed + 2, z = dir.z * speed})
elseif ctrl.down then
entity.object:set_velocity({
x = -dir.x * speed,
y = dir.y * speed + 2,
z = -dir.z * speed
})
entity.object:set_velocity(
{x = -dir.x * speed, y = dir.y * speed + 2, z = -dir.z * speed})
elseif not ctrl.down or ctrl.up or ctrl.jump then
entity.object:set_velocity({x = 0, y = -2, z = 0})
@ -501,11 +467,9 @@ function mobs.fly(entity, _, speed, shoots, arrow, moving_anim, stand_anim)
end
end
-- change animation if stopped
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
-- moving animation
entity:set_animation(moving_anim)
entity:set_animation(moving_anim) -- moving animation
end
end

View File

@ -66,8 +66,6 @@ mobs_can_hear (Enable Mob hearing) bool true
[Pathfinding]
# Enable pathfinding (default Enabled)
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)
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)

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