From b1defb4defe4b8a159bb69439a552cad504123a4 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Mon, 14 Feb 2011 11:43:42 +0200 Subject: fixed bug in sneaking --- src/map.cpp | 3 --- src/player.cpp | 65 +++++++++++++++++++++++++++++++++------------------------- src/player.h | 4 +++- 3 files changed, 40 insertions(+), 32 deletions(-) diff --git a/src/map.cpp b/src/map.cpp index e21336019..fe1056578 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -4466,9 +4466,6 @@ MapBlock * ServerMap::emergeBlock( /* This will create or load a sector if not found in memory. If block exists on disk, it will be loaded. - - NOTE: On old save formats, this will be slow, as it generates - lighting on blocks for them. */ ServerMapSector *sector; try{ diff --git a/src/player.cpp b/src/player.cpp index 60ab73b66..61ed87504 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -260,7 +260,8 @@ void RemotePlayer::move(f32 dtime, Map &map, f32 pos_max_d) */ LocalPlayer::LocalPlayer(): - m_last_walked_node(32767,32767,32767) + m_sneak_node(32767,32767,32767), + m_sneak_node_exists(false) { } @@ -359,10 +360,10 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d) If sneaking, keep in range from the last walked node and don't fall off from it */ - if(control.sneak) + if(control.sneak && m_sneak_node_exists) { f32 maxd = 0.5*BS + sneak_max; - v3f lwn_f = intToFloat(m_last_walked_node); + v3f lwn_f = intToFloat(m_sneak_node); position.X = rangelim(position.X, lwn_f.X-maxd, lwn_f.X+maxd); position.Z = rangelim(position.Z, lwn_f.Z-maxd, lwn_f.Z+maxd); @@ -532,40 +533,40 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d) } // xyz /* - If there is a walkable node directly under the player, save - the position of it. - */ - try{ - v3s16 pos_i_bottom = floatToInt(position - v3f(0,BS/2,0)); - if(content_walkable(map.getNode(pos_i_bottom).d)) - { - m_last_walked_node = pos_i_bottom; - } - } - catch(InvalidPositionException &e) - { - } - - /* - Check the neighbors of m_last_walked_node that are closer to - the player. If walkable, set m_last_walked_node to such. + //Check the neighbors of m_sneak_node that are closer to + //the player. If walkable, set m_sneak_node to such. + Check the nodes under the player to see if the player can + sneak. */ { v3s16 pos_i_bottom = floatToInt(position - v3f(0,BS/2,0)); - v3f lastwalkednode_pf = intToFloat(m_last_walked_node); - v2f lastwalkednode_p2df(lastwalkednode_pf.X, lastwalkednode_pf.Z); v2f player_p2df(position.X, position.Z); - f32 min_distance_f = player_p2df.getDistanceFrom(lastwalkednode_p2df); - v3s16 new_last_walked_node = m_last_walked_node; + f32 min_distance_f = 100000.0*BS; + if(m_sneak_node_exists) + { + v3f sneaknode_pf = intToFloat(m_sneak_node); + v2f sneaknode_p2df(sneaknode_pf.X, sneaknode_pf.Z); + f32 d_horiz_f = player_p2df.getDistanceFrom(sneaknode_p2df); + f32 d_vert_f = fabs(sneaknode_pf.Y + BS*0.5 - position.Y); + if(d_vert_f < 0.15*BS) + min_distance_f = d_horiz_f; + } + v3s16 new_sneak_node = m_sneak_node; for(s16 x=-1; x<=1; x++) for(s16 z=-1; z<=1; z++) { - v3s16 p = m_last_walked_node + v3s16(x,0,z); + v3s16 p = pos_i_bottom + v3s16(x,0,z); v3f pf = intToFloat(p); v2f node_p2df(pf.X, pf.Z); f32 distance_f = player_p2df.getDistanceFrom(node_p2df); - if(distance_f > min_distance_f) + f32 max_axis_distance_f = MYMAX( + fabs(player_p2df.X-node_p2df.X), + fabs(player_p2df.Y-node_p2df.Y)); + + if(distance_f > min_distance_f || + max_axis_distance_f > sneak_max+0.1*BS) continue; + try{ if(content_walkable(map.getNode(p).d) == false) continue; @@ -576,12 +577,20 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d) } min_distance_f = distance_f; - new_last_walked_node = p; + new_sneak_node = p; } - m_last_walked_node = new_last_walked_node; + m_sneak_node = new_sneak_node; + m_sneak_node_exists = (min_distance_f < 100000.0*BS*0.9); } + /* + If sneaking, the player's collision box can be in air, so + this has to be set explicitly + */ + if(m_sneak_node_exists) + touching_ground = true; + /* Set new position */ diff --git a/src/player.h b/src/player.h index 27ce1f5aa..16de6c924 100644 --- a/src/player.h +++ b/src/player.h @@ -323,7 +323,9 @@ public: private: // This is used for determining the sneaking range - v3s16 m_last_walked_node; + v3s16 m_sneak_node; + // Whether the player is allowed to sneak + bool m_sneak_node_exists; }; #endif // !SERVER -- cgit v1.2.3