mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-04-27 04:21:42 +00:00
Added server setting toggle for 'surface cucking' and 'exposed ceilings' vanilla bugs
This commit is contained in:
parent
91ee4f8a8f
commit
9fd309de56
17 changed files with 107 additions and 17 deletions
|
|
@ -1573,6 +1573,7 @@
|
|||
--- @class ServerSettings
|
||||
--- @field public bubbleDeath integer
|
||||
--- @field public enableCheats integer
|
||||
--- @field public fixCollisionBugs integer
|
||||
--- @field public headlessServer integer
|
||||
--- @field public playerInteractions PlayerInteractions
|
||||
--- @field public playerKnockbackStrength integer
|
||||
|
|
|
|||
|
|
@ -1979,6 +1979,7 @@
|
|||
| ----- | ---- | ------ |
|
||||
| bubbleDeath | `integer` | |
|
||||
| enableCheats | `integer` | |
|
||||
| fixCollisionBugs | `integer` | |
|
||||
| headlessServer | `integer` | |
|
||||
| playerInteractions | [enum PlayerInteractions](constants.md#enum-PlayerInteractions) | |
|
||||
| playerKnockbackStrength | `integer` | |
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "math_util.h"
|
||||
#include "game/game_init.h"
|
||||
#include "pc/utils/misc.h"
|
||||
#include "pc/network/network.h"
|
||||
|
||||
/**************************************************
|
||||
* WALLS *
|
||||
|
|
@ -240,6 +241,11 @@ static struct Surface *find_ceil_from_list(struct SurfaceNode *surfaceNode, s32
|
|||
|
||||
ceil = NULL;
|
||||
|
||||
// set pheight to highest value
|
||||
if (gServerSettings.fixCollisionBugs) {
|
||||
*pheight = CELL_HEIGHT_LIMIT;
|
||||
}
|
||||
|
||||
// Stay in this loop until out of ceilings.
|
||||
while (surfaceNode != NULL) {
|
||||
surf = surfaceNode->surface;
|
||||
|
|
@ -284,29 +290,39 @@ static struct Surface *find_ceil_from_list(struct SurfaceNode *surfaceNode, s32
|
|||
f32 height;
|
||||
|
||||
// If a wall, ignore it. Likely a remnant, should never occur.
|
||||
if (ny == 0.0f) {
|
||||
continue;
|
||||
}
|
||||
if (ny == 0.0f) { continue; }
|
||||
|
||||
// Find the ceil height at the specific point.
|
||||
height = -(x * nx + nz * z + oo) / ny;
|
||||
|
||||
// Reject ceilings below previously found ceiling
|
||||
if (gServerSettings.fixCollisionBugs && (height > *pheight)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Checks for ceiling interaction with a 78 unit buffer.
|
||||
//! (Exposed Ceilings) Because any point above a ceiling counts
|
||||
// as interacting with a ceiling, ceilings far below can cause
|
||||
// "invisible walls" that are really just exposed ceilings.
|
||||
if (y - (height - -78.0f) > 0.0f) {
|
||||
continue;
|
||||
// <Fixed when gServerSettings.fixCollisionBugs != 0>
|
||||
if (gServerSettings.fixCollisionBugs) {
|
||||
if (y > height) { continue; }
|
||||
} else {
|
||||
if (y - (height - -78.0f) > 0.0f) { continue; }
|
||||
}
|
||||
|
||||
*pheight = height;
|
||||
ceil = surf;
|
||||
break;
|
||||
|
||||
if (!gServerSettings.fixCollisionBugs) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! (Surface Cucking) Since only the first ceil is returned and not the lowest,
|
||||
// lower ceilings can be "cucked" by higher ceilings.
|
||||
// <Fixed when gServerSettings.fixCollisionBugs != 0>
|
||||
return ceil;
|
||||
}
|
||||
|
||||
|
|
@ -428,6 +444,11 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
|
|||
struct Surface *floor = NULL;
|
||||
s32 interpolate;
|
||||
|
||||
// set pheight to lowest value
|
||||
if (gServerSettings.fixCollisionBugs) {
|
||||
*pheight = FLOOR_LOWER_LIMIT;
|
||||
}
|
||||
|
||||
// Iterate through the list of floors until there are no more floors.
|
||||
while (surfaceNode != NULL) {
|
||||
surf = surfaceNode->surface;
|
||||
|
|
@ -524,6 +545,12 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
|
|||
|
||||
// Find the height of the floor at a given location.
|
||||
height = -(x * nx + nz * z + oo) / ny;
|
||||
|
||||
// Find highest floor
|
||||
if (gServerSettings.fixCollisionBugs && (height < *pheight)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Checks for floor interaction with a 78 unit buffer.
|
||||
if (y - (height + -78.0f) < 0.0f) {
|
||||
continue;
|
||||
|
|
@ -544,11 +571,15 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
|
|||
}
|
||||
|
||||
floor = surf;
|
||||
break;
|
||||
|
||||
if (!gServerSettings.fixCollisionBugs) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//! (Surface Cucking) Since only the first floor is returned and not the highest,
|
||||
// higher floors can be "cucked" by lower floors.
|
||||
// <Fixed when gServerSettings.fixCollisionBugs != 0>
|
||||
return floor;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "game/game_init.h"
|
||||
#include "engine/math_util.h"
|
||||
#include "game/level_update.h"
|
||||
#include "pc/network/network.h"
|
||||
|
||||
s32 unused8038BE90;
|
||||
|
||||
|
|
@ -151,7 +152,11 @@ static void add_surface_to_cell(s16 dynamic, s16 cellX, s16 cellZ, struct Surfac
|
|||
// many functions only use the first triangle in surface order that fits,
|
||||
// missing higher surfaces.
|
||||
// upperY would be a better sort method.
|
||||
surfacePriority = surface->vertex1[1] * sortDir;
|
||||
// <Fixed when gServerSettings.fixCollisionBugs != 0>
|
||||
|
||||
surfacePriority = gServerSettings.fixCollisionBugs
|
||||
? (surface->upperY * sortDir)
|
||||
: (surface->vertex1[1] * sortDir);
|
||||
|
||||
newNode->surface = surface;
|
||||
|
||||
|
|
|
|||
|
|
@ -623,6 +623,18 @@ f32 vec3f_find_ceil(Vec3f pos, f32 height, struct Surface **ceil) {
|
|||
return find_ceil(pos[0], height + 80.0f, pos[2], ceil);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the ceiling from a vec3f horizontally and a height (with 80 vertical buffer).
|
||||
* Prevents exposed ceiling bug
|
||||
*/
|
||||
// Prevent exposed ceilings
|
||||
f32 vec3f_mario_ceil(Vec3f pos, f32 height, struct Surface **ceil) {
|
||||
if (gServerSettings.fixCollisionBugs) {
|
||||
height = MAX(height, pos[1]) + 3.0f;
|
||||
}
|
||||
return vec3f_find_ceil(pos, height, ceil);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if Mario is facing "downhill."
|
||||
*/
|
||||
|
|
@ -1434,7 +1446,7 @@ copyPlayerGoto:;
|
|||
m->floorHeight = find_floor(m->pos[0], m->pos[1], m->pos[2], &m->floor);
|
||||
}
|
||||
|
||||
m->ceilHeight = vec3f_find_ceil(&m->pos[0], m->floorHeight, &m->ceil);
|
||||
m->ceilHeight = vec3f_mario_ceil(&m->pos[0], m->floorHeight, &m->ceil);
|
||||
gasLevel = find_poison_gas_level(m->pos[0], m->pos[2]);
|
||||
m->waterLevel = find_water_level(m->pos[0], m->pos[2]);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ s32 mario_get_floor_class(struct MarioState *m);
|
|||
u32 mario_get_terrain_sound_addend(struct MarioState *m);
|
||||
struct Surface *resolve_and_return_wall_collisions(Vec3f pos, f32 offset, f32 radius);
|
||||
f32 vec3f_find_ceil(Vec3f pos, f32 height, struct Surface **ceil);
|
||||
f32 vec3f_mario_ceil(Vec3f pos, f32 height, struct Surface **ceil);
|
||||
s32 mario_facing_downhill(struct MarioState *m, s32 turnYaw);
|
||||
u32 mario_floor_is_slippery(struct MarioState *m);
|
||||
s32 mario_floor_is_slope(struct MarioState *m);
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ s32 set_pole_position(struct MarioState *m, f32 offsetY) {
|
|||
collided = f32_find_wall_collision(&m->pos[0], &m->pos[1], &m->pos[2], 60.0f, 50.0f);
|
||||
collided |= f32_find_wall_collision(&m->pos[0], &m->pos[1], &m->pos[2], 30.0f, 24.0f);
|
||||
|
||||
ceilHeight = vec3f_find_ceil(m->pos, m->pos[1], &ceil);
|
||||
ceilHeight = vec3f_mario_ceil(m->pos, m->pos[1], &ceil);
|
||||
if (m->pos[1] > ceilHeight - 160.0f) {
|
||||
m->pos[1] = ceilHeight - 160.0f;
|
||||
marioObj->oMarioPolePos = m->pos[1] - m->usedObj->oPosY;
|
||||
|
|
@ -333,7 +333,7 @@ s32 perform_hanging_step(struct MarioState *m, Vec3f nextPos) {
|
|||
|
||||
m->wall = resolve_and_return_wall_collisions(nextPos, 50.0f, 50.0f);
|
||||
floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor);
|
||||
ceilHeight = vec3f_find_ceil(nextPos, floorHeight, &ceil);
|
||||
ceilHeight = vec3f_mario_ceil(nextPos, floorHeight, &ceil);
|
||||
|
||||
if (floor == NULL) {
|
||||
return HANG_HIT_CEIL_OR_OOB;
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ u32 perform_water_full_step(struct MarioState *m, Vec3f nextPos) {
|
|||
|
||||
wall = resolve_and_return_wall_collisions(nextPos, 10.0f, 110.0f);
|
||||
floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor);
|
||||
ceilHeight = vec3f_find_ceil(nextPos, floorHeight, &ceil);
|
||||
ceilHeight = vec3f_mario_ceil(nextPos, floorHeight, &ceil);
|
||||
|
||||
if (floor == NULL) {
|
||||
return WATER_STEP_CANCELLED;
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@ static s32 perform_ground_quarter_step(struct MarioState *m, Vec3f nextPos) {
|
|||
upperWall = resolve_and_return_wall_collisions(nextPos, 60.0f, 50.0f);
|
||||
|
||||
floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor);
|
||||
ceilHeight = vec3f_find_ceil(nextPos, floorHeight, &ceil);
|
||||
ceilHeight = vec3f_mario_ceil(nextPos, floorHeight, &ceil);
|
||||
|
||||
waterLevel = find_water_level(nextPos[0], nextPos[2]);
|
||||
|
||||
|
|
@ -406,7 +406,7 @@ s32 perform_air_quarter_step(struct MarioState *m, Vec3f intendedPos, u32 stepAr
|
|||
lowerWall = resolve_and_return_wall_collisions(nextPos, 30.0f, 50.0f);
|
||||
|
||||
floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor);
|
||||
ceilHeight = vec3f_find_ceil(nextPos, floorHeight, &ceil);
|
||||
ceilHeight = vec3f_mario_ceil(nextPos, floorHeight, &ceil);
|
||||
|
||||
waterLevel = find_water_level(nextPos[0], nextPos[2]);
|
||||
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ bool configSkipIntro = 0;
|
|||
bool configShareLives = 0;
|
||||
bool configEnableCheats = 0;
|
||||
bool configBubbleDeath = true;
|
||||
bool configFixCollBugs = true;
|
||||
unsigned int configAmountofPlayers = 16;
|
||||
bool configHUD = true;
|
||||
#ifdef DISCORDRPC
|
||||
|
|
@ -204,6 +205,7 @@ static const struct ConfigOption options[] = {
|
|||
{.name = "frame_limit" , .type = CONFIG_TYPE_UINT , .uintValue = &configFrameLimit},
|
||||
{.name = "amount_of_players", .type = CONFIG_TYPE_UINT , .uintValue = &configAmountofPlayers},
|
||||
{.name = "bubble_death", .type = CONFIG_TYPE_BOOL , .boolValue = &configBubbleDeath},
|
||||
{.name = "fix_collision_bugs", .type = CONFIG_TYPE_BOOL , .boolValue = &configFixCollBugs},
|
||||
{.name = "coop_draw_distance", .type = CONFIG_TYPE_UINT , .uintValue = &configDrawDistance},
|
||||
{.name = "coop_host_port", .type = CONFIG_TYPE_UINT , .uintValue = &configHostPort},
|
||||
{.name = "coop_host_save_slot", .type = CONFIG_TYPE_UINT , .uintValue = &configHostSaveSlot},
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ extern bool configSkipIntro;
|
|||
extern bool configShareLives;
|
||||
extern bool configEnableCheats;
|
||||
extern bool configBubbleDeath;
|
||||
extern bool configFixCollBugs;
|
||||
extern unsigned int configAmountofPlayers;
|
||||
#ifdef DISCORDRPC
|
||||
extern bool configDiscordRPC;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ static void djui_panel_host_player_text_change(struct DjuiBase* caller) {
|
|||
}
|
||||
|
||||
void djui_panel_host_settings_create(struct DjuiBase* caller) {
|
||||
f32 bodyHeight = 32 * 8 + 64 * 1 + 16 * 8;
|
||||
f32 bodyHeight = 32 * 9 + 64 * 1 + 16 * 9;
|
||||
|
||||
struct DjuiBase* defaultBase = NULL;
|
||||
struct DjuiThreePanel* panel = djui_panel_menu_create(bodyHeight, "\\#ff0800\\S\\#1be700\\E\\#00b3ff\\T\\#ffef00\\T\\#ff0800\\I\\#1be700\\N\\#00b3ff\\G\\#ffef00\\S");
|
||||
|
|
@ -83,7 +83,11 @@ void djui_panel_host_settings_create(struct DjuiBase* caller) {
|
|||
struct DjuiCheckbox* checkbox5 = djui_checkbox_create(&body->base, "Bubble on death", &configBubbleDeath);
|
||||
djui_base_set_size_type(&checkbox5->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&checkbox5->base, 1.0f, 32);
|
||||
|
||||
|
||||
struct DjuiCheckbox* checkbox6 = djui_checkbox_create(&body->base, "Fix collision bugs", &configFixCollBugs);
|
||||
djui_base_set_size_type(&checkbox6->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&checkbox6->base, 1.0f, 32);
|
||||
|
||||
struct DjuiRect* rect1 = djui_rect_create(&body->base);
|
||||
djui_base_set_size_type(&rect1->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&rect1->base, 1.0f, 32);
|
||||
|
|
|
|||
|
|
@ -1729,10 +1729,11 @@ static struct LuaObjectField sRayIntersectionInfoFields[LUA_RAY_INTERSECTION_INF
|
|||
{ "surface", LVT_COBJECT_P, offsetof(struct RayIntersectionInfo, surface), false, LOT_SURFACE },
|
||||
};
|
||||
|
||||
#define LUA_SERVER_SETTINGS_FIELD_COUNT 8
|
||||
#define LUA_SERVER_SETTINGS_FIELD_COUNT 9
|
||||
static struct LuaObjectField sServerSettingsFields[LUA_SERVER_SETTINGS_FIELD_COUNT] = {
|
||||
{ "bubbleDeath", LVT_U8, offsetof(struct ServerSettings, bubbleDeath), false, LOT_NONE },
|
||||
{ "enableCheats", LVT_U8, offsetof(struct ServerSettings, enableCheats), false, LOT_NONE },
|
||||
{ "fixCollisionBugs", LVT_U8, offsetof(struct ServerSettings, fixCollisionBugs), false, LOT_NONE },
|
||||
{ "headlessServer", LVT_U8, offsetof(struct ServerSettings, headlessServer), false, LOT_NONE },
|
||||
{ "playerInteractions", LVT_S32, offsetof(struct ServerSettings, playerInteractions), false, LOT_NONE },
|
||||
{ "playerKnockbackStrength", LVT_U8, offsetof(struct ServerSettings, playerKnockbackStrength), false, LOT_NONE },
|
||||
|
|
|
|||
|
|
@ -8606,6 +8606,31 @@ int smlua_func_vec3f_find_ceil(lua_State* L) {
|
|||
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
int smlua_func_vec3f_mario_ceil(lua_State* L) {
|
||||
if(!smlua_functions_valid_param_count(L, 3)) { return 0; }
|
||||
|
||||
|
||||
f32* pos = smlua_get_vec3f_from_buffer();
|
||||
pos[0] = smlua_get_number_field(1, "x");
|
||||
pos[1] = smlua_get_number_field(1, "y");
|
||||
pos[2] = smlua_get_number_field(1, "z");
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1"); return 0; }
|
||||
f32 height = smlua_to_number(L, 2);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2"); return 0; }
|
||||
// struct Surface** ceil = (struct Surface**)smlua_to_cobject(L, 3, LOT_???); <--- UNIMPLEMENTED
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 3"); return 0; }
|
||||
|
||||
lua_pushnumber(L, vec3f_mario_ceil(pos, height, ceil));
|
||||
|
||||
smlua_push_number_field(1, "x", pos[0]);
|
||||
smlua_push_number_field(1, "y", pos[1]);
|
||||
smlua_push_number_field(1, "z", pos[2]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
||||
//////////////////////////////
|
||||
|
|
@ -17281,6 +17306,7 @@ void smlua_bind_functions_autogen(void) {
|
|||
smlua_bind_function(L, "update_mario_pos_for_anim", smlua_func_update_mario_pos_for_anim);
|
||||
smlua_bind_function(L, "update_mario_sound_and_camera", smlua_func_update_mario_sound_and_camera);
|
||||
//smlua_bind_function(L, "vec3f_find_ceil", smlua_func_vec3f_find_ceil); <--- UNIMPLEMENTED
|
||||
//smlua_bind_function(L, "vec3f_mario_ceil", smlua_func_vec3f_mario_ceil); <--- UNIMPLEMENTED
|
||||
|
||||
// mario_actions_airborne.c
|
||||
smlua_bind_function(L, "check_common_airborne_cancels", smlua_func_check_common_airborne_cancels);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ struct ServerSettings gServerSettings = {
|
|||
.enableCheats = 0,
|
||||
.bubbleDeath = 1,
|
||||
.headlessServer = 0,
|
||||
.fixCollisionBugs = 1,
|
||||
};
|
||||
|
||||
void network_set_system(enum NetworkSystemType nsType) {
|
||||
|
|
@ -91,6 +92,7 @@ bool network_init(enum NetworkType inNetworkType) {
|
|||
gServerSettings.shareLives = configShareLives;
|
||||
gServerSettings.enableCheats = configEnableCheats;
|
||||
gServerSettings.bubbleDeath = configBubbleDeath;
|
||||
gServerSettings.fixCollisionBugs = configFixCollBugs;
|
||||
#if defined(RAPI_DUMMY) || defined(WAPI_DUMMY)
|
||||
gServerSettings.headlessServer = (inNetworkType == NT_SERVER);
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ struct ServerSettings {
|
|||
u8 enableCheats;
|
||||
u8 bubbleDeath;
|
||||
u8 headlessServer;
|
||||
u8 fixCollisionBugs;
|
||||
};
|
||||
|
||||
// Networking-specific externs
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ void network_send_join(struct Packet* joinRequestPacket) {
|
|||
packet_write(&p, &gServerSettings.shareLives, sizeof(u8));
|
||||
packet_write(&p, &gServerSettings.enableCheats, sizeof(u8));
|
||||
packet_write(&p, &gServerSettings.bubbleDeath, sizeof(u8));
|
||||
packet_write(&p, &gServerSettings.fixCollisionBugs, sizeof(u8));
|
||||
packet_write(&p, &gServerSettings.headlessServer, sizeof(u8));
|
||||
packet_write(&p, eeprom, sizeof(u8) * 512);
|
||||
|
||||
|
|
@ -170,6 +171,7 @@ void network_receive_join(struct Packet* p) {
|
|||
packet_read(p, &gServerSettings.shareLives, sizeof(u8));
|
||||
packet_read(p, &gServerSettings.enableCheats, sizeof(u8));
|
||||
packet_read(p, &gServerSettings.bubbleDeath, sizeof(u8));
|
||||
packet_read(p, &gServerSettings.fixCollisionBugs, sizeof(u8));
|
||||
packet_read(p, &gServerSettings.headlessServer, sizeof(u8));
|
||||
packet_read(p, eeprom, sizeof(u8) * 512);
|
||||
packet_read(p, &modCount, sizeof(u8));
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue