Merge pull request 'Mob Fixes' (#3242) from mob_fixes into master

Reviewed-on: https://git.minetest.land/MineClone2/MineClone2/pulls/3242
Reviewed-by: Michieal <michieal@noreply.git.minetest.land>
This commit is contained in:
ancientmarinerdev 2023-01-11 01:11:07 +00:00
commit 2ed3c1c480
11 changed files with 150 additions and 55 deletions

@ -306,7 +306,7 @@ function mob_class:do_states(dtime)
end end
local function update_timers (self, dtime) local function update_timers (self, dtime)
-- knockback timer -- knockback timer. set in on_punch
if self.pause_timer > 0 then if self.pause_timer > 0 then
self.pause_timer = self.pause_timer - dtime self.pause_timer = self.pause_timer - dtime
return true return true
@ -330,17 +330,15 @@ end
-- main mob function -- main mob function
function mob_class:on_step(dtime) function mob_class:on_step(dtime)
self.lifetimer = self.lifetimer - dtime
local pos = self.object:get_pos() local pos = self.object:get_pos()
if not pos then return end if not pos then return end
if self:check_despawn(pos) then return true end if self:check_despawn(pos, dtime) then return true end
self:slow_mob() self:slow_mob()
if self:falling(pos) then return end if self:falling(pos) then return end
self:check_suspend() self:check_suspend()
self:check_water_flow() self:check_water_flow()
self:env_danger_movement_checks (dtime) self:env_danger_movement_checks (dtime)
@ -355,21 +353,17 @@ function mob_class:on_step(dtime)
if self.state == "die" then return end if self.state == "die" then return end
if self.jump_sound_cooloff > 0 then self:follow_flop() -- Mob following code.
self.jump_sound_cooloff = self.jump_sound_cooloff - dtime
end
if self.opinion_sound_cooloff > 0 then
self.opinion_sound_cooloff = self.opinion_sound_cooloff - dtime
end
--Mob following code. self:set_animation_speed() -- set animation speed relitive to velocity
self:follow_flop()
--set animation speed relitive to velocity
self:set_animation_speed()
self:check_smooth_rotation(dtime) self:check_smooth_rotation(dtime)
self:check_head_swivel(dtime) self:check_head_swivel(dtime)
if self.jump_sound_cooloff > 0 then
self.jump_sound_cooloff = self.jump_sound_cooloff - dtime
end
self:do_jump() self:do_jump()
self:set_armor_texture() self:set_armor_texture()
self:check_runaway_from() self:check_runaway_from()
@ -390,6 +384,9 @@ function mob_class:on_step(dtime)
self:check_particlespawners(dtime) self:check_particlespawners(dtime)
self:check_item_pickup() self:check_item_pickup()
if self.opinion_sound_cooloff > 0 then
self.opinion_sound_cooloff = self.opinion_sound_cooloff - dtime
end
-- mob plays random sound at times. Should be 120. Zombie and mob farms are ridiculous -- mob plays random sound at times. Should be 120. Zombie and mob farms are ridiculous
if math.random(1, 70) == 1 then if math.random(1, 70) == 1 then
self:mob_sound("random", true) self:mob_sound("random", true)

@ -280,30 +280,55 @@ local function dir_to_pitch(dir)
return -math.atan2(-dir.y, xz) return -math.atan2(-dir.y, xz)
end end
function mob_class:check_head_swivel(dtime) local function who_are_you_looking_at (self)
if not self.head_swivel or type(self.head_swivel) ~= "string" then return end
local final_rotation = vector.new(0,0,0)
local oldp,oldr = self.object:get_bone_position(self.head_swivel)
local pos = self.object:get_pos() local pos = self.object:get_pos()
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 10)) do local stop_look_at_player_chance = math.random(833/self.curiosity)
if obj:is_player() and not self.attack or obj:get_luaentity() and obj:get_luaentity().name == self.name and self ~= obj:get_luaentity() then -- was 10000 - div by 12 for avg entities as outside loop
if not self._locked_object then
if math.random(5000/self.curiosity) == 1 or vector.distance(pos,obj:get_pos())<4 and obj:is_player() then local stop_look_at_player = stop_look_at_player_chance == 1
self._locked_object = obj
end
else
if math.random(10000/self.curiosity) == 1 then
self._locked_object = nil
end
end
end
end
if self.attack or self.following then if self.attack or self.following then
self._locked_object = self.attack or self.following self._locked_object = self.attack or self.following
elseif self._locked_object then
if stop_look_at_player then
--minetest.log("Stop look: ".. self.name)
self._locked_object = nil
end end
elseif not self._locked_object then
if math.random(1, 30) then
--minetest.log("Change look check: ".. self.name)
local look_at_player_chance = math.random(20/self.curiosity)
-- was 5000 but called in loop based on entities. so div by 12 as estimate avg of entities found,
-- then div by 20 as less freq lookup
local look_at_player = look_at_player_chance == 1
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 8)) do
if obj:is_player() and vector.distance(pos,obj:get_pos()) < 4 then
--minetest.log("Change look to player: ".. self.name)
self._locked_object = obj
break
elseif obj:is_player() or (obj:get_luaentity() and obj:get_luaentity().name == self.name and self ~= obj:get_luaentity()) then
if look_at_player then
--minetest.log("Change look to mob: ".. self.name)
self._locked_object = obj
break
end
end
end
end
end
end
function mob_class:check_head_swivel(dtime)
if not self.head_swivel or type(self.head_swivel) ~= "string" then return end
who_are_you_looking_at (self)
local final_rotation = vector.new(0,0,0)
local oldp,oldr = self.object:get_bone_position(self.head_swivel)
if self._locked_object and (self._locked_object:is_player() or self._locked_object:get_luaentity()) and self._locked_object:get_hp() > 0 then if self._locked_object and (self._locked_object:is_player() or self._locked_object:get_luaentity()) and self._locked_object:get_hp() > 0 then
local _locked_object_eye_height = 1.5 local _locked_object_eye_height = 1.5
@ -318,6 +343,7 @@ function mob_class:check_head_swivel(dtime)
if self.object:get_attach() then if self.object:get_attach() then
self_rot = self.object:get_attach():get_rotation() self_rot = self.object:get_attach():get_rotation()
end end
if self.rot then if self.rot then
local player_pos = self._locked_object:get_pos() local player_pos = self._locked_object:get_pos()
local direction_player = vector.direction(vector.add(self.object:get_pos(), vector.new(0, self.head_eye_height*.7, 0)), vector.add(player_pos, vector.new(0, _locked_object_eye_height, 0))) local direction_player = vector.direction(vector.add(self.object:get_pos(), vector.new(0, self.head_eye_height*.7, 0)), vector.add(player_pos, vector.new(0, _locked_object_eye_height, 0)))
@ -346,7 +372,7 @@ function mob_class:check_head_swivel(dtime)
elseif not self._locked_object and math.abs(oldr.y) > 3 and math.abs(oldr.x) < 3 then elseif not self._locked_object and math.abs(oldr.y) > 3 and math.abs(oldr.x) < 3 then
final_rotation = vector.multiply(oldr, 0.9) final_rotation = vector.multiply(oldr, 0.9)
else else
final_rotation = vector.new(0,0,0) --final_rotation = vector.new(0,0,0)
end end
mcl_util.set_bone_position(self.object,self.head_swivel, vector.new(0,self.bone_eye_height,self.horrizonatal_head_height), final_rotation) mcl_util.set_bone_position(self.object,self.head_swivel, vector.new(0,self.bone_eye_height,self.horrizonatal_head_height), final_rotation)

@ -244,6 +244,24 @@ local function count_mobs_total(mob_type)
return num return num
end end
local function count_mobs_all()
local mobs_found = {}
local num = 0
for _,entity in pairs(minetest.luaentities) do
if entity.is_mob then
local mob_type = entity.type -- animal / monster / npc
local mob_name = entity.name
if mobs_found[mob_name] then
mobs_found[mob_name] = mobs_found[mob_name] + 1
else
mobs_found[mob_name] = 1
end
num = num + 1
end
end
return mobs_found, num
end
local function count_mobs_total_cap(mob_type) local function count_mobs_total_cap(mob_type)
local num = 0 local num = 0
for _,l in pairs(minetest.luaentities) do for _,l in pairs(minetest.luaentities) do
@ -628,6 +646,9 @@ if mobs_spawn then
local perlin_noise local perlin_noise
-- Get pos to spawn, x and z are randomised, y is range
local function spawn_a_mob(pos, dimension, y_min, y_max) local function spawn_a_mob(pos, dimension, y_min, y_max)
--create a disconnected clone of the spawn dictionary --create a disconnected clone of the spawn dictionary
--prevents memory leak --prevents memory leak
@ -722,7 +743,9 @@ if mobs_spawn then
end) end)
end end
function mob_class:check_despawn(pos) function mob_class:check_despawn(pos, dtime)
self.lifetimer = self.lifetimer - dtime
-- Despawning: when lifetimer expires, remove mob -- Despawning: when lifetimer expires, remove mob
if remove_far if remove_far
and self.can_despawn == true and self.can_despawn == true
@ -755,5 +778,18 @@ minetest.register_chatcommand("mobstats",{
minetest.chat_send_player(n,"total mobs:"..count_mobs_total()) minetest.chat_send_player(n,"total mobs:"..count_mobs_total())
minetest.chat_send_player(n,"spawning attempts since server start:"..dbg_spawn_attempts) minetest.chat_send_player(n,"spawning attempts since server start:"..dbg_spawn_attempts)
minetest.chat_send_player(n,"successful spawns since server start:"..dbg_spawn_succ) minetest.chat_send_player(n,"successful spawns since server start:"..dbg_spawn_succ)
local mob_counts, total_mobs = count_mobs_all()
if (total_mobs) then
minetest.log("action", "Total mobs found: " .. total_mobs)
end
if mob_counts then
for k, v1 in pairs(mob_counts) do
minetest.log("action", "k: " .. tostring(k))
minetest.log("action", "v1: " .. tostring(v1))
end
end
end end
}) })

@ -12,13 +12,13 @@ mcl_mobs.register_mob("mobs_mc:chicken", {
description = S("Chicken"), description = S("Chicken"),
type = "animal", type = "animal",
spawn_class = "passive", spawn_class = "passive",
passive = true,
runaway = true,
hp_min = 4, hp_min = 4,
hp_max = 4, hp_max = 4,
xp_min = 1, xp_min = 1,
xp_max = 3, xp_max = 3,
collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.69, 0.2}, collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.69, 0.2},
runaway = true,
floats = 1, floats = 1,
head_swivel = "head.control", head_swivel = "head.control",
bone_eye_height = 4, bone_eye_height = 4,

@ -7,6 +7,7 @@ local cow_def = {
type = "animal", type = "animal",
spawn_class = "passive", spawn_class = "passive",
passive = true, passive = true,
runaway = true,
hp_min = 10, hp_min = 10,
hp_max = 10, hp_max = 10,
xp_min = 1, xp_min = 1,
@ -40,7 +41,6 @@ local cow_def = {
max = 2, max = 2,
looting = "common",}, looting = "common",},
}, },
runaway = true,
sounds = { sounds = {
random = "mobs_mc_cow", random = "mobs_mc_cow",
damage = "mobs_mc_cow_hurt", damage = "mobs_mc_cow_hurt",

@ -259,6 +259,7 @@ mcl_mobs.register_mob("mobs_mc:enderman", {
description = S("Enderman"), description = S("Enderman"),
type = "monster", type = "monster",
spawn_class = "passive", spawn_class = "passive",
can_despawn = true,
passive = true, passive = true,
pathfinding = 1, pathfinding = 1,
hp_min = 40, hp_min = 40,
@ -442,6 +443,7 @@ mcl_mobs.register_mob("mobs_mc:enderman", {
end end
end end
end end
-- TAKE AND PLACE STUFF BEHAVIOUR BELOW. -- TAKE AND PLACE STUFF BEHAVIOUR BELOW.
if not mobs_griefing then if not mobs_griefing then
return return
@ -469,6 +471,7 @@ mcl_mobs.register_mob("mobs_mc:enderman", {
local dug = minetest.get_node_or_nil(take_pos) local dug = minetest.get_node_or_nil(take_pos)
if dug and dug.name == "air" then if dug and dug.name == "air" then
self._taken_node = node.name self._taken_node = node.name
self.can_despawn = false
local def = minetest.registered_nodes[self._taken_node] local def = minetest.registered_nodes[self._taken_node]
-- Update animation and texture accordingly (adds visibly carried block) -- Update animation and texture accordingly (adds visibly carried block)
local block_type local block_type
@ -519,6 +522,7 @@ mcl_mobs.register_mob("mobs_mc:enderman", {
if success then if success then
local def = minetest.registered_nodes[self._taken_node] local def = minetest.registered_nodes[self._taken_node]
-- Update animation accordingly (removes visible block) -- Update animation accordingly (removes visible block)
self.can_despawn = true
self.animation = select_enderman_animation("normal") self.animation = select_enderman_animation("normal")
self:set_animation(self.animation.current) self:set_animation(self.animation.current)
if def.sounds and def.sounds.place then if def.sounds and def.sounds.place then

@ -6,6 +6,7 @@ mcl_mobs.register_mob("mobs_mc:pig", {
description = S("Pig"), description = S("Pig"),
type = "animal", type = "animal",
spawn_class = "passive", spawn_class = "passive",
passive = true,
runaway = true, runaway = true,
hp_min = 10, hp_min = 10,
hp_max = 10, hp_max = 10,

@ -56,6 +56,7 @@ mcl_mobs.register_mob("mobs_mc:sheep", {
description = S("Sheep"), description = S("Sheep"),
type = "animal", type = "animal",
spawn_class = "passive", spawn_class = "passive",
passive = true,
hp_min = 8, hp_min = 8,
hp_max = 8, hp_max = 8,
xp_min = 1, xp_min = 1,

@ -1930,8 +1930,6 @@ end)
--[=======[ MOB REGISTRATION AND SPAWNING ]=======] --[=======[ MOB REGISTRATION AND SPAWNING ]=======]
local pick_up = { "mcl_farming:bread", "mcl_farming:carrot_item", "mcl_farming:beetroot_item" , "mcl_farming:potato_item" }
mcl_mobs.register_mob("mobs_mc:villager", { mcl_mobs.register_mob("mobs_mc:villager", {
description = S("Villager"), description = S("Villager"),
type = "npc", type = "npc",
@ -1976,7 +1974,7 @@ mcl_mobs.register_mob("mobs_mc:villager", {
head_shake_start = 131, head_shake_end = 141, head_shake_loop = false, head_shake_start = 131, head_shake_end = 141, head_shake_loop = false,
head_nod_start = 121, head_nod_end = 131, head_nod_loop = false, head_nod_start = 121, head_nod_end = 131, head_nod_loop = false,
}, },
follow = pick_up, follow = { "mcl_farming:bread", "mcl_farming:carrot_item", "mcl_farming:beetroot_item" , "mcl_farming:potato_item" },
nofollow = true, nofollow = true,
view_range = 16, view_range = 16,
fear_height = 4, fear_height = 4,
@ -1986,7 +1984,7 @@ mcl_mobs.register_mob("mobs_mc:villager", {
_id = nil, _id = nil,
_profession = "unemployed", _profession = "unemployed",
look_at_player = true, look_at_player = true,
pick_up = pick_up, pick_up = { "mcl_farming:bread", "mcl_farming:carrot_item", "mcl_farming:beetroot_item" , "mcl_farming:potato_item" },
can_open_doors = true, can_open_doors = true,
on_pick_up = function(self,itementity) on_pick_up = function(self,itementity)
local clicker local clicker
@ -2003,6 +2001,7 @@ mcl_mobs.register_mob("mobs_mc:villager", {
return it return it
end, end,
on_rightclick = function(self, clicker) on_rightclick = function(self, clicker)
--minetest.log("In villager right click")
if self.child or self._profession == "unemployed" or self._profession == "nitwit" then if self.child or self._profession == "unemployed" or self._profession == "nitwit" then
self.order = nil self.order = nil
return return

@ -109,6 +109,7 @@ mcl_mobs.register_mob("mobs_mc:villager_zombie", {
clicker:set_wielded_item(wielditem) clicker:set_wielded_item(wielditem)
self._curing = math.random(3 * 60, 5 * 60) self._curing = math.random(3 * 60, 5 * 60)
self.shaking = true self.shaking = true
self.can_despawn = false
end end
end end
end, end,

@ -22,6 +22,8 @@ local DEBUG = false
local enable_burger = minetest.settings:get_bool("mcl_enable_hamburger",true) local enable_burger = minetest.settings:get_bool("mcl_enable_hamburger",true)
local use_alt = minetest.settings:get_bool("mcl_hamburger_alt_texture",false) local use_alt = minetest.settings:get_bool("mcl_hamburger_alt_texture",false)
local HAMBURGER_NAME = "mcl_hamburger:hamburger"
mcl_hamburger = {} mcl_hamburger = {}
if DEBUG then if DEBUG then
@ -32,12 +34,12 @@ end
function mcl_hamburger.register_burger_craft(cooked_meat) function mcl_hamburger.register_burger_craft(cooked_meat)
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "mcl_hamburger:hamburger", recipe = HAMBURGER_NAME,
burntime = 2, burntime = 2,
}) })
minetest.register_craft({ minetest.register_craft({
output = "mcl_hamburger:hamburger", output = HAMBURGER_NAME,
recipe = { recipe = {
{ "mcl_farming:bread"}, { "mcl_farming:bread"},
{ cooked_meat }, -- "mcl_mobitems:cooked_beef" for a reg hamburger. Grind up clowns for a Big Mac. { cooked_meat }, -- "mcl_mobitems:cooked_beef" for a reg hamburger. Grind up clowns for a Big Mac.
@ -45,7 +47,7 @@ function mcl_hamburger.register_burger_craft(cooked_meat)
}, },
}) })
minetest.register_craft({ minetest.register_craft({
output = "mcl_hamburger:hamburger", output = HAMBURGER_NAME,
recipe = { recipe = {
-- "mcl_mobitems:cooked_beef" for a reg hamburger. Grind up clowns for a Big Mac. -- "mcl_mobitems:cooked_beef" for a reg hamburger. Grind up clowns for a Big Mac.
{ "mcl_farming:bread", cooked_meat, "mcl_farming:bread"}, { "mcl_farming:bread", cooked_meat, "mcl_farming:bread"},
@ -72,23 +74,23 @@ if not enable_burger then
end end
if use_alt == false then if use_alt == false then
minetest.register_craftitem("mcl_hamburger:hamburger", hamburger_def) minetest.register_craftitem(HAMBURGER_NAME, hamburger_def)
else else
local hamburger_alt = table.copy(hamburger_def) local hamburger_alt = table.copy(hamburger_def)
hamburger_alt.inventory_image = "mcl_hamburger_alt.png" hamburger_alt.inventory_image = "mcl_hamburger_alt.png"
hamburger_alt.wield_image = "mcl_hamburger_alt.png" hamburger_alt.wield_image = "mcl_hamburger_alt.png"
minetest.register_craftitem("mcl_hamburger:hamburger", hamburger_alt) minetest.register_craftitem(HAMBURGER_NAME, hamburger_alt)
end end
local function register_achievements() local function register_achievements()
awards.register_achievement("mcl_hamburger:hamburger", { awards.register_achievement(HAMBURGER_NAME, {
title = S("Burger Time!"), title = S("Burger Time!"),
description = S("Craft a Hamburger."), description = S("Craft a Hamburger."),
icon = "mcl_hamburger_alt.png", icon = "mcl_hamburger_alt.png",
trigger = { trigger = {
type = "craft", type = "craft",
item = "mcl_hamburger:hamburger", item = HAMBURGER_NAME,
target = 1 target = 1
}, },
type = "Advancement", type = "Advancement",
@ -101,19 +103,47 @@ local function register_doc_entry()
-- register Doc entry -- register Doc entry
if minetest.get_modpath("doc") then if minetest.get_modpath("doc") then
doc.add_entry_alias("craftitems", "mcl_hamburger:hamburger", "craftitems", "mcl_hamburger:hamburger") doc.add_entry_alias("craftitems", HAMBURGER_NAME, "craftitems", HAMBURGER_NAME)
end end
end end
if enable_burger then if enable_burger then
-- make the villagers follow the item -- make the villagers follow the item
minetest.registered_entities["mobs_mc:villager"].nofollow = false local villager = minetest.registered_entities["mobs_mc:villager"]
-- add it to the follow items.
table.insert(minetest.registered_entities["mobs_mc:villager"].follow,"mcl_hamburger:hamburger") table.insert(villager.follow, HAMBURGER_NAME)
-- register the item and crafting recipe.
local original_rightclick = villager.on_rightclick
local new_on_rightclick = function(self, clicker)
--minetest.log("In wrapper function")
local item = clicker:get_wielded_item()
if item:get_name() == HAMBURGER_NAME then
if self.nofollow == true then
--minetest.log("Turn off nofollow")
self.nofollow = false
elseif self.nofollow == false then
--minetest.log("Turn on nofollow")
self.nofollow = true
end
else
--minetest.log("Not holding burger")
if self.nofollow == false then
--minetest.log("Turn on nofollow")
self.nofollow = true
end
original_rightclick(self, clicker)
end
--minetest.log("Finishing wrapper")
end
villager.on_rightclick = new_on_rightclick
mcl_hamburger.register_burger_craft("mcl_mobitems:cooked_beef") mcl_hamburger.register_burger_craft("mcl_mobitems:cooked_beef")
-- add in the super cool achievement(s)! minetest.register_alias("hamburger", HAMBURGER_NAME)
register_achievements() register_achievements()
register_doc_entry() register_doc_entry()
end end