From 818052dc6cf89cdc33fd5ff2fab91b00052d0324 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 12 May 2023 14:27:02 +0100 Subject: [PATCH 1/7] Fix mob textures getting reset on shutdown/startup --- mods/ENTITIES/mcl_mobs/api.lua | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index a5af89690..9c0beaeec 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -111,6 +111,21 @@ function mob_class:get_staticdata() return minetest.serialize(tmp) end +local function valid_texture(self, def_textures) + if not self.base_texture then + return false + end + + if self.texture_selected then + if #def_textures < self.texture_selected then + self.texture_selected = nil + else + return true + end + end + return false +end + function mob_class:mob_activate(staticdata, def, dtime) if not self.object:get_pos() or staticdata == "remove" then mcl_burning.extinguish(self.object) @@ -133,16 +148,20 @@ function mob_class:mob_activate(staticdata, def, dtime) end --If textures in definition change, reload textures - if not self.base_texture or (def.textures and table.indexof(def.textures, self.base_texture) == -1) then + if not valid_texture(self, def.textures) then + -- compatiblity with old simple mobs textures if type(def.textures[1]) == "string" then def.textures = {def.textures} end - local c = 1 - if #def.textures > c then c = #def.textures end + if not self.texture_selected then + local c = 1 + if #def.textures > c then c = #def.textures end + self.texture_selected = math.random(c) + end - self.base_texture = def.textures[math.random(c)] + self.base_texture = def.textures[self.texture_selected] self.base_mesh = def.mesh self.base_size = self.visual_size self.base_colbox = self.collisionbox From 72c3f87925bc08f6d07869cca1ac4ae171eb44ab Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 12 May 2023 15:33:49 +0100 Subject: [PATCH 2/7] Reduce excessive mob overhead --- mods/ENTITIES/mcl_mobs/api.lua | 7 +++++-- mods/ENTITIES/mcl_mobs/effects.lua | 6 +++--- mods/ENTITIES/mcl_mobs/movement.lua | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 9c0beaeec..092c8939c 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -407,8 +407,11 @@ local function on_step_work (self, dtime) self:check_water_flow() self:env_danger_movement_checks (dtime) - -- Follow code is heavy and probably shouldn't run when not in range, but we need to extract the cancel follow stuff - self:check_follow() + if player_in_active_range then + if mcl_util.check_dtime_timer(self, dtime, "onstep_follow", 0.2) then + self:check_follow() + end + end self:flop() self:check_smooth_rotation(dtime) diff --git a/mods/ENTITIES/mcl_mobs/effects.lua b/mods/ENTITIES/mcl_mobs/effects.lua index 696994d0d..1a1578834 100644 --- a/mods/ENTITIES/mcl_mobs/effects.lua +++ b/mods/ENTITIES/mcl_mobs/effects.lua @@ -269,7 +269,7 @@ function mob_class:set_animation(anim, fixed_frame) - if self:flight_check() and self.fly and anim == "walk" then anim = "fly" end + if self.fly and self:flight_check() and anim == "walk" then anim = "fly" end self._current_animation = self._current_animation or "" @@ -324,12 +324,12 @@ local function who_are_you_looking_at (self) self._locked_object = nil end elseif not self._locked_object then - if math.random(1, 30) then + if mcl_util.check_dtime_timer(self, dtime, "step_look_for_someone", 0.2) then --minetest.log("Change look check: ".. self.name) -- For the wither this was 20/60=0.33, so probably need to rebalance and divide rates. -- but frequency of check isn't good as it is costly. Making others too infrequent requires testing - local chance = 20/self.curiosity + local chance = 150/self.curiosity if chance < 1 then chance = 1 end local look_at_player_chance = math.random(chance) diff --git a/mods/ENTITIES/mcl_mobs/movement.lua b/mods/ENTITIES/mcl_mobs/movement.lua index 469ac9e85..21595ef54 100644 --- a/mods/ENTITIES/mcl_mobs/movement.lua +++ b/mods/ENTITIES/mcl_mobs/movement.lua @@ -623,7 +623,7 @@ function mob_class:check_runaway_from() end --- follow player if owner or holding item, if fish outta water then flop +-- follow player if owner or holding item function mob_class:check_follow() -- find player to follow if (self.follow ~= "" or self.order == "follow") and not self.following From 519b237ba85d570d28d2f905e3341bfbe113afde Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 12 May 2023 19:42:55 +0100 Subject: [PATCH 3/7] Jumping check only called once per mob_step and refactor duplicate water danger, cliff fall logic --- mods/ENTITIES/mcl_mobs/api.lua | 27 ++++++----- mods/ENTITIES/mcl_mobs/movement.lua | 75 ++++++++++++++--------------- 2 files changed, 52 insertions(+), 50 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 092c8939c..485ea1f65 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -325,6 +325,8 @@ function mob_class:do_states(dtime) return end + self:env_danger_movement_checks (dtime) + if self.state == PATHFINDING then self:check_gowp(dtime) elseif self.state == "attack" then @@ -405,13 +407,13 @@ local function on_step_work (self, dtime) -- End: Death/damage processing self:check_water_flow() - self:env_danger_movement_checks (dtime) - if player_in_active_range then - if mcl_util.check_dtime_timer(self, dtime, "onstep_follow", 0.2) then - self:check_follow() - end + if not self._jumping_cliff then + self._can_jump_cliff = self:can_jump_cliff() + else + self._can_jump_cliff = false end + self:flop() self:check_smooth_rotation(dtime) @@ -421,14 +423,17 @@ local function on_step_work (self, 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:check_runaway_from() - self:monster_attack() - self:npc_attack() + if mcl_util.check_dtime_timer(self, dtime, "onstep_engage", 0.2) then + self:check_follow() + self:check_runaway_from() + self:monster_attack() + self:npc_attack() + end self:check_herd(dtime) + + if self.jump_sound_cooloff > 0 then self.jump_sound_cooloff = self.jump_sound_cooloff - dtime end + self:do_jump() end self:check_aggro(dtime) diff --git a/mods/ENTITIES/mcl_mobs/movement.lua b/mods/ENTITIES/mcl_mobs/movement.lua index 21595ef54..147930b87 100644 --- a/mods/ENTITIES/mcl_mobs/movement.lua +++ b/mods/ENTITIES/mcl_mobs/movement.lua @@ -4,8 +4,9 @@ local DEFAULT_FALL_SPEED = -9.81*1.5 local FLOP_HEIGHT = 6 local FLOP_HOR_SPEED = 1.5 -local node_snow = "mcl_core:snow" +local CHECK_HERD_FREQUENCY = 4 +local node_snow = "mcl_core:snow" local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false @@ -202,12 +203,8 @@ function mob_class:can_jump_cliff() end -- is mob facing a cliff or danger -function mob_class:is_at_cliff_or_danger(can_jump_cliff) - if can_jump_cliff == nil then - can_jump_cliff = self:can_jump_cliff() - end - - if self.fear_height == 0 or can_jump_cliff or self._jumping_cliff or not self.object:get_luaentity() then -- 0 for no falling protection! +function mob_class:is_at_cliff_or_danger() + if self.fear_height == 0 or self._jumping_cliff or self._can_jump_cliff or not self.object:get_luaentity() then -- 0 for no falling protection! return false end @@ -242,12 +239,16 @@ end -- copy the 'mob facing cliff_or_danger check' from above, and rework to avoid water -function mob_class:is_at_water_danger(can_jump_cliff) - if can_jump_cliff == nil then - can_jump_cliff = self:can_jump_cliff() +function mob_class:is_at_water_danger() + if self.water_damage == 0 and self.breath_max == -1 then + --minetest.log("Do not need a water check for: " .. self.name) + return end - if not self.object:get_luaentity() or can_jump_cliff or self._jumping_cliff then + local in_water_danger = self:is_node_waterhazard(self.standing_in) or self:is_node_waterhazard(self.standing_on) + if in_water_danger then return false end -- If you're in trouble, do not stop + + if not self.object:get_luaentity() or self._jumping_cliff or self._can_jump_cliff then return false end local yaw = self.object:get_yaw() @@ -262,25 +263,16 @@ function mob_class:is_at_water_danger(can_jump_cliff) local ypos = pos.y + self.collisionbox[2] -- just above floor - local free_fall, blocker = minetest.line_of_sight( + local los, blocker = minetest.line_of_sight( vector.new(pos.x + dir_x, ypos, pos.z + dir_z), vector.new(pos.x + dir_x, ypos - 3, pos.z + dir_z)) - if free_fall then - return true - else + if not los then local bnode = minetest.get_node(blocker) local waterdanger = self:is_node_waterhazard(bnode.name) - if - waterdanger and (self:is_node_waterhazard(self.standing_in) or self:is_node_waterhazard( self.standing_on)) then - return false - elseif waterdanger and (self:is_node_waterhazard(self.standing_in) or self:is_node_waterhazard(self.standing_on)) == false then + + if waterdanger and not in_water_danger then return true - else - local def = minetest.registered_nodes[bnode.name] - if def and def.walkable then - return false - end end end @@ -290,24 +282,29 @@ end function mob_class:env_danger_movement_checks(dtime) local yaw = 0 - local can_jump_cliff = self:can_jump_cliff() - if self.state ~= "attack" and self:is_at_water_danger(can_jump_cliff) then - if math.random(1, 10) <= 6 then - self:set_velocity(0) - self.state = "stand" - self:set_animation( "stand") + if self.state ~= "attack" and self:is_at_water_danger() then + --minetest.log("At water danger for mob, stop?: " .. self.name) + if math.random(1, 10) <= 7 then + if self.state ~= "stand" then + self:set_velocity(0) + self.state = "stand" + self:set_animation( "stand") + end yaw = yaw + math.random(-0.5, 0.5) yaw = self:set_yaw( yaw, 8) + return end end - if self:is_at_cliff_or_danger(can_jump_cliff) then - self:set_velocity(0) - self.state = "stand" - self:set_animation( "stand") + --[[if self:is_at_cliff_or_danger(can_jump_cliff) then + if self.state ~= "stand" then + self:set_velocity(0) + self.state = "stand" + self:set_animation( "stand") + end local yaw = self.object:get_yaw() or 0 yaw = self:set_yaw( yaw + 0.78, 8) - end + end--]] end -- jump if facing a solid node (not fences or gates) @@ -378,7 +375,7 @@ function mob_class:do_jump() end local ndef = minetest.registered_nodes[nod.name] - if self.walk_chance == 0 or ndef and ndef.walkable or self:can_jump_cliff() then + if self.walk_chance == 0 or ndef and ndef.walkable or self._can_jump_cliff then if minetest.get_item_group(nod.name, "fence") == 0 and minetest.get_item_group(nod.name, "fence_gate") == 0 @@ -388,7 +385,7 @@ function mob_class:do_jump() v.y = self.jump_height + 0.1 * 3 - if self:can_jump_cliff() then + if self._can_jump_cliff then v=vector.multiply(v, vector.new(2.8,1,2.8)) end @@ -724,7 +721,7 @@ function mob_class:flop() return elseif self.state == "flop" then self.state = "stand" - self.object:set_acceleration({x = 0, y = 0, z = 0}) + self.object:set_acceleration(vector.zero()) self:set_velocity(0) end end @@ -756,7 +753,7 @@ function mob_class:check_herd(dtime) if self.move_in_group == false then return end check_herd_timer = check_herd_timer + dtime - if check_herd_timer < 4 then return end + if check_herd_timer < CHECK_HERD_FREQUENCY then return end check_herd_timer = 0 for _,o in pairs(minetest.get_objects_inside_radius(pos,self.view_range)) do local l = o:get_luaentity() From 3d1fb8cf4af394e42263ccb3f994a14988740584 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 12 May 2023 20:17:13 +0100 Subject: [PATCH 4/7] Clean up and optimise falling --- mods/ENTITIES/mcl_mobs/physics.lua | 37 +++++++++++------------------- 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/physics.lua b/mods/ENTITIES/mcl_mobs/physics.lua index 2859cfe98..55199d9f3 100644 --- a/mods/ENTITIES/mcl_mobs/physics.lua +++ b/mods/ENTITIES/mcl_mobs/physics.lua @@ -903,47 +903,36 @@ function mob_class:falling(pos) -- floating in water (or falling) local v = self.object:get_velocity() if v then + local new_acceleration + if v.y > 0 then -- apply gravity when moving up - self.object:set_acceleration({ - x = 0, - y = DEFAULT_FALL_SPEED, - z = 0 - }) - + new_acceleration = vector.new(0, DEFAULT_FALL_SPEED, 0) elseif v.y <= 0 and v.y > self.fall_speed then -- fall downwards at set speed - self.object:set_acceleration({ - x = 0, - y = self.fall_speed, - z = 0 - }) + new_acceleration = vector.new(0, self.fall_speed, 0) else -- stop accelerating once max fall speed hit - self.object:set_acceleration({x = 0, y = 0, z = 0}) + new_acceleration =vector.zero() end + + self.object:set_acceleration(new_acceleration) end local acc = self.object:get_acceleration() - if minetest.registered_nodes[node_ok(pos).name].groups.lava then + local registered_node = minetest.registered_nodes[node_ok(pos).name] + + if registered_node.groups.lava then if acc and self.floats_on_lava == 1 then - self.object:set_acceleration({ - x = 0, - y = -self.fall_speed / (math.max(1, v.y) ^ 2), - z = 0 - }) + self.object:set_acceleration(vector.new(0, -self.fall_speed / (math.max(1, v.y) ^ 2), 0)) end end -- in water then float up - if minetest.registered_nodes[node_ok(pos).name].groups.water then + if registered_node.groups.water then if acc and self.floats == 1 then - self.object:set_acceleration({ - x = 0, - y = -self.fall_speed / (math.max(1, v.y) ^ 2), - z = 0 - }) + self.object:set_acceleration(vector.new(0, -self.fall_speed / (math.max(1, v.y) ^ 2), 0)) end else -- fall damage onto solid ground From f326fa620f1e715c541d56d59be4afce303f42f6 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 12 May 2023 21:00:01 +0100 Subject: [PATCH 5/7] Optimise do states and env danger check --- mods/ENTITIES/mcl_mobs/api.lua | 8 +++---- mods/ENTITIES/mcl_mobs/movement.lua | 33 ++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 485ea1f65..323d25f10 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -316,7 +316,7 @@ end -- execute current state (stand, walk, run, attacks) -- returns true if mob has died -function mob_class:do_states(dtime) +function mob_class:do_states(dtime, player_in_active_range) --if self.can_open_doors then check_doors(self) end -- knockback timer. set in on_punch @@ -325,7 +325,7 @@ function mob_class:do_states(dtime) return end - self:env_danger_movement_checks (dtime) + self:env_danger_movement_checks(player_in_active_range) if self.state == PATHFINDING then self:check_gowp(dtime) @@ -336,7 +336,7 @@ function mob_class:do_states(dtime) else if mcl_util.check_dtime_timer(self, dtime, "onstep_dostates", 1) then if self.state == "stand" then - self:do_states_stand() + self:do_states_stand(player_in_active_range) elseif self.state == "walk" then self:do_states_walk() elseif self.state == "runaway" then @@ -452,7 +452,7 @@ local function on_step_work (self, dtime) end end - if self:do_states(dtime) then return end + if self:do_states(dtime, player_in_active_range) then return end if mobs_debug then self:update_tag() end diff --git a/mods/ENTITIES/mcl_mobs/movement.lua b/mods/ENTITIES/mcl_mobs/movement.lua index 147930b87..377e25f6e 100644 --- a/mods/ENTITIES/mcl_mobs/movement.lua +++ b/mods/ENTITIES/mcl_mobs/movement.lua @@ -6,6 +6,8 @@ local FLOP_HOR_SPEED = 1.5 local CHECK_HERD_FREQUENCY = 4 +local PATHFINDING = "gowp" + local node_snow = "mcl_core:snow" local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false @@ -279,10 +281,19 @@ function mob_class:is_at_water_danger() return false end -function mob_class:env_danger_movement_checks(dtime) +function mob_class:env_danger_movement_checks(player_in_active_range) local yaw = 0 - if self.state ~= "attack" and self:is_at_water_danger() then + if not player_in_active_range then return end + + if self.state == PATHFINDING + or self.state == "attack" + or self.state == "stand" + or self.state == "runaway" then + return + end + + if self:is_at_water_danger() then --minetest.log("At water danger for mob, stop?: " .. self.name) if math.random(1, 10) <= 7 then if self.state ~= "stand" then @@ -884,7 +895,7 @@ function mob_class:do_states_walk() end end -function mob_class:do_states_stand() +function mob_class:do_states_stand(player_in_active_range) local yaw = self.object:get_yaw() or 0 if math.random(1, 4) == 1 then @@ -928,14 +939,16 @@ function mob_class:do_states_stand() if self.order == "stand" or self.order == "sleep" or self.order == "work" then else - if self.walk_chance ~= 0 - and self.facing_fence ~= true - and math.random(1, 100) <= self.walk_chance - and self:is_at_cliff_or_danger() == false then + if player_in_active_range then + if self.walk_chance ~= 0 + and self.facing_fence ~= true + and math.random(1, 100) <= self.walk_chance + and self:is_at_cliff_or_danger() == false then - self:set_velocity(self.walk_velocity) - self.state = "walk" - self:set_animation( "walk") + self:set_velocity(self.walk_velocity) + self.state = "walk" + self:set_animation( "walk") + end end end end From 952a90bfde3665a48f9059fa3d73cb08eb6a5825 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Fri, 12 May 2023 23:45:11 +0100 Subject: [PATCH 6/7] Re-organise mob_step for better clarity --- mods/ENTITIES/mcl_mobs/api.lua | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 323d25f10..d4913305d 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -436,22 +436,23 @@ local function on_step_work (self, dtime) self:do_jump() end - self:check_aggro(dtime) - - self:check_particlespawners(dtime) - - if self.do_custom and self.do_custom(self, dtime) == false then return end - if mcl_util.check_dtime_timer(self, dtime, "onstep_occassional", 1) then - self:check_breeding() if player_in_active_range then self:check_item_pickup() self:set_armor_texture() self:step_opinion_sound(dtime) end + + self:check_breeding() end + self:check_aggro(dtime) + + self:check_particlespawners(dtime) + + if self.do_custom and self.do_custom(self, dtime) == false then return end + if self:do_states(dtime, player_in_active_range) then return end if mobs_debug then self:update_tag() end From 5a059379b289456d457cf3b5644e8d434cce2c41 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Sat, 13 May 2023 18:10:20 +0100 Subject: [PATCH 7/7] Group damage logic. Remove physics falling logic out of suspend with duplicate falling call --- mods/ENTITIES/mcl_mobs/api.lua | 19 ++++--------------- mods/ENTITIES/mcl_mobs/physics.lua | 15 ++++++++++----- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index d4913305d..a9a1a0dad 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -387,25 +387,14 @@ local function on_step_work (self, dtime) end if self:falling(pos) then return end - - local player_in_active_range = self:player_in_active_range() - - self:check_suspend(player_in_active_range) - - if not self.fire_resistant then - mcl_burning.tick(self.object, dtime, self) - if not self.object:get_pos() then return end -- mcl_burning.tick may remove object immediately - - if self:check_for_death("fire", {type = "fire"}) then - return true - end - end - - if self:env_damage (dtime, pos) then return end + if self:step_damage (dtime, pos) then return end if self.state == "die" then return end -- End: Death/damage processing + local player_in_active_range = self:player_in_active_range() + self:check_suspend(player_in_active_range) + self:check_water_flow() if not self._jumping_cliff then diff --git a/mods/ENTITIES/mcl_mobs/physics.lua b/mods/ENTITIES/mcl_mobs/physics.lua index 55199d9f3..090b921c7 100644 --- a/mods/ENTITIES/mcl_mobs/physics.lua +++ b/mods/ENTITIES/mcl_mobs/physics.lua @@ -820,11 +820,19 @@ function mob_class:do_env_damage() return self:check_for_death("unknown", {type = "unknown"}) end -function mob_class:env_damage (dtime, pos) +function mob_class:step_damage (dtime, pos) + if not self.fire_resistant then + mcl_burning.tick(self.object, dtime, self) + if not self.object:get_pos() then return end -- mcl_burning.tick may remove object immediately + + if self:check_for_death("fire", {type = "fire"}) then + return true + end + end + -- environmental damage timer (every 1 second) self.env_damage_timer = self.env_damage_timer + dtime - if self.env_damage_timer > 1 then self.env_damage_timer = 0 @@ -1019,9 +1027,6 @@ function mob_class:check_suspend(player_in_active_range) self.object:set_acceleration(vector.zero()) self.object:set_velocity(vector.zero()) end - if acc.y == 0 and node_under == "air" then - self:falling(pos) - end end return true end