aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpecksin <78765996+pecksin@users.noreply.github.com>2022-09-27 16:22:36 -0400
committerGitHub <noreply@github.com>2022-09-27 16:22:36 -0400
commit6ac38aa2c82d83971226c8a07236aeb79479522d (patch)
treeae17a2945a6a5f564f1e8eba4f863a4cde7108ab
parent907dcdcf7bb513ecfeb1c988f071f497dcfbf765 (diff)
downloadminetest-6ac38aa2c82d83971226c8a07236aeb79479522d.tar.xz
Restore and enhance bouncy behavior (#11939)
-rw-r--r--doc/lua_api.txt4
-rw-r--r--src/client/localplayer.cpp91
2 files changed, 72 insertions, 23 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index a801c6019..dac242f67 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -1868,7 +1868,9 @@ to games.
* `attached_node`: if the node under it is not a walkable block the node will be
dropped as an item. If the node is wallmounted the wallmounted direction is
checked.
-* `bouncy`: value is bounce speed in percent
+* `bouncy`: value is bounce speed in percent.
+ If positive, jump/sneak on floor impact will increase/decrease bounce height.
+ Negative value is the same bounciness, but non-controllable.
* `connect_to_raillike`: makes nodes of raillike drawtype with same group value
connect to each other
* `dig_immediate`: Player can always pick up node without reducing tool wear
diff --git a/src/client/localplayer.cpp b/src/client/localplayer.cpp
index f9caf9e8b..ef249235b 100644
--- a/src/client/localplayer.cpp
+++ b/src/client/localplayer.cpp
@@ -331,8 +331,8 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
}
/*
- If the player's feet touch the topside of any node, this is
- set to true.
+ If the player's feet touch the topside of any node
+ at the END of clientstep, then this is set to true.
Player is allowed to jump when this is true.
*/
@@ -432,23 +432,47 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
const ContentFeatures &f = nodemgr->get(map->getNode(m_standing_node));
const ContentFeatures &f1 = nodemgr->get(map->getNode(m_standing_node + v3s16(0, 1, 0)));
+ // We can jump from a bouncy node we collided with this clientstep,
+ // even if we are not "touching" it at the end of clientstep.
+ int standing_node_bouncy = 0;
+ if (result.collides && m_speed.Y > 0.0f) {
+ // must use result.collisions here because sometimes collision_info
+ // is passed in prepopulated with a problematic floor.
+ for (const auto &colinfo : result.collisions) {
+ if (colinfo.axis == COLLISION_AXIS_Y) {
+ // we cannot rely on m_standing_node because "sneak stuff"
+ standing_node_bouncy = itemgroup_get(nodemgr->get(map->getNode(colinfo.node_p)).groups, "bouncy");
+ if (standing_node_bouncy != 0)
+ break;
+ }
+ }
+ }
+
// Determine if jumping is possible
m_disable_jump = itemgroup_get(f.groups, "disable_jump") ||
itemgroup_get(f1.groups, "disable_jump");
- m_can_jump = ((touching_ground && !is_climbing) || sneak_can_jump) && !m_disable_jump;
+ m_can_jump = ((touching_ground && !is_climbing) || sneak_can_jump || standing_node_bouncy != 0)
+ && !m_disable_jump;
- // Jump key pressed while jumping off from a bouncy block
- if (m_can_jump && control.jump && itemgroup_get(f.groups, "bouncy") &&
- m_speed.Y >= -0.5f * BS) {
- float jumpspeed = movement_speed_jump * physics_override.jump;
- if (m_speed.Y > 1.0f) {
- // Reduce boost when speed already is high
- m_speed.Y += jumpspeed / (1.0f + (m_speed.Y / 16.0f));
+ // Jump/Sneak key pressed while bouncing from a bouncy block
+ float jumpspeed = movement_speed_jump * physics_override.jump;
+ if (m_can_jump && (control.jump || control.sneak) && standing_node_bouncy > 0) {
+ // controllable (>0) bouncy block
+ if (!control.jump) {
+ // sneak pressed, but not jump
+ // Subjective testing indicates 1/3 bounce decrease works well.
+ jumpspeed = -m_speed.Y / 3.0f;
} else {
- m_speed.Y += jumpspeed;
+ // jump pressed
+ // Reduce boost when speed already is high
+ jumpspeed = jumpspeed / (1.0f + (m_speed.Y * 2.8f / jumpspeed));
}
+ m_speed.Y += jumpspeed;
setSpeed(m_speed);
m_can_jump = false;
+ } else if(m_speed.Y > jumpspeed && standing_node_bouncy < 0) {
+ // uncontrollable bouncy is limited to normal jump height.
+ m_can_jump = false;
}
// Autojump
@@ -897,8 +921,8 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d,
m_standing_node = floatToInt(m_position, BS);
/*
- If the player's feet touch the topside of any node, this is
- set to true.
+ If the player's feet touch the topside of any node
+ at the END of clientstep, then this is set to true.
Player is allowed to jump when this is true.
*/
@@ -1028,22 +1052,45 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d,
*/
const ContentFeatures &f = nodemgr->get(map->getNode(getStandingNodePos()));
+ // We can jump from a bouncy node we collided with this clientstep,
+ // even if we are not "touching" it at the end of clientstep.
+ int standing_node_bouncy = 0;
+ if (result.collides && m_speed.Y > 0.0f) {
+ // must use result.collisions here because sometimes collision_info
+ // is passed in prepopulated with a problematic floor.
+ for (const auto &colinfo : result.collisions) {
+ if (colinfo.axis == COLLISION_AXIS_Y) {
+ // we cannot rely on m_standing_node because "sneak stuff"
+ standing_node_bouncy = itemgroup_get(nodemgr->get(map->getNode(colinfo.node_p)).groups, "bouncy");
+ if (standing_node_bouncy != 0)
+ break;
+ }
+ }
+ }
+
// Determine if jumping is possible
m_disable_jump = itemgroup_get(f.groups, "disable_jump");
- m_can_jump = touching_ground && !m_disable_jump;
+ m_can_jump = (touching_ground || standing_node_bouncy != 0) && !m_disable_jump;
- // Jump key pressed while jumping off from a bouncy block
- if (m_can_jump && control.jump && itemgroup_get(f.groups, "bouncy") &&
- m_speed.Y >= -0.5f * BS) {
- float jumpspeed = movement_speed_jump * physics_override.jump;
- if (m_speed.Y > 1.0f) {
- // Reduce boost when speed already is high
- m_speed.Y += jumpspeed / (1.0f + (m_speed.Y / 16.0f));
+ // Jump/Sneak key pressed while bouncing from a bouncy block
+ float jumpspeed = movement_speed_jump * physics_override.jump;
+ if (m_can_jump && (control.jump || control.sneak) && standing_node_bouncy > 0) {
+ // controllable (>0) bouncy block
+ if (!control.jump) {
+ // sneak pressed, but not jump
+ // Subjective testing indicates 1/3 bounce decrease works well.
+ jumpspeed = -m_speed.Y / 3.0f;
} else {
- m_speed.Y += jumpspeed;
+ // jump pressed
+ // Reduce boost when speed already is high
+ jumpspeed = jumpspeed / (1.0f + (m_speed.Y * 2.8f / jumpspeed));
}
+ m_speed.Y += jumpspeed;
setSpeed(m_speed);
m_can_jump = false;
+ } else if(m_speed.Y > jumpspeed && standing_node_bouncy < 0) {
+ // uncontrollable bouncy is limited to normal jump height.
+ m_can_jump = false;
}
// Autojump