mirror of
https://github.com/ElCeejo/creatura.git
synced 2025-04-30 05:41:46 -04:00
Performance Improvements
This commit is contained in:
parent
a71cf18e84
commit
b8de610493
5 changed files with 144 additions and 101 deletions
22
api.lua
22
api.lua
|
@ -355,8 +355,13 @@ function creatura.sensor_ceil(self, range, water)
|
|||
return dist, node
|
||||
end
|
||||
|
||||
local get_objects = minetest.get_objects_inside_radius
|
||||
|
||||
function creatura.get_nearby_player(self, range)
|
||||
local objects = minetest.get_objects_inside_radius(self:get_center_pos(), range or self.tracking_range)
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return end
|
||||
local stored_objs = self._nearby_objs or {}
|
||||
local objects = (#stored_objs > 0 and stored_objs) or get_objects(pos, range or self.tracking_range)
|
||||
for _, object in ipairs(objects) do
|
||||
if object:is_player()
|
||||
and creatura.is_alive(object) then
|
||||
|
@ -366,7 +371,10 @@ function creatura.get_nearby_player(self, range)
|
|||
end
|
||||
|
||||
function creatura.get_nearby_players(self, range)
|
||||
local objects = minetest.get_objects_inside_radius(self:get_center_pos(), range or self.tracking_range)
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return end
|
||||
local stored_objs = self._nearby_objs or {}
|
||||
local objects = (#stored_objs > 0 and stored_objs) or get_objects(pos, range or self.tracking_range)
|
||||
local nearby = {}
|
||||
for _, object in ipairs(objects) do
|
||||
if object:is_player()
|
||||
|
@ -378,7 +386,10 @@ function creatura.get_nearby_players(self, range)
|
|||
end
|
||||
|
||||
function creatura.get_nearby_object(self, name, range)
|
||||
local objects = minetest.get_objects_inside_radius(self:get_center_pos(), range or self.tracking_range)
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return end
|
||||
local stored_objs = self._nearby_objs or {}
|
||||
local objects = (#stored_objs > 0 and stored_objs) or get_objects(pos, range or self.tracking_range)
|
||||
for _, object in ipairs(objects) do
|
||||
local ent = creatura.is_alive(object) and object:get_luaentity()
|
||||
if ent
|
||||
|
@ -392,7 +403,10 @@ function creatura.get_nearby_object(self, name, range)
|
|||
end
|
||||
|
||||
function creatura.get_nearby_objects(self, name, range)
|
||||
local objects = minetest.get_objects_inside_radius(self:get_center_pos(), range or self.tracking_range)
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return end
|
||||
local stored_objs = self._nearby_objs or {}
|
||||
local objects = (#stored_objs > 0 and stored_objs) or get_objects(pos, range or self.tracking_range)
|
||||
local nearby = {}
|
||||
for _, object in ipairs(objects) do
|
||||
local ent = creatura.is_alive(object) and object:get_luaentity()
|
||||
|
|
|
@ -74,6 +74,14 @@ function creatura.get_boid_members(pos, radius, name)
|
|||
table.insert(members, object)
|
||||
end
|
||||
end
|
||||
if #members > 1 then
|
||||
for _, object in ipairs(members) do
|
||||
local ent = object and object:get_luaentity()
|
||||
if ent then
|
||||
ent._movement_data.boids = members
|
||||
end
|
||||
end
|
||||
end
|
||||
return members
|
||||
end
|
||||
|
||||
|
|
45
methods.lua
45
methods.lua
|
@ -32,15 +32,15 @@ local vec_add = vector.add
|
|||
local yaw2dir = minetest.yaw_to_dir
|
||||
local dir2yaw = minetest.dir_to_yaw
|
||||
|
||||
--[[local function debugpart(pos, time, tex)
|
||||
local function debugpart(pos, time, tex)
|
||||
minetest.add_particle({
|
||||
pos = pos,
|
||||
texture = tex or "creatura_particle_red.png",
|
||||
expirationtime = time or 3,
|
||||
expirationtime = time or 0.55,
|
||||
glow = 6,
|
||||
size = 1
|
||||
size = 8
|
||||
})
|
||||
end]]
|
||||
end
|
||||
|
||||
---------------------
|
||||
-- Local Utilities --
|
||||
|
@ -101,7 +101,7 @@ end
|
|||
return false
|
||||
end]]
|
||||
|
||||
local function get_collision(self)
|
||||
function creatura.get_collision(self)
|
||||
local yaw = self.object:get_yaw()
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return end
|
||||
|
@ -113,41 +113,36 @@ local function get_collision(self)
|
|||
-- Loop
|
||||
local pos_x, pos_z = ahead.x, ahead.z
|
||||
for x = -width, width, width / ceil(width) do
|
||||
local vec1 = {
|
||||
x = cos(yaw) * ((pos_x + x) - pos_x) + pos_x,
|
||||
y = pos.y + height,
|
||||
z = sin(yaw) * ((pos_x + x) - pos_x) + pos_z
|
||||
}
|
||||
local vec2 = {
|
||||
x = cos(yaw) * ((pos_x + x) - pos_x) + pos_x,
|
||||
y = pos.y,
|
||||
z = sin(yaw) * ((pos_x + x) - pos_x) + pos_z
|
||||
}
|
||||
local ray = raycast(vec1, vec2, false)
|
||||
if ray then
|
||||
local collision = ray.intersection_point
|
||||
if collision.y - pos.y <= (self.stepheight or 1.1) then
|
||||
local step = creatura.get_node_def({x = vec1.x, y = vec1.y + 0.5, z = vec1.z})
|
||||
if step.walkable then
|
||||
return true, collision
|
||||
end
|
||||
for y = 0, height, height / ceil(height) do
|
||||
local pos2 = {
|
||||
x = cos(yaw) * ((pos_x + x) - pos_x) + pos_x,
|
||||
y = pos.y + y,
|
||||
z = sin(yaw) * ((pos_x + x) - pos_x) + pos_z
|
||||
}
|
||||
if pos2.y - pos.y > (self.stepheight or 1.1)
|
||||
and creatura.get_node_def(pos2).walkable then
|
||||
return true, pos2
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local get_collision = creatura.get_collision
|
||||
|
||||
local function get_avoidance_dir(self)
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return end
|
||||
local _, col_pos = get_collision(self)
|
||||
if col_pos then
|
||||
local vel = self.object:get_velocity()
|
||||
local ahead = vec_add(pos, vec_normal(self.object:get_velocity()))
|
||||
vel.y = 0
|
||||
local vel_len = vec_len(vel) * (1 + (self.step_delay or 0))
|
||||
local ahead = vec_add(pos, vec_normal(vel))
|
||||
local avoidance_force = vector.subtract(ahead, col_pos)
|
||||
avoidance_force.y = 0
|
||||
local vel_len = vec_len(vel)
|
||||
avoidance_force = vec_multi(vec_normal(avoidance_force), (vel_len > 1 and vel_len) or 1)
|
||||
debugpart(vec_add(ahead, avoidance_force))
|
||||
return vec_dir(pos, vec_add(ahead, avoidance_force))
|
||||
end
|
||||
end
|
||||
|
|
160
mob_meta.lua
160
mob_meta.lua
|
@ -215,12 +215,12 @@ function mob:do_velocity()
|
|||
local vel = self.object:get_velocity()
|
||||
local yaw = self.object:get_yaw()
|
||||
if not yaw then return end
|
||||
local dir = minetest.yaw_to_dir(yaw)
|
||||
local horz_vel = data.horz_vel
|
||||
local vert_vel = data.vert_vel
|
||||
vel.x = (horz_vel and horz_vel * dir.x) or vel.x
|
||||
if horz_vel and horz_vel < 1 then horz_vel = 1 end
|
||||
vel.x = (horz_vel and (sin(yaw) * -horz_vel)) or vel.x
|
||||
vel.y = vert_vel or vel.y
|
||||
vel.z = (horz_vel and horz_vel * dir.z) or vel.z
|
||||
vel.z = (horz_vel and (cos(yaw) * horz_vel)) or vel.z
|
||||
self.object:set_velocity(vel)
|
||||
end
|
||||
|
||||
|
@ -629,6 +629,27 @@ function mob:get_target(target)
|
|||
return true, line_of_sight, tpos
|
||||
end
|
||||
|
||||
function mob:store_nearby_objects()
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return end
|
||||
local objects = minetest.get_objects_inside_radius(pos, self.tracking_range or 8)
|
||||
if #objects < 1 then return end
|
||||
local objs = {}
|
||||
for _, object in ipairs(objects) do
|
||||
if creatura.is_alive(object)
|
||||
and object ~= self.object then
|
||||
local ent = object:get_luaentity()
|
||||
local player = object:is_player()
|
||||
if (ent
|
||||
and not ent._ignore)
|
||||
or player then
|
||||
table.insert(objs, object)
|
||||
end
|
||||
end
|
||||
end
|
||||
self._nearby_objs = objs
|
||||
end
|
||||
|
||||
-- Actions
|
||||
|
||||
function mob:set_action(func)
|
||||
|
@ -784,6 +805,8 @@ function mob:activate(staticdata, dtime)
|
|||
end
|
||||
end
|
||||
|
||||
self:store_nearby_objects()
|
||||
|
||||
if self.activate_func then
|
||||
self:activate_func(self, staticdata, dtime)
|
||||
end
|
||||
|
@ -806,20 +829,27 @@ function mob:on_step(dtime, moveresult)
|
|||
if moveresult then
|
||||
self.touching_ground = moveresult.touching_ground
|
||||
end
|
||||
local stand_pos
|
||||
local stand_node
|
||||
if step_tick <= 0 then
|
||||
-- Physics
|
||||
if self._physics then
|
||||
self:_physics(moveresult)
|
||||
end
|
||||
-- Vitals
|
||||
if self._vitals then
|
||||
self:_vitals()
|
||||
end
|
||||
stand_pos = self.object:get_pos()
|
||||
if not stand_pos then return end
|
||||
stand_node = minetest.get_node(stand_pos)
|
||||
-- Cached Geometry
|
||||
self.properties = self.object:get_properties()
|
||||
self.width = self:get_hitbox()[4] or 0.5
|
||||
self.height = self:get_height() or 1
|
||||
end
|
||||
if stand_pos
|
||||
and stand_node then
|
||||
if self._vitals then
|
||||
self:_vitals(stand_pos, stand_node)
|
||||
end
|
||||
if self._physics then
|
||||
self:_physics(moveresult, stand_pos, stand_node)
|
||||
end
|
||||
end
|
||||
if self:timer(10) then self:store_nearby_objects() end -- Reduce expensive calls
|
||||
self:do_velocity()
|
||||
self:do_turn()
|
||||
if self.utility_stack
|
||||
|
@ -931,16 +961,14 @@ local function collision_detection(self)
|
|||
end
|
||||
end
|
||||
|
||||
local function water_physics(self)
|
||||
local function water_physics(self, pos, node)
|
||||
-- Props
|
||||
local gravity = self._movement_data.gravity
|
||||
local height = self.height
|
||||
-- Vectors
|
||||
local floor_pos = self.object:get_pos()
|
||||
floor_pos.y = floor_pos.y + 0.01
|
||||
local surface_pos = floor_pos
|
||||
local floor_node = minetest.get_node(floor_pos)
|
||||
if minetest.get_item_group(floor_node.name, "liquid") < 1 then
|
||||
pos.y = pos.y + 0.01
|
||||
local surface_pos = pos
|
||||
if minetest.get_item_group(node.name, "liquid") < 1 then
|
||||
self.object:set_acceleration({
|
||||
x = 0,
|
||||
y = gravity,
|
||||
|
@ -951,13 +979,13 @@ local function water_physics(self)
|
|||
end
|
||||
return
|
||||
end
|
||||
self.in_liquid = floor_node.name
|
||||
self.in_liquid = node.name
|
||||
-- Get submergence (Not the most accurate, but reduces lag)
|
||||
for i = 1, math.ceil(height * 3) do
|
||||
local step_pos = {
|
||||
x = floor_pos.x,
|
||||
y = floor_pos.y + 0.5 * i,
|
||||
z = floor_pos.z
|
||||
x = pos.x,
|
||||
y = pos.y + 0.5 * i,
|
||||
z = pos.z
|
||||
}
|
||||
if minetest.get_item_group(minetest.get_node(step_pos).name, "liquid") > 0 then
|
||||
surface_pos = step_pos
|
||||
|
@ -966,7 +994,7 @@ local function water_physics(self)
|
|||
end
|
||||
end
|
||||
-- Apply Physics
|
||||
local submergence = surface_pos.y - floor_pos.y
|
||||
local submergence = surface_pos.y - pos.y
|
||||
local vel = self.object:get_velocity()
|
||||
local bouyancy = self.bouyancy_multiplier or 1
|
||||
local accel = (submergence - vel.y * abs(vel.y) * 0.4) * bouyancy
|
||||
|
@ -988,23 +1016,27 @@ local function water_physics(self)
|
|||
})
|
||||
end
|
||||
|
||||
function mob:_physics(moveresult)
|
||||
if not self.object then return end
|
||||
water_physics(self)
|
||||
function mob:_physics(moveresult, pos, node)
|
||||
if not pos then return end
|
||||
water_physics(self, pos, node)
|
||||
-- Step up nodes
|
||||
do_step(self, moveresult)
|
||||
-- Object collision
|
||||
collision_detection(self)
|
||||
if not self.in_liquid
|
||||
and not self.touching_ground then
|
||||
local in_liquid = self.in_liquid
|
||||
local on_ground = self.touching_ground
|
||||
if not in_liquid
|
||||
and not on_ground then
|
||||
self.is_falling = true
|
||||
else
|
||||
self.is_falling = false
|
||||
end
|
||||
if not self.in_liquid
|
||||
and self._movement_data.gravity ~= 0 then
|
||||
local move_data = self._movement_data
|
||||
if not in_liquid
|
||||
and not move_data.func
|
||||
and move_data.gravity ~= 0 then
|
||||
local vel = self.object:get_velocity()
|
||||
if self.touching_ground then
|
||||
if on_ground then
|
||||
local nvel = vector.multiply(vel, 0.2)
|
||||
if nvel.x < 0.2
|
||||
and nvel.z < 0.2 then
|
||||
|
@ -1166,67 +1198,55 @@ end
|
|||
|
||||
-- Vitals
|
||||
|
||||
function mob:_vitals()
|
||||
local stand_pos = self.object:get_pos()
|
||||
if not stand_pos then return end
|
||||
function mob:_vitals(pos, node)
|
||||
if not pos or not node then return end
|
||||
local stand_def = creatura.get_node_def(node.name)
|
||||
local max_fall = self.max_fall or 0
|
||||
if max_fall > 0 then
|
||||
local fall_start = self._fall_start
|
||||
if self.is_falling
|
||||
and not fall_start then
|
||||
self._fall_start = stand_pos.y
|
||||
elseif fall_start then
|
||||
if self.touching_ground
|
||||
and not self.in_liquid then
|
||||
local damage = fall_start - stand_pos.y
|
||||
local in_liquid = self.in_liquid
|
||||
local on_ground = self.touching_ground
|
||||
local damage
|
||||
if max_fall > 0
|
||||
and not in_liquid then
|
||||
local fall_start = self._fall_start or (not on_ground and pos.y)
|
||||
if fall_start then
|
||||
if on_ground then
|
||||
damage = fall_start - pos.y
|
||||
if damage < max_fall then
|
||||
self._fall_start = nil
|
||||
return
|
||||
damage = nil
|
||||
end
|
||||
local resist = self.fall_resistance or 0
|
||||
self:hurt(damage - (damage * resist))
|
||||
self:indicate_damage()
|
||||
if random(4) < 2 then
|
||||
self:play_sound("hurt")
|
||||
end
|
||||
self._fall_start = nil
|
||||
elseif self.in_liquid then
|
||||
damage = damage - damage * resist
|
||||
self._fall_start = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
if self:timer(1) then
|
||||
local head_pos = vec_raise(stand_pos, self.height)
|
||||
local head_pos = vec_raise(pos, self.height)
|
||||
local head_node = minetest.get_node(head_pos)
|
||||
local head_def = creatura.get_node_def(head_node.name)
|
||||
if head_def.drawtype == "liquid"
|
||||
and minetest.get_item_group(head_node.name, "water") > 0 then
|
||||
if minetest.get_item_group(head_node.name, "liquid") > 0 then
|
||||
if self._breath <= 0 then
|
||||
self:hurt(1)
|
||||
self:indicate_damage()
|
||||
if random(4) < 2 then
|
||||
self:play_sound("hurt")
|
||||
end
|
||||
damage = (damage or 0) + 1
|
||||
else
|
||||
self._breath = self._breath - 1
|
||||
self:memorize("_breath", self._breath)
|
||||
end
|
||||
end
|
||||
local stand_node = minetest.get_node(stand_pos)
|
||||
local stand_def = creatura.get_node_def(stand_node.name)
|
||||
if minetest.get_item_group(stand_node.name, "fire") > 0
|
||||
if minetest.get_item_group(stand_def.name, "fire") > 0
|
||||
and stand_def.damage_per_second then
|
||||
local damage = stand_def.damage_per_second
|
||||
local resist = self.fire_resistance or 0.5
|
||||
self:hurt(damage - damage * resist)
|
||||
self:indicate_damage()
|
||||
if random(4) < 2 then
|
||||
self:play_sound("hurt")
|
||||
end
|
||||
damage = (damage or 0) + stand_def.damage_per_second * resist
|
||||
end
|
||||
end
|
||||
if damage then
|
||||
self:hurt(damage)
|
||||
self:indicate_damage()
|
||||
if random(4) < 2 then
|
||||
self:play_sound("hurt")
|
||||
end
|
||||
end
|
||||
-- Entity Cramming
|
||||
if self:timer(5) then
|
||||
local objects = minetest.get_objects_inside_radius(stand_pos, 0.2)
|
||||
local objects = minetest.get_objects_inside_radius(pos, 0.2)
|
||||
if #objects > 10 then
|
||||
self:indicate_damage()
|
||||
self.hp = self:memorize("hp", -1)
|
||||
|
|
|
@ -134,9 +134,9 @@ function creatura.find_lvm_path(self, start, goal, obj_width, obj_height, max_op
|
|||
fly = fly or false
|
||||
swim = swim or false
|
||||
|
||||
start = start
|
||||
if vec_dist(start, goal) > (self.tracking_range or 128) then return {} end
|
||||
|
||||
--self._path_data.start = start
|
||||
self._path_data.start = start
|
||||
|
||||
local path_neighbors = {
|
||||
{x = 1, y = 0, z = 0},
|
||||
|
@ -276,6 +276,12 @@ function creatura.find_lvm_path(self, start, goal, obj_width, obj_height, max_op
|
|||
self._path_data.open = openSet
|
||||
self._path_data.closedSet = closedSet
|
||||
|
||||
local current_start = vec_round(self._path_data.start)
|
||||
|
||||
if closedSet[minetest.hash_node_position(current_start)] then
|
||||
start_index = minetest.hash_node_position(current_start)
|
||||
end
|
||||
|
||||
-- Reconstruct path if end is reached
|
||||
if ((is_on_ground(_goal)
|
||||
or fly)
|
||||
|
|
Loading…
Add table
Reference in a new issue