mirror of
https://git.minetest.land/MineClone2/MineClone2.git
synced 2024-12-29 04:37:31 +01:00
Merge pull request 'Optimise mobs' (#3720) from optimise_mobs into master
Reviewed-on: https://git.minetest.land/MineClone2/MineClone2/pulls/3720
This commit is contained in:
commit
6ded4d2322
@ -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
|
||||
@ -297,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
|
||||
@ -306,6 +325,8 @@ function mob_class:do_states(dtime)
|
||||
return
|
||||
end
|
||||
|
||||
self:env_danger_movement_checks(player_in_active_range)
|
||||
|
||||
if self.state == PATHFINDING then
|
||||
self:check_gowp(dtime)
|
||||
elseif self.state == "attack" then
|
||||
@ -315,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
|
||||
@ -366,30 +387,22 @@ 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
|
||||
|
||||
self:check_water_flow()
|
||||
self:env_danger_movement_checks (dtime)
|
||||
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
|
||||
self._can_jump_cliff = self:can_jump_cliff()
|
||||
else
|
||||
self._can_jump_cliff = false
|
||||
end
|
||||
|
||||
-- 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()
|
||||
self:flop()
|
||||
|
||||
self:check_smooth_rotation(dtime)
|
||||
@ -399,14 +412,28 @@ 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
|
||||
|
||||
if mcl_util.check_dtime_timer(self, dtime, "onstep_occassional", 1) then
|
||||
|
||||
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)
|
||||
@ -415,17 +442,7 @@ local function on_step_work (self, 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
|
||||
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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -4,8 +4,11 @@ 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 PATHFINDING = "gowp"
|
||||
|
||||
local node_snow = "mcl_core:snow"
|
||||
|
||||
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
|
||||
|
||||
@ -202,12 +205,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 +241,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,52 +265,57 @@ 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
|
||||
|
||||
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
|
||||
|
||||
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 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
|
||||
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 +386,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 +396,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
|
||||
|
||||
@ -623,7 +631,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
|
||||
@ -724,7 +732,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 +764,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()
|
||||
@ -887,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
|
||||
@ -931,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
|
||||
|
@ -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
|
||||
|
||||
@ -903,47 +911,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
|
||||
@ -1030,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
|
||||
|
Loading…
Reference in New Issue
Block a user