Perfect Dark Collision Detection: Difference between revisions

From The Elite Wiki
Jump to: navigation, search
m (Fix links to headings)
m (Fix links again)
 
Line 208: Line 208:
=== Lifts ===
=== Lifts ===


If the player is in a lift, the ground value returned will be the lift floor's Y value. The game compares the ground value with the previous frame's ground value to see how much they moved and in what direction. If ascending and the lift has a flag to make it do ceiling checks, the game will check if the player is being squished into the ceiling (see [https://wiki.the-elite.net/wiki/Perfect_Dark_Collision_Detection#Volume tests Volume Tests]). If all is well then the player's Y value will be updated according to the lift's movement amount. If the player is being squished into the ceiling then their Y value won't be updated and they'll likely clip through the lift.
If the player is in a lift, the ground value returned will be the lift floor's Y value. The game compares the ground value with the previous frame's ground value to see how much they moved and in what direction. If ascending and the lift has a flag to make it do ceiling checks, the game will check if the player is being squished into the ceiling (see [https://wiki.the-elite.net/wiki/Perfect_Dark_Collision_Detection#Volume_tests Volume Tests]). If all is well then the player's Y value will be updated according to the lift's movement amount. If the player is being squished into the ceiling then their Y value won't be updated and they'll likely clip through the lift.


=== Ladders ===
=== Ladders ===


If the player is on a ladder and off the ground (according to the ground value returned earlier) then the game attempts to move them up or down in their climb direction. If a collision occurs (see [https://wiki.the-elite.net/wiki/Perfect_Dark_Collision_Detection#Volume tests Volume Tests]) then they are not moved. This can happen due to ascending and hitting a ceiling, or descending and hitting the top of an object or guard who is in the way.
If the player is on a ladder and off the ground (according to the ground value returned earlier) then the game attempts to move them up or down in their climb direction. If a collision occurs (see [https://wiki.the-elite.net/wiki/Perfect_Dark_Collision_Detection#Volume_tests Volume Tests]) then they are not moved. This can happen due to ascending and hitting a ceiling, or descending and hitting the top of an object or guard who is in the way.


If the player is on a ladder but the ground value paired with the player's descend speed would suggest that they're reaching the ground, the game will attempt to move them onto the ground. If a collision occurs (see [https://wiki.the-elite.net/wiki/Perfect_Dark_Collision_Detection#Volume tests Volume Tests]) then they will stay where they are on the ladder. If no collision occurs then they are placed on the ground and no longer on the ladder.
If the player is on a ladder but the ground value paired with the player's descend speed would suggest that they're reaching the ground, the game will attempt to move them onto the ground. If a collision occurs (see [https://wiki.the-elite.net/wiki/Perfect_Dark_Collision_Detection#Volume_tests Volume Tests]) then they will stay where they are on the ladder. If no collision occurs then they are placed on the ground and no longer on the ladder.


=== Ascending ===
=== Ascending ===
Line 222: Line 222:
If the ground value returned by the collision system is higher than the player's feet, the game will ascend the player but smoothed over a few frames. This is done to remove any jaggedness when going up a staircase. If you are moving fast and the staircase is steep enough, you may notice your face gets close to the steps before the "spring" kicks in and bounces you up. This is why.
If the ground value returned by the collision system is higher than the player's feet, the game will ascend the player but smoothed over a few frames. This is done to remove any jaggedness when going up a staircase. If you are moving fast and the staircase is steep enough, you may notice your face gets close to the steps before the "spring" kicks in and bounces you up. This is why.


When ascending, collision checks take place (see [https://wiki.the-elite.net/wiki/Perfect_Dark_Collision_Detection#Volume tests Volume Tests]). If the collision hits something then the player's ascension is stopped. If the player hits a hoverbike, it will blow up.
When ascending, collision checks take place (see [https://wiki.the-elite.net/wiki/Perfect_Dark_Collision_Detection#Volume_tests Volume Tests]). If the collision hits something then the player's ascension is stopped. If the player hits a hoverbike, it will blow up.


=== Falling ===
=== Falling ===


If the ground value returned by the collision system is below the player's feet, the game will calculate or increment the fall speed and do a collision check (see [https://wiki.the-elite.net/wiki/Perfect_Dark_Collision_Detection#Volume tests Volume Tests]).
If the ground value returned by the collision system is below the player's feet, the game will calculate or increment the fall speed and do a collision check (see [https://wiki.the-elite.net/wiki/Perfect_Dark_Collision_Detection#Volume_tests Volume Tests]).


* If there is no collision then the player continues falling for up to 4 seconds at which point they will automatically die.
* If there is no collision then the player continues falling for up to 4 seconds at which point they will automatically die.

Latest revision as of 00:27, 15 March 2025

Metrics

Where three numbers are used, this refers to crouching/ducking/standing. Where one number is used it's the same regardless of crouch state.

Normal gameplay (no cheats)
Metric Joanna Mr Blonde Elvis Hoverbike
Radius 30 30 30 90
Eye height 159 169 106 159
Height 172 182 133 172
Y pos Feet + 69/114/159 Feet + 74/122/169 Feet + 69/88/106 Ground + ~163
Collision ymin Feet + 30 Feet + 30 Feet + 30 Ground + 20
Collision ymax Feet + 82/127/172 Feet + 87/135/182 Feet + 96/115/133 Ground + 136

When using the Small Jo cheat, all metrics are the same as being double crouched normally. This is likely to avoid any unexpected collision issues due to a smaller bounding box:

When using the Small Jo cheat
Metric Joanna Mr Blonde Elvis Hoverbike
Radius 30 30 30 90
Eye height 159 169 106 159
Height 172 182 133 172
Y pos Feet + 69 Feet + 69 Feet + 69 Ground + ~163
Collision ymin Feet + 30 Feet + 30 Feet + 30 Ground + 20
Collision ymax Feet + 82 Feet + 82 Feet + 96 Ground + 136

Geometry Types

There are 4 types of geometry:

  • Integer Tiles (GEOTYPE_TILE_I): An integer tile is a tile with integer vertices. This is the most common geometry. Everything in a stage's data file is an integer tile. An integer tile supports up to 64 vertices but the game uses at most 12 in one tile. Most of these are triangles or quads. When 4 or more vertices are used, they must all lie on the same plane. Integer tiles are never created or moved dynamically during gameplay; they only exist in the stage's tile data file.
  • Float Tiles (GEOTYPE_TILE_F): A float tile is a tile with floating point (ie. decimal) vertices. They are created and updated automatically by lifts, escalators and certain doors.
  • Blocks (GEOTYPE_BLOCK): A block geometry is something with 3-8 corners (X/Z) plus a bottom Y and top Y. For example, desks have 4 corners. Most objects use block geometry.
  • Cylinders (GEOTYPE_CYL): A cylinder geometry has a bottom Y, top Y and a radius. They are used for all characters in the game, including Joanna, Dr Caroll and the Chicago robot. Some objects can also use cylinder geometry, such as hoverbikes.

The player's cylinder bottom is at roughly knee height (30cm above feet). For other characters the cylinder bottom is at their feet.

Geometry Flags

Each geometry type can have flags. All geometry types use the same set of flags, although it doesn't make sense to set a character's cylinder as a climbable ladder.

For integer tiles, flags are set in the stage's tile data file. For the other geometry types, they are set automatically when created. Once geometry flags are set they are never changed.

GEOFLAG_FLOOR1 (0001) and GEOFLAG_FLOOR2 (0002)

Almost all walkable tiles in the game have both of these flags. FLOOR1 allows the tile to be used in lookahead calculations even at short distance. FLOOR2 is nothing special. When looking for floor tiles the game will look for tiles with either flag.

The game uses floor tiles to find the ground Y value. They are only used for vertical movement. For horizontal movement they are completely ignored.

GEOFLAG_WALL (0004)

Tiles with this flag will block both your horizontal and vertical movement. The developers didn't intend for you to be able to land on wall tiles, but if you do you can walk around on them.

Most wall tiles are implemented using just a bounding box. This means that a wall tile that is a quad tile on an incline is effectively a rectangular prism when it comes to preventing movement.

Because Jo's cylinder bottom is 30cm above her feet, all wall tiles must reach this height to be able to block her movement.

GEOFLAG_BLOCK_SIGHT (0008) and GEOFLAG_BLOCK_SHOOT (0010)

The player's shots will hit rendered polygons, but sight and shots by guards and other characters are based on geometry.

These flags denote which geometry will block a character's sight or shots. Almost all floor and wall tiles have both of these flags set, as well as objects and characters. Places where it makes sense to not have these flags include catwalks, railings, and the circular room in Deep Sea SA/PA immediately after the first teleport.

A gap in wall tiles may result in a line of sight check passing when it shouldn't. Each line of sight test can specify whether a line going out of bounds should fail the test or not, so it depends on the purpose of the test.

GEOFLAG_LIFTFLOOR (0020)

Each lift creates its own geometry. The lift's floor tile is automatically given this flag, along with GEOFLAG_FLOOR1, GEOFLAG_FLOOR2 and a few others.

GEOFLAG_LADDER (0040)

Tiles with this flag can be climbed by both players and guards.

GEOFLAG_RAMPWALL (0080)

As mentioned earlier, wall tiles are implemented with a simple bounding box check. This means a single vertical wall triangle is treated like a quad, so if a player gets on top of it then they can move across it.

This works fine for most walls, but it's a problem for wall triangles which are used as the side of a ramp or staircase without railings. The player will be unable to jump off the ramp part-way up because of the bounding box check. If GEOFLAG_RAMPWALL is set on the wall, the game will do a more expensive calculation to find out if the player is colliding with the triangle, taking the slope of the triangle into account.

In Investigation, on the little ramps near the lasers, the lack of this flag on the ramp sides is what prevents you from walking halfway up then off into the laser. The lack of the flag is also what allows you to walk across the top edge of the side and then jump off, making the laser skip possible.

On Villa's outside staircase where we jump onto the railing, the railing wall is split into two tiles, one taller than the other, and neither of them have this flag. This means we have to clear the first triangle's length so we can land on the lower one. If these walls used GEOFLAG_RAMPWALL then the tile geometry would be the same as what's visually rendered and we'd be able to jump onto it more easily.

GEOFLAG_SLOPE (0100)

This is an optimisation flag, used in conjunction with GEOFLAG_RAMPWALL (see above).

GEOFLAG_SLOPE is given to both the ramp floor and the ramp wall. Then, if the player is on the ramp and attempts to walk off it through the wall's bounding box, the game can avoid having to calculate their collision with the ramp wall because it knows they were just on the ramp and therefore cannot hit it.

GEOFLAG_UNDERWATER (0200)

Tiles with this flag will have their floortype set to water by the collision system, instead of using whatever is in the tile data. The floortype affects the sound it makes when you walk on it or shoot it. The flag seems unnecessary as the floortype could have just been set in the data.

GEOFLAG_0400 (0400)

No tiles exist with this flag and it also isn't read by the collision system, but it's included here anyway.

GEOFLAG_AIBOTCROUCH (0800) and GEOFLAG_AIBOTDUCK (1000)

Used only in multiplayer arenas. Simulants who walk on these tiles will duck or crouch. It's used in tight spaces such as the Warehouse and Felicity vents.

GEOFLAG_STEP (2000)

Also known as the upwarp flag.

This flag is set on steep, traversable slopes such as the staircases in Pelagic II, as well as the floor above it. Without the flag, a player may clip through the staircase if moving at high-speed. With the flag, the collision system will allow the tile to be used as a ground value even if it's above the player, which will result in them warping up onto the tile instead of falling out of bounds.

It only works if the player is in the same room as the tile.

GEOFLAG_DIE (4000)

Landing on this tile will kill the player. They are placed mostly in the Skedar Ruins ravine. Note that even without this flag, the player will die if they reach the death barrier (Y value -30000) or has been falling for 4 seconds.

GEOFLAG_LADDER_PLAYERONLY (8000)

Tiles with this flag can be climbed by players but not guards. Used in most ledges in Chicago.

Horizontal Movement

On each frame, the game calculates a desired position for Jo to move to then does a series of tests to figure out the final position. Each time a test passes, Jo's position will be updated to the tested position. Each time a test fails, Jo's position is left unchanged by that test. Jo can go through several position changes in one frame as it figures out her final position for that frame.

High level overview

For brevity, I've simplified the decision tree into three common scenarios.

Scenario #1: No obstacles

  • The game tests the requested position. It is free of obstacles, and the test has updated Jo's position, so it doesn't need to do anything else.

Scenario #2: Colliding with a wall (or other obstacle)

  • The game tests the requested position. It finds there's a wall in the way. Jo's position has not changed.
  • The game calculates the position a quarter of the distance to the wall and tests it. This test passes. Jo's position is changed.
  • The game calculates a position that has slid parallel to the wall and tests it. This test passes. Jo's position is changed again.

The final test is not done if the player is R-leaning, so you don't slide along a wall during R-leans.

The quarter distance check is likely done to make the player hug the wall smoothly instead of stopping abruptly.

Scenario #3: Colliding with both a wall and a closer obstacle

  • The game tests the requested position. It finds there's a wall in the way.
  • The game calculates the position a quarter of the distance to the wall and tests it. It finds there's a second, closer obstacle within this quarter distance.
  • The game calculates the position a quarter of the distance to the closer obstacle and tests it. We'll assume this test passes.
  • The game calculates a position that has slid parallel to the closer obstacle and tests it. This test passes. Jo's position is changed again.

The final test is not done if R-leaning.

In this scenario, if some of the later tests fail then some further tests (not documented above) are done.

Test logic

The game will do different tests depending on the player's speed. If the player is moving slowly (half their radius or less on this frame, ie. <= 15cm) then the low-speed test is done. If they are moving fast (> 15cm on this frame) then the high-speed tests are done. This check is actually not a true speed test, but is done per axis, meaning you could be moving at 14cm in the X direction and 14cm in the Z direction for a total of 19.8cm and still get the low-speed test. This is important when it comes to out of bounds movement on the hoverbike, which is explained later on in this page.

The low-speed test does a cylinder volume test:

  • It looks for geometry with GEOFLAG_WALL which intersects with the destination cylinder position. Floor geometry is ignored. If there are multiple geometry colliding with the destination then the collision system uses the move direction to determine which geometry would be hit first so it can determine which edge is hit.

The high-speed test attempts to do two things:

  • A cylinder move test from the old to the new position, failing if any geometry intersects the path or if the destination is out of bounds. It looks for tiles with GEOFLAG_WALL, ignoring floors.
  • If the above test passes, it does the same cylinder volume test as the low-speed test.

The cylinder move test has two flaws:

  1. It doesn't factor Jo's radius into it at all. For the purpose of the test, she is a toothpick. A tall toothpick.
  2. It fails to detect out of bounds in all cases.

It detects out of bounds by tracing a line from the old position at eye height to the new position through portals (doorways) and room bounding boxes. If it crosses into another room, it must be through a portal. If the new position cannot be reached through portals, the portal check returns the last known room. To detect when this happens, the collision system takes the room number returned by the portal check and tests that the room's bounding box covers the destination position. If it doesn't, it concludes that it's out of bounds and will not let Jo move to that position.

But obviously, we are able to clip out of bounds in many places and fall to our deaths. In most cases this is because while the destination position is on the other side of a wall tile, it's still within the bounding box of the room so the collision engine sees it as in bounds. In other cases, such as Defection's rooftop, we are moving too slowly to trigger the high-speed test so the out-of-bounds test does not apply.

This check also affects us while fully out of bounds too. If you are not within the bounding box of any room and are moving quickly, you may experience stuckages. When falling long distances while out of bounds it is usually stopping us from lateral movement too, but it's hard to observe this when you're falling through the void. In Defection, we are moving on a diagonal axis while falling and also don't have much lateral speed due to being recently crouched, so we don't reach the high-speed limits for the test to run.

These rules apply to the hoverbike too. When out of bounds with the hoverbike, the bike doesn't fall so it becomes much more obvious that this is happening.

Vertical Movement

Finding ground Y

On each frame, the game asks the collision system to find the Y value of the ground. This is done by passing the player's current position, rooms and player's radius to the collision system. In this case, "rooms" means any rooms the player is standing in. This is usually a single room but can contain two or more if standing between rooms, such as in a doorway.

The collision system searches for geometry within those rooms which intersect with Jo's radius, ignoring Y. You can think of it as a two-dimensional top-down check. The search is for floor tiles only, meaning wall tiles, blocks and cylinders are ignored. These floor tiles are collected into a list, which is then analysed to decide the ground value.

  • Each tile in the list is checked to see if Jo's centre point is vertically inside the tile or whether her radius is merely overlapping part of the tile. We shall call these on-tile and off-tile geometries.
  • For each on-tile without GEOFLAG_STEP, it finds the Y value of that particular X/Z spot on the tile. It notes the highest one which is still below Jo's current Y value and remembers it as the best.
  • For each on-tile with GEOFLAG_STEP, it finds the Y value of that particular X/Z spot on the tile. If it's higher than the current best but still lower than Jo, or there is no current best (ie. no on-tiles without GEOFLAG_STEP) then it remembers this tile as the best.
  • If there were no on-tiles or any tile in the list has GEOFLAG_SLOPE, then the collision system must search the off-tiles too. It takes the highest Y that is above the previous best yet still below Jo's Y value, unless the tile has GEOFLAG_STEP in which case it can be above Jo.
  • The best Y value is then returned.
  • If the list was empty, the collision system returns a large negative number which will cause Jo to fall.

Lifts

If the player is in a lift, the ground value returned will be the lift floor's Y value. The game compares the ground value with the previous frame's ground value to see how much they moved and in what direction. If ascending and the lift has a flag to make it do ceiling checks, the game will check if the player is being squished into the ceiling (see Volume Tests). If all is well then the player's Y value will be updated according to the lift's movement amount. If the player is being squished into the ceiling then their Y value won't be updated and they'll likely clip through the lift.

Ladders

If the player is on a ladder and off the ground (according to the ground value returned earlier) then the game attempts to move them up or down in their climb direction. If a collision occurs (see Volume Tests) then they are not moved. This can happen due to ascending and hitting a ceiling, or descending and hitting the top of an object or guard who is in the way.

If the player is on a ladder but the ground value paired with the player's descend speed would suggest that they're reaching the ground, the game will attempt to move them onto the ground. If a collision occurs (see Volume Tests) then they will stay where they are on the ladder. If no collision occurs then they are placed on the ground and no longer on the ladder.

Ascending

This applies to stairs, ramps, and upwarps.

If the ground value returned by the collision system is higher than the player's feet, the game will ascend the player but smoothed over a few frames. This is done to remove any jaggedness when going up a staircase. If you are moving fast and the staircase is steep enough, you may notice your face gets close to the steps before the "spring" kicks in and bounces you up. This is why.

When ascending, collision checks take place (see Volume Tests). If the collision hits something then the player's ascension is stopped. If the player hits a hoverbike, it will blow up.

Falling

If the ground value returned by the collision system is below the player's feet, the game will calculate or increment the fall speed and do a collision check (see Volume Tests).

  • If there is no collision then the player continues falling for up to 4 seconds at which point they will automatically die.
  • If there is a collision then the game checks what they've landed on.
    • If it's another character, and that character is in a lift, and it's solo/co-op/counter-op, they are killed (eg. Elvis in Attack Ship).
    • If it's another player, and that player is in a lift, and it's co-op/counter-op mode, the lift-dwelling player is killed.

When landing, there is some code related to absorbing the landing and making some moans, none of which is important for speedrunning.

Volume tests

Many of the features above use the same function to do collision checks after attempting to move the player vertically. These are all a simple cylinder volume test at the new position, comparing against both floors and walls. An unobstructed line to the new location is not required.

Hoverbike

The collision mechanics for horizontal movement on the hoverbike are the same as walking, but using the hoverbike's height and radius instead of Jo's. The hoverbike's radius is 90cm, so to trigger the high-speed tests you need to be travelling at over 45cm in one frame on the X or Z axis.

Vertical movement is handled entirely differently. On each frame, the hoverbike calculates its ground value. This is done using a radius of just 5cm.

  • If the ground value returned from the collision system is below the death barrier then the hoverbike will not change its ground value. This is why it doesn't fall when out of bounds.
  • If the ground value returned from the collision system is above the death barrier then the hoverbike will add 50cm for the hover, plus some variance for bobbing, and transition to it smoothly over several frames. This transition can be rapid (faster than falling) if driving off a ledge, or from high out of bounds into bounds.

You may think that the 5cm radius would allow you to fall through gaps that you wouldn't be able to on foot, and this is true, but there needs to be a floor tile underneath to make the bike fall. Given the limited places where hoverbikes can be used, there is likely no geometry reachable on the bike that meets this criteria.

Mounting

The player must press B twice to mount the hoverbike. The first B press usually results in the player grabbing the bike, however this is not necessary. The first B press is not checked for angles or collisions.

On the second press, the game figures out which object is in front of you. To do this, it iterates the list of on-screen objects.

  • The hoverbike must be within 200cm.
  • The angle must be within 22.5 degrees. I'm not sure if this is each side or total.

These are extremely lax requiremenets for mounting a hoverbike. Provided it's in range and in front of Joanna, she will move through solid geometry to get on the bike, as seen in Infiltration and Escape.

In Escape, the hoverbike isn't actually on-screen but is still in the on-screen props list. This is because the hangar room is on-screen. The hangar room is on-screen because destructable terrain is not a factor in room visibility.

Dismounting

The game tries to dismount in several angles until it finds one that is clear of obstacles. The order is: left, right, front left, front right, back left, back right, directly in front, directly behind. If all angles are blocked then she'll remain on the hoverbike.

When testing each angle:

  • It calculates a position that is the edge of the bike + Jo's radius + 10cm, effectively giving her a 10cm gap to the bike.
  • It traces a line from Jo's eyes to the position, following it through portals/doorways and ignoring geometry. This trace will stop short if it goes out of bounds. The trace returns the last known room number.
  • It checks that the room returned by the above test contains the position in its bounding box. If not, it means the position is through a wall so this angle is considered failed.
  • If all is good so far, it does a cylinder movement test. Using Jo's cylinder height, it checks for geometry that intersects her path off the bike. Only geometry with GEOFLAG_WALL is considered.
  • If the above test passes then the dismount occurs.

Note that the final test does not consider Jo's radius at all, so it's possible for her to clip through thin vertical gaps when dismounting.

Grabbed Objects

When holding on to a crate, hoverbed or hoverbike, the horizontal movement is a simplified version of the walking moment.

  • The game tries to move you to the requested position.
  • If this fails, a quarter step is NOT done. Instead, it tries to move you parallel to the wall/obstacle.

There are special collision checks for turning with a grabbed object. If turning the grabbed object into a wall or other obstacle, it will try to move Jo instead. The exact logic for this is not fully understood, but there are collision tests when moving Jo and they appear to be done correctly.

For vertical movement, the game finds the ground value in the same way as when walking normally, at Jo's position and radius. The game will transition Jo to the new Y value over several frames. When falling, this results in a rapid fall (faster than gravity). However, Jo will automatically let go of any grabbed object if she is at least 50cm above the ground, which makes her enter walking mode and start a normal gravity-based fall.

Out Of Bounds

Room finding

In Perfect Dark, multiple rooms can share the same coordinate space, so you can't simply take a position and figure out which room it's in. It has to be determined using a nearby reference position and room.

Whenever Jo's position coordinates are changed, the game will update her room list too. It does this by doing a line test from her position and room on the previous frame to the new position. The line is traced through portals and neighbouring rooms to determine which room the destination is in. The line is usually very short because you can't move far in one frame, so there's usually only one room involved, or two if crossing between rooms. If the destination is outside of the room's geometry but still within the bounding box of the room, then the player's room is still considered to be this one and all is fine and dandy. Geometry is not a factor in this check.

If the destination is outside of the room's bounding box, then at this point the game knows for sure that you're out of bounds. It will do a room search to find any room containing the destination position within the room's bounding box. If this doesn't yield any results, it will do a room search for any room whose bounding box is underneath the destination position. If this doesn't yield any results then the player's last known room is preserved as their current room. This is then all repeated on the next frame on so on, using the last known room as the reference room.

In Defection, if you land on the outside ring and use the X to enter the programmer's hallway, you will fall straight through the hallway room unless you move backwards towards the glass. This seems to contradict what is written above. After all, if you are out of bounds then it should find your position inside the hallway's room bounding box. The reason for this is that the outside room (room 0009) has a huge bounding box that extends into the tower. When you clip through the wall, the game blieves you are still in that room's bounding box, so it doesn't think you're out of bounds. When you move towards the glass you are touching the portal between the outside room and the hallway room, thus enabling the hallway room.

While out of bounds, we will usually be either:

  1. walking around on the top of wall tiles, in which case we are intersecting that room's bounding box and updating our room to that one, or
  2. falling rapidly towards a quick and certain death, hoping to make it into a room's bounding box before dropping past it.

If we enter a room's bounding box laterally (ie. from the side) then we may find ourselves embedded in a wall tile. This is because only geometry for our current room is tested, and when we enter this room's bounding box we are already intersecting the wall tile. When this happens, we may be able to free ourselves with lag, otherwise we are doomed to remain stuck in the wall for eternity or until we abort (whichever comes first).

Room selection has nothing to do with rooms being loaded or not. All room bounding boxes and collision data is always loaded; it's only the graphics data which is loaded on the fly. If you enter the bounding box of a room that's doesn't have its graphics loaded, the game will load it immediately.

List of Collision Bugs

Clipping horizontally through steep floors

If a floor tile is steep and Joanna is moving quickly, she can move past the tile in a single frame and never read the ground value from it. The developers used GEOFLAG_STEP on these tiles and the floor above to work around this in the most common places, but there are tiles which don't have the flag and are still possible to clip through.

Some notable ones are:

  • Infiltration, near the mine field as per the world record strategy.
  • Crash Site as per the world record strategy.
  • Pelagic II, on the staircases. These have GEOFLAG_STEP, so you need to have enough speed, a good angle and lucky timing to make it past them in one frame.

Using the hoverbike gives you extra speed, which increases the chances of clipping through these tiles.

Clipping vertically through walls

This is the same principle as clipping horizontally through steep floors, but on a different axis. It requires finding a tile with GEOFLAG_WALL which is horizontal or close to it, and having a way to get on top of that wall tile. Once on the tile, with enough lag Jo will fall right through. The player should be crouched to make this easier.

The way it works is pretty simple: When standing on a wall tile the game can't find any ground value so it tries to make Jo fall. It calculates a position a bit below Jo and does a volume test. But it usually finds the wall she's standing on, so the test fails and she stays where she is. With high lag, the tested position will be lower. If the tested position is entirely below the wall, the volume test passes and Jo's position will be updated to below the wall where she'll start a free fall. There is no line of sight check for falling because the game expects to find a ground value.

This is possible in any place where you can stand on a wall tile, even vertical ones, provided you can create enough lag. In most cases you can just walk off them into out of bounds anyway, so this expoit is only useful if there's another wall tile next you to preventing that. And of course, there has to be something below you that is worth getting to.

The only known practical application for this is in Deep Sea, in the room above the SA megaweapon activation area. Some wall tiles along the edge of the room are lower than the floor next to them, allowing you to drop onto the wall and then clip through with lag. It's been proven that you need to achieve a frame rate of 3 frames per second or lower to make it occur in this spot.

T junctions

A T junction is where three floor tiles intersect, but don't share a vertex in common. For example:

    ___________
   |           |
   |___________|
   |     |     |
   |_____|_____|

Here are 3 quads, but the top quad does not have a vertex in the middle of the diagram. This can happen with triangles too, or a mix between each.

When a T junction occurs, and the top edge of the T does not align to the X or Z axis, a bug occurs where a gap is created. Because the game uses floating point decimals for coordinates, and floats are only approximations of numbers, it is possible for a player to have an X/Z coordinate that fails the point-in-tile test for all three tiles when calculating the ground value. This effectively means the player is standing in a thin gap between tiles.

Falling through gaps

When the player is standing in a small gap between tiles (either due to a T junction, misaligned vertices, or a missing floor tile), there is a chance that the player will fall through it. I'm talking about gaps that are smaller than Jo is fat. Refer to section "Finding ground Y".

  • If there is a floor tile in the same room underneath the gap, and the player's centre point is vertically "in" that tile, the ground value of that tile will be returned, causing the player to start falling.
  • If there is no floor tile underneath, the game finds the tiles partially overlapping her radius and correctly figures out the Y value based on that, resulting in her staying where she is.

Of course, if there's a gap that is wider than Jo's fatness then she'll fall right through even if there's no tile underneath. The only place where this can unintentionally happen is in the Ruins (MP) arena, near the big rectangular outdoor room, in the doorway.

Clipping through gaps in walls

For a wall clip to work:

  • There must be a vertical gap in the wall, even a tiny one.
  • The angle of the player's movement must go through the gap.
  • The position that the game wants to put Jo in must pass a cylinder volume test, for geometry using GEOFLAG_WALL. In other words, the destination position must be free of collisions.
  • The gap must be tall enough to fit Jo's height.
  • The destination position on the other side must be within the current room's bounding box.

When the game is lagging, the distance Jo wants to move is bigger to compensate. Therefore, with higher lag Jo has a higher chance of clearing the wall geometry and moving into a vacant space.

This is also the mechanic behind door warping in GoldenEye. You can door warp in Perfect Dark, but most doors open quickly and it is difficult to time a weapon switch to induce lag.

Upwarps

If you manage to get underneath a tile which has GEOFLAG_STEP, and that tile is in Jo's last known room, Jo will warp up to the tile even if it's a huge distance. This is by design, although perhaps not intended to be used at huge distances.

There is one known place where an upwarp can occur while in bounds. In the Skedar (MP) arena, in the big room with four ramps, if you stand on the bottom floor against the wall you can warp up with a bit of luck. The requirements for this to work are:

  • The floor tile on top of the ledge must have GEOFLAG_STEP.
  • The ledge must not be aligned to the X or Z axis.

This happens due to a float precision issue where the collision system calculates that you are ever so slightly overlapping the GEOFLAG_STEP tile, causing you to warp up.

Ascending forever (multiplayer)

Some multiplayer arenas (eg. Sewers) have lifts without roofs. If one player stands on the lift and another player lands on their head, the higher player will ascend when the lift rises but remain floating in the air when the lift descends. When the lift rises again, they will continue to ascend.

This only works when landing on human players, not simulants. And it only works in multiplayer player because guards will die if you jump on them in a lift in solo missions.

It is unknown why this occurs.