parent
d66f8f2b6d
commit
6a32824066
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
||||
|
|
Loading…
Reference in New Issue