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

Compare commits

...

30 Commits

Author SHA1 Message Date
83f0b901a4 add self.messages field 2022-08-04 08:21:59 +01:00
e4ac59609a add mob protection to infotext 2022-07-31 10:20:32 +01:00
7ac8506dda add fallback node for is_node_dangerous 2022-07-29 18:52:28 +01:00
90df44aeaf comment unused vars 2022-07-22 14:12:30 +01:00
25ab9591e4 add 'can_leap' setting to mob def, update api.txt 2022-07-12 08:37:38 +01:00
8e6fa64f2d fix premature mob death and drops 2022-07-07 17:09:34 +01:00
ce7c4c1449 adjust mob count when using /clear_mobs 2022-07-04 11:00:52 +01:00
08dcdf382a add /clear_mobs command 2022-07-04 10:43:28 +01:00
d2a4150dcb extend mob reach when on top of player to fix issue 2022-06-28 08:08:35 +01:00
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
9 changed files with 207 additions and 120 deletions

222
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 = "20210920", version = "20220804",
intllib = S, intllib = S,
invis = minetest.global_exists("invisibility") and invisibility or {} invis = minetest.global_exists("invisibility") and invisibility or {}
} }
@ -86,8 +106,8 @@ local stuck_timeout = 3 -- how long before stuck mod starts searching
local stuck_path_timeout = 5 -- 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"
local node_permanent_flame = "fire:permanent_flame" --local node_permanent_flame = "fire:permanent_flame"
local node_ice = "default:ice" local node_ice = "default:ice"
local node_snowblock = "default:snowblock" local node_snowblock = "default:snowblock"
local node_snow = "default:snow" local node_snow = "default:snow"
@ -254,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
@ -401,8 +421,7 @@ function mob_class:set_animation(anim, force)
self.object:set_animation({ self.object:set_animation({
x = self.animation[anim .. "_start"], x = self.animation[anim .. "_start"],
y = self.animation[anim .. "_end"]}, y = self.animation[anim .. "_end"]},
self.animation[anim .. "_speed"] or self.animation[anim .. "_speed"] or self.animation.speed_normal or 15,
self.animation.speed_normal or 15,
0, self.animation[anim .. "_loop"] ~= false) 0, self.animation[anim .. "_loop"] ~= false)
end end
@ -526,6 +545,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)
@ -730,7 +750,7 @@ 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 colour -- update nametag and infotext
function mob_class:update_tag() function mob_class:update_tag()
local col = "#00FF00" local col = "#00FF00"
@ -764,8 +784,16 @@ function mob_class:update_tag()
end end
if self.protected then
if self.protected == 2 then
text = text .. "\nProtection: Level 2"
else
text = text .. "\nProtection: Level 1"
end
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 "\nOwner: " .. self.owner)
.. text .. text
-- set changes -- set changes
@ -894,18 +922,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
-- 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() self:update_tag()
-- end
return false return false
end end
@ -989,32 +1006,30 @@ end
-- get node but use fallback for nil or unknown -- get node but use fallback for nil or unknown
local node_ok = function(pos, fallback) local node_ok = function(pos, fallback)
fallback = fallback or mobs.fallback_node
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 return node
end end
return minetest.registered_nodes[fallback] return minetest.registered_nodes[(fallback or mobs.fallback_node)]
end 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
@ -1026,11 +1041,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
@ -1053,7 +1072,7 @@ function mob_class:is_at_cliff()
return true return true
end end
local bnode = node_ok(blocker) local bnode = node_ok(blocker, "air")
-- will we drop onto dangerous node? -- will we drop onto dangerous node?
if is_node_dangerous(self, bnode.name) then if is_node_dangerous(self, bnode.name) then
@ -1074,14 +1093,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
-- if self.htimer < 1 and self.nametag2 then
-- self.nametag = self.nametag2
-- self.nametag2 = nil
self:update_tag() 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
@ -1250,15 +1262,9 @@ function mob_class:do_jump()
-- set y_pos to base of mob -- set y_pos to base of mob
pos.y = pos.y + self.collisionbox[2] pos.y = pos.y + self.collisionbox[2]
-- what is in front of mob? -- what is in front of mob and above?
local nod = node_ok({ local nod = node_ok({x = pos.x + dir_x, y = pos.y + 0.5, z = pos.z + dir_z})
x = pos.x + dir_x, y = pos.y + 0.5, z = pos.z + dir_z local nodt = node_ok({x = pos.x + dir_x, y = pos.y + 1.5, z = pos.z + dir_z})
})
-- what is above and in front?
local nodt = node_ok({
x = pos.x + dir_x, y = pos.y + 1.5, z = pos.z + dir_z
})
local blocked = minetest.registered_nodes[nodt.name].walkable local blocked = minetest.registered_nodes[nodt.name].walkable
@ -1266,6 +1272,7 @@ function mob_class:do_jump()
if nod.name:find("fence") or nod.name:find("gate") or nod.name:find("wall") then if nod.name:find("fence") or nod.name:find("gate") or nod.name:find("wall") then
self.facing_fence = true self.facing_fence = true
end end
--[[ --[[
print("on: " .. self.standing_on print("on: " .. self.standing_on
.. ", front: " .. nod.name .. ", front: " .. nod.name
@ -1274,6 +1281,13 @@ print("on: " .. self.standing_on
.. ", fence: " .. (self.facing_fence and "yes" or "no") .. ", fence: " .. (self.facing_fence and "yes" or "no")
) )
]] ]]
-- if mob can leap then remove blockages and let them try
if self.can_leap == true then
blocked = false
self.facing_fence = false
end
-- jump if standing on solid node (not snow) and not blocked -- jump if standing on solid node (not snow) and not blocked
if (self.walk_chance == 0 or minetest.registered_items[nod.name].walkable) if (self.walk_chance == 0 or minetest.registered_items[nod.name].walkable)
and not blocked and not self.facing_fence and nod.name ~= node_snow then and not blocked and not self.facing_fence and nod.name ~= node_snow then
@ -1444,8 +1458,7 @@ function mob_class:breed()
local pos = self.object:get_pos() local pos = self.object:get_pos()
effect({x = pos.x, y = pos.y + 1, z = pos.z}, 8, effect({x = pos.x, y = pos.y + 1, z = pos.z}, 8, "heart.png", 3, 4, 1, 0.1)
"heart.png", 3, 4, 1, 0.1)
local objs = minetest.get_objects_inside_radius(pos, 3) local objs = minetest.get_objects_inside_radius(pos, 3)
local ent local ent
@ -1466,6 +1479,7 @@ function mob_class:breed()
local selfname = self.name:split(":") local selfname = self.name:split(":")
if entname[1] == selfname[1] then if entname[1] == selfname[1] then
entname = entname[2]:split("_") entname = entname[2]:split("_")
selfname = selfname[2]:split("_") selfname = selfname[2]:split("_")
@ -1553,7 +1567,7 @@ function mob_class:breed()
self.base_selbox[4] * .5, self.base_selbox[4] * .5,
self.base_selbox[5] * .5, self.base_selbox[5] * .5,
self.base_selbox[6] * .5 self.base_selbox[6] * .5
}, }
}) })
-- tamed and owned by parents' owner -- tamed and owned by parents' owner
ent2.child = true ent2.child = true
@ -1629,13 +1643,10 @@ end
function mob_class:day_docile() function mob_class:day_docile()
if self.docile_by_day == false then if self.docile_by_day == false then
return false return false
elseif self.docile_by_day == true elseif self.docile_by_day == true
and self.time_of_day > 0.2 and self.time_of_day > 0.2
and self.time_of_day < 0.8 then and self.time_of_day < 0.8 then
return true return true
end end
end end
@ -1680,6 +1691,7 @@ end
local pathfinder_mod = minetest.get_modpath("pathfinder") 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)
@ -2108,7 +2120,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]
@ -2365,11 +2377,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
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") 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
@ -2618,7 +2641,7 @@ function mob_class:do_states(dtime)
yaw = yaw_to_pos(self, p) yaw = yaw_to_pos(self, p)
-- move towards enemy if beyond mob reach -- move towards enemy if beyond mob reach
if dist > self.reach then if dist > (self.reach + (self.reach_ext or 0)) then
-- path finding by rnd -- path finding by rnd
if self.pathfinding -- only if mob has pathfinding enabled if self.pathfinding -- only if mob has pathfinding enabled
@ -2630,8 +2653,13 @@ function mob_class:do_states(dtime)
-- distance padding to stop spinning mob -- distance padding to stop spinning mob
local pad = abs(p.x - s.x) + abs(p.z - s.z) local pad = abs(p.x - s.x) + abs(p.z - s.z)
self.reach_ext = 0 -- extended ready off by default
if self.at_cliff or pad < 0.2 then if self.at_cliff or pad < 0.2 then
-- when on top of player extend reach slightly so player can
-- still be attacked.
self.reach_ext = 0.8
self:set_velocity(0) self:set_velocity(0)
self:set_animation("stand") self:set_animation("stand")
else else
@ -2989,7 +3017,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
@ -3132,8 +3160,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
@ -3262,7 +3288,7 @@ function mob_class:mob_activate(staticdata, def, dtime)
if type(self.armor) == "table" then if type(self.armor) == "table" then
armor = table_copy(self.armor) armor = table_copy(self.armor)
else else
armor = {fleshy = self.armor} -- immortal = 1 armor = {fleshy = self.armor, immortal = 1}
end end
self.object:set_armor_groups(armor) self.object:set_armor_groups(armor)
@ -3344,8 +3370,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)
@ -3372,9 +3397,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
@ -3396,8 +3421,7 @@ function mob_class:on_step(dtime, moveresult)
-- if standing inside solid block then jump to escape -- if standing inside solid block then jump to escape
if minetest.registered_nodes[self.standing_in].walkable if minetest.registered_nodes[self.standing_in].walkable
and minetest.registered_nodes[self.standing_in].drawtype and minetest.registered_nodes[self.standing_in].drawtype == "normal" then
== "normal" then
self.object:set_velocity({ self.object:set_velocity({
x = 0, x = 0,
@ -3571,6 +3595,7 @@ minetest.register_entity(name, setmetatable({
on_flop = def.on_flop, on_flop = def.on_flop,
do_custom = def.do_custom, do_custom = def.do_custom,
jump_height = def.jump_height, jump_height = def.jump_height,
can_leap = def.can_leap,
drawtype = def.drawtype, -- DEPRECATED, use rotate instead drawtype = def.drawtype, -- DEPRECATED, use rotate instead
rotate = rad(def.rotate or 0), -- 0=front 90=side 180=back 270=side2 rotate = rad(def.rotate or 0), -- 0=front 90=side 180=back 270=side2
glow = def.glow, glow = def.glow,
@ -3655,6 +3680,7 @@ minetest.register_entity(name, setmetatable({
stay_near = def.stay_near, stay_near = def.stay_near,
randomly_turn = def.randomly_turn ~= false, randomly_turn = def.randomly_turn ~= false,
ignore_invisibility = def.ignore_invisibility, ignore_invisibility = def.ignore_invisibility,
messages = def.messages,
on_spawn = def.on_spawn, on_spawn = def.on_spawn,
@ -3672,7 +3698,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))
@ -3841,7 +3867,7 @@ function mobs:add_mob(pos, def)
ent.base_selbox[4] * .5, ent.base_selbox[4] * .5,
ent.base_selbox[5] * .5, ent.base_selbox[5] * .5,
ent.base_selbox[6] * .5 ent.base_selbox[6] * .5
}, }
}) })
ent.child = true ent.child = true
@ -4337,7 +4363,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
@ -4388,7 +4414,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
@ -4474,7 +4500,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 not self --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
@ -4643,8 +4669,7 @@ function mobs:protect(self, clicker)
pos.y = pos.y + self.collisionbox[2] + 0.5 pos.y = pos.y + self.collisionbox[2] + 0.5
effect(self.object:get_pos(), 25, "mobs_protect_particle.png", effect(self.object:get_pos(), 25, "mobs_protect_particle.png", 0.5, 4, 2, 15)
0.5, 4, 2, 15)
self:mob_sound("mobs_spell") self:mob_sound("mobs_spell")
@ -4678,15 +4703,6 @@ 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)
@ -4694,7 +4710,6 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
-- 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 = math.floor(self.hornytimer + ( self.hornytimer = math.floor(self.hornytimer + (
(CHILD_GROW_TIME - self.hornytimer) * 0.1)) (CHILD_GROW_TIME - self.hornytimer) * 0.1))
@ -4833,7 +4848,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end) end)
-- compatibility function for old entities to new modpack entities -- 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
@ -4864,3 +4879,44 @@ function mobs:alias_mob(old_name, new_name)
end end
}) })
end end
-- admin command to remove untamed mobs around players
minetest.register_chatcommand("clear_mobs", {
params = "<text>",
description = "Remove untamed mobs from around players.",
privs = {server = true},
func = function (name, param)
local count = 0
for _, player in pairs(minetest.get_connected_players()) do
if player then
local pos = player:get_pos()
local objs = minetest.get_objects_inside_radius(pos, 28)
for _, obj in pairs(objs) do
if obj then
local ent = obj:get_luaentity()
-- only remove mobs redo mobs that are not tamed
if ent and ent._cmi_is_mob and ent.tamed ~= true then
remove_mob(ent, true)
count = count + 1
end
end
end
end
end
minetest.chat_send_player(name, S("@1 mobs removed.", count))
end
})

13
api.txt
View File

@ -42,6 +42,8 @@ functions needed for the mob to work properly which contains the following:
randomly turn while walking or standing. randomly turn while walking or standing.
'jump' when true allows your mob to jump updwards. 'jump' when true allows your mob to jump updwards.
'jump_height' holds the height your mob can jump, 0 to disable jumping. 'jump_height' holds the height your mob can jump, 0 to disable jumping.
'can_leap' when true obstacles like fences or pits wont stop a mob
from trying to jump out.
'stepheight' height of a block that your mob can easily walk up onto, 'stepheight' height of a block that your mob can easily walk up onto,
defaults to 1.1. defaults to 1.1.
'fly' when true allows your mob to fly around instead of walking. 'fly' when true allows your mob to fly around instead of walking.
@ -223,6 +225,9 @@ functions needed for the mob to work properly which contains the following:
'fly_start' when a mob is flying. 'fly_start' when a mob is flying.
'fly_end' 'fly_end'
'fly_speed' 'fly_speed'
'jump_start' when a mob is jumping
'jump_end'
'jump_speed'
'punch_start' when a mob melee attacks. 'punch_start' when a mob melee attacks.
'punch_end' 'punch_end'
'punch_speed' 'punch_speed'
@ -415,7 +420,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)
@ -691,6 +696,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"
------------------------------------ ------------------------------------

View File

@ -8,3 +8,4 @@ lucky_block?
cmi? cmi?
toolranks? toolranks?
pathfinder? 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 = depends =
optional_depends = default, tnt, dye, farming, invisibility, intllib, lucky_block, cmi, toolranks, pathfinder 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)
player:set_attach(entity.object, "", attach_at, entity.player_rotation) if is_50 then
player_api.player_attached[player:get_player_name()] = true 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_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
if is_50 then
player_api.set_animation(player, "sit", 30) 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,