1
0
mirror of https://codeberg.org/tenplus1/mobs_redo.git synced 2025-07-21 17:40:29 +02:00

Compare commits

...

32 Commits

Author SHA1 Message Date
ca34cc2274 fix api typo (thanks bastrabun :) 2022-05-21 08:04:38 +01:00
168014b86f tidy api 2022-05-14 11:21:36 +01:00
6f8b6fe3f5 select proper animation for flying mobs 2022-05-01 08:15:25 +01:00
dd16d63e8e revert hover 2022-04-30 14:35:59 +01:00
7bb5e2b382 add "hover" animation 2022-04-30 12:26:36 +01:00
7b429df9e9 tweak riding functions 2022-04-21 08:28:35 +01:00
0e72f0ca81 tweak mobs.drive() speed (thanks auouymous) 2022-04-18 08:31:25 +01:00
fb42be6b28 nil checks 2022-03-14 08:29:25 +00:00
f54c3da9d7 add nil check 2022-03-13 16:30:20 +00:00
65e369e5fc add 0.4.x compatibility when riding mod 2022-03-01 09:04:38 +00:00
9f74408792 remove owner infotext if no owner present 2022-02-05 12:25:01 +00:00
18c7f0a422 update translation checks (thanks mckaygerhard) 2022-01-20 08:54:08 +00:00
2fb7bf2c66 update api.txt for mob_object change 2022-01-18 06:41:29 +00:00
f01e8a61d0 rename var 2022-01-16 07:44:53 +00:00
b756aa50f5 fix crash (thanks SwissalpS) 2022-01-16 07:05:49 +00:00
e83620553d add mobs:is_node_dangerous(self, nodename) global function 2022-01-15 09:41:21 +00:00
e5d1958e16 add nil checks for riding mobs 2022-01-03 17:35:51 +00:00
6a4a02f3fb fix translations (thanks nixnoxus) 2021-12-12 08:13:54 +00:00
5d88766b74 add pointed_thing to on_rightclick vars 2021-11-16 20:22:15 +00:00
d31da2d069 mod loaded msg 2021-11-14 14:21:32 +00:00
00db86c924 fix intllib return 2021-11-14 14:18:28 +00:00
26ec61ee29 lasso can pick up animal babies 2021-09-20 10:49:19 +01:00
a8ca00dc56 fix self.follow list 2021-09-05 08:16:40 +01:00
4c80a55c04 add breeding info on hover and items followed on shift+rightclick mob (thanks nixnoxus) 2021-08-16 10:48:16 +01:00
deee28fc59 added 'arrow_override' function to mob definition 2021-08-01 18:58:21 +01:00
ab44080ff8 do not despawn tamed monsters 2021-07-31 08:35:53 +01:00
9f46182bb4 remove need for default mod 2021-07-22 09:48:56 +01:00
2535b5636e add support for MarkBu's pathfinder mod 2021-07-22 09:34:21 +01:00
2d014a75c4 tweak "stand" mobs velocity 2021-07-21 19:38:41 +01:00
db3831dccf update api.txt 2021-07-14 15:53:20 +01:00
29b2204f7c add 'mobs_spawn_monster_protected' switch (thanks 0siribix) 2021-07-14 15:43:02 +01:00
7fbfd9d59c fix "stand" mobs fall jitter 2021-07-13 16:56:53 +01:00
12 changed files with 215 additions and 114 deletions

210
api.lua
View File

@ -1,14 +1,34 @@
-- Load support for intllib.
local MP = minetest.get_modpath(minetest.get_current_modname()) local MP = minetest.get_modpath(minetest.get_current_modname())
local S = minetest.get_translator and minetest.get_translator("mobs_redo") or
dofile(MP .. "/intllib.lua") -- Check for translation method
local S
if minetest.get_translator ~= nil then
S = minetest.get_translator("mobs") -- 5.x translation function
else
if minetest.get_modpath("intllib") then
dofile(minetest.get_modpath("intllib") .. "/init.lua")
if intllib.make_gettext_pair then
gettext, ngettext = intllib.make_gettext_pair() -- new gettext method
else
gettext = intllib.Getter() -- old text file method
end
S = gettext
else -- boilerplate function
S = function(str, ...)
local args = {...}
return str:gsub("@%d+", function(match)
return args[tonumber(match:sub(2))]
end)
end
end
end
-- CMI support check -- CMI support check
local use_cmi = minetest.global_exists("cmi") local use_cmi = minetest.global_exists("cmi")
mobs = { mobs = {
mod = "redo", mod = "redo",
version = "20210614", version = "20220514",
intllib = S, intllib = S,
invis = minetest.global_exists("invisibility") and invisibility or {} invis = minetest.global_exists("invisibility") and invisibility or {}
} }
@ -56,6 +76,7 @@ local disable_blood = settings:get_bool("mobs_disable_blood")
local mobs_drop_items = settings:get_bool("mobs_drop_items") ~= false local mobs_drop_items = settings:get_bool("mobs_drop_items") ~= false
local mobs_griefing = settings:get_bool("mobs_griefing") ~= false local mobs_griefing = settings:get_bool("mobs_griefing") ~= false
local spawn_protected = settings:get_bool("mobs_spawn_protected") ~= false local spawn_protected = settings:get_bool("mobs_spawn_protected") ~= false
local spawn_monster_protected = settings:get_bool("mobs_spawn_monster_protected") ~= false
local remove_far = settings:get_bool("remove_far_mobs") ~= false local remove_far = settings:get_bool("remove_far_mobs") ~= false
local mob_area_spawn = settings:get_bool("mob_area_spawn") local mob_area_spawn = settings:get_bool("mob_area_spawn")
local difficulty = tonumber(settings:get("mob_difficulty")) or 1.0 local difficulty = tonumber(settings:get("mob_difficulty")) or 1.0
@ -82,7 +103,7 @@ local aoc_range = tonumber(settings:get("active_block_range")) * 16
-- pathfinding settings -- pathfinding settings
local enable_pathfinding = true local enable_pathfinding = true
local stuck_timeout = 3 -- how long before stuck mod starts searching local stuck_timeout = 3 -- how long before stuck mod starts searching
local stuck_path_timeout = 10 -- how long will mob follow path before giving up local stuck_path_timeout = 5 -- how long will mob follow path before giving up
-- default nodes -- default nodes
local node_fire = "fire:basic_flame" local node_fire = "fire:basic_flame"
@ -159,6 +180,7 @@ local mob_class = {
attack_players = true, attack_players = true,
attack_npcs = true, attack_npcs = true,
facing_fence = false, facing_fence = false,
_breed_countdown = nil,
_cmi_is_mob = true _cmi_is_mob = true
} }
@ -252,9 +274,9 @@ local check_for = function(look_for, look_inside)
return true return true
end end
if str:find("group:") then if str and str:find("group:") then
local group = str:split(":")[2] local group = str:split(":")[2] or ""
if minetest.get_item_group(look_for, group) ~= 0 then if minetest.get_item_group(look_for, group) ~= 0 then
return true return true
@ -273,7 +295,9 @@ function mob_class:set_velocity(v)
-- halt mob if it has been ordered to stay -- halt mob if it has been ordered to stay
if self.order == "stand" then if self.order == "stand" then
self.object:set_velocity({x = 0, y = 0, z = 0}) local vel = self.object:get_velocity() or {y = 0}
self.object:set_velocity({x = 0, y = vel.y, z = 0})
return return
end end
@ -522,6 +546,7 @@ local new_line_of_sight = function(self, pos1, pos2, stepsize)
return false return false
end end
-- check line of sight using raycasting (thanks Astrobe) -- check line of sight using raycasting (thanks Astrobe)
local ray_line_of_sight = function(self, pos1, pos2) local ray_line_of_sight = function(self, pos1, pos2)
@ -719,6 +744,13 @@ function mobs:effect(pos, amount, texture, min_size, max_size,
end end
-- Thanks Wuzzy for the following editable settings
local HORNY_TIME = 30
local HORNY_AGAIN_TIME = 60 * 5 -- 5 minutes
local CHILD_GROW_TIME = 60 * 20 -- 20 minutes
-- update nametag colour -- update nametag colour
function mob_class:update_tag() function mob_class:update_tag()
@ -737,9 +769,25 @@ function mob_class:update_tag()
col = "#FF0000" col = "#FF0000"
end end
-- build infotext local text = ""
if self.horny == true then
text = "\nLoving: " .. (self.hornytimer - (HORNY_TIME + HORNY_AGAIN_TIME))
elseif self.child == true then
text = "\nGrowing: " .. (self.hornytimer - CHILD_GROW_TIME)
elseif self._breed_countdown then
text = "\nBreeding: " .. self._breed_countdown
end
self.infotext = "Health: " .. self.health .. " / " .. self.hp_max self.infotext = "Health: " .. self.health .. " / " .. self.hp_max
.. "\n" .. "Owner: " .. self.owner .. (self.owner == "" and "" or "\n" .. "Owner: " .. self.owner)
.. text
-- set changes -- set changes
self.object:set_properties({ self.object:set_properties({
@ -867,18 +915,7 @@ function mob_class:check_for_death(cmi_cause)
self.health = self.hp_max self.health = self.hp_max
end end
-- backup nametag so we can show health stats self:update_tag()
-- if not self.nametag2 then
-- self.nametag2 = self.nametag or ""
-- end
-- if show_health
-- and (cmi_cause and cmi_cause.type == "punch") then
-- self.htimer = 2
-- self.nametag = "♥ " .. self.health .. " / " .. self.hp_max
self:update_tag()
-- end
return false return false
end end
@ -975,19 +1012,19 @@ end
-- Returns true is node can deal damage to self -- Returns true is node can deal damage to self
local is_node_dangerous = function(self, nodename) function mobs:is_node_dangerous(mob_object, nodename)
if self.water_damage > 0 if mob_object.water_damage > 0
and minetest.get_item_group(nodename, "water") ~= 0 then and minetest.get_item_group(nodename, "water") ~= 0 then
return true return true
end end
if self.lava_damage > 0 if mob_object.lava_damage > 0
and minetest.get_item_group(nodename, "lava") ~= 0 then and minetest.get_item_group(nodename, "lava") ~= 0 then
return true return true
end end
if self.fire_damage > 0 if mob_object.fire_damage > 0
and minetest.get_item_group(nodename, "fire") ~= 0 then and minetest.get_item_group(nodename, "fire") ~= 0 then
return true return true
end end
@ -999,11 +1036,15 @@ local is_node_dangerous = function(self, nodename)
return false return false
end end
local function is_node_dangerous(mob_object, nodename)
return mobs:is_node_dangerous(mob_object, nodename)
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.fear_height == 0 then -- 0 for no falling protection! if self.driver or self.fear_height == 0 then -- 0 for no falling protection!
return false return false
end end
@ -1047,14 +1088,7 @@ function mob_class:do_env_damage()
self.htimer = self.htimer - 1 self.htimer = self.htimer - 1
end end
-- reset nametag after showing health stats self:update_tag()
-- if self.htimer < 1 and self.nametag2 then
-- self.nametag = self.nametag2
-- self.nametag2 = nil
self:update_tag()
-- end
local pos = self.object:get_pos() ; if not pos then return end local pos = self.object:get_pos() ; if not pos then return end
@ -1355,10 +1389,6 @@ function mob_class:follow_holding(clicker)
return false return false
end end
-- Thanks Wuzzy for the following editable settings
local HORNY_TIME = 30
local HORNY_AGAIN_TIME = 60 * 5 -- 5 minutes
local CHILD_GROW_TIME = 60 * 20 -- 20 minutes
-- 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()
@ -1411,6 +1441,8 @@ function mob_class:breed()
self.hornytimer = 0 self.hornytimer = 0
self.horny = false self.horny = false
end end
self:update_tag()
end end
-- find another same animal who is also horny and mate if nearby -- find another same animal who is also horny and mate if nearby
@ -1466,6 +1498,8 @@ function mob_class:breed()
self.hornytimer = HORNY_TIME + 1 self.hornytimer = HORNY_TIME + 1
ent.hornytimer = HORNY_TIME + 1 ent.hornytimer = HORNY_TIME + 1
self:update_tag()
-- have we reached active mob limit -- have we reached active mob limit
if active_limit > 0 and active_mobs >= active_limit then if active_limit > 0 and active_mobs >= active_limit then
minetest.chat_send_player(self.owner, minetest.chat_send_player(self.owner,
@ -1651,6 +1685,9 @@ local can_dig_drop = function(pos)
return false return false
end end
local pathfinder_mod = minetest.get_modpath("pathfinder")
-- path finding and smart mob routine by rnd, -- path finding and smart mob routine by rnd,
-- line_of_sight and other edits by Elkien3 -- 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)
@ -1779,13 +1816,18 @@ function mob_class:smart_mobs(s, p, dist, dtime)
jumpheight = 1 jumpheight = 1
end end
self.path.way = minetest.find_path(s, p1, 16, jumpheight, if pathfinder_mod then
dropheight, "Dijkstra") self.path.way = pathfinder.find_path(s, p1, self, dtime)
else
self.path.way = minetest.find_path(s, p1, 16, jumpheight,
dropheight, "Dijkstra")
end
--[[ --[[
-- show path using particles -- show path using particles
if self.path.way and #self.path.way > 0 then if self.path.way and #self.path.way > 0 then
print("-- path length:" .. tonumber(#self.path.way)) print("-- path length:" .. tonumber(#self.path.way))
for _,pos in pairs(self.path.way) do for _,pos in pairs(self.path.way) do
minetest.add_particle({ minetest.add_particle({
pos = pos, pos = pos,
@ -2074,7 +2116,7 @@ function mob_class:follow_flop()
for n = 1, #players do for n = 1, #players do
if get_distance(players[n]:get_pos(), s) < self.view_range if players[n] and get_distance(players[n]:get_pos(), s) < self.view_range
and not is_invisible(self, players[n]:get_player_name()) then and not is_invisible(self, players[n]:get_player_name()) then
self.following = players[n] self.following = players[n]
@ -2331,11 +2373,22 @@ function mob_class:do_states(dtime)
else else
self:set_velocity(self.walk_velocity) self:set_velocity(self.walk_velocity)
-- figure out which animation to use while in motion
if self:flight_check() if self:flight_check()
and self.animation and self.animation
and self.animation.fly_start and self.animation.fly_start
and self.animation.fly_end then and self.animation.fly_end then
self:set_animation("fly")
local on_ground = minetest.registered_nodes[self.standing_on].walkable
local in_water = minetest.registered_nodes[self.standing_in].groups.water
if on_ground and in_water then
self:set_animation("fly")
elseif on_ground then
self:set_animation("walk")
else
self:set_animation("fly")
end
else else
self:set_animation("walk") self:set_animation("walk")
end end
@ -2693,6 +2746,12 @@ function mob_class:do_states(dtime)
local obj = minetest.add_entity(p, self.arrow) local obj = minetest.add_entity(p, self.arrow)
local ent = obj:get_luaentity() local ent = obj:get_luaentity()
local amount = (vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) ^ 0.5 local amount = (vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) ^ 0.5
-- check for custom override for arrow
if self.arrow_override then
self.arrow_override(ent)
end
local v = ent.velocity or 1 -- or set to default local v = ent.velocity or 1 -- or set to default
ent.switch = 1 ent.switch = 1
@ -2949,7 +3008,7 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
if self:check_for_death({type = "punch", puncher = hitter, hot = hot}) then if self:check_for_death({type = "punch", puncher = hitter, hot = hot}) then
return true return true
end end
end -- END if damage end
-- knock back effect (only on full punch) -- knock back effect (only on full punch)
if self.knock_back and tflp >= punch_interval then if self.knock_back and tflp >= punch_interval then
@ -3092,8 +3151,6 @@ function mob_class:mob_staticdata()
end end
end end
--print('===== '..self.name..'\n'.. dump(tmp)..'\n=====\n')
return minetest.serialize(tmp) return minetest.serialize(tmp)
end end
@ -3253,7 +3310,7 @@ function mob_class:mob_activate(staticdata, def, dtime)
self.object:set_texture_mod(self.texture_mods) self.object:set_texture_mod(self.texture_mods)
-- set 5.x flag to remove monsters when map area unloaded -- set 5.x flag to remove monsters when map area unloaded
if remove_far and self.type == "monster" then if remove_far and self.type == "monster" and not self.tamed then
self.static_save = false self.static_save = false
end end
@ -3304,8 +3361,7 @@ function mob_class:mob_expire(pos, dtime)
end end
end end
-- minetest.log("action", -- minetest.log("action", S("lifetimer expired, removed @1", self.name))
-- S("lifetimer expired, removed @1", self.name))
effect(pos, 15, "tnt_smoke.png", 2, 4, 2, 0) effect(pos, 15, "tnt_smoke.png", 2, 4, 2, 0)
@ -3332,9 +3388,9 @@ function mob_class:on_step(dtime, moveresult)
-- early warning check, if no yaw then no entity, skip rest of function -- early warning check, if no yaw then no entity, skip rest of function
if not yaw then return end if not yaw then return end
-- get node at foot level every quarter second
self.node_timer = (self.node_timer or 0) + dtime self.node_timer = (self.node_timer or 0) + dtime
-- get nodes above and below foot level every 1/4 second
if self.node_timer > 0.25 then if self.node_timer > 0.25 then
self.node_timer = 0 self.node_timer = 0
@ -3563,6 +3619,7 @@ minetest.register_entity(name, setmetatable({
armor = def.armor, armor = def.armor,
on_rightclick = def.on_rightclick, on_rightclick = def.on_rightclick,
arrow = def.arrow, arrow = def.arrow,
arrow_override = def.arrow_override,
shoot_interval = def.shoot_interval, shoot_interval = def.shoot_interval,
sounds = def.sounds, sounds = def.sounds,
animation = def.animation, animation = def.animation,
@ -3631,7 +3688,7 @@ minetest.register_entity(name, setmetatable({
get_staticdata = function(self) get_staticdata = function(self)
return self:mob_staticdata(self) return self:mob_staticdata(self)
end, end
}, mob_class_meta)) }, mob_class_meta))
@ -3956,8 +4013,10 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
return return
end end
-- mobs cannot spawn in protected areas when enabled -- check if mob can spawn inside protected areas
if not spawn_protected if (spawn_protected == false
or (spawn_monster_protected == false
and minetest.registered_entities[name].type == "monster"))
and minetest.is_protected(pos, "") then and minetest.is_protected(pos, "") then
--print("--- inside protected area", name) --print("--- inside protected area", name)
return return
@ -4294,7 +4353,7 @@ function mobs:register_egg(mob, desc, background, addegg, no_creative)
if def and def.on_rightclick then if def and def.on_rightclick then
return def.on_rightclick( return def.on_rightclick(
pointed_thing.under, under, placer, itemstack) pointed_thing.under, under, placer, itemstack, pointed_thing)
end end
if pos if pos
@ -4345,7 +4404,7 @@ function mobs:register_egg(mob, desc, background, addegg, no_creative)
if def and def.on_rightclick then if def and def.on_rightclick then
return def.on_rightclick( return def.on_rightclick(
pointed_thing.under, under, placer, itemstack) pointed_thing.under, under, placer, itemstack, pointed_thing)
end end
if pos if pos
@ -4431,7 +4490,7 @@ end
function mobs:capture_mob(self, clicker, chance_hand, chance_net, function mobs:capture_mob(self, clicker, chance_hand, chance_net,
chance_lasso, force_take, replacewith) chance_lasso, force_take, replacewith)
if self.child if not self
or not clicker:is_player() or not clicker:is_player()
or not clicker:get_inventory() then or not clicker:get_inventory() then
return false return false
@ -4635,38 +4694,28 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
if self.health >= self.hp_max then if self.health >= self.hp_max then
self.health = self.hp_max self.health = self.hp_max
-- if self.htimer < 1 then
-- minetest.chat_send_player(clicker:get_player_name(),
-- S("@1 at full health (@2)",
-- self.name:split(":")[2], tostring(self.health)))
-- self.htimer = 5
-- end
end end
self.object:set_hp(self.health) self.object:set_hp(self.health)
self:update_tag()
-- make children grow quicker -- make children grow quicker
if self.child == true then if self.child == true then
-- self.hornytimer = self.hornytimer + 20
-- deduct 10% of the time to adulthood -- deduct 10% of the time to adulthood
self.hornytimer = self.hornytimer + ( self.hornytimer = math.floor(self.hornytimer + (
(CHILD_GROW_TIME - self.hornytimer) * 0.1) (CHILD_GROW_TIME - self.hornytimer) * 0.1))
--print ("====", self.hornytimer) --print ("====", self.hornytimer)
return true return true
end end
-- feed and tame -- feed and tame
self.food = (self.food or 0) + 1 self.food = (self.food or 0) + 1
self._breed_countdown = feed_count - self.food
if self.food >= feed_count then if self.food >= feed_count then
self.food = 0 self.food = 0
self._breed_countdown = nil
if breed and self.hornytimer == 0 then if breed and self.hornytimer == 0 then
self.horny = true self.horny = true
@ -4681,6 +4730,7 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
end end
self.tamed = true self.tamed = true
self.static_save = true
if not self.owner or self.owner == "" then if not self.owner or self.owner == "" then
self.owner = clicker:get_player_name() self.owner = clicker:get_player_name()
@ -4691,6 +4741,8 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
self:mob_sound(self.sounds.random) self:mob_sound(self.sounds.random)
end end
self:update_tag()
return true return true
end end
@ -4720,6 +4772,22 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
return true return true
end end
-- if mob follows items and user right clicks while holding sneak it shows info
if self.follow then
if clicker:get_player_control().sneak then
if type(self.follow) == "string" then
self.follow = {self.follow}
end
minetest.chat_send_player(clicker:get_player_name(),
S("@1 follows:\n- @2",
self.name:split(":")[2],
table.concat(self.follow, "\n- ")))
end
end
return false return false
end end

12
api.txt
View File

@ -123,6 +123,8 @@ functions needed for the mob to work properly which contains the following:
continue chasing. continue chasing.
'arrow' holds the pre-defined arrow object to shoot when 'arrow' holds the pre-defined arrow object to shoot when
attacking. attacking.
'arrow_override' function that allows tweaking of arrow entity from
inside mob definition (self) passed to function.
'dogshoot_switch' allows switching between attack types by using timers 'dogshoot_switch' allows switching between attack types by using timers
(1 for shoot, 2 for dogfight) (1 for shoot, 2 for dogfight)
'dogshoot_count_max' contains how many seconds before switching from 'dogshoot_count_max' contains how many seconds before switching from
@ -413,7 +415,7 @@ the mobs:spawn, so it is recommended to use the above instead.
mobs:register_spawn(name, nodes, max_light, min_light, chance, mobs:register_spawn(name, nodes, max_light, min_light, chance,
active_object_count, max_height, day_toggle) active_object_count, max_height, day_toggle)
mobs:spawn_specfic(name, nodes, neighbors, min_light, max_light, interval, mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, interval,
chance, active_object_count, min_height, max_height, day_toggle, on_spawn) chance, active_object_count, min_height, max_height, day_toggle, on_spawn)
A simpler way to handle mob spawns has been added with the mobs:spawn(def) A simpler way to handle mob spawns has been added with the mobs:spawn(def)
@ -689,6 +691,12 @@ space to spawn mob [name], if so then a new position is returned for use,
otherwise nil is returned. otherwise nil is returned.
mobs:is_node_dangerous(mob_object, nodename)
This function returns true if the node name given is harmful to the mob (mob_object),
it is mainly used when a mob is near a node it has to avoid.
External Settings for "minetest.conf" External Settings for "minetest.conf"
------------------------------------ ------------------------------------
@ -699,6 +707,8 @@ External Settings for "minetest.conf"
is false) is false)
'mobs_spawn_protected' if set to false then mobs will not spawn in protected 'mobs_spawn_protected' if set to false then mobs will not spawn in protected
areas (default is true) areas (default is true)
'mobs_spawn_monster_protected' if set to false then monsters will not spawn in
protected areas (default is true)
'remove_far_mobs' if true then untamed mobs that are outside players 'remove_far_mobs' if true then untamed mobs that are outside players
visual range will be removed (default is true) visual range will be removed (default is true)
'mobname' can change specific mob chance rate (0 to disable) and 'mobname' can change specific mob chance rate (0 to disable) and

View File

@ -10,7 +10,6 @@ minetest.register_craftitem("mobs:nametag", {
if minetest.get_modpath("dye") and minetest.get_modpath("farming") then if minetest.get_modpath("dye") and minetest.get_modpath("farming") then
minetest.register_craft({ minetest.register_craft({
-- type = "shapeless",
output = "mobs:nametag", output = "mobs:nametag",
recipe = {{"default:paper", "dye:black", "farming:string"}} recipe = {{"default:paper", "dye:black", "farming:string"}}
}) })
@ -149,7 +148,7 @@ minetest.register_craft({
-- make sure we can register fences -- make sure we can register fences
if default.register_fence then if minetest.get_modpath("default") and default.register_fence then
-- mob fence (looks like normal fence but collision is 2 high) -- mob fence (looks like normal fence but collision is 2 high)
default.register_fence("mobs:fence_wood", { default.register_fence("mobs:fence_wood", {
@ -165,6 +164,7 @@ default.register_fence("mobs:fence_wood", {
} }
} }
}) })
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", {
@ -197,8 +197,6 @@ minetest.register_craft({
} }
}) })
end
-- items that can be used as fuel -- items that can be used as fuel
minetest.register_craft({ minetest.register_craft({
@ -361,9 +359,9 @@ minetest.register_node("mobs:meatblock", {
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 = {choppy = 1, oddly_breakable_by_hand = 1, flammable = 2}, groups = {choppy = 1, oddly_breakable_by_hand = 1, flammable = 2},
sounds = default.node_sound_leaves_defaults(), sounds = default and default.node_sound_leaves_defaults(),
on_place = minetest.rotate_node, on_place = minetest.rotate_node,
on_use = minetest.item_eat(20), on_use = minetest.item_eat(20)
}) })
minetest.register_craft({ minetest.register_craft({

View File

@ -1,4 +1,4 @@
default default?
tnt? tnt?
dye? dye?
farming? farming?
@ -7,3 +7,5 @@ intllib?
lucky_block? lucky_block?
cmi? cmi?
toolranks? toolranks?
pathfinder?
player_api?

View File

@ -22,4 +22,4 @@ dofile(path .. "/spawner.lua")
-- Lucky Blocks -- Lucky Blocks
dofile(path .. "/lucky_block.lua") dofile(path .. "/lucky_block.lua")
minetest.log("action", "[MOD] Mobs Redo loaded") print("[MOD] Mobs Redo loaded")

View File

@ -1,3 +0,0 @@
-- Support for the old multi-load method
dofile(minetest.get_modpath("intllib").."/init.lua")

View File

@ -11,7 +11,7 @@ msgstr ""
"PO-Revision-Date: 2017-07-02 14:27+0200\n" "PO-Revision-Date: 2017-07-02 14:27+0200\n"
"Last-Translator: Wuzzy <almikes@aol.com>\n" "Last-Translator: Wuzzy <almikes@aol.com>\n"
"Language-Team: \n" "Language-Team: \n"
"Language: de_DE\n" "Language: de\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"

View File

@ -1,4 +1,4 @@
name = mobs name = mobs
depends = default depends =
optional_depends = tnt, dye, farming, invisibility, intllib, lucky_block, cmi, toolranks optional_depends = default, tnt, dye, farming, invisibility, intllib, lucky_block, cmi, toolranks, pathfinder, player_api
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.

View File

@ -1,14 +1,16 @@
-- lib_mount by Blert2112 (edited by TenPlus1) -- lib_mount by Blert2112 (edited by TenPlus1)
local is_50 = minetest.get_modpath("player_api") -- 5.x compatibility
local abs, cos, floor, sin, sqrt, pi = local abs, cos, floor, sin, sqrt, pi =
math.abs, math.cos, math.floor, math.sin, math.sqrt, math.pi math.abs, math.cos, math.floor, math.sin, math.sqrt, math.pi
------------------------------------------------------------------------------
-- --
-- Helper functions -- Helper functions
-- --
local node_ok = function(pos, fallback) local node_ok = function(pos, fallback)
fallback = fallback or mobs.fallback_node fallback = fallback or mobs.fallback_node
local node = minetest.get_node_or_nil(pos) local node = minetest.get_node_or_nil(pos)
@ -46,6 +48,7 @@ end
local function get_sign(i) local function get_sign(i)
i = i or 0 i = i or 0
if i == 0 then if i == 0 then
@ -57,6 +60,7 @@ end
local function get_velocity(v, yaw, y) local function get_velocity(v, yaw, y)
local x = -sin(yaw) * v local x = -sin(yaw) * v
local z = cos(yaw) * v local z = cos(yaw) * v
@ -71,6 +75,8 @@ end
local function force_detach(player) local function force_detach(player)
if not player then return end
local attached_to = player:get_attach() local attached_to = player:get_attach()
if not attached_to then if not attached_to then
@ -85,19 +91,27 @@ local function force_detach(player)
end end
player:set_detach() player:set_detach()
player_api.player_attached[player:get_player_name()] = false
player:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
player_api.set_animation(player, "stand", 30)
player:set_properties({visual_size = {x = 1, y = 1}})
local name = player:get_player_name()
if is_50 then
player_api.player_attached[name] = false
player_api.set_animation(player, "stand", 30)
else
default.player_attached[name] = false
default.player_set_animation(player, "stand", 30)
end
player:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
player:set_properties({visual_size = {x = 1, y = 1}})
end end
-------------------------------------------------------------------------------
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
force_detach(player) force_detach(player)
end) end)
minetest.register_on_shutdown(function() minetest.register_on_shutdown(function()
local players = minetest.get_connected_players() local players = minetest.get_connected_players()
@ -107,12 +121,12 @@ minetest.register_on_shutdown(function()
end end
end) end)
minetest.register_on_dieplayer(function(player) minetest.register_on_dieplayer(function(player)
force_detach(player) force_detach(player)
return true return true
end) end)
-------------------------------------------------------------------------------
-- Just for correct detaching -- Just for correct detaching
local function find_free_pos(pos) local function find_free_pos(pos)
@ -147,7 +161,6 @@ local function find_free_pos(pos)
return pos return pos
end end
-------------------------------------------------------------------------------
function mobs.attach(entity, player) function mobs.attach(entity, player)
@ -169,8 +182,13 @@ function mobs.attach(entity, player)
force_detach(player) force_detach(player)
if is_50 then
player_api.player_attached[player:get_player_name()] = true
else
default.player_attached[player:get_player_name()] = true
end
player:set_attach(entity.object, "", attach_at, entity.player_rotation) player:set_attach(entity.object, "", attach_at, entity.player_rotation)
player_api.player_attached[player:get_player_name()] = true
player:set_eye_offset(eye_offset, {x = 0, y = 0, z = 0}) player:set_eye_offset(eye_offset, {x = 0, y = 0, z = 0})
player:set_properties({ player:set_properties({
@ -183,7 +201,12 @@ function mobs.attach(entity, player)
minetest.after(0.2, function() minetest.after(0.2, function()
if player and player:is_player() then if player and player:is_player() then
player_api.set_animation(player, "sit", 30)
if is_50 then
player_api.set_animation(player, "sit", 30)
else
default.player_set_animation(player, "sit", 30)
end
end end
end) end)
@ -192,6 +215,7 @@ end
function mobs.detach(player) function mobs.detach(player)
force_detach(player) force_detach(player)
minetest.after(0.1, function() minetest.after(0.1, function()
@ -218,7 +242,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
end end
local acce_y = 0 local acce_y = 0
local velo = entity.object:get_velocity() local velo = entity.object:get_velocity() ; if not velo then return end
entity.v = get_v(velo) * get_sign(entity.v) entity.v = get_v(velo) * get_sign(entity.v)
@ -230,7 +254,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
-- move forwards -- move forwards
if ctrl.up then if ctrl.up then
entity.v = entity.v + entity.accel / 10 entity.v = entity.v + entity.accel * dtime
-- move backwards -- move backwards
elseif ctrl.down then elseif ctrl.down then
@ -239,7 +263,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
return return
end end
entity.v = entity.v - entity.accel / 10 entity.v = entity.v - entity.accel * dtime
end end
-- mob rotation -- mob rotation
@ -262,6 +286,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
entity.object:set_yaw(horz - entity.rotate) entity.object:set_yaw(horz - entity.rotate)
if can_fly then if can_fly then
-- fly up -- fly up
if ctrl.jump then if ctrl.jump then
@ -271,7 +296,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
elseif velo.y > 0 then elseif velo.y > 0 then
velo.y = velo.y - 0.1 velo.y = velo.y - dtime
if velo.y < 0 then velo.y = 0 end if velo.y < 0 then velo.y = 0 end
end end
@ -285,7 +310,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
elseif velo.y < 0 then elseif velo.y < 0 then
velo.y = velo.y + 0.1 velo.y = velo.y + dtime
if velo.y > 0 then velo.y = 0 end if velo.y > 0 then velo.y = 0 end
end end
@ -330,14 +355,10 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
end end
-- enforce speed limit forward and reverse -- enforce speed limit forward and reverse
local max_spd = entity.max_speed_reverse if entity.v > entity.max_speed_forward then
entity.v = entity.max_speed_forward
if get_sign(entity.v) >= 0 then elseif entity.v < -entity.max_speed_reverse then
max_spd = entity.max_speed_forward entity.v = -entity.max_speed_reverse
end
if abs(entity.v) > max_spd then
entity.v = entity.v - get_sign(entity.v)
end end
-- Set position, velocity and acceleration -- Set position, velocity and acceleration
@ -345,7 +366,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
if not p then return end if not p then return end
local new_acce = {x = 0, y = -9.81, z = 0} local new_acce = {x = 0, y = entity.fall_speed, z = 0}
p.y = p.y - 0.5 p.y = p.y - 0.5
@ -427,14 +448,15 @@ end
-- directional flying routine by D00Med (edited by TenPlus1) -- directional flying routine by D00Med (edited by TenPlus1)
function mobs.fly(entity, _, speed, shoots, arrow, moving_anim, stand_anim) function mobs.fly(entity, _, speed, shoots, arrow, moving_anim, stand_anim)
local ctrl = entity.driver:get_player_control() local ctrl = entity.driver:get_player_control() ; if not ctrl then return end
local velo = entity.object:get_velocity() local velo = entity.object:get_velocity()
local dir = entity.driver:get_look_dir() local dir = entity.driver:get_look_dir()
local yaw = entity.driver:get_look_horizontal() + 1.57 -- offset fix between old and new commands local yaw = entity.driver:get_look_horizontal() + 1.57
if not ctrl or not velo then return end if not ctrl or not velo then return end
if ctrl.up then if ctrl.up then
entity.object:set_velocity({ entity.object:set_velocity({
x = dir.x * speed, x = dir.x * speed,
y = dir.y * speed + 2, y = dir.y * speed + 2,

View File

@ -23,7 +23,8 @@ Lucky Blocks: 9
Changelog: Changelog:
- 1.55 - Add 'peaceful_player' privelage and setting so mobs don't attack specific players (thanks sfence) - 1.56 - Added arrow_override function to mob definition to tweak arrow entity settings, tamed monsters no longer despawn when outside loaded map area.
- 1.55 - Add 'peaceful_player' privelage and setting so mobs don't attack specific players (thanks sfence), add support for MarkBu's pathfinder mod, remove need for default mod
- 1.54 - Simplified animal breeding function, added editable settings (thanks Wuzzy), Child mobs now take 20 mins to grow up, reverted to simple mob spawning with setting to use area checks, on_flop added, air_damage added. - 1.54 - Simplified animal breeding function, added editable settings (thanks Wuzzy), Child mobs now take 20 mins to grow up, reverted to simple mob spawning with setting to use area checks, on_flop added, air_damage added.
- 1.53 - Added 'on_map_load' settings to mobs:spawn so that mobs will only spawn when new areas of map are loaded. - 1.53 - Added 'on_map_load' settings to mobs:spawn so that mobs will only spawn when new areas of map are loaded.
- 1.52 - Added 'mob_active_limit' in settings to set number of mobs in game, - 1.52 - Added 'mob_active_limit' in settings to set number of mobs in game,

View File

@ -13,6 +13,9 @@ mobs_griefing (Griefing Mobs) bool true
# If false then Mobs no longer spawn inside player protected areas # If false then Mobs no longer spawn inside player protected areas
mobs_spawn_protected (Spawn Mobs in protected areas) bool true mobs_spawn_protected (Spawn Mobs in protected areas) bool true
# If false then Monsters no longer spawn inside player protected areas
mobs_spawn_monster_protected (Spawn Monsters in protected areas) bool true
# If true Mobs will be removed once a map chunk is out of view # If true Mobs will be removed once a map chunk is out of view
remove_far_mobs (Remove far Mobs) bool true remove_far_mobs (Remove far Mobs) bool true