*/
LocalPlayer::LocalPlayer():
- m_last_walked_node(32767,32767,32767)
+ m_sneak_node(32767,32767,32767),
+ m_sneak_node_exists(false)
{
}
{
v3f position = getPosition();
v3f oldpos = position;
- v3s16 oldpos_i = floatToInt(oldpos);
+ v3s16 oldpos_i = floatToInt(oldpos, BS);
/*std::cout<<"oldpos_i=("<<oldpos_i.X<<","<<oldpos_i.Y<<","
<<oldpos_i.Z<<")"<<std::endl;*/
*/
// Player position in nodes
- v3s16 pos_i = floatToInt(position);
+ v3s16 pos_i = floatToInt(position, BS);
/*
Check if player is in water (the oscillating value)
// If in water, the threshold of coming out is at higher y
if(in_water)
{
- v3s16 pp = floatToInt(position + v3f(0,BS*0.1,0));
+ v3s16 pp = floatToInt(position + v3f(0,BS*0.1,0), BS);
in_water = content_liquid(map.getNode(pp).d);
}
// If not in water, the threshold of going in is at lower y
else
{
- v3s16 pp = floatToInt(position + v3f(0,BS*0.5,0));
+ v3s16 pp = floatToInt(position + v3f(0,BS*0.5,0), BS);
in_water = content_liquid(map.getNode(pp).d);
}
}
Check if player is in water (the stable value)
*/
try{
- v3s16 pp = floatToInt(position + v3f(0,0,0));
+ v3s16 pp = floatToInt(position + v3f(0,0,0), BS);
in_water_stable = content_liquid(map.getNode(pp).d);
}
catch(InvalidPositionException &e)
Make it a bit larger than the maximum distance of movement
*/
//f32 d = pos_max_d * 1.1;
- // A fairly large value in here makes moving much smoother
+ // A fairly large value in here makes moving smoother
f32 d = 0.15*BS;
// This should always apply, otherwise there are glitches
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, BS);
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);
for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
{
try{
- if(content_walkable(map.getNode(v3s16(x,y,z)).d) == false){
+ // Player collides into walkable nodes
+ if(content_walkable(map.getNode(v3s16(x,y,z)).d) == false)
continue;
- }
}
catch(InvalidPositionException &e)
{
// walking over map borders
}
- core::aabbox3d<f32> nodebox = Map::getNodeBox(
- v3s16(x,y,z));
+ core::aabbox3d<f32> nodebox = getNodeBox(v3s16(x,y,z), BS);
/*
See if the player is touching ground.
} // 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 nodes under the player to see from which node the
+ player is sneaking from, if any.
*/
{
- 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);
+ v3s16 pos_i_bottom = floatToInt(position - v3f(0,BS/2,0), BS);
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 already seeking from some node, compare to it.
+ /*if(m_sneak_node_exists)
+ {
+ v3f sneaknode_pf = intToFloat(m_sneak_node, BS);
+ 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);
+ // Ignore if player is not on the same level (likely dropped)
+ 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);
- v3f pf = intToFloat(p);
+ v3s16 p = pos_i_bottom + v3s16(x,0,z);
+ v3f pf = intToFloat(p, BS);
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 > 0.5*BS + sneak_max + 0.1*BS)
continue;
+
try{
+ // The node to be sneaked on has to be walkable
if(content_walkable(map.getNode(p).d) == false)
continue;
+ // And the node above it has to be nonwalkable
+ if(content_walkable(map.getNode(p+v3s16(0,1,0)).d) == true)
+ continue;
}
catch(InvalidPositionException &e)
{
}
min_distance_f = distance_f;
- new_last_walked_node = p;
+ new_sneak_node = p;
}
- m_last_walked_node = new_last_walked_node;
+ bool sneak_node_found = (min_distance_f < 100000.0*BS*0.9);
+
+ if(control.sneak && m_sneak_node_exists)
+ {
+ if(sneak_node_found)
+ m_sneak_node = new_sneak_node;
+ }
+ else
+ {
+ m_sneak_node = new_sneak_node;
+ m_sneak_node_exists = sneak_node_found;
+ }
+
+ /*
+ If sneaking, the player's collision box can be in air, so
+ this has to be set explicitly
+ */
+ if(sneak_node_found && control.sneak)
+ touching_ground = true;
}
/*