Update mobs_redo mod to Git commit db3831d...

db3831dccf
master
Jordan Irwin 2021-07-15 06:20:11 -07:00
parent d66f8f2b6d
commit 6a32824066
7 changed files with 275 additions and 235 deletions

View File

@ -57,7 +57,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
* [config][] ([MIT][lic.config]) -- version: 1.1 *2020-03-26*
* [formspecs][] ([MIT][lic.formspecs]) -- version: 2.6 *2020-03-12*
* [mobkit][] ([MIT][lic.mobkit]) -- version: [ddea141 Git][ver.mobkit] *2021-02-01*
* [mobs_redo][] ([MIT][lic.mobs_redo] / [CC BY][lic.ccby3.0] / [CC0][lic.cc0]) -- version: [f6e16a5 Git][ver.mobs_redo] *2021-04-11*
* [mobs_redo][] ([MIT][lic.mobs_redo] / [CC BY][lic.ccby3.0] / [CC0][lic.cc0]) -- version: [db3831d Git][ver.mobs_redo] *2021-07-14*
* [signs_lib][] ([LGPL][lic.lgpl3.0] / [CC BY-SA][lic.ccbysa4.0]) -- version: [2021-03-04-2][ver.signs_lib]
* lighting/
* [glow][] ([GPL][lic.gpl2.0]) -- version: [4c015a0 Git][ver.glow] *2019-02-05*
@ -629,7 +629,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
[ver.mobs_cow]: https://github.com/AntumMT/mod-mobs_animal/tree/85af09a
[ver.mobs_kitten]: https://github.com/AntumMT/mod-mobs_animal/tree/b3bf401
[ver.mobs_rat]: https://github.com/AntumMT/mod-mobs_animal/tree/2a8d115
[ver.mobs_redo]: https://notabug.org/TenPlus1/mobs_redo/src/f6e16a550330cf6a641753c03ebe331682294939
[ver.mobs_redo]: https://notabug.org/TenPlus1/mobs_redo/src/db3831dccf3616e3baaad325fede487d38954191
[ver.monsters_aggressive]: https://github.com/AntumMT/mp-monsters_aggressive/tree/89a8187
[ver.monsters_passive]: https://github.com/AntumMT/mp-monsters_passive/tree/b07fe19
[ver.more_chests]: https://github.com/minetest-mods/more_chests/tree/6be8145

View File

@ -8,7 +8,7 @@ local use_cmi = minetest.global_exists("cmi")
mobs = {
mod = "redo",
version = "20210411",
version = "20210714",
intllib = S,
invis = minetest.global_exists("invisibility") and invisibility or {}
}
@ -28,8 +28,7 @@ local rad = math.rad
local atann = math.atan
local atan = function(x)
if not x or x ~= x then
--error("atan bassed NaN")
return 0
return 0 -- NaN
else
return atann(x)
end
@ -57,6 +56,7 @@ local disable_blood = settings:get_bool("mobs_disable_blood")
local mobs_drop_items = settings:get_bool("mobs_drop_items") ~= false
local mobs_griefing = settings:get_bool("mobs_griefing") ~= 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 mob_area_spawn = settings:get_bool("mob_area_spawn")
local difficulty = tonumber(settings:get("mob_difficulty")) or 1.0
@ -66,9 +66,9 @@ local mob_nospawn_range = tonumber(settings:get("mob_nospawn_range") or 12)
local active_limit = tonumber(settings:get("mob_active_limit") or 0)
local mob_chance_multiplier = tonumber(settings:get("mob_chance_multiplier") or 1)
local peaceful_player_enabled = settings:get_bool("enable_peaceful_player")
local mob_smooth_rotate = settings:get_bool("mob_smooth_rotate") ~= false
local active_mobs = 0
-- Peaceful mode message so players will know there are no monsters
if peaceful_only then
minetest.register_on_joinplayer(function(player)
@ -224,10 +224,7 @@ function mob_class:collision()
for _,object in ipairs(minetest.get_objects_inside_radius(pos, width)) do
if object:is_player()
or (object:get_luaentity()
and object:get_luaentity()._cmi_is_mob == true
and object ~= self.object) then
if object:is_player() then
local pos2 = object:get_pos()
local vec = {x = pos.x - pos2.x, z = pos.z - pos2.z}
@ -277,7 +274,7 @@ function mob_class:set_velocity(v)
-- halt mob if it has been ordered to stay
if self.order == "stand" then
self.object:set_velocity({x = 0, y = 0, z = 0})
self.object:set_velocity({x = 0, y = self.fall_speed, z = 0})
return
end
@ -339,10 +336,12 @@ function mob_class:set_yaw(yaw, delay)
yaw = 0
end
delay = delay or 0
delay = mob_smooth_rotate and (delay or 0) or 0
if delay == 0 then
self.object:set_yaw(yaw)
return yaw
end
@ -404,7 +403,6 @@ function mob_class:set_animation(anim, force)
0, self.animation[anim .. "_loop"] ~= false)
end
-- above function exported for mount.lua
function mobs:set_animation(entity, anim)
entity.set_animation(entity, anim)
end
@ -591,7 +589,7 @@ function mob_class:attempt_flight_correction(override)
local escape_direction = vdirection(pos, escape_target)
self.object:set_velocity(
vmultiply(escape_direction, 1)) --self.run_velocity))
vmultiply(escape_direction, 1))
return true
end
@ -643,7 +641,7 @@ function mobs:yaw_to_pos(self, target, rot)
end
-- if stay near set then check periodically for nodes and turn towards them
-- if stay near set then periodically check for nodes and turn towards them
function mob_class:do_stay_near()
if not self.stay_near then return false end
@ -740,9 +738,15 @@ function mob_class:update_tag()
col = "#FF0000"
end
-- build infotext
self.infotext = "Health: " .. self.health .. " / " .. self.hp_max
.. "\n" .. "Owner: " .. self.owner
-- set changes
self.object:set_properties({
nametag = self.nametag,
nametag_color = col
nametag_color = col,
infotext = self.infotext
})
end
@ -790,10 +794,7 @@ function mob_class:item_drop()
end
-- only drop rare items (drops.min = 0) if killed by player
if death_by_player then
obj = minetest.add_item(pos, ItemStack(item .. " " .. num))
elseif self.drops[n].min ~= 0 then
if death_by_player or self.drops[n].min ~= 0 then
obj = minetest.add_item(pos, ItemStack(item .. " " .. num))
end
@ -868,18 +869,17 @@ function mob_class:check_for_death(cmi_cause)
end
-- backup nametag so we can show health stats
if not self.nametag2 then
self.nametag2 = self.nametag or ""
end
-- 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
-- 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
-- end
return false
end
@ -1049,13 +1049,13 @@ function mob_class:do_env_damage()
end
-- reset nametag after showing health stats
if self.htimer < 1 and self.nametag2 then
-- if self.htimer < 1 and self.nametag2 then
self.nametag = self.nametag2
self.nametag2 = nil
-- self.nametag = self.nametag2
-- self.nametag2 = nil
self:update_tag()
end
-- end
local pos = self.object:get_pos() ; if not pos then return end
@ -1079,8 +1079,7 @@ function mob_class:do_env_damage()
local nodef = minetest.registered_nodes[self.standing_in]
-- water
if self.water_damage ~= 0
and nodef.groups.water then
if self.water_damage ~= 0 and nodef.groups.water then
self.health = self.health - self.water_damage
@ -1092,8 +1091,7 @@ function mob_class:do_env_damage()
end
-- lava damage
elseif self.lava_damage ~= 0
and nodef.groups.lava then
elseif self.lava_damage ~= 0 and nodef.groups.lava then
self.health = self.health - self.lava_damage
@ -1105,8 +1103,7 @@ function mob_class:do_env_damage()
end
-- fire damage
elseif self.fire_damage ~= 0
and nodef.groups.fire then
elseif self.fire_damage ~= 0 and nodef.groups.fire then
self.health = self.health - self.fire_damage
@ -1239,58 +1236,58 @@ function mob_class:do_jump()
local blocked = minetest.registered_nodes[nodt.name].walkable
--print("standing on:", self.standing_on, pos.y - 0.25)
--print("in front:", nod.name, pos.y + 0.5)
--print("in front above:", nodt.name, pos.y + 1.5)
-- are we facing a fence or wall
if nod.name:find("fence") or nod.name:find("gate") or nod.name:find("wall") then
self.facing_fence = true
end
--[[
print("on: " .. self.standing_on
.. ", front: " .. nod.name
.. ", front above: " .. nodt.name
.. ", blocked: " .. (blocked and "yes" or "no")
.. ", fence: " .. (self.facing_fence and "yes" or "no")
)
]]
-- jump if standing on solid node (not snow) and not blocked
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
-- jump if standing on solid node (not snow) and not blocked above
if (self.walk_chance == 0
or minetest.registered_items[nod.name].walkable)
and not blocked
and nod.name ~= node_snow then
local v = self.object:get_velocity()
if not nod.name:find("fence")
and not nod.name:find("gate")
and not nod.name:find("wall") then
v.y = self.jump_height
local v = self.object:get_velocity()
self:set_animation("jump") -- only when defined
v.y = self.jump_height
self.object:set_velocity(v)
self:set_animation("jump") -- only when defined
-- when in air move forward
minetest.after(0.3, function(self, v)
self.object:set_velocity(v)
if self.object:get_luaentity() then
-- when in air move forward
minetest.after(0.3, function(self, v)
if self.object:get_luaentity() then
self.object:set_acceleration({
x = v.x * 2,
y = 0,
z = v.z * 2
})
end
end, self, v)
if self:get_velocity() > 0 then
self:mob_sound(self.sounds.jump)
self.object:set_acceleration({
x = v.x * 2,
y = 0,
z = v.z * 2
})
end
end, self, v)
return true
else
self.facing_fence = true
if self:get_velocity() > 0 then
self:mob_sound(self.sounds.jump)
end
self.jump_count = 0
return true
end
-- if blocked against a block/wall for 5 counts then turn
if not self.following
and (self.facing_fence or blocked) then
-- if blocked for 3 counts then turn
if not self.following and (self.facing_fence or blocked) then
self.jump_count = (self.jump_count or 0) + 1
if self.jump_count > 4 then
if self.jump_count > 2 then
local yaw = self.object:get_yaw() or 0
local turn = random(0, 2) + 1.35
@ -1361,7 +1358,7 @@ end
-- Thanks Wuzzy for the following editable settings
local HORNY_TIME = 30
local HORNY_AGAIN_TIME = 300
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
@ -1389,16 +1386,15 @@ function mob_class:breed()
if self.on_grown then
self.on_grown(self)
else
-- jump when fully grown so as not to fall into ground
-- self.object:set_velocity({
-- x = 0,
-- y = self.jump_height,
-- z = 0
-- })
local pos = self.object:get_pos() ; if not pos then return end
local ent = self.object:get_luaentity()
pos.y = pos.y + (ent.collisionbox[2] * -1) - 0.4
self.object:set_pos(pos)
-- jump slightly when fully grown so as not to fall into ground
self.object:set_velocity({x = 0, y = 0.5, z = 0 })
end
end
@ -1621,6 +1617,40 @@ end
local los_switcher = false
local height_switcher = false
local can_dig_drop = function(pos)
if minetest.is_protected(pos, "") then
return false
end
local node = node_ok(pos, "air").name
local ndef = minetest.registered_nodes[node]
if node ~= "ignore"
and ndef
and ndef.drawtype ~= "airlike"
and not ndef.groups.level
and not ndef.groups.unbreakable
and not ndef.groups.liquid then
local drops = minetest.get_node_drops(node)
for _, item in ipairs(drops) do
minetest.add_item({
x = pos.x - 0.5 + random(),
y = pos.y - 0.5 + random(),
z = pos.z - 0.5 + random()
}, item)
end
minetest.remove_node(pos)
return true
end
return false
end
-- path finding and smart mob routine by rnd,
-- line_of_sight and other edits by Elkien3
@ -1786,8 +1816,8 @@ function mob_class:smart_mobs(s, p, dist, dtime)
-- lets make way by digging/building if not accessible
if self.pathfinding == 2 and mobs_griefing then
-- is player higher than mob?
if s.y < p1.y then
-- is player more than 1 block higher than mob?
if p1.y > (s.y + 1) then
-- build upwards
if not minetest.is_protected(s, "") then
@ -1795,8 +1825,7 @@ function mob_class:smart_mobs(s, p, dist, dtime)
local ndef1 = minetest.registered_nodes[self.standing_in]
if ndef1 and (ndef1.buildable_to or ndef1.groups.liquid) then
minetest.set_node(s, {name = mobs.fallback_node})
minetest.set_node(s, {name = mobs.fallback_node})
end
end
@ -1806,27 +1835,19 @@ function mob_class:smart_mobs(s, p, dist, dtime)
s.y = s.y + sheight
-- remove one block above to make room to jump
if not minetest.is_protected(s, "") then
local node1 = node_ok(s, "air").name
local ndef1 = minetest.registered_nodes[node1]
if node1 ~= "air"
and node1 ~= "ignore"
and ndef1
and not ndef1.groups.level
and not ndef1.groups.unbreakable
and not ndef1.groups.liquid then
minetest.set_node(s, {name = "air"})
minetest.add_item(s, ItemStack(node1))
end
end
can_dig_drop(s)
s.y = s.y - sheight
self.object:set_pos({x = s.x, y = s.y + 2, z = s.z})
-- is player more than 1 block lower than mob
elseif p1.y < (s.y - 1) then
-- dig down
s.y = s.y - self.collisionbox[4] - 0.2
can_dig_drop(s)
else -- dig 2 blocks to make door toward player direction
local yaw1 = self.object:get_yaw() + pi / 2
@ -1836,37 +1857,12 @@ function mob_class:smart_mobs(s, p, dist, dtime)
z = s.z + sin(yaw1)
}
if not minetest.is_protected(p1, "") then
-- dig bottom node first incase of door
can_dig_drop(p1)
local node1 = node_ok(p1, "air").name
local ndef1 = minetest.registered_nodes[node1]
p1.y = p1.y + 1
if node1 ~= "air"
and node1 ~= "ignore"
and ndef1
and not ndef1.groups.level
and not ndef1.groups.unbreakable
and not ndef1.groups.liquid then
minetest.add_item(p1, ItemStack(node1))
minetest.set_node(p1, {name = "air"})
end
p1.y = p1.y + 1
node1 = node_ok(p1, "air").name
ndef1 = minetest.registered_nodes[node1]
if node1 ~= "air"
and node1 ~= "ignore"
and ndef1
and not ndef1.groups.level
and not ndef1.groups.unbreakable
and not ndef1.groups.liquid then
minetest.add_item(p1, ItemStack(node1))
minetest.set_node(p1, {name = "air"})
end
end
can_dig_drop(p1)
end
end
@ -2598,7 +2594,10 @@ function mob_class:do_states(dtime)
self:smart_mobs(s, p, dist, dtime)
end
if self.at_cliff then
-- distance padding to stop spinning mob
local pad = abs(p.x - s.x) + abs(p.z - s.z)
if self.at_cliff or pad < 0.2 then
self:set_velocity(0)
self:set_animation("stand")
@ -2616,7 +2615,6 @@ function mob_class:do_states(dtime)
self:set_animation("walk")
end
end
else -- rnd: if inside reach range
self.path.stuck = false
@ -2652,9 +2650,11 @@ function mob_class:do_states(dtime)
self.attack = attached
end
local dgroup = self.damage_group or "fleshy"
self.attack:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = self.damage}
damage_groups = {[dgroup] = self.damage}
}, nil)
end
end
@ -2761,11 +2761,7 @@ function mob_class:falling(pos)
end
-- fall at set speed
self.object:set_acceleration({
x = 0,
y = fall_speed,
z = 0
})
self.object:set_acceleration({x = 0, y = fall_speed, z = 0})
end
@ -2788,8 +2784,9 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
-- error checking when mod profiling is enabled
if not tool_capabilities then
minetest.log("warning",
"[mobs] Mod profiling enabled, damage not enabled")
minetest.log("warning", "[mobs] Mod profiling enabled, damage not enabled")
return true
end
@ -2865,6 +2862,7 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
if self.immune_to[n][1] == weapon_def.name then
damage = self.immune_to[n][2] or 0
break
-- if "all" then no tools deal damage unless it's specified in list
@ -2877,13 +2875,14 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
-- healing
if damage <= -1 then
self.health = self.health - floor(damage)
return true
end
if use_cmi
and cmi.notify_punch(
self.object, hitter, tflp, tool_capabilities, dir, damage) then
and cmi.notify_punch(self.object, hitter, tflp, tool_capabilities, dir, damage) then
return true
end
@ -2902,10 +2901,8 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
end
end
if tr then
if weapon_def.original_description then
toolranks.new_afteruse(weapon, hitter, nil, {wear = wear})
end
if tr and weapon_def.original_description then
toolranks.new_afteruse(weapon, hitter, nil, {wear = wear})
else
weapon:add_wear(wear)
end
@ -2915,21 +2912,11 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
-- only play hit sound and show blood effects if damage is 1 or over
if damage >= 1 then
-- weapon sounds
if weapon_def.sounds then
-- select tool use sound if found, or fallback to default
local snd = weapon_def.sound and weapon_def.sound.use
or "default_punch"
local s = random(0, #weapon_def.sounds)
minetest.sound_play(weapon_def.sounds[s], {
object = self.object,
max_hear_distance = 8
}, true)
else
minetest.sound_play("default_punch", {
object = self.object,
max_hear_distance = 5
}, true)
end
minetest.sound_play(snd, {object = self.object, max_hear_distance = 8}, true)
-- blood_particles
if not disable_blood and self.blood_amount > 0 then
@ -2938,8 +2925,7 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
local blood = self.blood_texture
local amount = self.blood_amount
pos.y = pos.y + (-self.collisionbox[2]
+ self.collisionbox[5]) * .5
pos.y = pos.y + (-self.collisionbox[2] + self.collisionbox[5]) * .5
-- lots of damage = more blood :)
if damage > 10 then
@ -2952,7 +2938,6 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
end
effect(pos, amount, blood, 1, 2, 1.75, nil, nil, true)
end
-- do damage
@ -2962,29 +2947,13 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
local hot = tool_capabilities and tool_capabilities.damage_groups
and tool_capabilities.damage_groups.fire
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
end
--[[ add healthy afterglow when hit (causes lag with large textures)
minetest.after(0.1, function()
if not self.object:get_luaentity() then return end
self.object:set_texture_mod("^[colorize:#c9900070")
minetest.after(0.3, function()
if not self.object:get_luaentity() then return end
self.object:set_texture_mod(self.texture_mods)
end)
end) ]]
end -- END if damage
-- 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
local v = self.object:get_velocity()
@ -3006,11 +2975,7 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
-- use tool knockback value or default
kb = tool_capabilities.damage_groups["knockback"] or kb
self.object:set_velocity({
x = dir.x * kb,
y = up,
z = dir.z * kb
})
self.object:set_velocity({x = dir.x * kb, y = up, z = dir.z * kb})
self.pause_timer = 0.25
end
@ -3257,10 +3222,8 @@ function mob_class:mob_activate(staticdata, def, dtime)
local armor
if type(self.armor) == "table" then
armor = table_copy(self.armor)
-- armor.immortal = 1
else
-- armor = {immortal = 1, fleshy = self.armor}
armor = {fleshy = self.armor}
armor = {fleshy = self.armor} -- immortal = 1
end
self.object:set_armor_groups(armor)
@ -3358,23 +3321,7 @@ end
-- main mob function
function mob_class:on_step(dtime, moveresult)
--[[ moveresult contains this for physical mobs
{
touching_ground = boolean,
collides = boolean,
standing_on_object = boolean,
collisions = {
{
type = string, -- "node" or "object",
axis = string, -- "x", "y" or "z"
node_pos = vector, -- if type is "node"
object = ObjectRef, -- if type is "object"
old_velocity = vector,
new_velocity = vector,
}}
}]]
if self.state == "die" then return end ----------------
if self.state == "die" then return end
if use_cmi then
cmi.notify_step(self.object, dtime)
@ -3563,6 +3510,13 @@ function mobs:register_mob(name, def)
mobs.spawning_mobs[name] = {}
local collisionbox = def.collisionbox or {-0.25, -0.25, -0.25, 0.25, 0.25, 0.25}
-- quick fix to stop mobs glitching through nodes if too small
if -collisionbox[2] + collisionbox[5] < 1.01 then
collisionbox[5] = collisionbox[2] + 0.99
end
minetest.register_entity(name, setmetatable({
stepheight = def.stepheight,
@ -3584,8 +3538,8 @@ minetest.register_entity(name, setmetatable({
lifetimer = def.lifetimer,
hp_min = max(1, (def.hp_min or 5) * difficulty),
hp_max = max(1, (def.hp_max or 10) * difficulty),
collisionbox = def.collisionbox,
selectionbox = def.selectionbox or def.collisionbox,
collisionbox = collisionbox, --def.collisionbox,
selectionbox = def.selectionbox or collisionbox, --def.collisionbox,
visual = def.visual,
visual_size = def.visual_size,
mesh = def.mesh,
@ -3594,6 +3548,8 @@ minetest.register_entity(name, setmetatable({
walk_velocity = def.walk_velocity,
run_velocity = def.run_velocity,
damage = max(0, (def.damage or 0) * difficulty),
damage_group = def.damage_group,
damage_texture_modifier = def.damage_texture_modifier,
light_damage = def.light_damage,
light_damage_min = def.light_damage_min,
light_damage_max = def.light_damage_max,
@ -3891,11 +3847,13 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
local numbers = settings:get(name)
if numbers then
numbers = numbers:split(",")
chance = tonumber(numbers[1]) or chance
aoc = tonumber(numbers[2]) or aoc
if chance == 0 then
minetest.log("warning",
string.format("[mobs] %s has spawning disabled", name))
return
@ -3999,8 +3957,10 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
return
end
-- mobs cannot spawn in protected areas when enabled
if not spawn_protected
-- check if mob can spawn inside protected areas
if (spawn_protected == false
or (spawn_monster_protected == false
and minetest.registered_entities[name].type == "monster"))
and minetest.is_protected(pos, "") then
--print("--- inside protected area", name)
return
@ -4127,7 +4087,10 @@ function mobs:register_arrow(name, def)
minetest.register_entity(name, {
physical = false,
physical = def.physical or false,
collide_with_objects = def.collide_with_objects or false,
static_save = false,
visual = def.visual,
visual_size = def.visual_size,
textures = def.textures,
@ -4286,7 +4249,7 @@ function mobs:boom(self, pos, radius)
radius = radius,
damage_radius = radius,
sound = self.sounds and self.sounds.explode,
explode_center = true,
explode_center = true
})
else
mobs:safe_boom(self, pos, radius)
@ -4618,7 +4581,8 @@ function mobs:protect(self, clicker)
return true
end
if self.protected then
if (self.protected and tool_name == "mobs:protector")
or (self.protected == 2 and tool_name == "mobs:protector2") then
minetest.chat_send_player(name, S("Already protected!"))
return true
end
@ -4675,14 +4639,14 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
self.health = self.hp_max
if self.htimer < 1 then
-- 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)))
-- 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
-- self.htimer = 5
-- end
end
self.object:set_hp(self.health)
@ -4824,14 +4788,13 @@ function mobs:alias_mob(old_name, new_name)
-- entity
minetest.register_entity(":" .. old_name, {
physical = false,
physical = false, static_save = false,
on_activate = function(self, staticdata)
if minetest.registered_entities[new_name] then
minetest.add_entity(self.object:get_pos(),
new_name, staticdata)
minetest.add_entity(self.object:get_pos(), new_name, staticdata)
end
remove_mob(self)

View File

@ -56,6 +56,8 @@ functions needed for the mob to work properly which contains the following:
'view_range' how many nodes in distance the mob can see a player.
'damage' how many health points the mob does to a player or another
mob when melee attacking.
'damage_group' group in which damage is dealt, dedaults to "fleshy".
'damage_texture_modifier' applies texture modifier on hit e.g "^[brighten"
'knock_back' when true has mobs falling backwards when hit, the greater
the damage the more they move back.
'fear_height' is how high a cliff or edge has to be before the mob stops
@ -465,6 +467,8 @@ This function registers a arrow for mobs with the attack type shoot.
'visual' same is in minetest.register_entity()
'visual_size' same is in minetest.register_entity()
'textures' same is in minetest.register_entity()
'physical' same is in minetest.register_entity() [default: false]
'collide_with_objects' same as above
'velocity' the velocity of the arrow
'drop' if set to true any arrows hitting a node will drop as item
'hit_player' a function that is called when the arrow hits a player;
@ -695,6 +699,8 @@ External Settings for "minetest.conf"
is false)
'mobs_spawn_protected' if set to false then mobs will not spawn in protected
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
visual range will be removed (default is true)
'mobname' can change specific mob chance rate (0 to disable) and
@ -718,6 +724,7 @@ External Settings for "minetest.conf"
'mob_area_spawn' When true will check surrounding area the size of the
mob for obstructions before spawning, otherwise it
defaults to checking the height of the mob only.
'mob_smooth_rotate' Enables smooth rotation when mobs turn by default.
Players can override the spawn chance for each mob registered by adding a line
to their minetest.conf file with a new value, the lower the value the more each

View File

@ -10,9 +10,9 @@ minetest.register_craftitem("mobs:nametag", {
if minetest.get_modpath("dye") and minetest.get_modpath("farming") then
minetest.register_craft({
type = "shapeless",
-- type = "shapeless",
output = "mobs:nametag",
recipe = {"default:paper", "dye:black", "farming:string"}
recipe = {{"default:paper", "dye:black", "farming:string"}}
})
end
@ -299,12 +299,18 @@ minetest.register_tool(":mobs:mob_reset_stick", {
tex_obj = obj
-- get base texture
local bt = tex_obj:get_luaentity().base_texture[1]
if type(bt) ~= "string" then
bt = ""
end
local name = user:get_player_name()
local tex = ""
minetest.show_formspec(name, "mobs_texture", "size[8,4]"
.. "field[0.5,1;7.5,0;name;"
.. minetest.formspec_escape(S("Enter texture:")) .. ";" .. tex .. "]"
.. minetest.formspec_escape(S("Enter texture:")) .. ";" .. bt .. "]"
.. "button_exit[2.5,3.5;3,1;mob_texture_change;"
.. minetest.formspec_escape(S("Change")) .. "]")
end
@ -362,10 +368,10 @@ minetest.register_node("mobs:meatblock", {
minetest.register_craft({
output = "mobs:meatblock",
type = "shapeless",
-- type = "shapeless",
recipe = {
"group:food_meat", "group:food_meat", "group:food_meat",
"group:food_meat", "group:food_meat", "group:food_meat",
"group:food_meat", "group:food_meat", "group:food_meat"
{"group:food_meat", "group:food_meat", "group:food_meat"},
{"group:food_meat", "group:food_meat", "group:food_meat"},
{"group:food_meat", "group:food_meat", "group:food_meat"}
}
})

View File

@ -22,6 +22,7 @@ end
local function node_is(pos)
local node = node_ok(pos)
if node.name == "air" then
@ -69,6 +70,7 @@ end
local function force_detach(player)
local attached_to = player:get_attach()
if not attached_to then
@ -97,7 +99,9 @@ minetest.register_on_leaveplayer(function(player)
end)
minetest.register_on_shutdown(function()
local players = minetest.get_connected_players()
for i = 1, #players do
force_detach(players[i])
end
@ -112,6 +116,7 @@ end)
-- Just for correct detaching
local function find_free_pos(pos)
local check = {
{x = 1, y = 0, z = 0},
{x = 1, y = 1, z = 0},
@ -124,10 +129,14 @@ local function find_free_pos(pos)
}
for _, c in pairs(check) do
local npos = {x = pos.x + c.x, y = pos.y + c.y, z = pos.z + c.z}
local node = minetest.get_node_or_nil(npos)
if node and node.name then
local def = minetest.registered_nodes[node.name]
if def and not def.walkable and
def.liquidtype == "none" then
return npos
@ -141,6 +150,7 @@ end
-------------------------------------------------------------------------------
function mobs.attach(entity, player)
entity.player_rotation = entity.player_rotation or {x = 0, y = 0, z = 0}
entity.driver_attach_at = entity.driver_attach_at or {x = 0, y = 0, z = 0}
entity.driver_eye_offset = entity.driver_eye_offset or {x = 0, y = 0, z = 0}
@ -154,6 +164,7 @@ function mobs.attach(entity, player)
local attach_at = entity.driver_attach_at
local eye_offset = entity.driver_eye_offset
entity.driver = player
force_detach(player)
@ -170,6 +181,7 @@ function mobs.attach(entity, player)
})
minetest.after(0.2, function()
if player and player:is_player() then
player_api.set_animation(player, "sit", 30)
end
@ -183,9 +195,13 @@ function mobs.detach(player)
force_detach(player)
minetest.after(0.1, function()
if player and player:is_player() then
local pos = find_free_pos(player:get_pos())
pos.y = pos.y + 0.5
player:set_pos(pos)
end
end)
@ -193,8 +209,8 @@ end
function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
local yaw = entity.object:get_yaw() or 0
local yaw = entity.object:get_yaw() or 0
local rot_view = 0
if entity.player_rotation.y == 90 then
@ -208,14 +224,17 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
-- process controls
if entity.driver then
local ctrl = entity.driver:get_player_control()
-- move forwards
if ctrl.up then
entity.v = entity.v + entity.accel / 10
-- move backwards
elseif ctrl.down then
if entity.max_speed_reverse == 0 and entity.v == 0 then
return
end
@ -225,7 +244,9 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
-- mob rotation
local horz
if entity.alt_turn == true then
horz = yaw
if ctrl.left then
@ -243,21 +264,29 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
if can_fly then
-- fly up
if ctrl.jump then
velo.y = velo.y + 1
if velo.y > entity.accel then velo.y = entity.accel end
elseif velo.y > 0 then
velo.y = velo.y - 0.1
if velo.y < 0 then velo.y = 0 end
end
-- fly down
if ctrl.sneak then
velo.y = velo.y - 1
if velo.y < -entity.accel then velo.y = -entity.accel end
elseif velo.y < 0 then
velo.y = velo.y + 0.1
if velo.y > 0 then velo.y = 0 end
end
else
@ -274,6 +303,7 @@ 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
mobs:set_animation(entity, stand_anim)
end
@ -292,8 +322,10 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
entity.v = entity.v - 0.02 * s
if s ~= get_sign(entity.v) then
entity.object:set_velocity({x = 0, y = 0, z = 0})
entity.v = 0
return
end
@ -310,6 +342,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
-- Set position, velocity and acceleration
local p = entity.object:get_pos()
if not p then return end
local new_acce = {x = 0, y = -9.81, z = 0}
@ -320,18 +353,23 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
local v = entity.v
if ni == "air" then
if can_fly == true then
new_acce.y = 0
end
elseif ni == "liquid" or ni == "lava" then
if ni == "lava" and entity.lava_damage ~= 0 then
entity.lava_counter = (entity.lava_counter or 0) + dtime
if entity.lava_counter > 1 then
minetest.sound_play("default_punch", {
object = entity.object,
max_hear_distance = 5
})
}, true)
entity.object:punch(entity.object, 1.0, {
full_punch_interval = 1.0,
@ -343,11 +381,14 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
end
local terrain_type = entity.terrain_type
if terrain_type == 2 or terrain_type == 3 then
new_acce.y = 0
p.y = p.y + 1
if node_is(p) == "liquid" then
if velo.y >= 5 then
velo.y = 5
elseif velo.y < 0 then
@ -357,7 +398,9 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
end
else
if abs(velo.y) < 1 then
local pos = entity.object:get_pos()
if not pos then return end
pos.y = floor(pos.y) + 0.5
@ -371,6 +414,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
end
local new_velo = get_velocity(v, yaw - rot_view, velo.y)
new_acce.y = new_acce.y + acce_y
entity.object:set_velocity(new_velo)
@ -382,11 +426,14 @@ end
-- 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()
local velo = entity.object:get_velocity()
local dir = entity.driver:get_look_dir()
local yaw = entity.driver:get_look_horizontal() + 1.57 -- offset fix between old and new commands
if not ctrl or not velo then return end
if ctrl.up then
entity.object:set_velocity({
x = dir.x * speed,
@ -395,6 +442,7 @@ function mobs.fly(entity, _, speed, shoots, arrow, moving_anim, stand_anim)
})
elseif ctrl.down then
entity.object:set_velocity({
x = -dir.x * speed,
y = dir.y * speed + 2,
@ -409,6 +457,7 @@ function mobs.fly(entity, _, speed, shoots, arrow, moving_anim, stand_anim)
-- firing arrows
if ctrl.LMB and ctrl.sneak and shoots then
local pos = entity.object:get_pos()
local obj = minetest.add_entity({
x = pos.x + 0 + dir.x * 2.5,
@ -416,11 +465,15 @@ function mobs.fly(entity, _, speed, shoots, arrow, moving_anim, stand_anim)
z = pos.z + 0 + dir.z * 2.5}, arrow)
local ent = obj:get_luaentity()
if ent then
ent.switch = 1 -- for mob specific arrows
ent.owner_id = tostring(entity.object) -- so arrows dont hurt entity you are riding
local vec = {x = dir.x * 6, y = dir.y * 6, z = dir.z * 6}
yaw = entity.driver:get_look_horizontal()
obj:set_yaw(yaw + pi / 2)
obj:set_velocity(vec)
else

View File

@ -13,6 +13,9 @@ mobs_griefing (Griefing Mobs) bool true
# If false then Mobs no longer spawn inside player protected areas
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
remove_far_mobs (Remove far Mobs) bool true
@ -39,3 +42,6 @@ mob_area_spawn (Mob Area Spawn) bool false
# Enable peaceful player attack prevention
enable_peaceful_player (Mobs do not attack peaceful player without reason) bool false
# Enable mobs smooth rotation
mob_smooth_rotate (Smooth rotation for mobs) bool true

View File

@ -1245,6 +1245,11 @@ mob_area_spawn (Mob Area Spawn) bool false
# Enable peaceful player attack prevention
enable_peaceful_player (Mobs do not attack peaceful player without reason) bool false
# If false then Monsters no longer spawn inside player protected areas
mobs_spawn_monster_protected (Spawn Monsters in protected areas) bool true
# Enable mobs smooth rotation
mob_smooth_rotate (Smooth rotation for mobs) bool true
[**cmer]