Crouch Flying Glitch

From P2SR Wiki

Revision as of 11:51, 28 October 2020 by BigDaniel (talk | contribs)

Crouch Flying Glitch


Overview

Technical Explanation

Written by: Krzyhau

Introduction

Crouch Flying Glitch (also known as CFG, Funnel Fly, Excursion Funnel Glitch or ExFu Glitch) is a glitch found the day Portal 2 was released. It lets you preserve the anti-gravity aspect of a funnel outside of it, allowing you to basically fly anywhere you want. While the glitch is heavily used in full game and Challenge Mode speedruns, it wasn’t fully understood apart from the fact that you need to crouch/uncrouch within a funnel while being completely still. In this document, using my knowledge about this game’s engine, my own observations and partially leaked source code of Portal 2 that happened in April 2020, I’ll try to lay out the general principles and technical details about Crouch Flying Glitch.


Physics System

Before I explain the logic behind excursion funnels, I need to mention certain aspects of physics in this game.

The game operates on two physics simulations: Qphysics and Vphysics. Qphysics (Quake physics) is a simple hull-based physics engine which is used for interactions with world brushes, players, NPCs and brush-based entities (like func_door). Vphysics (Havok physics) is much more advanced physics engine designed to simulate Newtonian Mechanics. It’s used by almost every prop and physics based entity in this game.

Some entities, like player, uses both physics engines. While movement is handled mostly by Qphys, all physics interaction are computed by Vphysics. You can observe both of them in action using developer 1 and ent_bbox player in the console and then walking around (orange wireframe is Qphys, yellow box is Vphys).

There’s a lot to talk about Vphys but one aspect we’re interested in the most right now is Vphys object being asleep. Generally speaking, when object stops moving completely, it becomes asleep and is ignored by physics simulation, probably to save computing power. Then, when the object is awaken by other objects or internal changes, physics simulation on the object is resumed. This property is one of key components of Crouch Fly Glitch and I’ll get back to it later.

One last important thing to note is that the player entity, apart from having its own Qphys collision hull, it also has two Vphys shadow models - one for standing and one for crouching, and the game switches their collision state depending on current player’s crouching state (if you’re crouching, standing shadow model’s collision is disabled and crouching one is enabled, and vice versa).

The glitch is mostly related to Vphys, so you don’t need to bother about Qphys. Just be aware that it exists lmao.

Funnels

Funnels are projected trigger-based entities. Almost entire of player and funnel interaction system is included within these three functions:

  1. Entering the funnel trigger CPortal_Player::SetInTractorBeam(CTrigger_TractorBeam*)(github leak link)
  2. Leaving the funnel trigger CPortal_Player::SetLeaveTractorBeam(CTrigger_TractorBeam*, bool)(github leak link)
  3. Movement within the funnel CPortalGameMovement::TBeamMove() (github leak link)

From this code leak we know that the game operates on two variables: m_nTractorBeamCount, keeping track of how many funnels player is in. m_hTractorBeam, containing a funnel the game should use to calculate movement.

When the game detects player entering the funnel, proper funnel handle is set, counter is increased and player’s gravity is set to basically 0.

When the game detects player exiting the funnel, counter is decreased and only when it reaches 0, the gravity is reset to default value. When it’s bigger than 0, the game looks for new funnel handle (if no new funnel handle [different than a previous one] is found, the handle is left as NULL).

Also, it’s important to say that both of player’s Vphys shadows can both enter and exit funnel on their own, meaning that entering funnel with crouched Vphys shadow model is a separate event from entering funnel with standing Vphys shadow model, even though they both execute the same function.

CFG explanation

Now that you know all the theory behind physics and funnels, let me briefly explain what this glitch is about (if you haven’t figured it out by yourself already):

Normally, when player (un)crouches within a funnel, the game detects the previous Vphys shadow leaving the funnel (its collision is disabled, meaning it’s no longer touching the funnel) and the new one entering it, so the counter basically remains the same and the only suspicious thing is the sound caused by the new Vphys shadow entering it.

But when player (un)crouches after being completely still, the game does not detect previous Vphys shadow leaving the funnel (it’s asleep, so no physics updates are made on this vphys object), meaning that player enters the funnel second time, bringing the funnel counter to 2. Thanks to this, leaving the funnel right now brings the counter to 1 (even though player is not in any funnel at this point), allowing them to keep the low gravity. Updating vphys shadow by changing its state/funnel state causes it to leave the funnel, effectively getting rid of the glitch.

Simple, right?!

NAQ (Never Asked Questions)

Q: Why preserving funnel fly after save/map loading is a thing? And why it’s gone when I’m touching a funnel after that?

A: When transitioning/loading a save, the game preserves the low gravity but nothing related to funnels/vphys shadows within player object. This means, the game is functioning as usual, except you have low gravity before touching a funnel.

Q: Wait, does that mean it’s possible to get the counter to 2, then leave the funnel with one of Vphys shadows by (un)crouching to clear the funnel handle but still having the low gravity effect, effectively being able to fly within the funnel but in opposite direction?

A: yes.

Q: Could you do the same with trigger_once? Funnels are trigger-based entities, right?

A: uhh idk

Q: Can I get a simplified version of this explanation, for my easy-to-grasp-copy-pasta needs?

A: Here you go:

Player entity has two hitboxes for physics purposes: one for standing and one for crouching. When you enter a funnel and stop moving, your current hitbox becomes inactive, so when you switch to the other one, the game won’t detect the previous one leaving the funnel. Thanks to that, the game will think you’re in two funnels. If you then exit it, it will still think you’re in one funnel, retaining the anti-gravity effect. Of course, it’s slightly more complicated than that but I would need at least two pages to explain everything.