From 897f0c35806af230de8089428ea79ac6ee56ffb3 Mon Sep 17 00:00:00 2001 From: sapier Date: Thu, 10 Jan 2013 20:44:38 +0000 Subject: [PATCH] improve collision checking for pos_is_ok --- mobf/README | 1 + mobf/environment.lua | 167 +++++++++++++++++++++++++++++++++---- mobf/generic_functions.lua | 31 +++++++ 3 files changed, 183 insertions(+), 16 deletions(-) diff --git a/mobf/README b/mobf/README index 37d8818..d077202 100644 --- a/mobf/README +++ b/mobf/README @@ -156,6 +156,7 @@ Changes 1.9.12 -fixed drop avoidance not working if dropping to water (due to another fix) -improve house spawning -add ostrich +-improve collision checking for pos_is_ok Changes 1.9.11 diff --git a/mobf/environment.lua b/mobf/environment.lua index 83a83cc..fd6f0c6 100644 --- a/mobf/environment.lua +++ b/mobf/environment.lua @@ -305,6 +305,26 @@ function environment.checksurface(pos,surface) end +function environment.get_min_max_ground_dist(entity) + local min_ground_distance = 0 + local max_ground_distance = 0 + + if entity.environment.max_height_above_ground ~= nil then + max_ground_distance = entity.environment.max_height_above_ground + end + + if entity.environment.min_height_above_ground ~= nil then + min_ground_distance = entity.environment.min_height_above_ground + end + + if entity.data.movement.canfly == nil or + entity.data.movement.canfly == false then + max_ground_distance = 1 + end + + return min_ground_distance,max_ground_distance +end + ------------------------------------------------------------------------------- -- name: pos_is_ok(pos,entity) -- @@ -327,23 +347,9 @@ end --! -wrong_surface -@>position is above surface mob shouldn't be --! -invalid -@>unable to check position ------------------------------------------------------------------------------- -function environment.pos_is_ok(pos,entity) +function environment.old_pos_is_ok(pos,entity) - local min_ground_distance = 0 - local max_ground_distance = 0 - - if entity.environment.max_height_above_ground ~= nil then - max_ground_distance = entity.environment.max_height_above_ground - end - - if entity.environment.min_height_above_ground ~= nil then - min_ground_distance = entity.environment.min_height_above_ground - end - - if entity.data.movement.canfly == nil or - entity.data.movement.canfly == false then - max_ground_distance = 1 - end + local min_ground_distance,max_ground_distance = environment.get_min_max_ground_dist(entity) dbg_mobf.environment_lvl2("MOBF: Checking pos "..printpos(pos)) @@ -426,6 +432,135 @@ function environment.pos_is_ok(pos,entity) return "collision" +end + +------------------------------------------------------------------------------- +-- name: pos_is_ok(pos,entity) +-- +--! @brief check if a position is suitable for an mob +--! @memberof environment +-- +--! @param pos position to check +--! @param entity mob to check +--! @return suitability of position for mob values: +--! -ok -@>position is ok +--! -collision -@>position is within a node +--! -collision_jumpable -@>position is within a node that can be jumped onto +--! -drop -@>position is a drop +--! -drop_above_water -@>position is to far above water +--! -above_water -@>position is right over water +--! -in_water -@>position is within a water node(source or flow) +--! -in_air -@>position is in air +--! -above_limit -@>position is above level limit +--! -below_limit -@>position is below level limit +--! -wrong_surface -@>position is above surface mob shouldn't be +--! -invalid -@>unable to check position +------------------------------------------------------------------------------- +function environment.pos_is_ok(pos,entity,jumpcheck) + + local min_ground_distance,max_ground_distance = environment.get_min_max_ground_dist(entity) + + local cornerpositions = {} + + table.insert(cornerpositions,pos) + --read positions at corners + table.insert(cornerpositions,mobf_round_pos({x=pos.x + entity.collisionbox[4],y=pos.y,z=pos.z + entity.collisionbox[6]})) + table.insert(cornerpositions,mobf_round_pos({x=pos.x + entity.collisionbox[4],y=pos.y,z=pos.z + entity.collisionbox[3]})) + table.insert(cornerpositions,mobf_round_pos({x=pos.x + entity.collisionbox[1],y=pos.y,z=pos.z + entity.collisionbox[6]})) + table.insert(cornerpositions,mobf_round_pos({x=pos.x + entity.collisionbox[1],y=pos.y,z=pos.z + entity.collisionbox[3]})) + + local lastpos = nil + + local retval = "temp_ok" + + --check if mob at pos will be in correct environment + for i=1,#cornerpositions,1 do + if not mobf_pos_is_same(lastpos,cornerpositions[i]) then + local node_to_check = minetest.env:get_node(cornerpositions[i]) + + if node_to_check == nil then + mobf_bug_warning(LOGLEVEL_ERROR,"MOBF: BUG!!!! checking position with invalid node") + retval = "invalid" + break + end + + if not environment.is_media_element(node_to_check.name,entity.environment.media) == true then + dbg_mobf.environment_lvl3("MOBF: at pos " .. printpos(cornerpositions[i]) .. " not within environment") + + if mobf_pos_is_same(pos,cornerpositions[i]) then + if node_to_check.name == "default:water_source" or + node_to_check.name == "default:water_flowing" then + retval = "in_water" + break + end + + if node_to_check.name == "air" then + retval = "in_air" + break + end + + --TODO maybe replace by "invalid medium" + else + retval = "collision" + end + end + end + lastpos = cornerpositions[i] + end + + -- + if retval == "temp_ok" then + dbg_mobf.environment_lvl2("MOBF: \tin environment") + local ground_distance = mobf_ground_distance(pos,entity.environment.media) + + --following return codes are only usefull for non flying + if entity.data.movement.canfly == nil or + entity.data.movement.canfly == false then + + if mobf_above_water(pos) then + + if ground_distance > max_ground_distance then + dbg_mobf.environment_lvl2("MOBF: \tdropping above water") + retval = "drop_above_water" + end + dbg_mobf.environment_lvl2("MOBF: \tabove water") + retval = "above_water" + end + + if ground_distance > max_ground_distance then + dbg_mobf.environment_lvl2("MOBF: \tdropping") + retval = "drop" + else + dbg_mobf.environment_lvl2("MOBF: \tsurface dependent") + retval = environment.checksurface(pos,entity.environment.surfaces) + end + else + local miny,maxy = environment.get_absolute_min_max_pos(entity.environment,pos) + if pos.y < miny then + retval = "below_limit" + end + + if pos.y > maxy then + retval = "above_limit" + end + + retval = environment.checksurface(pos,entity.environment.surfaces) + end + end + + if retval == "collision" and jumpcheck then + if environment.extended_pos_is_ok(pos,entity,false) == "ok" then + retval = "collision_jumpable" + end + end + + return retval +end + +function environment.state_prio(oldstate,newstate) + + + end ------------------------------------------------------------------------------- diff --git a/mobf/generic_functions.lua b/mobf/generic_functions.lua index 21f70e3..ba8f3c4 100644 --- a/mobf/generic_functions.lua +++ b/mobf/generic_functions.lua @@ -857,4 +857,35 @@ function mobf_calc_vector_components(dir_radians,absolute_speed) return retval end + +------------------------------------------------------------------------------- +-- name: mobf_pos_is_same(pos1,pos2) +-- +--! @brief check if two positions are equal +-- +--! @param pos1 +--! @param pos2 +-- +--! @return true/false +------------------------------------------------------------------------------- +function mobf_pos_is_same(pos1,pos2) + if pos1 == nil or + pos2 == nil then + return false + end + + if pos1.x ~= pos2.x or + pos1.y ~= pos2.y or + pos1.z ~= pos2.z or + pos1.x == nil or + pos1.y == nil or + pos1.z == nil or + pos2.x == nil or + pos2.y == nil or + pos2.z == nil then + return false + end + + return true +end --!@}