You've already forked Microtransactions64
mirror of
https://github.com/Print-and-Panic/Microtransactions64.git
synced 2026-01-21 10:17:19 -08:00
Merge remote-tracking branch 'thecozies/water-surface-type'
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
* linker script syntax.
|
||||
*/
|
||||
|
||||
#define USE_EXT_RAM
|
||||
#ifndef USE_EXT_RAM
|
||||
#define RAM_END 0x80400000
|
||||
#else
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
// Surface Types
|
||||
#define SURFACE_DEFAULT 0x0000 // Environment default
|
||||
#define SURFACE_BURNING 0x0001 // Lava / Frostbite (in SL), but is used mostly for Lava
|
||||
#define SURFACE_NEW_WATER 0x0002 // Custom water surface
|
||||
#define SURFACE_NEW_WATER_BOTTOM 0x0003 // Custom water surface bottom marker
|
||||
#define SURFACE_0004 0x0004 // Unused, has no function and has parameters
|
||||
#define SURFACE_HANGABLE 0x0005 // Ceiling that Mario can climb on
|
||||
#define SURFACE_SLOW 0x0009 // Slow down Mario, unused
|
||||
|
||||
80
src/engine/extended_bounds.h
Normal file
80
src/engine/extended_bounds.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#ifndef __EXTENDED_BOUNDS_H__
|
||||
#define __EXTENDED_BOUNDS_H__
|
||||
|
||||
/*
|
||||
Better Extended Bounds by anonymous_moose
|
||||
Thanks to someone2639 for the shiftable segments patch
|
||||
Thanks to Wiseguy for the Surface Pool Full error code and 4x bounds fix
|
||||
|
||||
0: Regular bounds
|
||||
Same as vanilla sm64, boundaries are (-8192 to 8191)
|
||||
16x16 collision cells.
|
||||
1: 2x extended bounds
|
||||
level boundaries are twice as big (-16384 to 16383)
|
||||
Collision calculations remain as fast as vanilla, at the cost of using more RAM.
|
||||
32x32 collision cells.
|
||||
2: Regular bounds (performance)
|
||||
Same boundaries as vanilla (-8192 to 8191), but with twice the amount of collision cells
|
||||
Trades more RAM usage for faster collision calculations.
|
||||
32x32 collision cells.
|
||||
3: 4x extended bounds
|
||||
level boundaries are 4 times as big (-32768 to 32767)
|
||||
Collision calculations remain as fast as vanilla, at the cost of using far more RAM (16 times vanilla).
|
||||
64x64 collision cells.
|
||||
|
||||
|
||||
If you see "SURFACE POOL FULL" or "SURFACE NODE POOL FULL" in game, you should increase
|
||||
SURFACE_POOL_SIZE or SURFACE_NODE_POOL_SIZE, respectively, or reduce the amount of
|
||||
collision surfaces in your level.
|
||||
*/
|
||||
|
||||
//for the static assert macro
|
||||
#include "macros.h"
|
||||
|
||||
//set this to the extended bounds mode you want, then do "make clean".
|
||||
#define EXTENDED_BOUNDS_MODE 1
|
||||
|
||||
//the maximum amount of collision surfaces (static and dynamic combined)
|
||||
//8200 should work fine for a 2x extended stage, the vanilla value is 2300
|
||||
#define SURFACE_POOL_SIZE 4000
|
||||
|
||||
//make this approximately (amount of collision cells) + (SURFACE_POOL_SIZE * 3)
|
||||
//22000 should work fine for a 2x extended stage, the vanilla value is 7000
|
||||
#define SURFACE_NODE_POOL_SIZE 12000
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//don't touch the stuff past this point unless you know what you're doing!
|
||||
|
||||
//default value to check if the user set a proper extended bounds mode
|
||||
#define LEVEL_BOUNDARY_MAX 0x0000
|
||||
|
||||
#if EXTENDED_BOUNDS_MODE == 0
|
||||
#undef LEVEL_BOUNDARY_MAX // Undefine the old value to avoid compiler warnings
|
||||
#define LEVEL_BOUNDARY_MAX 0x2000L
|
||||
#define CELL_SIZE 0x400
|
||||
#elif EXTENDED_BOUNDS_MODE == 1
|
||||
#undef LEVEL_BOUNDARY_MAX
|
||||
#define LEVEL_BOUNDARY_MAX 0x4000L
|
||||
#define CELL_SIZE 0x400
|
||||
#elif EXTENDED_BOUNDS_MODE == 2
|
||||
#undef LEVEL_BOUNDARY_MAX
|
||||
#define LEVEL_BOUNDARY_MAX 0x2000L
|
||||
#define CELL_SIZE 0x200
|
||||
#elif EXTENDED_BOUNDS_MODE == 3
|
||||
#undef LEVEL_BOUNDARY_MAX
|
||||
#define LEVEL_BOUNDARY_MAX 0x8000L
|
||||
#define CELL_SIZE 0x400
|
||||
#endif
|
||||
|
||||
STATIC_ASSERT(LEVEL_BOUNDARY_MAX != 0, "You must set a valid extended bounds mode!");
|
||||
|
||||
#define NUM_CELLS (2 * LEVEL_BOUNDARY_MAX / CELL_SIZE)
|
||||
|
||||
#define NOT_ENOUGH_ROOM_FOR_SURFACES (1 << 0)
|
||||
#define NOT_ENOUGH_ROOM_FOR_NODES (1 << 1)
|
||||
|
||||
|
||||
#endif // __EXTENDED_BOUNDS_H__
|
||||
@@ -110,12 +110,12 @@ static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode,
|
||||
|
||||
// Determine if checking for the camera or not.
|
||||
if (gCheckingSurfaceCollisionsForCamera) {
|
||||
if (surf->flags & SURFACE_FLAG_NO_CAM_COLLISION) {
|
||||
if (surf->flags & SURFACE_FLAG_NO_CAM_COLLISION || surf->type == SURFACE_NEW_WATER || surf->type == SURFACE_NEW_WATER_BOTTOM) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Ignore camera only surfaces.
|
||||
if (surf->type == SURFACE_CAMERA_BOUNDARY) {
|
||||
if (surf->type == SURFACE_CAMERA_BOUNDARY || surf->type == SURFACE_NEW_WATER || surf->type == SURFACE_NEW_WATER_BOTTOM) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -257,12 +257,12 @@ static struct Surface *find_ceil_from_list(struct SurfaceNode *surfaceNode, s32
|
||||
|
||||
// Determine if checking for the camera or not.
|
||||
if (gCheckingSurfaceCollisionsForCamera != 0) {
|
||||
if (surf->flags & SURFACE_FLAG_NO_CAM_COLLISION) {
|
||||
if (surf->flags & SURFACE_FLAG_NO_CAM_COLLISION || surf->type == SURFACE_NEW_WATER || surf->type == SURFACE_NEW_WATER_BOTTOM) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Ignore camera only surfaces.
|
||||
else if (surf->type == SURFACE_CAMERA_BOUNDARY) {
|
||||
else if (surf->type == SURFACE_CAMERA_BOUNDARY || surf->type == SURFACE_NEW_WATER || surf->type == SURFACE_NEW_WATER_BOTTOM) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -432,7 +432,7 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
|
||||
|
||||
// Determine if we are checking for the camera or not.
|
||||
if (gCheckingSurfaceCollisionsForCamera != 0) {
|
||||
if (surf->flags & SURFACE_FLAG_NO_CAM_COLLISION) {
|
||||
if (surf->flags & SURFACE_FLAG_NO_CAM_COLLISION || surf->type == SURFACE_NEW_WATER || surf->type == SURFACE_NEW_WATER_BOTTOM) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -468,6 +468,77 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
|
||||
return floor;
|
||||
}
|
||||
|
||||
static s16 check_within_triangle_bounds(s32 x, s32 z, struct Surface *surf) {
|
||||
register s32 x1, z1, x2, z2, x3, z3;
|
||||
x1 = surf->vertex1[0];
|
||||
z1 = surf->vertex1[2];
|
||||
x2 = surf->vertex2[0];
|
||||
z2 = surf->vertex2[2];
|
||||
|
||||
if ((z1 - z) * (x2 - x1) - (x1 - x) * (z2 - z1) < 0) return FALSE;
|
||||
|
||||
x3 = surf->vertex3[0];
|
||||
z3 = surf->vertex3[2];
|
||||
|
||||
if ((z2 - z) * (x3 - x2) - (x2 - x) * (z3 - z2) < 0) return FALSE;
|
||||
if ((z3 - z) * (x1 - x3) - (x3 - x) * (z1 - z3) < 0) return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Find the height of the floor at a given location
|
||||
static f32 get_floor_height_at_location(s32 x, s32 z, struct Surface *surf) {
|
||||
return -(x * surf->normal.x + surf->normal.z * z + surf->originOffset) / surf->normal.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through the list of water floors and find the first water floor under a given point.
|
||||
*/
|
||||
struct Surface *find_water_floor_from_list(struct SurfaceNode *surfaceNode, s32 x, s32 y, s32 z,
|
||||
f32 *pheight) {
|
||||
register struct Surface *surf;
|
||||
struct Surface *floor = NULL;
|
||||
struct SurfaceNode *topSurfaceNode = surfaceNode;
|
||||
struct SurfaceNode *bottomSurfaceNode = surfaceNode;
|
||||
f32 height = FLOOR_LOWER_LIMIT;
|
||||
f32 bottomHeight = FLOOR_LOWER_LIMIT;
|
||||
|
||||
// Iterate through the list of water floors until there are no more water floors.
|
||||
while (bottomSurfaceNode != NULL) {
|
||||
f32 curBottomHeight = FLOOR_LOWER_LIMIT;
|
||||
surf = bottomSurfaceNode->surface;
|
||||
bottomSurfaceNode = bottomSurfaceNode->next;
|
||||
|
||||
if (surf->type != SURFACE_NEW_WATER_BOTTOM || !check_within_triangle_bounds(x, z, surf)) continue;
|
||||
|
||||
curBottomHeight = get_floor_height_at_location(x, z, surf);
|
||||
|
||||
if (curBottomHeight < y - 78.0f) continue;
|
||||
if (curBottomHeight >= y - 78.0f) bottomHeight = curBottomHeight;
|
||||
}
|
||||
|
||||
// Iterate through the list of water tops until there are no more water tops.
|
||||
while (topSurfaceNode != NULL) {
|
||||
f32 curHeight = FLOOR_LOWER_LIMIT;
|
||||
surf = topSurfaceNode->surface;
|
||||
topSurfaceNode = topSurfaceNode->next;
|
||||
|
||||
if (surf->type == SURFACE_NEW_WATER_BOTTOM || !check_within_triangle_bounds(x, z, surf)) continue;
|
||||
|
||||
curHeight = get_floor_height_at_location(x, z, surf);
|
||||
|
||||
if (bottomHeight != FLOOR_LOWER_LIMIT && curHeight > bottomHeight) continue;
|
||||
|
||||
if (curHeight > height) {
|
||||
height = curHeight;
|
||||
*pheight = curHeight;
|
||||
floor = surf;
|
||||
}
|
||||
}
|
||||
|
||||
return floor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the height of the highest floor below a point.
|
||||
*/
|
||||
@@ -579,10 +650,93 @@ f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor) {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the highest water floor under a given position and return the height.
|
||||
*/
|
||||
f32 find_water_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor) {
|
||||
s16 cellZ, cellX;
|
||||
|
||||
struct Surface *floor = NULL;
|
||||
struct SurfaceNode *surfaceList;
|
||||
|
||||
f32 height = FLOOR_LOWER_LIMIT;
|
||||
|
||||
s16 x = (s16) xPos;
|
||||
s16 y = (s16) yPos;
|
||||
s16 z = (s16) zPos;
|
||||
|
||||
if (x <= -LEVEL_BOUNDARY_MAX || x >= LEVEL_BOUNDARY_MAX) {
|
||||
return height;
|
||||
}
|
||||
if (z <= -LEVEL_BOUNDARY_MAX || z >= LEVEL_BOUNDARY_MAX) {
|
||||
return height;
|
||||
}
|
||||
|
||||
// Each level is split into cells to limit load, find the appropriate cell.
|
||||
cellX = ((x + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & NUM_CELLS_INDEX;
|
||||
cellZ = ((z + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & NUM_CELLS_INDEX;
|
||||
|
||||
// Check for surfaces that are a part of level geometry.
|
||||
surfaceList = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER].next;
|
||||
floor = find_water_floor_from_list(surfaceList, x, y, z, &height);
|
||||
|
||||
if (floor == NULL) {
|
||||
height = FLOOR_LOWER_LIMIT;
|
||||
} else {
|
||||
*pfloor = floor;
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* ENVIRONMENTAL BOXES *
|
||||
**************************************************/
|
||||
|
||||
/**
|
||||
* Finds the height of water at a given location.
|
||||
*/
|
||||
f32 find_water_level_and_floor(f32 x, f32 z, struct Surface **pfloor) {
|
||||
s32 i;
|
||||
s32 numRegions;
|
||||
s16 val;
|
||||
f32 loX, hiX, loZ, hiZ;
|
||||
f32 waterLevel = FLOOR_LOWER_LIMIT;
|
||||
s16 *p = gEnvironmentRegions;
|
||||
struct Surface *floor = NULL;
|
||||
|
||||
if (gCheckingSurfaceCollisionsForCamera) {
|
||||
waterLevel = find_water_floor(x, gLakituState.pos[1], z, &floor);
|
||||
} else {
|
||||
waterLevel = find_water_floor(x, gMarioState->pos[1], z, &floor);
|
||||
}
|
||||
|
||||
if (p != NULL && waterLevel == FLOOR_LOWER_LIMIT) {
|
||||
numRegions = *p++;
|
||||
|
||||
for (i = 0; i < numRegions; i++) {
|
||||
val = *p++;
|
||||
loX = *p++;
|
||||
loZ = *p++;
|
||||
hiX = *p++;
|
||||
hiZ = *p++;
|
||||
|
||||
// If the location is within a water box and it is a water box.
|
||||
// Water is less than 50 val only, while above is gas and such.
|
||||
if (loX < x && x < hiX && loZ < z && z < hiZ && val < 50) {
|
||||
// Set the water height. Since this breaks, only return the first height.
|
||||
waterLevel = *p;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
} else {
|
||||
*pfloor = floor;
|
||||
}
|
||||
|
||||
return waterLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the height of water at a given location.
|
||||
*/
|
||||
@@ -593,8 +747,15 @@ f32 find_water_level(f32 x, f32 z) {
|
||||
f32 loX, hiX, loZ, hiZ;
|
||||
f32 waterLevel = FLOOR_LOWER_LIMIT;
|
||||
s16 *p = gEnvironmentRegions;
|
||||
struct Surface *floor;
|
||||
|
||||
if (p != NULL) {
|
||||
if (gCheckingSurfaceCollisionsForCamera) {
|
||||
waterLevel = find_water_floor(x, gLakituState.pos[1], z, &floor);
|
||||
} else {
|
||||
waterLevel = find_water_floor(x, gMarioState->pos[1], z, &floor);
|
||||
}
|
||||
|
||||
if (p != NULL && waterLevel == FLOOR_LOWER_LIMIT) {
|
||||
numRegions = *p++;
|
||||
|
||||
for (i = 0; i < numRegions; i++) {
|
||||
|
||||
@@ -5,10 +5,8 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
// Range level area is 16384x16384 (-8192 to +8192 in x and z)
|
||||
#define LEVEL_BOUNDARY_MAX 0x2000 // 8192
|
||||
#include "engine/extended_bounds.h"
|
||||
|
||||
#define CELL_SIZE (1 << 10) // 0x400
|
||||
|
||||
#define CELL_HEIGHT_LIMIT 20000
|
||||
#define FLOOR_LOWER_LIMIT -11000
|
||||
@@ -42,6 +40,7 @@ f32 find_ceil(f32 posX, f32 posY, f32 posZ, struct Surface **pceil);
|
||||
f32 find_floor_height_and_data(f32 xPos, f32 yPos, f32 zPos, struct FloorGeometry **floorGeo);
|
||||
f32 find_floor_height(f32 x, f32 y, f32 z);
|
||||
f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor);
|
||||
f32 find_water_level_and_floor(f32 x, f32 z, struct Surface **pfloor);
|
||||
f32 find_water_level(f32 x, f32 z);
|
||||
f32 find_poison_gas_level(f32 x, f32 z);
|
||||
void debug_surface_list_info(f32 xPos, f32 zPos);
|
||||
|
||||
@@ -37,6 +37,8 @@ s16 sSurfacePoolSize;
|
||||
|
||||
u8 unused8038EEA8[0x30];
|
||||
|
||||
u8 gSurfacePoolError = 0;
|
||||
|
||||
/**
|
||||
* Allocate the part of the surface node pool to contain a surface node.
|
||||
*/
|
||||
@@ -49,7 +51,8 @@ static struct SurfaceNode *alloc_surface_node(void) {
|
||||
//! A bounds check! If there's more surface nodes than 7000 allowed,
|
||||
// we, um...
|
||||
// Perhaps originally just debug feedback?
|
||||
if (gSurfaceNodesAllocated >= 7000) {
|
||||
if (gSurfaceNodesAllocated >= SURFACE_NODE_POOL_SIZE) {
|
||||
gSurfacePoolError |= NOT_ENOUGH_ROOM_FOR_NODES;
|
||||
}
|
||||
|
||||
return node;
|
||||
@@ -68,6 +71,7 @@ static struct Surface *alloc_surface(void) {
|
||||
// we, um...
|
||||
// Perhaps originally just debug feedback?
|
||||
if (gSurfacesAllocated >= sSurfacePoolSize) {
|
||||
gSurfacePoolError |= NOT_ENOUGH_ROOM_FOR_SURFACES;
|
||||
}
|
||||
|
||||
surface->type = 0;
|
||||
@@ -89,6 +93,7 @@ static void clear_spatial_partition(SpatialPartitionCell *cells) {
|
||||
(*cells)[SPATIAL_PARTITION_FLOORS].next = NULL;
|
||||
(*cells)[SPATIAL_PARTITION_CEILS].next = NULL;
|
||||
(*cells)[SPATIAL_PARTITION_WALLS].next = NULL;
|
||||
(*cells)[SPATIAL_PARTITION_WATER].next = NULL;
|
||||
|
||||
cells++;
|
||||
}
|
||||
@@ -115,9 +120,10 @@ static void add_surface_to_cell(s16 dynamic, s16 cellX, s16 cellZ, struct Surfac
|
||||
s16 priority;
|
||||
s16 sortDir;
|
||||
s16 listIndex;
|
||||
s16 isWater = surface->type == SURFACE_NEW_WATER || surface->type == SURFACE_NEW_WATER_BOTTOM;
|
||||
|
||||
if (surface->normal.y > 0.01) {
|
||||
listIndex = SPATIAL_PARTITION_FLOORS;
|
||||
listIndex = isWater ? SPATIAL_PARTITION_WATER : SPATIAL_PARTITION_FLOORS;
|
||||
sortDir = 1; // highest to lowest, then insertion order
|
||||
} else if (surface->normal.y < -0.01) {
|
||||
listIndex = SPATIAL_PARTITION_CEILS;
|
||||
@@ -197,7 +203,7 @@ static s16 max_3(s16 a0, s16 a1, s16 a2) {
|
||||
* time). This function determines the lower cell for a given x/z position.
|
||||
* @param coord The coordinate to test
|
||||
*/
|
||||
static s16 lower_cell_index(s16 coord) {
|
||||
static s16 lower_cell_index(s32 coord) {
|
||||
s16 index;
|
||||
|
||||
// Move from range [-0x2000, 0x2000) to [0, 0x4000)
|
||||
@@ -229,7 +235,7 @@ static s16 lower_cell_index(s16 coord) {
|
||||
* time). This function determines the upper cell for a given x/z position.
|
||||
* @param coord The coordinate to test
|
||||
*/
|
||||
static s16 upper_cell_index(s16 coord) {
|
||||
static s16 upper_cell_index(s32 coord) {
|
||||
s16 index;
|
||||
|
||||
// Move from range [-0x2000, 0x2000) to [0, 0x4000)
|
||||
@@ -524,8 +530,8 @@ static void load_environmental_regions(s16 **data) {
|
||||
* Allocate some of the main pool for surfaces (2300 surf) and for surface nodes (7000 nodes).
|
||||
*/
|
||||
void alloc_surface_pools(void) {
|
||||
sSurfacePoolSize = 2300;
|
||||
sSurfaceNodePool = main_pool_alloc(7000 * sizeof(struct SurfaceNode), MEMORY_POOL_LEFT);
|
||||
sSurfacePoolSize = SURFACE_POOL_SIZE;
|
||||
sSurfaceNodePool = main_pool_alloc(SURFACE_NODE_POOL_SIZE * sizeof(struct SurfaceNode), MEMORY_POOL_LEFT);
|
||||
sSurfacePool = main_pool_alloc(sSurfacePoolSize * sizeof(struct Surface), MEMORY_POOL_LEFT);
|
||||
|
||||
gCCMEnteredSlide = 0;
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "surface_collision.h"
|
||||
#include "types.h"
|
||||
|
||||
extern u8 gSurfacePoolError;
|
||||
|
||||
#define NUM_CELLS (2 * LEVEL_BOUNDARY_MAX / CELL_SIZE)
|
||||
#define NUM_CELLS_INDEX (NUM_CELLS - 1)
|
||||
|
||||
@@ -19,10 +21,11 @@ enum
|
||||
{
|
||||
SPATIAL_PARTITION_FLOORS,
|
||||
SPATIAL_PARTITION_CEILS,
|
||||
SPATIAL_PARTITION_WALLS
|
||||
SPATIAL_PARTITION_WALLS,
|
||||
SPATIAL_PARTITION_WATER
|
||||
};
|
||||
|
||||
typedef struct SurfaceNode SpatialPartitionCell[3];
|
||||
typedef struct SurfaceNode SpatialPartitionCell[4];
|
||||
|
||||
// Needed for bs bss reordering memes.
|
||||
extern s32 unused8038BE90;
|
||||
|
||||
@@ -874,21 +874,21 @@ void pan_ahead_of_player(struct Camera *c) {
|
||||
vec3f_add(c->focus, pan);
|
||||
}
|
||||
|
||||
s16 find_in_bounds_yaw_wdw_bob_thi(Vec3f pos, Vec3f origin, s16 yaw) {
|
||||
switch (gCurrLevelArea) {
|
||||
case AREA_WDW_MAIN:
|
||||
yaw = clamp_positions_and_find_yaw(pos, origin, 4508.f, -3739.f, 4508.f, -3739.f);
|
||||
break;
|
||||
case AREA_BOB:
|
||||
yaw = clamp_positions_and_find_yaw(pos, origin, 8000.f, -8000.f, 7050.f, -8000.f);
|
||||
break;
|
||||
case AREA_THI_HUGE:
|
||||
yaw = clamp_positions_and_find_yaw(pos, origin, 8192.f, -8192.f, 8192.f, -8192.f);
|
||||
break;
|
||||
case AREA_THI_TINY:
|
||||
yaw = clamp_positions_and_find_yaw(pos, origin, 2458.f, -2458.f, 2458.f, -2458.f);
|
||||
break;
|
||||
}
|
||||
s16 find_in_bounds_yaw_wdw_bob_thi(UNUSED Vec3f pos, UNUSED Vec3f origin, s16 yaw) {
|
||||
// switch (gCurrLevelArea) {
|
||||
// case AREA_WDW_MAIN:
|
||||
// yaw = clamp_positions_and_find_yaw(pos, origin, 4508.f, -3739.f, 4508.f, -3739.f);
|
||||
// break;
|
||||
// case AREA_BOB:
|
||||
// yaw = clamp_positions_and_find_yaw(pos, origin, 8000.f, -8000.f, 7050.f, -8000.f);
|
||||
// break;
|
||||
// case AREA_THI_HUGE:
|
||||
// yaw = clamp_positions_and_find_yaw(pos, origin, 8192.f, -8192.f, 8192.f, -8192.f);
|
||||
// break;
|
||||
// case AREA_THI_TINY:
|
||||
// yaw = clamp_positions_and_find_yaw(pos, origin, 2458.f, -2458.f, 2458.f, -2458.f);
|
||||
// break;
|
||||
// }
|
||||
return yaw;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "area.h"
|
||||
#include "save_file.h"
|
||||
#include "print.h"
|
||||
#include "engine/surface_load.h"
|
||||
|
||||
/* @file hud.c
|
||||
* This file implements HUD rendering and power meter animations.
|
||||
@@ -475,5 +476,14 @@ void render_hud(void) {
|
||||
if (hudDisplayFlags & HUD_DISPLAY_FLAG_TIMER) {
|
||||
render_hud_timer();
|
||||
}
|
||||
|
||||
if (gSurfacePoolError & NOT_ENOUGH_ROOM_FOR_SURFACES)
|
||||
{
|
||||
print_text(10, 40, "SURFACE POOL FULL");
|
||||
}
|
||||
if (gSurfacePoolError & NOT_ENOUGH_ROOM_FOR_NODES)
|
||||
{
|
||||
print_text(10, 60, "SURFACE NODE POOL FULL");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1167,6 +1167,24 @@ s32 transition_submerged_to_walking(struct MarioState *m) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transitions Mario from a submerged action to an airborne action.
|
||||
* You may want to change these actions to fit your hack
|
||||
*/
|
||||
s32 transition_submerged_to_airborne(struct MarioState *m) {
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
|
||||
vec3s_set(m->angleVel, 0, 0, 0);
|
||||
|
||||
if (m->heldObj == NULL) {
|
||||
if (m->input & INPUT_A_DOWN) return set_mario_action(m, ACT_DIVE, 0);
|
||||
else return set_mario_action(m, ACT_FREEFALL, 0);
|
||||
} else {
|
||||
if (m->input & INPUT_A_DOWN) return set_mario_action(m, ACT_HOLD_JUMP, 0);
|
||||
else return set_mario_action(m, ACT_HOLD_FREEFALL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the transition function typically for entering a submerged action for a
|
||||
* non-submerged action. This also applies the water surface camera preset.
|
||||
@@ -1175,7 +1193,8 @@ s32 set_water_plunge_action(struct MarioState *m) {
|
||||
m->forwardVel = m->forwardVel / 4.0f;
|
||||
m->vel[1] = m->vel[1] / 2.0f;
|
||||
|
||||
m->pos[1] = m->waterLevel - 100;
|
||||
// !BUG: Causes waterbox upwarp
|
||||
// m->pos[1] = m->waterLevel - 100;
|
||||
|
||||
m->faceAngle[2] = 0;
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ s32 hurt_and_set_mario_action(struct MarioState *m, u32 action, u32 actionArg, s
|
||||
s32 check_common_action_exits(struct MarioState *m);
|
||||
s32 check_common_hold_action_exits(struct MarioState *m);
|
||||
s32 transition_submerged_to_walking(struct MarioState *m);
|
||||
s32 transition_submerged_to_airborne(struct MarioState *m);
|
||||
s32 set_water_plunge_action(struct MarioState *m);
|
||||
s32 execute_mario_action(UNUSED struct Object *o);
|
||||
void init_mario(void);
|
||||
|
||||
@@ -1497,7 +1497,8 @@ static s32 act_hold_metal_water_fall_land(struct MarioState *m) {
|
||||
static s32 check_common_submerged_cancels(struct MarioState *m) {
|
||||
if (m->pos[1] > m->waterLevel - 80) {
|
||||
if (m->waterLevel - 80 > m->floorHeight) {
|
||||
m->pos[1] = m->waterLevel - 80;
|
||||
// m->pos[1] = m->waterLevel - 80; //! BUG: Downwarp swimming out of waterfalls
|
||||
return transition_submerged_to_airborne(m);
|
||||
} else {
|
||||
//! If you press B to throw the shell, there is a ~5 frame window
|
||||
// where your held object is the shell, but you are not in the
|
||||
|
||||
@@ -1840,12 +1840,10 @@ static s32 cur_obj_within_12k_bounds(void) {
|
||||
}
|
||||
|
||||
void cur_obj_move_using_vel_and_gravity(void) {
|
||||
if (cur_obj_within_12k_bounds()) {
|
||||
o->oPosX += o->oVelX;
|
||||
o->oPosZ += o->oVelZ;
|
||||
o->oVelY += o->oGravity; //! No terminal velocity
|
||||
o->oPosY += o->oVelY;
|
||||
}
|
||||
}
|
||||
|
||||
void cur_obj_move_using_fvel_and_gravity(void) {
|
||||
|
||||
@@ -696,7 +696,7 @@ static void geo_process_shadow(struct GraphNodeShadow *node) {
|
||||
gMatStackFixed[gMatStackIndex] = mtx;
|
||||
if (gShadowAboveWaterOrLava == TRUE) {
|
||||
geo_append_display_list((void *) VIRTUAL_TO_PHYSICAL(shadowList), 4);
|
||||
} else if (gMarioOnIceOrCarpet == 1) {
|
||||
} else if (gMarioOnIceOrCarpet == 1 || gShadowAboveCustomWater == 1) {
|
||||
geo_append_display_list((void *) VIRTUAL_TO_PHYSICAL(shadowList), 5);
|
||||
} else {
|
||||
geo_append_display_list((void *) VIRTUAL_TO_PHYSICAL(shadowList), 6);
|
||||
|
||||
@@ -102,6 +102,7 @@ shadowRectangle rectangles[2] = {
|
||||
|
||||
// See shadow.h for documentation.
|
||||
s8 gShadowAboveWaterOrLava;
|
||||
s8 gShadowAboveCustomWater;
|
||||
s8 gMarioOnIceOrCarpet;
|
||||
s8 sMarioOnFlyingCarpet;
|
||||
s16 sSurfaceTypeBelowShadow;
|
||||
@@ -177,14 +178,15 @@ u8 dim_shadow_with_distance(u8 solidity, f32 distFromFloor) {
|
||||
* Return the water level below a shadow, or 0 if the water level is below
|
||||
* -10,000.
|
||||
*/
|
||||
f32 get_water_level_below_shadow(struct Shadow *s) {
|
||||
f32 waterLevel = find_water_level(s->parentX, s->parentZ);
|
||||
f32 get_water_level_below_shadow(struct Shadow *s, struct Surface **waterFloor) {
|
||||
f32 waterLevel = find_water_level_and_floor(s->parentX, s->parentZ, waterFloor);
|
||||
if (waterLevel < FLOOR_LOWER_LIMIT_SHADOW) {
|
||||
return 0;
|
||||
} else if (s->parentY >= waterLevel && s->floorHeight <= waterLevel) {
|
||||
gShadowAboveWaterOrLava = TRUE;
|
||||
return waterLevel;
|
||||
}
|
||||
return waterLevel;
|
||||
//! @bug Missing return statement. This compiles to return `waterLevel`
|
||||
//! incidentally.
|
||||
}
|
||||
@@ -201,6 +203,7 @@ s8 init_shadow(struct Shadow *s, f32 xPos, f32 yPos, f32 zPos, s16 shadowScale,
|
||||
f32 waterLevel;
|
||||
f32 floorSteepness;
|
||||
struct FloorGeometry *floorGeometry;
|
||||
struct Surface *waterFloor = NULL;
|
||||
|
||||
s->parentX = xPos;
|
||||
s->parentY = yPos;
|
||||
@@ -208,18 +211,33 @@ s8 init_shadow(struct Shadow *s, f32 xPos, f32 yPos, f32 zPos, s16 shadowScale,
|
||||
|
||||
s->floorHeight = find_floor_height_and_data(s->parentX, s->parentY, s->parentZ, &floorGeometry);
|
||||
|
||||
if (gEnvironmentRegions != 0) {
|
||||
waterLevel = get_water_level_below_shadow(s);
|
||||
}
|
||||
waterLevel = get_water_level_below_shadow(s, &waterFloor);
|
||||
|
||||
// if (gEnvironmentRegions != 0) {
|
||||
// waterLevel = get_water_level_below_shadow(s);
|
||||
// }
|
||||
|
||||
if (gShadowAboveWaterOrLava) {
|
||||
//! @bug Use of potentially undefined variable `waterLevel`
|
||||
s->floorHeight = waterLevel;
|
||||
|
||||
// Assume that the water is flat.
|
||||
s->floorNormalX = 0;
|
||||
s->floorNormalY = 1.0;
|
||||
s->floorNormalZ = 0;
|
||||
s->floorOriginOffset = -waterLevel;
|
||||
if (waterFloor != NULL) {
|
||||
s->floorNormalX = waterFloor->normal.x;
|
||||
s->floorNormalY = waterFloor->normal.y;
|
||||
s->floorNormalZ = waterFloor->normal.z;
|
||||
s->floorOriginOffset = waterFloor->originOffset;
|
||||
gShadowAboveWaterOrLava = FALSE;
|
||||
gShadowAboveCustomWater = TRUE;
|
||||
s->solidity = 200;
|
||||
} else {
|
||||
gShadowAboveCustomWater = FALSE;
|
||||
// Assume that the water is flat.
|
||||
s->floorNormalX = 0;
|
||||
s->floorNormalY = 1.0;
|
||||
s->floorNormalZ = 0;
|
||||
s->floorOriginOffset = -waterLevel;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Don't draw a shadow if the floor is lower than expected possible,
|
||||
// or if the y-normal is negative (an unexpected result).
|
||||
@@ -853,6 +871,7 @@ Gfx *create_shadow_below_xyz(f32 xPos, f32 yPos, f32 zPos, s16 shadowScale, u8 s
|
||||
find_floor(xPos, yPos, zPos, &pfloor);
|
||||
|
||||
gShadowAboveWaterOrLava = FALSE;
|
||||
gShadowAboveCustomWater = FALSE;
|
||||
gMarioOnIceOrCarpet = 0;
|
||||
sMarioOnFlyingCarpet = 0;
|
||||
if (pfloor != NULL) {
|
||||
|
||||
@@ -38,6 +38,7 @@ extern s16 sSurfaceTypeBelowShadow;
|
||||
* Flag for if the current shadow is above water or lava.
|
||||
*/
|
||||
extern s8 gShadowAboveWaterOrLava;
|
||||
extern s8 gShadowAboveCustomWater;
|
||||
|
||||
/**
|
||||
* Flag for if Mario is on ice or a flying carpet.
|
||||
|
||||
Reference in New Issue
Block a user