Merge remote-tracking branch 'origin/dev' into moderation-rework

This commit is contained in:
EmeraldLockdown 2026-03-10 19:14:55 -05:00
commit f82637b8ec
11 changed files with 87 additions and 31 deletions

View file

@ -951,7 +951,7 @@ def build_function(function, do_extern):
sparam = build_param(fid, param, i)
param_var, param_value = sparam.split('=')
param_type = param_var.replace(pid, '').strip()
s += ' %s = (%s) NULL;\n' % (param_var.strip(), param_type)
s += ' %s = (%s) %s;\n' % (param_var.strip(), param_type, "NULL" if '*' in param_type else "0")
s += ' if (top >= %d) {\n' % (i)
s += ' %s = %s\n' % (pid, param_value.strip())
s += ' if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %%u for function \'%%s\'", %d, "%s"); return 0; }\n' % (i, fid)

Binary file not shown.

View file

@ -797,7 +797,22 @@ static s32 bhv_cmd_load_collision_data(void) {
// Command 0x2D: Sets the home position of the object to its current position.
// Usage: SET_HOME()
static s32 bhv_cmd_set_home(void) {
if (!(gCurrentObject->coopFlags & (COOP_OBJ_FLAG_LUA | COOP_OBJ_FLAG_NETWORK))) {
// COOP: only set home via behavior for the following cases
if (
// if the object wasn't created via Lua
!(gCurrentObject->coopFlags & COOP_OBJ_FLAG_LUA)
// if the object wasn't created via network
// OR
// the object has never had its home set via behavior AND its home is default (e.g. (0, 0, 0))
// (this case handles an object that needs its home set via behavior after being spawned by another player)
&& (
!(gCurrentObject->coopFlags & COOP_OBJ_FLAG_NETWORK)
|| (
!gCurrentObject->setHome
&& gCurrentObject->oHomeX == 0.0f && gCurrentObject->oHomeY == 0.0f && gCurrentObject->oHomeZ == 0.0f
)
)
) {
gCurrentObject->oHomeX = gCurrentObject->oPosX;
gCurrentObject->oHomeY = gCurrentObject->oPosY;
gCurrentObject->oHomeZ = gCurrentObject->oPosZ;

View file

@ -806,7 +806,10 @@ static void load_object_collision_model_internal(bool isSOC) {
for (s32 i = 0; i < MAX_PLAYERS; i++) {
f32 dist = dist_between_objects(gCurrentObject, gMarioStates[i].marioObj);
if (dist < tangibleDist) { anyPlayerInTangibleRange = TRUE; }
if (dist < tangibleDist) {
anyPlayerInTangibleRange = TRUE;
break;
}
}
// If the object collision is supposed to be loaded more than the

View file

@ -10,6 +10,9 @@
* in the enclosure nor in the room around it.
*/
static void handle_merry_go_round_music(void) {
// COOP: raise scope of this variable since floor check is no longer strictly tied to music
u16 marioFloorType = 0;
// If the music should play, play it and check whether it still should.
// Otherwise, don't play it and check whether it should.
if (o->oMerryGoRoundMusicShouldPlay == FALSE) {
@ -23,7 +26,7 @@ static void handle_merry_go_round_music(void) {
// Get Mario's floor and floor surface type
struct Surface *marioFloor = NULL;
struct Object *marioObject = gMarioObjects[0];
u16 marioFloorType = 0;
// COOP: `marioFloorType` originally here
if (marioObject) {
find_floor(marioObject->oPosX, marioObject->oPosY, marioObject->oPosZ, &marioFloor);
@ -37,7 +40,9 @@ static void handle_merry_go_round_music(void) {
// The cur_obj_is_mario_on_platform check is redundant since the merry-go-round
// has surface type 0x1A, so Mario cannot be on the merry-go-round
// without being on a floor with surface type 0x1A (SURFACE_MGR_MUSIC).
gMarioOnMerryGoRound = cur_obj_is_any_player_on_platform();
// COOP: `gMarioOnMerryGoRound` is used to determine if the merry-go-round Boos should be active
// for co-op, this means that this check needs to be separated from the music check, since music is client-side.
if (cur_obj_is_mario_on_platform() || marioFloorType == SURFACE_MGR_MUSIC) {
// If Mario is in the merry-go-round's enclosure, play only the merry-go-round music.
play_secondary_music(SEQ_EVENT_MERRY_GO_ROUND, 0, 78, 50);
@ -60,6 +65,28 @@ static void handle_merry_go_round_music(void) {
cur_obj_play_sound_1(SOUND_ENV_MERRY_GO_ROUND_CREAKING);
}
}
// COOP: floor check happens here
// `marioFloorType` refers to the local player's character
gMarioOnMerryGoRound = marioFloorType == SURFACE_MGR_MUSIC || cur_obj_is_any_player_on_platform();
if (!gMarioOnMerryGoRound) {
// check the other Marios' floors
// starting at 1 since local player was already checked
for (s32 i = 1; i < MAX_PLAYERS; i++) {
if (!is_player_active(&gMarioStates[i])) { continue; }
struct Object *marioObject = gMarioStates[i].marioObj;
if (marioObject == NULL) { continue; }
struct Surface *marioFloor = NULL;
find_floor(marioObject->oPosX, marioObject->oPosY, marioObject->oPosZ, &marioFloor);
if (marioFloor != NULL && marioFloor->type == SURFACE_MGR_MUSIC) {
gMarioOnMerryGoRound = TRUE;
break;
}
}
}
}
/**

View file

@ -56,16 +56,11 @@ void bhv_boo_init(void) {
static s32 boo_should_be_stopped(void) {
if (cur_obj_has_behavior(bhvMerryGoRoundBigBoo) || cur_obj_has_behavior(bhvMerryGoRoundBoo)) {
for (s32 i = 0; i < MAX_PLAYERS; i++) {
if (!is_player_active(&gMarioStates[i])) { continue; }
if (gMarioStates[i].currentRoom != BBH_DYNAMIC_SURFACE_ROOM && gMarioStates[i].currentRoom != BBH_NEAR_MERRY_GO_ROUND_ROOM) { return TRUE; }
}
return FALSE;
/*if (!gMarioOnMerryGoRound) {
if (!gMarioOnMerryGoRound) {
return TRUE;
} else {
return FALSE;
}*/
}
} else {
if (o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM) {
return TRUE;
@ -384,9 +379,7 @@ static void boo_chase_mario(f32 a0, s16 a1, f32 a2) {
if (boo_vanish_or_appear()) {
o->oInteractType = 0x8000;
u8 isMerryGoRoundBoo = (cur_obj_has_behavior(bhvMerryGoRoundBigBoo) || cur_obj_has_behavior(bhvMerryGoRoundBoo));
if (!isMerryGoRoundBoo && cur_obj_lateral_dist_from_obj_to_home(player) > 1500.0f) {
if (cur_obj_lateral_dist_from_obj_to_home(player) > 1500.0f) {
sp1A = cur_obj_angle_to_home();
} else {
sp1A = angleToPlayer;
@ -535,7 +528,8 @@ static void (*sBooActions[])(void) = {
};
void bhv_boo_loop(void) {
if (o->oAction < 3) {
// COOP: only sync when Boo isn't in a death state
if (o->oAction < 3 || o->oAction == 5) {
if (!sync_object_is_initialized(o->oSyncID)) {
struct SyncObject* so = boo_sync_object_init();
if (so) { so->syncDeathEvent = FALSE; }

View file

@ -1781,7 +1781,7 @@ s32 unused_update_mode_5_camera(UNUSED struct Camera *c, UNUSED Vec3f focus, UNU
return 0;
}
static void stub_camera_1(UNUSED s32 unused) {
UNUSED static void stub_camera_1(UNUSED s32 unused) {
}
void mode_boss_fight_camera(struct Camera *c) {
@ -5614,7 +5614,7 @@ void set_focus_rel_mario(struct Camera *c, f32 leftRight, f32 yOff, f32 forwBack
* @param forwBack offset to Mario's front/back, relative to his faceAngle
* @param yawOff offset to Mario's faceAngle, changes the direction of `leftRight` and `forwBack`
*/
static void unused_set_pos_rel_mario(struct Camera *c, f32 leftRight, f32 yOff, f32 forwBack, s16 yawOff) {
UNUSED static void unused_set_pos_rel_mario(struct Camera *c, f32 leftRight, f32 yOff, f32 forwBack, s16 yawOff) {
if (!c) { return; }
u16 yaw = sMarioCamState->faceAngle[1] + yawOff;
@ -7606,7 +7606,7 @@ void cutscene_unsoften_music(UNUSED struct Camera *c) {
seq_player_unlower_volume(SEQ_PLAYER_LEVEL, 60);
}
static void stub_camera_5(UNUSED struct Camera *c) {
UNUSED static void stub_camera_5(UNUSED struct Camera *c) {
}
BAD_RETURN(s32) cutscene_unused_start(UNUSED struct Camera *c) {
@ -8133,7 +8133,7 @@ BAD_RETURN(s32) cutscene_dance_rotate_move_towards_mario(struct Camera *c) {
/**
* Speculated to be dance-related due to its proximity to the other dance functions
*/
static BAD_RETURN(s32) cutscene_dance_unused(UNUSED struct Camera *c) {
UNUSED static BAD_RETURN(s32) cutscene_dance_unused(UNUSED struct Camera *c) {
}
/**
@ -9089,7 +9089,7 @@ BAD_RETURN(s32) cutscene_death_stomach_goto_mario(struct Camera *c) {
/**
* Ah, yes
*/
static void unused_water_death_move_to_side_of_mario(struct Camera *c) {
UNUSED static void unused_water_death_move_to_side_of_mario(struct Camera *c) {
water_death_move_to_mario_side(c);
}
@ -9377,7 +9377,7 @@ BAD_RETURN(s32) cutscene_enter_pyramid_top(struct Camera *c) {
}
}
static void unused_cutscene_goto_cvar(struct Camera *c) {
UNUSED static void unused_cutscene_goto_cvar(struct Camera *c) {
if (!c) { return; }
f32 dist;
@ -9543,7 +9543,7 @@ BAD_RETURN(s32) cutscene_read_message_start(struct Camera *c) {
sCutsceneVars[0].angle[0] = 0;
}
static void unused_cam_to_mario(struct Camera *c) {
UNUSED static void unused_cam_to_mario(struct Camera *c) {
if (!c) { return; }
Vec3s dir;
@ -10972,7 +10972,7 @@ void cutscene_palette_editor(struct Camera *c) {
&gDjuiPaletteToggle->base,
(
m->action == ACT_IDLE ||
m->action == ACT_PALETTE_EDITOR_CAP
m->action == ACT_PALETTE_EDITOR_CAP
) && !capMissing
);
}

View file

@ -18,6 +18,7 @@
#include "sound_init.h"
#include "mario.h"
#include "camera.h"
#include "bettercamera.h"
#include "object_list_processor.h"
#include "ingame_menu.h"
#include "obj_behaviors.h"
@ -471,6 +472,14 @@ void init_mario_after_warp(void) {
if (gCurrentArea) {
reset_camera(gCurrentArea->camera);
if (sWarpDest.type == WARP_TYPE_SAME_AREA && gCurrentArea->camera->mode == CAMERA_MODE_NEWCAM) {
// When we warp to a level in the same area, the camera mode never has the chance
// to reset. This is bad if our camera mode is newcam, since when init cam is called
// our old camera mode will be set to newcam, which causes newcam to not be able to be
// turned off. The fix is setting our mode to newcam's old mode
gCurrentArea->camera->mode = gNewCamera.savedMode;
gCurrentArea->camera->defMode = gNewCamera.savedDefMode;
}
}
sWarpDest.type = WARP_TYPE_NOT_WARPING;
sDelayedWarpOp = WARP_OP_NONE;

View file

@ -2942,19 +2942,27 @@ void bhv_init_room(void) {
void cur_obj_enable_rendering_if_mario_in_room(void) {
if (!o) { return; }
if (o->oRoom == -1) { return; }
if (gMarioCurrentRoom == 0) { return; }
// COOP: if any active player character's room is 0, then either:
// 1) There are no rooms in the area
// 2) They are on an object surface with no explicit room
// In vanilla, a room of 0 stops the game from checking if the object shouldn't be rendered
// In coop, this needs to be respected to ensure the object remains active in areas with rooms
u8 marioInRoom = FALSE;
// check if any player character can "see" the object's room
for (s32 i = 0; i < MAX_PLAYERS; i++) {
if (gMarioStates[i].currentRoom != 0) {
if (is_player_active(&gMarioStates[i])) {
// TODO: separate rendering and activation
if (gMarioStates[i].currentRoom == 0) { return; }
s16 currentRoom = gMarioStates[i].currentRoom;
if (currentRoom == o->oRoom) {
marioInRoom = TRUE;
} else if (gDoorAdjacentRooms[currentRoom][0] == o->oRoom) {
marioInRoom = TRUE;
} else if (gDoorAdjacentRooms[currentRoom][1] == o->oRoom) {
if (
currentRoom == o->oRoom
|| gDoorAdjacentRooms[currentRoom][0] == o->oRoom
|| gDoorAdjacentRooms[currentRoom][1] == o->oRoom
) {
marioInRoom = TRUE;
break;
}
}
}