Sneak glitch: Detect ledge for 2-node climb-up
authorparamat <mat.gregory@virginmedia.com>
Thu, 6 Apr 2017 14:58:12 +0000 (15:58 +0100)
committerparamat <mat.gregory@virginmedia.com>
Tue, 11 Apr 2017 04:41:13 +0000 (05:41 +0100)
Re-creates the old sneak-jump behaviour in new code.
Enabled by the 'sneak glitch' physics override.
When a ledge is detected the jump speed modifier is set to the larger
of 'physics override jump' and 1.3 to allow a 2-node climb-up.

An unexpected side-effect is the simple sneak ladder working smoothly.

src/localplayer.cpp
src/localplayer.h

index 4bf3012dd9e78650a674180dda2d47af1499c969..9dc3bf5aa87446568b95599da711b428326b2a01 100644 (file)
@@ -70,6 +70,7 @@ LocalPlayer::LocalPlayer(Client *client, const char *name):
        m_sneak_node_exists(false),
        m_need_to_get_new_sneak_node(true),
        m_sneak_ladder_detected(false),
+       m_ledge_detected(false),
        m_old_node_below(32767,32767,32767),
        m_old_node_below_type("air"),
        m_can_jump(false),
@@ -149,6 +150,29 @@ static bool detectSneakLadder(Map *map, INodeDefManager *nodemgr, v3s16 pos)
        return false;
 }
 
+static bool detectLedge(Map *map, INodeDefManager *nodemgr, v3s16 pos)
+{
+       bool is_valid_position;
+       MapNode node;
+       // X/Z vectors for 4 neighboring nodes
+       static const v2s16 vecs[] = {v2s16(-1, 0), v2s16(1, 0), v2s16(0, -1), v2s16(0, 1)};
+
+       for (u16 i = 0; i < ARRLEN(vecs); i++) {
+               const v2s16 vec = vecs[i];
+
+               node = GETNODE(map, pos, vec, 1, &is_valid_position);
+               if (is_valid_position && nodemgr->get(node).walkable) {
+                       // Ledge exists
+                       node = GETNODE(map, pos, vec, 2, &is_valid_position);
+                       if (is_valid_position && !nodemgr->get(node).walkable)
+                               // Space above ledge exists
+                               return true;
+               }
+       }
+
+       return false;
+}
+
 #undef GETNODE
 
 void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
@@ -409,6 +433,13 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
                }
        }
 
+       /*
+               If 'sneak glitch' enabled detect ledge for old sneak-jump
+               behaviour of climbing onto a ledge 2 nodes up.
+       */
+       if (physics_override_sneak_glitch && control.sneak && control.jump)
+               m_ledge_detected = detectLedge(map, nodemgr, floatToInt(position, BS));
+
        /*
                Set new position
        */
@@ -648,10 +679,18 @@ void LocalPlayer::applyControl(float dtime)
                                at its starting value
                        */
                        v3f speedJ = getSpeed();
-                       if(speedJ.Y >= -0.5 * BS)
-                       {
-                               speedJ.Y = movement_speed_jump * physics_override_jump;
-                               setSpeed(speedJ);
+                       if(speedJ.Y >= -0.5 * BS) {
+                               if (m_ledge_detected) {
+                                       // Limit jump speed to a minimum that allows
+                                       // jumping up onto a ledge 2 nodes up.
+                                       speedJ.Y = movement_speed_jump *
+                                                       MYMAX(physics_override_jump, 1.3f);
+                                       setSpeed(speedJ);
+                                       m_ledge_detected = false;
+                               } else {
+                                       speedJ.Y = movement_speed_jump * physics_override_jump;
+                                       setSpeed(speedJ);
+                               }
 
                                MtEvent *e = new SimpleTriggerEvent("PlayerJump");
                                m_client->event()->put(e);
index cac371cf1529f5061750cbec236731eb3e45d7b7..ae987b893bb22222e5f30ecbbfb95d1419385e79 100644 (file)
@@ -146,6 +146,9 @@ private:
        // Whether a "sneak ladder" structure is detected at the players pos
        // see detectSneakLadder() in the .cpp for more info (always false if disabled)
        bool m_sneak_ladder_detected;
+       // Whether a 2-node-up ledge is detected at the players pos,
+       // see detectLedge() in the .cpp for more info (always false if disabled).
+       bool m_ledge_detected;
 
        // Node below player, used to determine whether it has been removed,
        // and its old type