mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-04-25 19:42:20 +00:00
Merry-Go-Round Fixes (includes fixes for rooms and remote object-spawned objects) (#1094)
This commit is contained in:
parent
1f3de4fe0a
commit
52446ded91
5 changed files with 69 additions and 22 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue