diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index 319216798..6178b46d5 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -2715,7 +2715,7 @@ CAP = 6 PLAYER_PART_MAX = 7 --- @type PlayerParts -METAL = 6 +METAL = CAP --- @class DialogId diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 7ef5ae35c..ee317baf6 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -5402,6 +5402,15 @@ function is_point_close_to_object(obj, x, y, z, dist) -- ... end +--- @param x number +--- @param y number +--- @param z number +--- @param dist integer +--- @return integer +function is_point_within_radius_of_any_player(x, y, z, dist) + -- ... +end + --- @param x number --- @param y number --- @param z number @@ -5435,6 +5444,12 @@ function nearest_player_to_object(obj) -- ... end +--- @param obj Object +--- @return MarioState +function nearest_possible_mario_state_to_object(obj) + -- ... +end + --- @param collisionFlags integer --- @param floor Surface --- @return nil diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua index 20b1ac374..32d4208bc 100644 --- a/autogen/lua_definitions/structs.lua +++ b/autogen/lua_definitions/structs.lua @@ -742,6 +742,7 @@ --- @field public unkC4 number --- @field public usedObj Object --- @field public vel Vec3f +--- @field public visibleToEnemies integer --- @field public wall Surface --- @field public wallKickTimer integer --- @field public wallNormal Vec3f diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 2d1eb77ec..cd9f53d98 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -887,7 +887,7 @@ | SKIN | 5 | | CAP | 6 | | PLAYER_PART_MAX | 7 | -| METAL | 6 | +| METAL | CAP | [:arrow_up_small:](#) diff --git a/docs/lua/functions-3.md b/docs/lua/functions-3.md index 5f76aa9a7..28dc28702 100644 --- a/docs/lua/functions-3.md +++ b/docs/lua/functions-3.md @@ -7702,6 +7702,29 @@
+## [is_point_within_radius_of_any_player](#is_point_within_radius_of_any_player) + +### Lua Example +`local integerValue = is_point_within_radius_of_any_player(x, y, z, dist)` + +### Parameters +| Field | Type | +| ----- | ---- | +| x | `number` | +| y | `number` | +| z | `number` | +| dist | `integer` | + +### Returns +- `integer` + +### C Prototype +`s8 is_point_within_radius_of_any_player(f32 x, f32 y, f32 z, s32 dist);` + +[:arrow_up_small:](#) + +
+ ## [is_point_within_radius_of_mario](#is_point_within_radius_of_mario) ### Lua Example @@ -7805,6 +7828,26 @@
+## [nearest_possible_mario_state_to_object](#nearest_possible_mario_state_to_object) + +### Lua Example +`local MarioStateValue = nearest_possible_mario_state_to_object(obj)` + +### Parameters +| Field | Type | +| ----- | ---- | +| obj | [Object](structs.md#Object) | + +### Returns +[MarioState](structs.md#MarioState) + +### C Prototype +`struct MarioState* nearest_possible_mario_state_to_object(struct Object *obj);` + +[:arrow_up_small:](#) + +
+ ## [obj_check_floor_death](#obj_check_floor_death) ### Lua Example diff --git a/docs/lua/functions.md b/docs/lua/functions.md index f9265ab32..f42168d2c 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -1057,11 +1057,13 @@ - [is_player_active](functions-3.md#is_player_active) - [is_player_in_local_area](functions-3.md#is_player_in_local_area) - [is_point_close_to_object](functions-3.md#is_point_close_to_object) + - [is_point_within_radius_of_any_player](functions-3.md#is_point_within_radius_of_any_player) - [is_point_within_radius_of_mario](functions-3.md#is_point_within_radius_of_mario) - [nearest_interacting_mario_state_to_object](functions-3.md#nearest_interacting_mario_state_to_object) - [nearest_interacting_player_to_object](functions-3.md#nearest_interacting_player_to_object) - [nearest_mario_state_to_object](functions-3.md#nearest_mario_state_to_object) - [nearest_player_to_object](functions-3.md#nearest_player_to_object) + - [nearest_possible_mario_state_to_object](functions-3.md#nearest_possible_mario_state_to_object) - [obj_check_floor_death](functions-3.md#obj_check_floor_death) - [obj_check_if_facing_toward_angle](functions-3.md#obj_check_if_facing_toward_angle) - [obj_find_wall](functions-3.md#obj_find_wall) diff --git a/docs/lua/structs.md b/docs/lua/structs.md index 367f31e2f..534e24af8 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -1065,6 +1065,7 @@ | unkC4 | `number` | | | usedObj | [Object](structs.md#Object) | | | vel | [Vec3f](structs.md#Vec3f) | read-only | +| visibleToEnemies | `integer` | | | wall | [Surface](structs.md#Surface) | | | wallKickTimer | `integer` | | | wallNormal | [Vec3f](structs.md#Vec3f) | read-only | diff --git a/include/types.h b/include/types.h index ca5b36afa..d84a84fd4 100644 --- a/include/types.h +++ b/include/types.h @@ -393,6 +393,7 @@ struct MarioState /*????*/ u8 knockbackTimer; /*????*/ u8 specialTripleJump; /*????*/ Vec3f wallNormal; + /*????*/ u8 visibleToEnemies; }; struct TextureInfo diff --git a/src/game/behaviors/activated_bf_plat.inc.c b/src/game/behaviors/activated_bf_plat.inc.c index e180b95f1..98a40cdf3 100644 --- a/src/game/behaviors/activated_bf_plat.inc.c +++ b/src/game/behaviors/activated_bf_plat.inc.c @@ -79,8 +79,9 @@ void bhv_activated_back_and_forth_platform_update(void) { u8 doSendNetwork = FALSE; UNUSED s32 unused[3]; - struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + struct MarioState* marioState = nearest_possible_mario_state_to_object(o); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; // oVelY is used for vertical platforms' movement and also for // horizontal platforms' dipping up/down when Mario gets on/off them diff --git a/src/game/behaviors/amp.inc.c b/src/game/behaviors/amp.inc.c index 0376b2dc4..4b2a693f5 100644 --- a/src/game/behaviors/amp.inc.c +++ b/src/game/behaviors/amp.inc.c @@ -65,8 +65,8 @@ static void homing_amp_appear_loop(void) { // In Fixed cam, it is the point behind Mario the camera will go to when transitioning // to Lakitu cam. Homing amps will point themselves towards this point when appearing. struct Object* player = nearest_player_to_object(o); - f32 relativeTargetX = player->oPosX - o->oPosX; - f32 relativeTargetZ = player->oPosZ - o->oPosZ; + f32 relativeTargetX = player ? player->oPosX - o->oPosX : 10000; + f32 relativeTargetZ = player ? player->oPosZ - o->oPosZ : 10000; //f32 relativeTargetX = gLakituState.goalPos[0] - o->oPosX; //f32 relativeTargetZ = gLakituState.goalPos[2] - o->oPosZ; s16 targetYaw = atan2s(relativeTargetZ, relativeTargetX); @@ -97,7 +97,11 @@ static void homing_amp_appear_loop(void) { */ static void homing_amp_chase_loop(void) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; + + if (!player) { + o->oHomingAmpLockedOn = FALSE; + } // Lock on to Mario if he ever goes within 11.25 degrees of the amp's line of sight if ((angleToPlayer - 0x400 < o->oMoveAngleYaw) @@ -129,13 +133,15 @@ static void homing_amp_chase_loop(void) { // while curving towards him. o->oForwardVel = 10.0f; - obj_turn_toward_object(o, player, 16, 0x400); + if (player) { + obj_turn_toward_object(o, player, 16, 0x400); - // The amp's average Y will approach Mario's graphical Y position + 250 - // at a rate of 10 units per frame. Interestingly, this is different from - // the + 150 used while chasing him. Could this be a typo? - if (o->oHomingAmpAvgY < player->header.gfx.pos[1] + 250.0f) { - o->oHomingAmpAvgY += 10.0f; + // The amp's average Y will approach Mario's graphical Y position + 250 + // at a rate of 10 units per frame. Interestingly, this is different from + // the + 150 used while chasing him. Could this be a typo? + if (o->oHomingAmpAvgY < player->header.gfx.pos[1] + 250.0f) { + o->oHomingAmpAvgY += 10.0f; + } } } @@ -287,13 +293,15 @@ static void fixed_circling_amp_idle_loop(void) { struct Object* player = nearest_player_to_object(o); // Turn towards Mario, in both yaw and pitch. - f32 xToMario = player->header.gfx.pos[0] - o->oPosX; - f32 yToMario = player->header.gfx.pos[1] + 120.0f - o->oPosY; - f32 zToMario = player->header.gfx.pos[2] - o->oPosZ; - s16 vAngleToMario = atan2s(sqrtf(xToMario * xToMario + zToMario * zToMario), -yToMario); + if (player) { + f32 xToMario = player->header.gfx.pos[0] - o->oPosX; + f32 yToMario = player->header.gfx.pos[1] + 120.0f - o->oPosY; + f32 zToMario = player->header.gfx.pos[2] - o->oPosZ; + s16 vAngleToMario = atan2s(sqrtf(xToMario * xToMario + zToMario * zToMario), -yToMario); - obj_turn_toward_object(o, player, 19, 0x1000); - o->oFaceAnglePitch = approach_s16_symmetric(o->oFaceAnglePitch, vAngleToMario, 0x1000); + obj_turn_toward_object(o, player, 19, 0x1000); + o->oFaceAnglePitch = approach_s16_symmetric(o->oFaceAnglePitch, vAngleToMario, 0x1000); + } // Oscillate 40 units up and down. // Interestingly, 0x458 (1112 in decimal) is a magic number with no apparent significance. diff --git a/src/game/behaviors/bird.inc.c b/src/game/behaviors/bird.inc.c index 12a6a00e8..33550460e 100644 --- a/src/game/behaviors/bird.inc.c +++ b/src/game/behaviors/bird.inc.c @@ -16,7 +16,7 @@ static void bird_act_inactive(void) { // Start flying if the object is a spawned bird or if it's a spawner bird // and Mario is within 2000 units. struct Object* player = nearest_player_to_object(o); - if (o->oBehParams2ndByte == BIRD_BP_SPAWNED || dist_between_objects(o, player) < 2000.0f) { + if (o->oBehParams2ndByte == BIRD_BP_SPAWNED || (player && dist_between_objects(o, player) < 2000.0f)) { // If the object is a spawner bird, play the sound of birds flying away, // and spawn 6 spawned birds (which will start flying on the next frame). if (o->oBehParams2ndByte != BIRD_BP_SPAWNED) { diff --git a/src/game/behaviors/bobomb.inc.c b/src/game/behaviors/bobomb.inc.c index 6c2e6bd8d..5bd906719 100644 --- a/src/game/behaviors/bobomb.inc.c +++ b/src/game/behaviors/bobomb.inc.c @@ -54,7 +54,9 @@ void bobomb_check_interactions(void) { if ((o->oInteractStatus & INT_STATUS_MARIO_UNK1) != 0) { struct Object* player = nearest_player_to_object(o); - o->oMoveAngleYaw = player->header.gfx.angle[1]; + if (player) { + o->oMoveAngleYaw = player->header.gfx.angle[1]; + } o->oForwardVel = 25.0; o->oVelY = 30.0; o->oAction = BOBOMB_ACT_LAUNCHED; @@ -80,7 +82,8 @@ void bobomb_act_patrol(void) { collisionFlags = object_step(); struct Object* player = nearest_player_to_object(o); - if ((obj_return_home_if_safe(o, o->oHomeX, o->oHomeY, o->oHomeZ, 400) == 1) + if (player + && (obj_return_home_if_safe(o, o->oHomeX, o->oHomeY, o->oHomeZ, 400) == 1) && (obj_check_if_facing_toward_angle(o->oMoveAngleYaw, obj_angle_to_object(o, player), 0x2000) == TRUE)) { o->oBobombFuseLit = 1; o->oAction = BOBOMB_ACT_CHASE_MARIO; @@ -101,7 +104,9 @@ void bobomb_act_chase_mario(void) { cur_obj_play_sound_2(SOUND_OBJ_BOBOMB_WALK); struct Object* player = nearest_player_to_object(o); - obj_turn_toward_object(o, player, 16, 0x800); + if (player) { + obj_turn_toward_object(o, player, 16, 0x800); + } obj_check_floor_death(collisionFlags, sObjFloor); } @@ -314,7 +319,7 @@ void bobomb_buddy_act_idle(void) { } struct Object* player = nearest_player_to_object(o); - if (dist_between_objects(o, player) < 1000.0f) { + if (player && dist_between_objects(o, player) < 1000.0f) { o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, obj_angle_to_object(o, player), 0x140); } @@ -421,7 +426,7 @@ void bobomb_buddy_act_turn_to_talk(void) { } struct Object *player = nearest_interacting_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, angleToPlayer, 0x1000); if ((s16) o->oMoveAngleYaw == (s16) angleToPlayer) { o->oAction = BOBOMB_BUDDY_ACT_TALK; diff --git a/src/game/behaviors/boo.inc.c b/src/game/behaviors/boo.inc.c index 5301c8e01..d799209f2 100644 --- a/src/game/behaviors/boo.inc.c +++ b/src/game/behaviors/boo.inc.c @@ -83,7 +83,7 @@ static s32 boo_should_be_stopped(void) { static s32 boo_should_be_active(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, marioState->marioObj); + s32 distanceToPlayer = marioState ? dist_between_objects(o, marioState->marioObj) : 10000; u8 inRoom = FALSE; for (s32 i = 0; i < MAX_PLAYERS; i++) { @@ -178,6 +178,7 @@ static void boo_oscillate(s32 ignoreOpacity) { static s32 boo_vanish_or_appear(void) { struct Object* player = nearest_player_to_object(o); + if (!player) { return FALSE; } s32 angleToPlayer = obj_angle_to_object(o, player); s16 relativeAngleToMario = abs_angle_diff(angleToPlayer, o->oMoveAngleYaw); @@ -207,7 +208,7 @@ static s32 boo_vanish_or_appear(void) { static void boo_set_move_yaw_for_during_hit(s32 hurt) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; cur_obj_become_intangible(); @@ -301,12 +302,13 @@ static s32 big_boo_update_during_nonlethal_hit(f32 a0) { // returns whether death is complete static s32 boo_update_during_death(void) { struct Object* player = nearest_player_to_object(o); - struct Object *parentBigBoo; if (o->oTimer == 0) { o->oForwardVel = 40.0f; - o->oMoveAngleYaw = player->oMoveAngleYaw; + if (player) { + o->oMoveAngleYaw = player->oMoveAngleYaw; + } o->oBooDeathStatus = BOO_DEATH_STATUS_DYING; o->oFlags &= ~OBJ_FLAG_SET_FACE_YAW_TO_MOVE_YAW; } else { @@ -376,6 +378,7 @@ static s32 boo_get_attack_status(void) { // boo idle/chasing movement? static void boo_chase_mario(f32 a0, s16 a1, f32 a2) { struct MarioState* marioState = nearest_mario_state_to_object(o); + if (!marioState) { return; } struct Object* player = marioState->marioObj; s32 angleToPlayer = obj_angle_to_object(o, player); @@ -514,12 +517,14 @@ static void boo_act_4(void) { } struct MarioState* marioState = nearest_mario_state_to_object(o); - if (marioState->playerIndex != 0 || cur_obj_update_dialog(&gMarioStates[0], 2, 2, dialogID, 0, boo_act_4_continue_dialog)) { - create_sound_spawner(SOUND_OBJ_DYING_ENEMY1); - obj_mark_for_deletion(o); + if (marioState) { + if (marioState->playerIndex != 0 || cur_obj_update_dialog(&gMarioStates[0], 2, 2, dialogID, 0, boo_act_4_continue_dialog)) { + create_sound_spawner(SOUND_OBJ_DYING_ENEMY1); + obj_mark_for_deletion(o); - if (dialogID == (s32) gBehaviorValues.dialogs.GhostHuntAfterDialog) { // If the Big Boo should spawn, play the jingle - play_puzzle_jingle(); + if (dialogID == (s32) gBehaviorValues.dialogs.GhostHuntAfterDialog) { // If the Big Boo should spawn, play the jingle + play_puzzle_jingle(); + } } } } @@ -715,7 +720,7 @@ static void big_boo_act_4(void) { #endif struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (o->oBehParams2ndByte == 0) { obj_set_pos(o, 973, 0, 626); @@ -880,7 +885,7 @@ void bhv_merry_go_round_boo_manager_loop(void) { } struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; switch (o->oAction) { case 0: @@ -951,13 +956,14 @@ void bhv_boo_in_castle_loop(void) { if (!sync_object_is_initialized(o->oSyncID)) { boo_sync_object_init(); } struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; u8 inRoom = FALSE; for (s32 i = 0; i < MAX_PLAYERS; i++) { if (!is_player_active(&gMarioStates[i])) { continue; } + if (!marioState) { continue; } if (marioState->floor == NULL) { continue; } inRoom = inRoom || (marioState->floor->room == 1); } diff --git a/src/game/behaviors/boo_cage.inc.c b/src/game/behaviors/boo_cage.inc.c index d3673910c..b71d4a058 100644 --- a/src/game/behaviors/boo_cage.inc.c +++ b/src/game/behaviors/boo_cage.inc.c @@ -68,7 +68,7 @@ void bhv_boo_cage_loop(void) { play_puzzle_jingle(); } struct MarioState* marioState = nearest_mario_state_to_object(o); - if (marioState->playerIndex == 0) { + if (marioState && marioState->playerIndex == 0) { network_send_object(o); } o->parentObj = NULL; @@ -104,7 +104,7 @@ void bhv_boo_cage_loop(void) { o->oAction++; struct MarioState* marioState = nearest_mario_state_to_object(o); - if (marioState->playerIndex == 0) { + if (marioState && marioState->playerIndex == 0) { network_send_object(o); } } diff --git a/src/game/behaviors/bouncing_fireball.inc.c b/src/game/behaviors/bouncing_fireball.inc.c index 554d4ee8b..821e067cf 100644 --- a/src/game/behaviors/bouncing_fireball.inc.c +++ b/src/game/behaviors/bouncing_fireball.inc.c @@ -29,7 +29,7 @@ void bhv_bouncing_fireball_flame_loop(void) { void bhv_bouncing_fireball_loop(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; struct Object *sp2C; f32 sp28; diff --git a/src/game/behaviors/bowling_ball.inc.c b/src/game/behaviors/bowling_ball.inc.c index 2eb15fe78..b0b7dc30e 100644 --- a/src/game/behaviors/bowling_ball.inc.c +++ b/src/game/behaviors/bowling_ball.inc.c @@ -188,6 +188,7 @@ void bhv_generic_bowling_ball_spawner_loop(void) { o->oTimer = 0; struct Object* player = nearest_player_to_object(o); + if (!player) { return; } if (is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 1000) || (o->oPosY < player->header.gfx.pos[1])) @@ -222,6 +223,7 @@ void bhv_thi_bowling_ball_spawner_loop(void) { struct Object *bowlingBall; struct Object* player = nearest_player_to_object(o); + if (!player) { return; } if (o->oTimer == 256) o->oTimer = 0; diff --git a/src/game/behaviors/bowser.inc.c b/src/game/behaviors/bowser.inc.c index 700918136..3b88896ab 100644 --- a/src/game/behaviors/bowser.inc.c +++ b/src/game/behaviors/bowser.inc.c @@ -11,7 +11,7 @@ void bowser_tail_anchor_act_0(void) { cur_obj_scale(1.0f); if (bowser->oAction == 5 || bowser->oAction == 6 || bowser->oAction == 19 || bowser->oAction == 20) { bowser->oIntangibleTimer = -1; - } else if (obj_check_if_collided_with_object(o, player)) { + } else if (player && obj_check_if_collided_with_object(o, player)) { bowser->oIntangibleTimer = 0; o->oAction = 2; } else { @@ -92,7 +92,7 @@ void bhv_bowser_flame_spawn_loop(void) { o->oMoveAngleYaw = sp1C[5 * sp30 + 3] + (s16) bowser->oMoveAngleYaw; if (!(sp30 & 1)) { struct MarioState* marioState = nearest_mario_state_to_object(o); - if (marioState->playerIndex == 0) { + if (marioState && marioState->playerIndex == 0) { struct Object* flame = spawn_object(o, MODEL_RED_FLAME, bhvFlameMovingForwardGrowing); if (flame != NULL) { struct Object* spawn_objects[] = { flame }; @@ -141,7 +141,7 @@ s32 bowser_spawn_shockwave(void) { struct Object *wave; if (o->oBehParams2ndByte == 2) { struct MarioState* marioState = nearest_mario_state_to_object(o); - if (marioState->playerIndex == 0) { + if (marioState && marioState->playerIndex == 0) { wave = spawn_object(o, MODEL_BOWSER_WAVE, bhvBowserShockWave); if (wave != NULL) { wave->oPosY = o->oFloorHeight; @@ -248,6 +248,7 @@ static void bowser_debug_actions(void) // unused void bowser_bitdw_act_controller(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); + if (!marioState) { return; } struct Object* player = marioState->marioObj; s32 distanceToPlayer = dist_between_objects(o, player); if (marioState->playerIndex != 0) { return; } @@ -285,6 +286,7 @@ void bowser_bitdw_act_controller(void) { void bowser_bitfs_act_controller(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); + if (!marioState) { return; } struct Object* player = marioState->marioObj; s32 distanceToPlayer = dist_between_objects(o, player); if (marioState->playerIndex != 0) { return; } @@ -317,6 +319,7 @@ void bowser_bitfs_act_controller(void) { void bowser_general_bits_act_controller(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); + if (!marioState) { return; } struct Object* player = marioState->marioObj; s32 distanceToPlayer = dist_between_objects(o, player); if (marioState->playerIndex != 0) { return; } @@ -345,6 +348,7 @@ void bowser_set_act_jump(void) { void bowser_bits_act_controller(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); + if (!marioState) { return; } if (marioState->playerIndex != 0) { return; } switch (o->oBowserUnk110) { case 0: @@ -408,6 +412,7 @@ void bowser_act_breath_fire(void) { void bowser_act_walk_to_mario(void) // turn towards Mario { struct Object* player = nearest_player_to_object(o); + if (!player) { return; } s32 angleToPlayer = obj_angle_to_object(o, player); UNUSED s32 facing; // is Bowser facing Mario? @@ -441,6 +446,7 @@ void bowser_act_walk_to_mario(void) // turn towards Mario void bowser_act_teleport(void) { struct Object* player = nearest_player_to_object(o); + if (!player) { return; } s32 distanceToPlayer = dist_between_objects(o, player); s32 angleToPlayer = obj_angle_to_object(o, player); @@ -488,7 +494,7 @@ void bowser_act_spit_fire_into_sky(void) // only in sky if (frame > 24 && frame < 36) { cur_obj_play_sound_1(SOUND_AIR_BOWSER_SPIT_FIRE); struct MarioState* marioState = nearest_mario_state_to_object(o); - if (marioState->playerIndex == 0) { + if (marioState && marioState->playerIndex == 0) { struct Object* flame = NULL; if (frame == 35) { flame = spawn_object_relative(1, 0, 0x190, 0x64, o, MODEL_RED_FLAME, bhvBlueBowserFlame); @@ -681,6 +687,7 @@ void bowser_act_turn_from_edge(void) { void bowser_act_charge_mario(void) { struct Object* player = nearest_player_to_object(o); + if (!player) { return; } s32 angleToPlayer = obj_angle_to_object(o, player); s32 sp34; @@ -922,6 +929,7 @@ void bowser_dead_bounce(void) { s32 bowser_dead_wait_for_mario(void) { struct Object* player = nearest_player_to_object(o); + if (!player) { return 0; } s32 distanceToPlayer = dist_between_objects(o, player); s32 angleToPlayer = obj_angle_to_object(o, player); @@ -972,7 +980,7 @@ s32 bowser_dead_not_bits_end(void) { seq_player_lower_volume(SEQ_PLAYER_LEVEL, 60, 40); o->oBowserUnkF8++; } - if (should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog(marioState, 2, 18, *sBowserDefeatedDialogText[o->oBehParams2ndByte], 0, bowser_dead_not_bits_end_continue_dialog)) { + if (marioState && should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog(marioState, 2, 18, *sBowserDefeatedDialogText[o->oBehParams2ndByte], 0, bowser_dead_not_bits_end_continue_dialog)) { o->oBowserUnkF8++; cur_obj_play_sound_2(SOUND_GENERAL2_BOWSER_EXPLODE); seq_player_unlower_volume(SEQ_PLAYER_LEVEL, 60); @@ -984,7 +992,9 @@ s32 bowser_dead_not_bits_end(void) { bowser_dead_hide(); spawn_triangle_break_particles(20, 116, 1.0f, 0); bowser_spawn_grand_star_key(); - set_mario_npc_dialog(&gMarioStates[0], 0, NULL); + if (gMarioStates[0].visibleToEnemies) { + set_mario_npc_dialog(&gMarioStates[0], 0, NULL); + } return 1; } return 0; @@ -1004,7 +1014,7 @@ s32 bowser_dead_bits_end(void) { seq_player_lower_volume(SEQ_PLAYER_LEVEL, 60, 40); o->oBowserUnkF8++; } - if (should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog(marioState, 2, 18, dialogID, 0, bowser_dead_bits_end_continue_dialog)) { + if (marioState && should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog(marioState, 2, 18, dialogID, 0, bowser_dead_bits_end_continue_dialog)) { cur_obj_set_model(smlua_model_util_load(E_MODEL_BOWSER2)); seq_player_unlower_volume(SEQ_PLAYER_LEVEL, 60); seq_player_fade_out(SEQ_PLAYER_LEVEL, 1); @@ -1265,8 +1275,8 @@ void bowser_thrown_dropped_update(void) { void bhv_bowser_loop(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; // look for animation difference and override struct Animation* anim = NULL; @@ -1428,7 +1438,7 @@ Gfx *geo_update_body_rot_from_parent(s32 run, UNUSED struct GraphNode *node, Mat void bowser_open_eye_switch(struct Object *a0, struct GraphNodeSwitchCase *switchCase) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; s32 sp1C; s16 sp1A; @@ -1849,7 +1859,9 @@ void bhv_blue_flames_group_loop(void) { struct Object *flame; s32 i; if (o->oTimer == 0) { - o->oMoveAngleYaw = obj_angle_to_object(o, player); + if (player) { + o->oMoveAngleYaw = obj_angle_to_object(o, player); + } o->oBlueFlameNextScale = 5.0f; } if (o->oTimer < 16) { diff --git a/src/game/behaviors/bowser_bomb.inc.c b/src/game/behaviors/bowser_bomb.inc.c index 1b27aeb03..5acd83ae4 100644 --- a/src/game/behaviors/bowser_bomb.inc.c +++ b/src/game/behaviors/bowser_bomb.inc.c @@ -38,9 +38,9 @@ void bhv_bowser_bomb_loop(void) { } struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; + struct Object* player = marioState ? marioState->marioObj : NULL; - if (networkBowserBombHit == o->oSyncID || (marioState->playerIndex == 0 && obj_check_if_collided_with_object(o, player) == 1)) { + if (networkBowserBombHit == o->oSyncID || (marioState && marioState->playerIndex == 0 && player && obj_check_if_collided_with_object(o, player) == 1)) { bhv_bowser_bomb_hit_player(); } diff --git a/src/game/behaviors/bowser_puzzle_piece.inc.c b/src/game/behaviors/bowser_puzzle_piece.inc.c index 1d4e3f3bf..fa8250d97 100644 --- a/src/game/behaviors/bowser_puzzle_piece.inc.c +++ b/src/game/behaviors/bowser_puzzle_piece.inc.c @@ -127,7 +127,7 @@ void bhv_lll_bowser_puzzle_loop(void) { s32 i; UNUSED struct Object *sp28; struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (!sync_object_is_initialized(o->oSyncID)) { struct SyncObject *so = sync_object_init(o, SYNC_DISTANCE_ONLY_EVENTS); diff --git a/src/game/behaviors/bub.inc.c b/src/game/behaviors/bub.inc.c index e382d5abe..bb4e83fbd 100644 --- a/src/game/behaviors/bub.inc.c +++ b/src/game/behaviors/bub.inc.c @@ -48,6 +48,7 @@ void bub_act_0(void) { void bub_act_1(void) { struct Object* player = nearest_player_to_object(o); + if (!player) { return; } s32 distanceToPlayer = dist_between_objects(o, player); s32 angleToPlayer = obj_angle_to_object(o, player); f32 dy; @@ -80,6 +81,7 @@ void bub_act_1(void) { void bub_act_2(void) { struct Object* player = nearest_player_to_object(o); + if (!player) { return; } s32 distanceToPlayer = dist_between_objects(o, player); s32 angleToPlayer = obj_angle_to_object(o, player); f32 dy; @@ -129,7 +131,9 @@ void bhv_bub_loop(void) { struct Object* player = nearest_player_to_object(o); o->oCheepCheepUnkF4 = find_water_level(o->oPosX, o->oPosZ); - o->oCheepCheepUnkF8 = player->oPosY + o->oCheepCheepUnkFC; + if (player) { + o->oCheepCheepUnkF8 = player->oPosY + o->oCheepCheepUnkFC; + } o->oWallHitboxRadius = 30.0f; cur_obj_update_floor_and_walls(); cur_obj_call_action_function(sCheepCheepActions); diff --git a/src/game/behaviors/bubba.inc.c b/src/game/behaviors/bubba.inc.c index 4bc2a1b62..7dca671d8 100644 --- a/src/game/behaviors/bubba.inc.c +++ b/src/game/behaviors/bubba.inc.c @@ -14,8 +14,8 @@ static struct ObjectHitbox sBubbaHitbox = { void bubba_act_0(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; f32 sp24; @@ -54,9 +54,9 @@ void bubba_act_0(void) { void bubba_act_1(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; treat_far_home_as_mario(2500.0f, &distanceToPlayer, &angleToPlayer); @@ -83,7 +83,7 @@ void bubba_act_1(void) { obj_move_pitch_approach(o->oBubbaUnk1AC, 400); } } else { - if (abs_angle_diff(player->oFaceAngleYaw, angleToPlayer) < 0x3000) { + if (player && abs_angle_diff(player->oFaceAngleYaw, angleToPlayer) < 0x3000) { s16 val04 = 0x4000 - atan2s(800.0f, distanceToPlayer - 800.0f); if ((s16)(o->oMoveAngleYaw - angleToPlayer) < 0) { val04 = -val04; @@ -125,14 +125,16 @@ void bhv_bubba_loop(void) { } struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; UNUSED s32 unused; o->oInteractionSubtype &= ~INT_SUBTYPE_EATS_MARIO; - o->oBubbaUnk104 = obj_turn_pitch_toward_mario(marioState, 120.0f, 0); + if (marioState) { + o->oBubbaUnk104 = obj_turn_pitch_toward_mario(marioState, 120.0f, 0); + } if (abs_angle_diff(angleToPlayer, o->oMoveAngleYaw) < 0x1000 && abs_angle_diff(o->oBubbaUnk104 + 0x800, o->oMoveAnglePitch) < 0x2000) { diff --git a/src/game/behaviors/bullet_bill.inc.c b/src/game/behaviors/bullet_bill.inc.c index c4a4bc540..b1cf7ef01 100644 --- a/src/game/behaviors/bullet_bill.inc.c +++ b/src/game/behaviors/bullet_bill.inc.c @@ -28,8 +28,8 @@ void bullet_bill_act_0(void) { void bullet_bill_act_1(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; s16 sp1E = abs_angle_diff(angleToPlayer, o->oMoveAngleYaw); if (sp1E < 0x2000 && 400.0f < distanceToPlayer && distanceToPlayer < 1500.0f) @@ -38,8 +38,8 @@ void bullet_bill_act_1(void) { void bullet_bill_act_2(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; if (o->oTimer < 40) o->oForwardVel = 3.0f; diff --git a/src/game/behaviors/bully.inc.c b/src/game/behaviors/bully.inc.c index 4f80e9faf..b0b404699 100644 --- a/src/game/behaviors/bully.inc.c +++ b/src/game/behaviors/bully.inc.c @@ -122,7 +122,9 @@ void bully_check_mario_collision(void) { // Get the player who interacted with us. struct MarioState *player = nearest_interacting_mario_state_to_object(o); - o->oBullyLastNetworkPlayerIndex = gNetworkPlayers[player->playerIndex].globalIndex; + if (player) { + o->oBullyLastNetworkPlayerIndex = gNetworkPlayers[player->playerIndex].globalIndex; + } } } @@ -135,7 +137,9 @@ void bully_act_chase_mario(void) { if (o->oTimer < 10) { o->oForwardVel = 3.0; - obj_turn_toward_object(o, player, 16, 4096); + if (player) { + obj_turn_toward_object(o, player, 16, 4096); + } } else if (o->oBehParams2ndByte == BULLY_BP_SIZE_SMALL) { o->oForwardVel = 20.0; if (o->oTimer >= 31) { @@ -161,7 +165,9 @@ void bully_act_knockback(void) { o->oBullyKBTimerAndMinionKOCounter++; o->oFlags |= 0x8; /* bit 3 */ o->oMoveAngleYaw = o->oFaceAngleYaw; - obj_turn_toward_object(o, player, 16, 1280); + if (player) { + obj_turn_toward_object(o, player, 16, 1280); + } } else { o->header.gfx.animInfo.animFrame = 0; } diff --git a/src/game/behaviors/butterfly.inc.c b/src/game/behaviors/butterfly.inc.c index d389f8493..472b1ac93 100644 --- a/src/game/behaviors/butterfly.inc.c +++ b/src/game/behaviors/butterfly.inc.c @@ -43,6 +43,7 @@ void butterfly_step(s32 speed) { void butterfly_calculate_angle(void) { struct Object* player = nearest_player_to_object(o); + if (!player) { return; } player->oPosX += 5 * o->oButterflyYPhase / 4; player->oPosZ += 5 * o->oButterflyYPhase / 4; obj_turn_toward_object(o, player, 16, 0x300); @@ -60,7 +61,9 @@ void butterfly_act_rest(void) { o->oAction = BUTTERFLY_ACT_FOLLOW_MARIO; struct Object* player = nearest_player_to_object(o); - o->oMoveAngleYaw = player->header.gfx.angle[1]; + if (player) { + o->oMoveAngleYaw = player->header.gfx.angle[1]; + } } } diff --git a/src/game/behaviors/camera_lakitu.inc.c b/src/game/behaviors/camera_lakitu.inc.c index f64055d91..08929a271 100644 --- a/src/game/behaviors/camera_lakitu.inc.c +++ b/src/game/behaviors/camera_lakitu.inc.c @@ -67,6 +67,7 @@ static u8 camera_lakitu_intro_act_trigger_cutscene_continue_dialog(void) { */ static void camera_lakitu_intro_act_trigger_cutscene(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); + if (!marioState) { return; } struct Object* player = marioState->marioObj; //! These bounds are slightly smaller than the actual bridge bounds, allowing @@ -88,7 +89,7 @@ static u8 camera_lakitu_intro_act_spawn_cloud_continue_dialog(void) { */ static void camera_lakitu_intro_act_spawn_cloud(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - if (should_start_or_continue_dialog(marioState, o) && set_mario_npc_dialog(&gMarioStates[0], 2, camera_lakitu_intro_act_spawn_cloud_continue_dialog) == 2) { + if (marioState && should_start_or_continue_dialog(marioState, o) && set_mario_npc_dialog(&gMarioStates[0], 2, camera_lakitu_intro_act_spawn_cloud_continue_dialog) == 2) { o->oAction = CAMERA_LAKITU_INTRO_ACT_UNK2; o->oPosX = 1800.0f; @@ -113,9 +114,9 @@ static void camera_lakitu_intro_act_show_dialog(void) { if (lakituTargetLocalIndex != UNKNOWN_LOCAL_INDEX) { marioState = &gMarioStates[lakituTargetLocalIndex]; } - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; s16 targetMovePitch = 0; s16 targetMoveYaw = 0; @@ -123,7 +124,9 @@ static void camera_lakitu_intro_act_show_dialog(void) { cur_obj_play_sound_1(SOUND_AIR_LAKITU_FLY); // Face toward mario - o->oFaceAnglePitch = obj_turn_pitch_toward_mario(marioState, 120.0f, 0); + if (marioState) { + o->oFaceAnglePitch = obj_turn_pitch_toward_mario(marioState, 120.0f, 0); + } o->oFaceAngleYaw = angleToPlayer; // After finishing dialog, fly away and despawn @@ -142,7 +145,7 @@ static void camera_lakitu_intro_act_show_dialog(void) { targetMoveYaw = angleToPlayer; } else { if (lakituTargetLocalIndex == UNKNOWN_LOCAL_INDEX) { - if (marioState->playerIndex == 0) { + if (marioState && marioState->playerIndex == 0) { lakituTargetLocalIndex = 0; } else { goto afterChase; @@ -171,6 +174,7 @@ static void camera_lakitu_intro_act_show_dialog(void) { // Once within 1000 units, slow down approach_f32_ptr(&o->oCameraLakituSpeed, 20.0f, 1.0f); if (distanceToPlayer < 500.0f + && player && abs_angle_diff(player->oFaceAngleYaw, o->oFaceAngleYaw) > 0x7000) { // Once within 500 units and facing toward mario, come // to a stop @@ -178,7 +182,7 @@ static void camera_lakitu_intro_act_show_dialog(void) { } } } - } else if (should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, DIALOG_UNK2_FLAG_0, CUTSCENE_DIALOG, gBehaviorValues.dialogs.LakituIntroDialog, camera_lakitu_intro_act_show_dialog_continue_dialog) != 0) { + } else if (marioState && should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, DIALOG_UNK2_FLAG_0, CUTSCENE_DIALOG, gBehaviorValues.dialogs.LakituIntroDialog, camera_lakitu_intro_act_show_dialog_continue_dialog) != 0) { o->oCameraLakituFinishedDialog = TRUE; } } diff --git a/src/game/behaviors/cannon.inc.c b/src/game/behaviors/cannon.inc.c index 2712ef8f1..a942bd099 100644 --- a/src/game/behaviors/cannon.inc.c +++ b/src/game/behaviors/cannon.inc.c @@ -19,7 +19,7 @@ void opened_cannon_act_0(void) { cur_obj_enable_rendering(); struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (distanceToPlayer < 500.0f) { //cur_obj_become_tangible(); diff --git a/src/game/behaviors/capswitch.inc.c b/src/game/behaviors/capswitch.inc.c index d8fc6dc61..2e1479635 100644 --- a/src/game/behaviors/capswitch.inc.c +++ b/src/game/behaviors/capswitch.inc.c @@ -45,7 +45,7 @@ void cap_switch_act_2(void) { } } else { struct MarioState* marioState = nearest_mario_state_to_object(o); - if (should_start_or_continue_dialog(marioState, o)) { + if (marioState && should_start_or_continue_dialog(marioState, o)) { sp1C = cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 1, 0x0C, CUTSCENE_CAP_SWITCH_PRESS, 0, cap_switch_act_2_continue_dialog); if (sp1C) { o->oAction = 3; } } diff --git a/src/game/behaviors/castle_floor_trap.inc.c b/src/game/behaviors/castle_floor_trap.inc.c index c4d3c5a1c..19cec9c54 100644 --- a/src/game/behaviors/castle_floor_trap.inc.c +++ b/src/game/behaviors/castle_floor_trap.inc.c @@ -43,6 +43,7 @@ void bhv_castle_floor_trap_open(void) { void bhv_castle_floor_trap_close_detect(void) { struct Object* player = nearest_player_to_object(o); + if (!player) { return; } s32 distanceToPlayer = dist_between_objects(o, player); if (distanceToPlayer > 1000.0f) o->oAction = 3; // close trapdoor diff --git a/src/game/behaviors/chain_chomp.inc.c b/src/game/behaviors/chain_chomp.inc.c index 6e704a6e6..c6aada9de 100644 --- a/src/game/behaviors/chain_chomp.inc.c +++ b/src/game/behaviors/chain_chomp.inc.c @@ -165,8 +165,8 @@ static void chain_chomp_sub_act_turn(void) { obj_move_pitch_approach(0, 0x100); struct Object *player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; if (o->oMoveFlags & OBJ_MOVE_MASK_ON_GROUND) { cur_obj_rotate_yaw_toward(angleToPlayer, 0x400); @@ -524,8 +524,8 @@ void bhv_wooden_post_update(void) { o->oPosY = o->oHomeY + o->oWoodenPostOffsetY; } else if (!(o->oBehParams & WOODEN_POST_BP_NO_COINS_MASK)) { struct Object *player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; // Reset the timer once mario is far enough if (distanceToPlayer > 400.0f) { diff --git a/src/game/behaviors/chuckya.inc.c b/src/game/behaviors/chuckya.inc.c index 2387b4f29..443fef3df 100644 --- a/src/game/behaviors/chuckya.inc.c +++ b/src/game/behaviors/chuckya.inc.c @@ -39,8 +39,8 @@ void bhv_chuckya_anchor_mario_loop(void) { s32 unknown_chuckya_function(s32 sp20, f32 sp24, f32 sp28, s32 sp2C) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; s32 sp1C = 0; if (o->oChuckyaUnkF8 != 4) { if (sp24 < cur_obj_lateral_dist_from_mario_to_home()) { @@ -51,8 +51,9 @@ s32 unknown_chuckya_function(s32 sp20, f32 sp24, f32 sp28, s32 sp2C) { angleToPlayer = cur_obj_angle_to_home(); } } else if (distanceToPlayer > sp28) { - if (gGlobalTimer % (s16) sp2C == 0) + if ((gGlobalTimer % (s16) sp2C == 0) && player) { angleToPlayer = obj_angle_to_object(o, player); + } sp1C = 2; } else sp1C = 3; @@ -82,7 +83,7 @@ s32 approach_forward_vel(f32 *arr, f32 spC, f32 sp10) { void chuckya_act_0(void) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; s32 sp3C = 0; UNUSED u8 pad[16]; s32 sp28; diff --git a/src/game/behaviors/cloud.inc.c b/src/game/behaviors/cloud.inc.c index 0c6c5e778..afbef216c 100644 --- a/src/game/behaviors/cloud.inc.c +++ b/src/game/behaviors/cloud.inc.c @@ -67,7 +67,7 @@ static void cloud_fwoosh_update(void) { } struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (o->oCloudBlowing) { o->header.gfx.scale[0] += o->oCloudGrowSpeed; diff --git a/src/game/behaviors/coffin.inc.c b/src/game/behaviors/coffin.inc.c index ce2014e87..02fda7c35 100644 --- a/src/game/behaviors/coffin.inc.c +++ b/src/game/behaviors/coffin.inc.c @@ -94,11 +94,16 @@ void coffin_act_idle(void) { yawSin = sins(o->oFaceAngleYaw); struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; - dx = player->oPosX - o->oPosX; - dz = player->oPosZ - o->oPosZ; + if (player) { + dx = player->oPosX - o->oPosX; + dz = player->oPosZ - o->oPosZ; + } else { + dx = 10000; + dz = 10000; + } distForwards = dx * yawCos + dz * yawSin; distSideways = dz * yawCos - dx * yawSin; @@ -106,8 +111,8 @@ void coffin_act_idle(void) { // This checks a box around the coffin and if it has been a bit since it stood up. // It also checks in the case Mario is squished, so he doesn't get permanently squished. if (o->oTimer > 60 - && (distanceToPlayer > 100.0f || marioState->action == ACT_SQUISHED)) { - if (player->oPosY - o->oPosY < 200.0f && absf(distForwards) < 140.0f) { + && (distanceToPlayer > 100.0f || (marioState && marioState->action == ACT_SQUISHED))) { + if ((player && player->oPosY - o->oPosY < 200.0f) && absf(distForwards) < 140.0f) { if (distSideways < 150.0f && distSideways > -450.0f) { cur_obj_play_sound_2(SOUND_GENERAL_BUTTON_PRESS_2_LOWPRIO); o->oAction = COFFIN_ACT_STAND_UP; diff --git a/src/game/behaviors/controllable_platform.inc.c b/src/game/behaviors/controllable_platform.inc.c index d907fc252..891efa30f 100644 --- a/src/game/behaviors/controllable_platform.inc.c +++ b/src/game/behaviors/controllable_platform.inc.c @@ -147,7 +147,7 @@ void controllable_platform_check_walls(s8 sp1B, s8 sp1C[3], Vec3f sp20, UNUSED V } } - if (!is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 400)) { + if (!is_point_within_radius_of_any_player(o->oPosX, o->oPosY, o->oPosZ, 400)) { D_80331694 = 6; o->oControllablePlatformUnk100 = 1; o->oTimer = 0; @@ -172,7 +172,9 @@ void controllable_platform_shake_on_wall_hit(void) { } void controllable_platform_tilt_from_mario(void) { - struct Object* player = nearest_player_to_object(o); + struct MarioState* marioState = nearest_possible_mario_state_to_object(o); + struct Object* player = marioState ? marioState->marioObj : NULL; + if (!player) { return; } u8 playerCount = 0; f32 x = 0; @@ -200,7 +202,6 @@ void controllable_platform_tilt_from_mario(void) { o->oTimer = 0; o->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE; } - } else { } } diff --git a/src/game/behaviors/donut_platform.inc.c b/src/game/behaviors/donut_platform.inc.c index f82249afb..7e13bc126 100644 --- a/src/game/behaviors/donut_platform.inc.c +++ b/src/game/behaviors/donut_platform.inc.c @@ -36,7 +36,7 @@ void bhv_donut_platform_update(void) { } struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (o->oAction == 2) { cur_obj_set_pos_to_home(); diff --git a/src/game/behaviors/dorrie.inc.c b/src/game/behaviors/dorrie.inc.c index 6fb39ca8b..5b88ff723 100644 --- a/src/game/behaviors/dorrie.inc.c +++ b/src/game/behaviors/dorrie.inc.c @@ -159,8 +159,8 @@ void dorrie_act_raise_head(void) { void bhv_dorrie_update(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; if (!sync_object_is_initialized(o->oSyncID)) { for (s32 i = 0; i < MAX_PLAYERS; i++) { dorrieLiftingPlayer[i] = FALSE; } diff --git a/src/game/behaviors/elevator.inc.c b/src/game/behaviors/elevator.inc.c index b0dd0fdd6..19c78e49c 100644 --- a/src/game/behaviors/elevator.inc.c +++ b/src/game/behaviors/elevator.inc.c @@ -7,7 +7,7 @@ void elevator_starting_shake(void) { void elevator_act_0(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; + struct Object* player = marioState ? marioState->marioObj : NULL; u8 onPlatform = FALSE; for (s32 i = 0; i < MAX_PLAYERS; i++) { @@ -24,7 +24,7 @@ void elevator_act_0(void) { o->oAction = 1; } } - } else if (player->oPosY > o->oElevatorUnkFC || o->oElevatorUnk100 == 1) { + } else if ((player && player->oPosY > o->oElevatorUnkFC) || o->oElevatorUnk100 == 1) { o->oPosY = o->oElevatorUnkF8; if (onPlatform) { o->oAction = 2; @@ -36,12 +36,12 @@ void elevator_act_0(void) { } } - if (marioState->playerIndex == 0 && o->oAction != 0) { network_send_object(o); } + if (marioState && marioState->playerIndex == 0 && o->oAction != 0) { network_send_object(o); } } void elevator_act_1(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; + struct Object* player = marioState ? marioState->marioObj : NULL; cur_obj_play_sound_1(SOUND_ENV_ELEVATOR1); if (o->oTimer == 0 && cur_obj_is_any_player_on_platform()) { @@ -53,19 +53,19 @@ void elevator_act_1(void) { o->oPosY = o->oElevatorUnkF8; if (o->oElevatorUnk100 == 2 || o->oElevatorUnk100 == 1) { o->oAction = 3; - } else if (player->oPosY < o->oElevatorUnkFC) { + } else if (player && player->oPosY < o->oElevatorUnkFC) { o->oAction = 2; } else { o->oAction = 3; } } - if (marioState->playerIndex == 0 && o->oAction != 1) { network_send_object(o); } + if (marioState && marioState->playerIndex == 0 && o->oAction != 1) { network_send_object(o); } } void elevator_act_2(void) { // Pretty similar code to action 1 struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; + struct Object* player = marioState ? marioState->marioObj : NULL; cur_obj_play_sound_1(SOUND_ENV_ELEVATOR1); if (o->oTimer == 0 && cur_obj_is_any_player_on_platform()) { @@ -80,14 +80,14 @@ void elevator_act_2(void) { // Pretty similar code to action 1 o->oAction = 4; } else if (o->oElevatorUnk100 == 2) { o->oAction = 3; - } else if (player->oPosY > o->oElevatorUnkFC) { + } else if (player && player->oPosY > o->oElevatorUnkFC) { o->oAction = 1; } else { o->oAction = 3; } } - if (marioState->playerIndex == 0 && o->oAction != 2) { network_send_object(o); } + if (marioState && marioState->playerIndex == 0 && o->oAction != 2) { network_send_object(o); } } void elevator_act_4(void) { @@ -98,11 +98,11 @@ void elevator_act_4(void) { cur_obj_shake_screen(SHAKE_POS_SMALL); cur_obj_play_sound_2(SOUND_GENERAL_METAL_POUND); } - if (!mario_is_in_air_action(marioState) && !cur_obj_is_any_player_on_platform()) { + if (marioState && !mario_is_in_air_action(marioState) && !cur_obj_is_any_player_on_platform()) { o->oAction = 1; } - if (marioState->playerIndex == 0 && o->oAction != 4) { network_send_object(o); } + if (marioState && marioState->playerIndex == 0 && o->oAction != 4) { network_send_object(o); } } void elevator_act_3(void) // nearly identical to action 2 @@ -114,11 +114,11 @@ void elevator_act_3(void) // nearly identical to action 2 cur_obj_shake_screen(SHAKE_POS_SMALL); cur_obj_play_sound_2(SOUND_GENERAL_METAL_POUND); } - if (!mario_is_in_air_action(marioState) && !cur_obj_is_any_player_on_platform()) { + if (marioState && !mario_is_in_air_action(marioState) && !cur_obj_is_any_player_on_platform()) { o->oAction = 0; } - if (marioState->playerIndex == 0 && o->oAction != 3) { network_send_object(o); } + if (marioState && marioState->playerIndex == 0 && o->oAction != 3) { network_send_object(o); } } void bhv_elevator_init(void) { diff --git a/src/game/behaviors/enemy_lakitu.inc.c b/src/game/behaviors/enemy_lakitu.inc.c index 3e4a44c34..768b61c05 100644 --- a/src/game/behaviors/enemy_lakitu.inc.c +++ b/src/game/behaviors/enemy_lakitu.inc.c @@ -25,7 +25,7 @@ static struct ObjectHitbox sEnemyLakituHitbox = { */ static void enemy_lakitu_act_uninitialized(void) { struct Object *player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (distanceToPlayer < 2000.0f) { spawn_object_relative_with_scale(CLOUD_BP_LAKITU_CLOUD, 0, 0, 0, 2.0f, o, MODEL_MIST, bhvCloud); @@ -65,9 +65,9 @@ static void enemy_lakitu_update_vel_y(f32 offsetY) { */ static void enemy_lakitu_update_speed_and_angle(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; f32 minSpeed; s16 turnSpeed; @@ -78,8 +78,10 @@ static void enemy_lakitu_update_speed_and_angle(void) { } // Move faster the farther away mario is and the faster mario is moving - if ((minSpeed = 1.2f * marioState->forwardVel) < 8.0f) { - minSpeed = 8.0f; + if (marioState) { + if ((minSpeed = 1.2f * marioState->forwardVel) < 8.0f) { + minSpeed = 8.0f; + } } o->oForwardVel = distToMario * 0.04f; clamp_f32(&o->oForwardVel, minSpeed, 40.0f); @@ -106,9 +108,9 @@ static void enemy_lakitu_update_speed_and_angle(void) { */ static void enemy_lakitu_sub_act_no_spiny(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; treat_far_home_as_mario(2000.0f, &distanceToPlayer, &angleToPlayer); @@ -120,7 +122,7 @@ static void enemy_lakitu_sub_act_no_spiny(void) { } else if (o->oEnemyLakituNumSpinies < 3 && distanceToPlayer < 800.0f && abs_angle_diff(angleToPlayer, o->oFaceAngleYaw) < 0x4000) { - if (marioState->playerIndex == 0) { + if (marioState && marioState->playerIndex == 0) { struct Object* spiny = spawn_object(o, MODEL_SPINY_BALL, bhvSpiny); if (spiny != NULL) { o->prevObj = spiny; @@ -153,8 +155,8 @@ static void enemy_lakitu_sub_act_hold_spiny(void) { } struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; treat_far_home_as_mario(2000.0f, &distanceToPlayer, &angleToPlayer); @@ -222,7 +224,7 @@ static void enemy_lakitu_act_main(void) { } struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (distanceToPlayer <= o->oDrawingDistance) { cur_obj_move_standard(78); } diff --git a/src/game/behaviors/exclamation_box.inc.c b/src/game/behaviors/exclamation_box.inc.c index 5b91530bd..6a9c632ed 100644 --- a/src/game/behaviors/exclamation_box.inc.c +++ b/src/game/behaviors/exclamation_box.inc.c @@ -112,6 +112,7 @@ void exclamation_box_act_3(void) { } static s32 exclamation_replace_model(struct MarioState* m, s32 model) { + if (!m) { return model; } switch (model) { case MODEL_MARIOS_CAP: return m->character->capModelId; case MODEL_MARIOS_METAL_CAP: return m->character->capMetalModelId; @@ -122,8 +123,8 @@ static s32 exclamation_replace_model(struct MarioState* m, s32 model) { } void exclamation_box_spawn_contents(struct Struct802C0DF0 *a0, u8 a1) { - struct MarioState* m = nearest_mario_state_to_object(o); - struct Object* player = m->marioObj; + struct MarioState* marioState = nearest_mario_state_to_object(o); + struct Object* player = marioState ? marioState->marioObj : NULL; struct Object *sp1C = NULL; if (o->oExclamationBoxForce) { @@ -132,14 +133,16 @@ void exclamation_box_spawn_contents(struct Struct802C0DF0 *a0, u8 a1) { while (a0->unk0 != 99) { if (a1 == a0->unk0) { - s32 model = exclamation_replace_model(m, a0->model); + s32 model = exclamation_replace_model(marioState, a0->model); sp1C = spawn_object(o, model, a0->behavior); if (sp1C != NULL) { sp1C->oVelY = 20.0f; sp1C->oForwardVel = 3.0f; - sp1C->oMoveAngleYaw = player->oMoveAngleYaw; - sp1C->globalPlayerIndex = player->globalPlayerIndex; + if (player) { + sp1C->oMoveAngleYaw = player->oMoveAngleYaw; + sp1C->globalPlayerIndex = player->globalPlayerIndex; + } } o->oBehParams |= a0->unk2 << 24; if (a0->model == 122) diff --git a/src/game/behaviors/eyerok.inc.c b/src/game/behaviors/eyerok.inc.c index a402cf23c..ebb5709b3 100644 --- a/src/game/behaviors/eyerok.inc.c +++ b/src/game/behaviors/eyerok.inc.c @@ -15,7 +15,7 @@ static u8 eyerokBossImmediateUpdate = FALSE; static s32 eyerok_check_mario_relative_z(s32 arg0) { struct Object* player = nearest_player_to_object(o); - if (player->oPosZ - o->oHomeZ < arg0) { + if (player && player->oPosZ - o->oHomeZ < arg0) { return TRUE; } else { return FALSE; @@ -87,7 +87,7 @@ void bhv_eyerok_boss_init(void) { static void eyerok_boss_act_sleep(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (o->oTimer == 0) { } else if (distanceToPlayer < 500.0f) { cur_obj_play_sound_2(SOUND_OBJ_EYEROK_EXPLODE); @@ -171,7 +171,9 @@ static void eyerok_boss_act_fight(void) { } struct Object* player = nearest_player_to_object(o); - o->oEyerokBossUnk10C = player->oPosZ; + if (player) { + o->oEyerokBossUnk10C = player->oPosZ; + } clamp_f32(&o->oEyerokBossUnk10C, o->oPosZ + 400.0f, o->oPosZ + 1600.0f); } else if ((o->oEyerokBossActiveHand = o->oEyerokBossUnkFC & 0x1) == 0) { o->oEyerokBossActiveHand = -1; @@ -245,7 +247,7 @@ void bhv_eyerok_boss_loop(void) { static s32 eyerok_hand_check_attacked(void) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; if (o->oEyerokReceivedAttack != 0 && abs_angle_diff(angleToPlayer, o->oFaceAngleYaw) < 0x3000) { cur_obj_play_sound_2(SOUND_OBJ2_EYEROK_SOUND_SHORT); @@ -304,7 +306,7 @@ static void eyerok_hand_act_sleep(void) { static void eyerok_hand_act_idle(void) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; cur_obj_init_animation_with_sound(2); if (o->parentObj->oAction == EYEROK_BOSS_ACT_FIGHT) { @@ -321,7 +323,7 @@ static void eyerok_hand_act_idle(void) { o->oGravity = 0.0f; } else { o->oAction = EYEROK_HAND_ACT_FIST_PUSH; - if (o->parentObj->oPosX - player->oPosX < 0.0f) { + if (player && o->parentObj->oPosX - player->oPosX < 0.0f) { o->oMoveAngleYaw = -0x800; } else { o->oMoveAngleYaw = 0x800; @@ -341,7 +343,7 @@ static void eyerok_hand_act_idle(void) { static void eyerok_hand_act_open(void) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; o->parentObj->oEyerokBossUnk1AC = o->oBehParams2ndByte; if (cur_obj_init_anim_and_check_if_end(4)) { @@ -364,7 +366,7 @@ static void eyerok_hand_act_open(void) { static void eyerok_hand_act_show_eye(void) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; UNUSED s16 val06; cur_obj_init_animation_with_sound(5); @@ -392,7 +394,7 @@ static void eyerok_hand_act_show_eye(void) { if (o->parentObj->oEyerokBossNumHands != 2) { obj_face_yaw_approach(o->oMoveAngleYaw, 0x800); if (o->oTimer > 10 - && (o->oPosZ - player->oPosZ > 0.0f || (o->oMoveFlags & OBJ_MOVE_HIT_EDGE))) { + && ((player && o->oPosZ - player->oPosZ > 0.0f) || (o->oMoveFlags & OBJ_MOVE_HIT_EDGE))) { o->parentObj->oEyerokBossActiveHand = 0; o->oForwardVel = 0.0f; } @@ -489,8 +491,8 @@ static void eyerok_hand_act_retreat(void) { static void eyerok_hand_act_target_mario(void) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); - if (eyerok_check_mario_relative_z(400) != 0 || o->oPosZ - player->oPosZ > 0.0f + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; + if (eyerok_check_mario_relative_z(400) != 0 || (player && o->oPosZ - player->oPosZ > 0.0f) || o->oPosZ - o->parentObj->oPosZ > 1700.0f || absf(o->oPosX - o->parentObj->oPosX) > 900.0f || (o->oMoveFlags & OBJ_MOVE_HIT_WALL)) { o->oForwardVel = 0.0f; @@ -506,8 +508,8 @@ static void eyerok_hand_act_target_mario(void) { static void eyerok_hand_act_smash(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; s16 sp1E; if (o->oTimer > 20) { @@ -536,11 +538,11 @@ static void eyerok_hand_act_smash(void) { static void eyerok_hand_act_fist_push(void) { struct Object* player = nearest_player_to_object(o); - if (o->oTimer > 5 && (o->oPosZ - player->oPosZ > 0.0f || (o->oMoveFlags & OBJ_MOVE_HIT_EDGE))) { + if (o->oTimer > 5 && ((player && o->oPosZ - player->oPosZ > 0.0f) || (o->oMoveFlags & OBJ_MOVE_HIT_EDGE))) { o->oAction = EYEROK_HAND_ACT_FIST_SWEEP; o->oForwardVel = 0.0f; - if (o->oPosX - player->oPosX < 0.0f) { + if (player && o->oPosX - player->oPosX < 0.0f) { o->oMoveAngleYaw = 0x4000; } else { o->oMoveAngleYaw = -0x4000; diff --git a/src/game/behaviors/falling_pillar.inc.c b/src/game/behaviors/falling_pillar.inc.c index 990b64b3c..2ca09df1d 100644 --- a/src/game/behaviors/falling_pillar.inc.c +++ b/src/game/behaviors/falling_pillar.inc.c @@ -61,7 +61,7 @@ s16 bhv_falling_pillar_calculate_angle_in_front_of_mario(void) { */ void bhv_falling_pillar_loop(void) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; s16 angleInFrontOfMario; switch (o->oAction) { @@ -87,8 +87,10 @@ void bhv_falling_pillar_loop(void) { object_step_without_floor_orient(); // Calculate angle in front of Mario and turn towards it. - angleInFrontOfMario = bhv_falling_pillar_calculate_angle_in_front_of_mario(); - o->oFaceAngleYaw = approach_s16_symmetric(o->oFaceAngleYaw, angleInFrontOfMario, 0x400); + if (player) { + angleInFrontOfMario = bhv_falling_pillar_calculate_angle_in_front_of_mario(); + o->oFaceAngleYaw = approach_s16_symmetric(o->oFaceAngleYaw, angleInFrontOfMario, 0x400); + } // After 10 ticks, start falling. if (o->oTimer > 10) diff --git a/src/game/behaviors/fire_piranha_plant.inc.c b/src/game/behaviors/fire_piranha_plant.inc.c index 07f2dd259..adfee1642 100644 --- a/src/game/behaviors/fire_piranha_plant.inc.c +++ b/src/game/behaviors/fire_piranha_plant.inc.c @@ -53,8 +53,8 @@ void bhv_fire_piranha_plant_init(void) { static void fire_piranha_plant_act_hide(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; if (o->oFirePiranhaPlantDeathSpinTimer != 0) { o->oMoveAngleYaw += (s32) o->oFirePiranhaPlantDeathSpinVel; @@ -102,7 +102,7 @@ static void fire_piranha_plant_act_hide(void) { static void fire_piranha_plant_act_grow(void) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; cur_obj_init_anim_extend(4); diff --git a/src/game/behaviors/fire_spitter.inc.c b/src/game/behaviors/fire_spitter.inc.c index 19280a654..b6e2ff9fd 100644 --- a/src/game/behaviors/fire_spitter.inc.c +++ b/src/game/behaviors/fire_spitter.inc.c @@ -1,7 +1,7 @@ static void fire_spitter_act_idle(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; approach_f32_ptr(&o->header.gfx.scale[0], 0.2f, 0.002f); if (o->oTimer > 150 && distanceToPlayer < 800.0f && !(o->oMoveFlags & OBJ_MOVE_MASK_IN_WATER)) { o->oAction = FIRE_SPITTER_ACT_SPIT_FIRE; @@ -13,9 +13,10 @@ static void fire_spitter_act_spit_fire(void) { s32 scaleStatus; struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); - - o->oMoveAngleYaw = angleToPlayer; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; + if (player) { + o->oMoveAngleYaw = angleToPlayer; + } // Increase scale by 0.05, 0.04, ..., -0.03. Then wait ~8 frames, then // starting moving scale by 0.05 each frame toward 0.1. The first time diff --git a/src/game/behaviors/fish.inc.c b/src/game/behaviors/fish.inc.c index 8107b46d2..0c4e36c5d 100644 --- a/src/game/behaviors/fish.inc.c +++ b/src/game/behaviors/fish.inc.c @@ -103,10 +103,10 @@ static void fish_vertical_roam(s32 speed) { */ static void fish_act_roam(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; - f32 fishY = o->oPosY - player->oPosY; + f32 fishY = player ? (o->oPosY - player->oPosY) : 0; // Alters speed of animation for natural movement. if (o->oTimer < 10) { @@ -126,7 +126,9 @@ static void fish_act_roam(void) { o->oFishRoamDistance = random_float() * 500 + 200.0f; } - o->oFishGoalY = player->oPosY + o->oFishHeightOffset; + o->oFishGoalY = player + ? (player->oPosY + o->oFishHeightOffset) + : o->oFishHeightOffset; // If fish groups are too close, call fish_regroup() // Rotate the fish towards Mario. @@ -161,12 +163,14 @@ static void fish_act_roam(void) { */ static void fish_act_flee(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; - f32 fishY = o->oPosY - gMarioObject->oPosY; + f32 fishY = player ? (o->oPosY - player->oPosY) : 0; UNUSED s32 distance; - o->oFishGoalY = gMarioObject->oPosY + o->oFishHeightOffset; + o->oFishGoalY = player + ? (player->oPosY + o->oFishHeightOffset) + : o->oFishHeightOffset; // Initialize some variables when the flee action first starts. if (o->oTimer == 0) { @@ -193,7 +197,9 @@ static void fish_act_flee(void) { if (o->oForwardVel < o->oFishGoalVel) { o->oForwardVel = o->oForwardVel + 0.5; } - o->oFishGoalY = player->oPosY + o->oFishHeightOffset; + o->oFishGoalY = player + ? (player->oPosY + o->oFishHeightOffset) + : o->oFishHeightOffset; // Rotate fish away from Mario. cur_obj_rotate_yaw_toward(angleToPlayer + 0x8000, o->oFishYawVel); diff --git a/src/game/behaviors/flame.inc.c b/src/game/behaviors/flame.inc.c index fabc12976..6c1992580 100644 --- a/src/game/behaviors/flame.inc.c +++ b/src/game/behaviors/flame.inc.c @@ -2,7 +2,7 @@ void bhv_small_piranha_flame_loop(void) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; if ((u16)(o->oBehParams >> 16) == 0) { if (o->oTimer > 0) { diff --git a/src/game/behaviors/flamethrower.inc.c b/src/game/behaviors/flamethrower.inc.c index ed75bd660..a01dc7f4d 100644 --- a/src/game/behaviors/flamethrower.inc.c +++ b/src/game/behaviors/flamethrower.inc.c @@ -41,8 +41,8 @@ void bhv_flamethrower_loop(void) { sync_object_init_field(o, &o->oFlameThowerUnk110); } struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; struct Object *flame; f32 flameVel; @@ -51,7 +51,7 @@ void bhv_flamethrower_loop(void) { UNUSED u8 pad[8]; if (o->oAction == 0) { if (gCurrLevelNum != LEVEL_BBH || gMarioOnMerryGoRound == TRUE) { - if (marioState->playerIndex == 0 && distanceToPlayer < 2000.0f) { + if (marioState && marioState->playerIndex == 0 && distanceToPlayer < 2000.0f) { o->oAction++; network_send_object(o); } diff --git a/src/game/behaviors/fly_guy.inc.c b/src/game/behaviors/fly_guy.inc.c index 8383092ca..6dfd7dffe 100644 --- a/src/game/behaviors/fly_guy.inc.c +++ b/src/game/behaviors/fly_guy.inc.c @@ -29,8 +29,8 @@ static s16 sFlyGuyJitterAmounts[] = { 0x1000, -0x2000, 0x2000 }; */ static void fly_guy_act_idle(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; treat_far_home_as_mario(2000.0f, &distanceToPlayer, &angleToPlayer); @@ -63,9 +63,9 @@ static void fly_guy_act_idle(void) { */ static void fly_guy_act_approach_mario(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; treat_far_home_as_mario(2000.0f, &distanceToPlayer, &angleToPlayer); @@ -80,14 +80,16 @@ static void fly_guy_act_approach_mario(void) { // If facing toward mario and we are either near mario laterally or // far above him if (abs_angle_diff(angleToPlayer, o->oFaceAngleYaw) < 0x2000) { - if (o->oPosY - player->oPosY > 400.0f || distanceToPlayer < 400.0f) { + if ((player && o->oPosY - player->oPosY > 400.0f) || distanceToPlayer < 400.0f) { // Either shoot fire or lunge if (o->oBehParams2ndByte != 0 && random_u16() % 2) { o->oAction = FLY_GUY_ACT_SHOOT_FIRE; o->oFlyGuyScaleVel = 0.06f; } else { o->oAction = FLY_GUY_ACT_LUNGE; - o->oFlyGuyLungeTargetPitch = obj_turn_pitch_toward_mario(marioState, -200.0f, 0); + if (marioState) { + o->oFlyGuyLungeTargetPitch = obj_turn_pitch_toward_mario(marioState, -200.0f, 0); + } o->oForwardVel = 25.0f * coss(o->oFlyGuyLungeTargetPitch); o->oVelY = 25.0f * -sins(o->oFlyGuyLungeTargetPitch); @@ -129,7 +131,7 @@ static void fly_guy_act_lunge(void) { obj_face_yaw_approach(o->oMoveAngleYaw, 0x800); // Continue moving upward until at least 200 units above mario - if (o->oPosY < player->oPosY + 200.0f) { + if (player && o->oPosY < player->oPosY + 200.0f) { obj_y_vel_approach(20.0f, 0.5f); } else if (obj_y_vel_approach(0.0f, 0.5f)) { // Wait until roll is zero @@ -147,8 +149,8 @@ static void fly_guy_act_lunge(void) { */ static void fly_guy_act_shoot_fire(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; treat_far_home_as_mario(2000.0f, NULL, &angleToPlayer); @@ -169,7 +171,7 @@ static void fly_guy_act_shoot_fire(void) { o->oAction = FLY_GUY_ACT_IDLE; } else { // We have reached below scale 1.2 in the shrinking portion - s16 fireMovePitch = obj_turn_pitch_toward_mario(marioState, 0.0f, 0); + s16 fireMovePitch = marioState ? obj_turn_pitch_toward_mario(marioState, 0.0f, 0) : 0; cur_obj_play_sound_2(SOUND_OBJ_FLAME_BLOWN); clamp_s16(&fireMovePitch, 0x800, 0x3000); diff --git a/src/game/behaviors/flying_bookend_switch.inc.c b/src/game/behaviors/flying_bookend_switch.inc.c index 54deea13f..9984ccad6 100644 --- a/src/game/behaviors/flying_bookend_switch.inc.c +++ b/src/game/behaviors/flying_bookend_switch.inc.c @@ -37,7 +37,7 @@ struct ObjectHitbox sBookSwitchHitbox = { void flying_bookend_act_0(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - if (obj_is_near_to_and_facing_mario(marioState, 400.0f, 0x3000)) { + if (marioState && obj_is_near_to_and_facing_mario(marioState, 400.0f, 0x3000)) { cur_obj_play_sound_2(SOUND_OBJ_DEFAULT_DEATH); o->oAction = 1; o->oBookendUnkF4 = o->oFaceAnglePitch + 0x7FFF; @@ -70,14 +70,16 @@ void flying_bookend_act_1(void) { void flying_bookend_act_2(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; cur_obj_init_animation_with_sound(1); cur_obj_update_floor_and_walls(); if (o->oForwardVel == 0.0f) { - obj_turn_pitch_toward_mario(marioState, 120.0f, 1000); + if (marioState) { + obj_turn_pitch_toward_mario(marioState, 120.0f, 1000); + } o->oFaceAnglePitch = o->oMoveAnglePitch + 0x7FFF; cur_obj_rotate_yaw_toward(angleToPlayer, 1000); @@ -136,12 +138,12 @@ void bhv_bookend_spawn_loop(void) { if (!sync_object_is_initialized(o->oSyncID)) { sync_object_init(o, SYNC_DISTANCE_ONLY_EVENTS); } struct MarioState* marioState = nearest_mario_state_to_object(o); - if (marioState->playerIndex != 0) { return; } + if (marioState && marioState->playerIndex != 0) { return; } struct Object* book; if (!(o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM)) { - if (o->oTimer > 40 && obj_is_near_to_and_facing_mario(marioState, 600.0f, 0x2000)) { + if (o->oTimer > 40 && marioState && obj_is_near_to_and_facing_mario(marioState, 600.0f, 0x2000)) { book = spawn_object(o, MODEL_BOOKEND, bhvFlyingBookend); if (book != NULL) { book->oAction = 3; @@ -177,7 +179,7 @@ void bookshelf_manager_act_1(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); struct SyncObject* so = sync_object_get(o->oSyncID); if (o->oBookSwitchManagerUnkF8 == 0) { - if (so && so->owned && obj_is_near_to_and_facing_mario(marioState, 500.0f, 0x3000)) { + if (so && so->owned && marioState && obj_is_near_to_and_facing_mario(marioState, 500.0f, 0x3000)) { o->oBookSwitchManagerUnkF8 = 1; network_send_object(o); } @@ -328,8 +330,8 @@ void bhv_book_switch_loop(void) { s16 sp34; struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; struct SyncObject* so = sync_object_get(o->oSyncID); o->header.gfx.scale[0] = 2.0f; @@ -379,7 +381,7 @@ void bhv_book_switch_loop(void) { } } else { sp36 = random_u16() & 0x1; - sp34 = player->oPosZ + 1.5f * marioState->vel[2]; + sp34 = (marioState && player) ? player->oPosZ + 1.5f * marioState->vel[2] : 0; play_sound(SOUND_MENU_CAMERA_BUZZ, gGlobalSoundSource); if (sp34 > 0) { diff --git a/src/game/behaviors/goomba.inc.c b/src/game/behaviors/goomba.inc.c index a4e3c47e3..4a7179388 100644 --- a/src/game/behaviors/goomba.inc.c +++ b/src/game/behaviors/goomba.inc.c @@ -172,8 +172,8 @@ static void goomba_act_walk(void) { o->oGoombaTurningAwayFromWall = obj_resolve_collisions_and_turn(o->oGoombaTargetYaw, 0x200); } else { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; treat_far_home_as_mario(1000.0f, &distanceToPlayer, &angleToPlayer); // If far from home, walk toward home. @@ -234,7 +234,7 @@ static void goomba_act_attacked_mario(void) { //! This can happen even when the goomba is already in the air. It's // hard to chain these in practice struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; goomba_begin_jump(); o->oGoombaTargetYaw = angleToPlayer; o->oGoombaTurningAwayFromWall = FALSE; diff --git a/src/game/behaviors/haunted_chair.inc.c b/src/game/behaviors/haunted_chair.inc.c index f12ee9304..6d3f73be2 100644 --- a/src/game/behaviors/haunted_chair.inc.c +++ b/src/game/behaviors/haunted_chair.inc.c @@ -39,7 +39,7 @@ void haunted_chair_act_0(void) { s16 val0E; struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (o->parentObj != o) { if (o->oHauntedChairUnk104 == 0) { @@ -110,8 +110,8 @@ void haunted_chair_act_1(void) { cur_obj_update_floor_and_walls(); struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; if (o->oTimer < 70) { if (o->oTimer < 50) { @@ -127,7 +127,9 @@ void haunted_chair_act_1(void) { if (o->oHauntedChairUnkF4 != 0) { if (--o->oHauntedChairUnkF4 == 0) { cur_obj_play_sound_2(SOUND_GENERAL_HAUNTED_CHAIR); - o->oMoveAnglePitch = obj_turn_pitch_toward_mario(marioState, 120.0f, 0); + if (marioState) { + o->oMoveAnglePitch = obj_turn_pitch_toward_mario(marioState, 120.0f, 0); + } o->oMoveAngleYaw = angleToPlayer; obj_compute_vel_from_move_pitch(50.0f); } else if (o->oHauntedChairUnkF4 > 20) { diff --git a/src/game/behaviors/heave_ho.inc.c b/src/game/behaviors/heave_ho.inc.c index 1c9cf2f1c..7b84f977e 100644 --- a/src/game/behaviors/heave_ho.inc.c +++ b/src/game/behaviors/heave_ho.inc.c @@ -7,7 +7,7 @@ void bhv_heave_ho_throw_mario_loop(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); if (gMarioStates[0].heldByObj == o->parentObj) { marioState = &gMarioStates[0]; } - struct Object* player = marioState->marioObj; + struct Object* player = marioState ? marioState->marioObj : NULL; o->oParentRelativePosX = 200.0f; o->oParentRelativePosY = -50.0f; o->oParentRelativePosZ = 0.0f; @@ -19,9 +19,13 @@ void bhv_heave_ho_throw_mario_loop(void) { break; case 2: cur_obj_play_sound_2(SOUND_OBJ_HEAVEHO_TOSSED); - player->oInteractStatus |= INT_STATUS_MARIO_UNK2; - marioState->forwardVel = -45.0f; - marioState->vel[1] = 95.0f; + if (player) { + player->oInteractStatus |= INT_STATUS_MARIO_UNK2; + } + if (marioState) { + marioState->forwardVel = -45.0f; + marioState->vel[1] = 95.0f; + } o->parentObj->oHeaveHoUnk88 = 0; o->parentObj->usingObj = NULL; break; @@ -47,7 +51,7 @@ void heave_ho_act_1(void) { void heave_ho_act_2(void) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; UNUSED s32 unused; s16 angleVel; diff --git a/src/game/behaviors/hidden_star.inc.c b/src/game/behaviors/hidden_star.inc.c index 3e7c51dc5..5d97d24bf 100644 --- a/src/game/behaviors/hidden_star.inc.c +++ b/src/game/behaviors/hidden_star.inc.c @@ -58,7 +58,7 @@ void bhv_hidden_star_loop(void) { /* TODO: this is likely not a checkpoint but a Secret */ void bhv_hidden_star_trigger_loop(void) { - if ((o->oInteractStatus & INT_STATUS_INTERACTED) || obj_check_if_collided_with_object(o, gMarioObjects[0]) == 1) { + if ((o->oInteractStatus & INT_STATUS_INTERACTED) || (gMarioStates[0].visibleToEnemies && obj_check_if_collided_with_object(o, gMarioObjects[0]) == 1)) { struct Object *hiddenStar = cur_obj_nearest_object_with_behavior(bhvHiddenStar); if (hiddenStar != NULL) { diff --git a/src/game/behaviors/kickable_board.inc.c b/src/game/behaviors/kickable_board.inc.c index bf48569d7..9ab23b777 100644 --- a/src/game/behaviors/kickable_board.inc.c +++ b/src/game/behaviors/kickable_board.inc.c @@ -42,7 +42,7 @@ void bhv_kickable_board_loop(void) { switch (o->oAction) { case 0: o->oFaceAnglePitch = 0; - if (check_mario_attacking(marioState)) { + if (marioState && check_mario_attacking(marioState)) { init_kickable_board_rock(); o->oAction++; if (sync_object_is_owned_locally(o->oSyncID)) { network_send_object(o); } @@ -53,13 +53,15 @@ void bhv_kickable_board_loop(void) { o->oFaceAnglePitch = 0; load_object_collision_model(); o->oFaceAnglePitch = -sins(o->oKickableBoardF4) * o->oKickableBoardF8; - if (o->oTimer > 30 && (sp24 = check_mario_attacking(marioState))) { - if (marioState->marioObj->oPosY > o->oPosY + 160.0f && sp24 == 2) { - o->oAction++; - cur_obj_play_sound_2(SOUND_GENERAL_BUTTON_PRESS_2); - if (sync_object_is_owned_locally(o->oSyncID)) { network_send_object(o); } - } else - o->oTimer = 0; + if (marioState) { + if (o->oTimer > 30 && (sp24 = check_mario_attacking(marioState))) { + if (marioState->marioObj->oPosY > o->oPosY + 160.0f && sp24 == 2) { + o->oAction++; + cur_obj_play_sound_2(SOUND_GENERAL_BUTTON_PRESS_2); + if (sync_object_is_owned_locally(o->oSyncID)) { network_send_object(o); } + } else + o->oTimer = 0; + } } if (o->oTimer != 0) { o->oKickableBoardF8 -= 8; diff --git a/src/game/behaviors/king_bobomb.inc.c b/src/game/behaviors/king_bobomb.inc.c index 7b89e596e..17710e01b 100644 --- a/src/game/behaviors/king_bobomb.inc.c +++ b/src/game/behaviors/king_bobomb.inc.c @@ -7,6 +7,7 @@ struct MarioState* king_bobomb_nearest_mario_state() { do { for (s32 i = 0; i < MAX_PLAYERS; i++) { if (checkActive && !is_player_active(&gMarioStates[i])) { continue; } + if (!gMarioStates[i].visibleToEnemies) { continue; } float ydiff = (o->oPosY - gMarioStates[i].marioObj->oPosY); if (ydiff >= 1200) { continue; } @@ -57,11 +58,11 @@ void king_bobomb_act_0(void) { cur_obj_init_animation_with_sound(5); cur_obj_set_pos_to_home(); o->oHealth = gBehaviorValues.KingBobombHealth; - if (should_start_or_continue_dialog(marioState, o) && cur_obj_can_mario_activate_textbox_2(&gMarioStates[0], 500.0f, 100.0f)) { + if (marioState && should_start_or_continue_dialog(marioState, o) && cur_obj_can_mario_activate_textbox_2(&gMarioStates[0], 500.0f, 100.0f)) { o->oSubAction++; seq_player_lower_volume(SEQ_PLAYER_LEVEL, 60, 40); } - } else if (should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 1, CUTSCENE_DIALOG, gBehaviorValues.dialogs.KingBobombIntroDialog, king_bobomb_act_0_continue_dialog)) { + } else if (marioState && should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 1, CUTSCENE_DIALOG, gBehaviorValues.dialogs.KingBobombIntroDialog, king_bobomb_act_0_continue_dialog)) { o->oAction = 2; o->oFlags |= OBJ_FLAG_HOLDABLE; } @@ -219,7 +220,7 @@ void king_bobomb_act_7(void) { cur_obj_init_animation_with_sound(2); struct MarioState* marioState = nearest_mario_state_to_object(o); - u8 updateDialog = should_start_or_continue_dialog(marioState, o) || (gMarioStates[0].pos[1] >= o->oPosY - 100.0f); + u8 updateDialog = (marioState && should_start_or_continue_dialog(marioState, o)) || (gMarioStates[0].pos[1] >= o->oPosY - 100.0f); if (updateDialog && cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 2, CUTSCENE_DIALOG, gBehaviorValues.dialogs.KingBobombDefeatDialog, king_bobomb_act_7_continue_dialog)) { o->oAction = 8; network_send_object(o); @@ -329,11 +330,11 @@ void king_bobomb_act_5(void) { // bobomb returns home o->oAction = 0; stop_background_music(SEQUENCE_ARGS(4, SEQ_EVENT_BOSS)); } - if (should_start_or_continue_dialog(marioState, o) && cur_obj_can_mario_activate_textbox_2(&gMarioStates[0], 500.0f, 100.0f)) + if (marioState && should_start_or_continue_dialog(marioState, o) && cur_obj_can_mario_activate_textbox_2(&gMarioStates[0], 500.0f, 100.0f)) o->oSubAction++; break; case 4: - if (should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 1, CUTSCENE_DIALOG, gBehaviorValues.dialogs.KingBobombCheatDialog, king_bobomb_act_5_continue_dialog)) + if (marioState && should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 1, CUTSCENE_DIALOG, gBehaviorValues.dialogs.KingBobombCheatDialog, king_bobomb_act_5_continue_dialog)) o->oAction = 2; break; } diff --git a/src/game/behaviors/klepto.inc.c b/src/game/behaviors/klepto.inc.c index a7f690446..b4a3730d5 100644 --- a/src/game/behaviors/klepto.inc.c +++ b/src/game/behaviors/klepto.inc.c @@ -20,6 +20,7 @@ static u8 sKleptoAttackHandlers[] = { 2, 2, 5, 5, 2, 2 }; static void klepto_target_mario(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); + if (!marioState) { return; } struct Object* player = marioState->marioObj; s32 angleToPlayer = obj_angle_to_object(o, player); o->oKleptoDistanceToTarget = lateral_dist_between_objects(player, o); @@ -131,14 +132,14 @@ static void klepto_change_target(void) { s32 newTarget = 0; struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (distanceToPlayer > 2000.0f) { f32 minTargetDist = 99999.0f; for (s32 i = 0; i < 3; i++) { - f32 dx = player->oPosX - sKleptoTargetPositions[i][0]; - f32 dz = player->oPosZ - sKleptoTargetPositions[i][2]; + f32 dx = player ? player->oPosX - sKleptoTargetPositions[i][0] : 10000; + f32 dz = player ? player->oPosZ - sKleptoTargetPositions[i][2] : 10000; f32 targetDist = sqrtf(dx * dx + dz * dz); if (targetDist < minTargetDist) { @@ -162,7 +163,7 @@ static void klepto_change_target(void) { static void klepto_circle_target(f32 radius, f32 targetSpeed) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (o->oAnimState != KLEPTO_ANIM_STATE_HOLDING_NOTHING && ((o->oTimer > 60 && distanceToPlayer > 2000.0f) @@ -227,7 +228,7 @@ static void klepto_act_turn_toward_mario(void) { klepto_target_mario(); struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; if (klepto_set_and_check_if_anim_at_end() && cur_obj_check_if_at_animation_end() && o->oKleptoDistanceToTarget > 800.0f && abs_angle_diff(angleToPlayer, o->oFaceAngleYaw) < 0x800 && o->oKleptoUnk1B0 < 0x400) { @@ -245,9 +246,9 @@ static void klepto_act_turn_toward_mario(void) { static void klepto_act_dive_at_mario(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; approach_f32_ptr(&o->oKleptoSpeed, 60.0f, 10.0f); if (o->oSoundStateID == 2) { @@ -264,7 +265,7 @@ static void klepto_act_dive_at_mario(void) { } } } else { - f32 dy = o->oPosY - player->oPosY; + f32 dy = player ? (o->oPosY - player->oPosY) : (o->oPosY); if (o->oSoundStateID == 3) { cur_obj_set_anim_if_at_end(4); } else if (o->oVelY > 0.0f && dy > 200.0f) { @@ -274,7 +275,9 @@ static void klepto_act_dive_at_mario(void) { o->oKleptoUnk1B0 = -0x3000; if (o->oAnimState == KLEPTO_ANIM_STATE_HOLDING_NOTHING) { if (o->oSubAction == 0) { - o->oKleptoUnk1B0 = obj_turn_pitch_toward_mario(marioState, 0.0f, 0); + if (marioState) { + o->oKleptoUnk1B0 = obj_turn_pitch_toward_mario(marioState, 0.0f, 0); + } o->oKleptoYawToTarget = angleToPlayer; if (dy < 160.0f) { @@ -282,7 +285,8 @@ static void klepto_act_dive_at_mario(void) { } } - if (marioState->action != ACT_SLEEPING + if (marioState + && marioState->action != ACT_SLEEPING && !(marioState->action & (ACT_FLAG_SHORT_HITBOX | ACT_FLAG_BUTT_OR_STOMACH_SLIDE)) && distanceToPlayer < 200.0f && dy > 50.0f && dy < 90.0f) { if (sync_object_is_owned_locally(o->oSyncID) && mario_lose_cap_to_enemy(marioState, 1) && marioState->playerIndex == 0) { @@ -366,8 +370,8 @@ void obj_set_speed_to_zero(void) { void bhv_klepto_update(void) { struct MarioState *marioState = nearest_mario_state_to_object(o); - struct Object *player = marioState->marioObj; - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object *player = marioState ? marioState->marioObj : NULL; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; cur_obj_update_floor_and_walls(); @@ -447,7 +451,7 @@ void bhv_klepto_update(void) { o->oMoveAngleYaw = angleToPlayer + 0x8000; o->oFlags &= ~0x00000008; cur_obj_become_intangible(); - } else if (marioState->action == ACT_SLEEPING || (marioState->action & (ACT_FLAG_SHORT_HITBOX | ACT_FLAG_BUTT_OR_STOMACH_SLIDE))) { + } else if ((marioState && marioState->action == ACT_SLEEPING) || (marioState && marioState->action & (ACT_FLAG_SHORT_HITBOX | ACT_FLAG_BUTT_OR_STOMACH_SLIDE))) { cur_obj_become_intangible(); } else { cur_obj_become_tangible(); diff --git a/src/game/behaviors/koopa.inc.c b/src/game/behaviors/koopa.inc.c index ae0201a0e..208f8127e 100644 --- a/src/game/behaviors/koopa.inc.c +++ b/src/game/behaviors/koopa.inc.c @@ -345,14 +345,16 @@ void shelled_koopa_attack_handler(s32 attackType) { // If attacked from the side, get knocked away from mario if (attackType != ATTACK_FROM_ABOVE && attackType != ATTACK_GROUND_POUND_OR_TWIRL) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); - o->oMoveAngleYaw = angleToPlayer; + if (player) { + s32 angleToPlayer = obj_angle_to_object(o, player); + o->oMoveAngleYaw = angleToPlayer; + } } cur_obj_set_model(smlua_model_util_load(E_MODEL_KOOPA_WITHOUT_SHELL)); struct MarioState* marioState = nearest_mario_state_to_object(o); - if (marioState->playerIndex == 0) { + if (marioState && marioState->playerIndex == 0) { struct Object* shell = spawn_object(o, MODEL_KOOPA_SHELL, bhvKoopaShell); if (shell != NULL) { sync_object_set_id(shell); @@ -628,7 +630,7 @@ u8 koopa_the_quick_act_show_init_text_continue_dialog(void) { return o->oAction static void koopa_the_quick_act_show_init_text(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); s32 response = 0; - if (should_start_or_continue_dialog(marioState, o)) { + if (marioState && should_start_or_continue_dialog(marioState, o)) { response = obj_update_race_proposition_dialog(&gMarioStates[0], *sKoopaTheQuickProperties[o->oKoopaTheQuickRaceIndex].initText, koopa_the_quick_act_show_init_text_continue_dialog); } @@ -734,7 +736,7 @@ static void koopa_the_quick_act_race(void) { koopa_the_quick_animate_footsteps(); struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (o->parentObj->oKoopaRaceEndpointRaceStatus != 0 && distanceToPlayer > 1500.0f && (o->oPathedPrevWaypointFlags & WAYPOINT_MASK_00FF) < 28) { @@ -862,7 +864,7 @@ static void koopa_the_quick_act_after_race(void) { o->oFlags &= ~OBJ_FLAG_ACTIVE_FROM_AFAR; } } else if (o->parentObj->oKoopaRaceEndpointUnk100 > 0) { - if (should_start_or_continue_dialog(marioState, o)) { + if (marioState && should_start_or_continue_dialog(marioState, o)) { s32 dialogResponse = cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 1, CUTSCENE_DIALOG, o->parentObj->oKoopaRaceEndpointUnk100, koopa_the_quick_act_after_race_continue_dialog); if (dialogResponse != 0) { o->parentObj->oKoopaRaceEndpointUnk100 = -1; @@ -931,8 +933,8 @@ void bhv_koopa_update(void) { koopa_the_quick_update(); } else if (obj_update_standard_actions(o->oKoopaAgility * 1.5f)) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; o->oKoopaDistanceToMario = distanceToPlayer; o->oKoopaAngleToMario = angleToPlayer; @@ -966,7 +968,7 @@ void bhv_koopa_update(void) { void bhv_koopa_race_endpoint_update(void) { if (o->oKoopaRaceEndpointRaceBegun && !o->oKoopaRaceEndpointRaceEnded) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (o->oKoopaRaceEndpointKoopaFinished || distanceToPlayer < 400.0f) { o->oKoopaRaceEndpointRaceEnded = TRUE; level_control_timer(TIMER_CONTROL_STOP); diff --git a/src/game/behaviors/koopa_shell.inc.c b/src/game/behaviors/koopa_shell.inc.c index 81c58f466..675aff459 100644 --- a/src/game/behaviors/koopa_shell.inc.c +++ b/src/game/behaviors/koopa_shell.inc.c @@ -70,7 +70,9 @@ void bhv_koopa_shell_loop(void) { cur_obj_if_hit_wall_bounce_away(); if (o->oInteractStatus & INT_STATUS_INTERACTED) { o->oAction++; - o->heldByPlayerIndex = marioState->playerIndex; + if (marioState) { + o->heldByPlayerIndex = marioState->playerIndex; + } } o->oFaceAngleYaw += 0x1000; cur_obj_move_standard(-20); @@ -78,7 +80,9 @@ void bhv_koopa_shell_loop(void) { break; case 1: player = gMarioStates[o->heldByPlayerIndex].marioObj; - obj_copy_pos(o, player); + if (player) { + obj_copy_pos(o, player); + } sp34 = cur_obj_update_floor_height_and_get_floor(); if (absf(find_water_level(o->oPosX, o->oPosZ) - o->oPosY) < 10.0f) koopa_shell_spawn_water_drop(); @@ -89,7 +93,9 @@ void bhv_koopa_shell_loop(void) { koopa_shell_spawn_sparkles(10.0f); } else koopa_shell_spawn_sparkles(10.0f); - o->oFaceAngleYaw = player->oMoveAngleYaw; + if (player) { + o->oFaceAngleYaw = player->oMoveAngleYaw; + } if (o->oInteractStatus & INT_STATUS_STOP_RIDING) { o->heldByPlayerIndex = 0; obj_mark_for_deletion(o); diff --git a/src/game/behaviors/mad_piano.inc.c b/src/game/behaviors/mad_piano.inc.c index 4d6a467a8..91e265a67 100644 --- a/src/game/behaviors/mad_piano.inc.c +++ b/src/game/behaviors/mad_piano.inc.c @@ -15,12 +15,12 @@ static void mad_piano_act_wait(void) { cur_obj_init_animation_with_sound(0); struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (distanceToPlayer < 500.0f) { if (o->oTimer > 20) { - if (marioState->forwardVel > 10.0f) { + if (marioState && marioState->forwardVel > 10.0f) { o->oAction = MAD_PIANO_ACT_ATTACK; cur_obj_become_tangible(); } @@ -38,9 +38,9 @@ static void mad_piano_act_attack(void) { cur_obj_play_sound_at_anim_range(0, 0, SOUND_OBJ_MAD_PIANO_CHOMPING); struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; if (distanceToPlayer < 500.0f) { o->oTimer = 0; diff --git a/src/game/behaviors/metal_box.inc.c b/src/game/behaviors/metal_box.inc.c index bebf97411..bad92d420 100644 --- a/src/game/behaviors/metal_box.inc.c +++ b/src/game/behaviors/metal_box.inc.c @@ -31,19 +31,21 @@ void bhv_pushable_loop(void) { } struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; + struct Object* player = marioState ? marioState->marioObj : NULL; UNUSED s16 unused; s16 sp1C; obj_set_hitbox(o, &sMetalBoxHitbox); o->oForwardVel = 0.0f; - if (obj_check_if_collided_with_object(o, player) && marioState->flags & MARIO_UNKNOWN_31) { - sp1C = obj_angle_to_object(o, player); - if (abs_angle_diff(sp1C, player->oMoveAngleYaw) > 0x4000) { - o->oMoveAngleYaw = (s16)((player->oMoveAngleYaw + 0x2000) & 0xc000); - if (check_if_moving_over_floor(8.0f, 150.0f)) { - o->oForwardVel = 4.0f; - cur_obj_play_sound_1(SOUND_ENV_METAL_BOX_PUSH); + if (player) { + if (obj_check_if_collided_with_object(o, player) && marioState && marioState->flags & MARIO_UNKNOWN_31) { + sp1C = obj_angle_to_object(o, player); + if (abs_angle_diff(sp1C, player->oMoveAngleYaw) > 0x4000) { + o->oMoveAngleYaw = (s16)((player->oMoveAngleYaw + 0x2000) & 0xc000); + if (check_if_moving_over_floor(8.0f, 150.0f)) { + o->oForwardVel = 4.0f; + cur_obj_play_sound_1(SOUND_ENV_METAL_BOX_PUSH); + } } } } diff --git a/src/game/behaviors/mips.inc.c b/src/game/behaviors/mips.inc.c index fcf8ae843..b8f704fc2 100644 --- a/src/game/behaviors/mips.inc.c +++ b/src/game/behaviors/mips.inc.c @@ -104,7 +104,7 @@ s16 bhv_mips_find_furthest_waypoint_to_mario(void) { // Is the waypoint within 800 units of MIPS? if (is_point_close_to_object(o, x, y, z, 800)) { // Is this further from Mario than the last waypoint? - distanceToMario = sqr(x - player->header.gfx.pos[0]) + sqr(z - player->header.gfx.pos[2]); + distanceToMario = player ? (sqr(x - player->header.gfx.pos[0]) + sqr(z - player->header.gfx.pos[2])) : 10000; if (furthestWaypointDistance < distanceToMario) { furthestWaypointIndex = i; furthestWaypointDistance = distanceToMario; diff --git a/src/game/behaviors/moneybag.inc.c b/src/game/behaviors/moneybag.inc.c index aa0a78a54..e1afa68e4 100644 --- a/src/game/behaviors/moneybag.inc.c +++ b/src/game/behaviors/moneybag.inc.c @@ -41,7 +41,7 @@ void bhv_moneybag_init(void) { void moneybag_check_mario_collision(void) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; obj_set_hitbox(o, &sMoneybagHitbox); diff --git a/src/game/behaviors/monty_mole.inc.c b/src/game/behaviors/monty_mole.inc.c index 63733fdde..399b4f512 100644 --- a/src/game/behaviors/monty_mole.inc.c +++ b/src/game/behaviors/monty_mole.inc.c @@ -67,7 +67,7 @@ static struct Object *monty_mole_select_available_hole(f32 minDistToMario) { while (hole != NULL) { player = nearest_player_to_object(hole); - distanceToPlayer = dist_between_objects(hole, player); + distanceToPlayer = player ? dist_between_objects(hole, player) : 10000; if (hole->oMontyMoleHoleCooldown == 0) { if (distanceToPlayer < 1500.0f && distanceToPlayer > minDistToMario) { numAvailableHoles++; @@ -85,7 +85,7 @@ static struct Object *monty_mole_select_available_hole(f32 minDistToMario) { while (hole != NULL) { player = nearest_player_to_object(hole); - distanceToPlayer = dist_between_objects(hole, player); + distanceToPlayer = player ? dist_between_objects(hole, player) : 10000; if (hole->oMontyMoleHoleCooldown == 0) { if (distanceToPlayer < 1500.0f && distanceToPlayer > minDistToMario) { if (numAvailableHoles == selectedHole) { @@ -196,7 +196,7 @@ static void monty_mole_act_select_hole(void) { if (o->oBehParams2ndByte != MONTY_MOLE_BP_NO_ROCK) { minDistToMario = 200.0f; - } else if (marioState->forwardVel < 8.0f) { + } else if (marioState && marioState->forwardVel < 8.0f) { minDistToMario = 100.0f; } else { minDistToMario = 500.0f; @@ -219,13 +219,13 @@ static void monty_mole_act_select_hole(void) { o->oPosZ = o->oMontyMoleCurrentHole->oPosZ; struct Object* holePlayer = nearest_player_to_object(o->oMontyMoleCurrentHole); - s32 angleToHolePlayer = obj_angle_to_object(o->oMontyMoleCurrentHole, holePlayer); + s32 angleToHolePlayer = holePlayer ? obj_angle_to_object(o->oMontyMoleCurrentHole, holePlayer) : 0; o->oFaceAnglePitch = 0; o->oMoveAngleYaw = angleToHolePlayer; struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (distanceToPlayer > 500.0f || minDistToMario > 100.0f || random_sign() < 0) { o->oAction = MONTY_MOLE_ACT_RISE_FROM_HOLE; @@ -268,7 +268,7 @@ static void monty_mole_act_rise_from_hole(void) { */ static void monty_mole_act_spawn_rock(void) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; struct Object *rock; @@ -296,7 +296,7 @@ static void monty_mole_act_spawn_rock(void) { */ static void monty_mole_act_begin_jump_into_hole(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - if (cur_obj_init_anim_and_check_if_end(3) || obj_is_near_to_and_facing_mario(marioState, 1000.0f, 0x4000)) { + if (cur_obj_init_anim_and_check_if_end(3) || (marioState && obj_is_near_to_and_facing_mario(marioState, 1000.0f, 0x4000))) { o->oAction = MONTY_MOLE_ACT_JUMP_INTO_HOLE; o->oVelY = 40.0f; o->oGravity = -6.0f; @@ -490,7 +490,7 @@ static void monty_mole_rock_act_held(void) { if (o->parentObj == NULL || o->parentObj->prevObj == NULL) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (distanceToPlayer > 600.0f) { distanceToPlayer = 600.0f; } diff --git a/src/game/behaviors/moving_coin.inc.c b/src/game/behaviors/moving_coin.inc.c index df6abc9e2..934a68047 100644 --- a/src/game/behaviors/moving_coin.inc.c +++ b/src/game/behaviors/moving_coin.inc.c @@ -146,7 +146,7 @@ void bhv_blue_coin_sliding_jumping_init(void) { void blue_coin_sliding_away_from_mario(void) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; s16 collisionFlags; diff --git a/src/game/behaviors/mr_blizzard.inc.c b/src/game/behaviors/mr_blizzard.inc.c index b8156b508..63f613770 100644 --- a/src/game/behaviors/mr_blizzard.inc.c +++ b/src/game/behaviors/mr_blizzard.inc.c @@ -108,8 +108,8 @@ static void mr_blizzard_act_spawn_snowball(void) { static void mr_blizzard_act_hide_unhide(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; if (distanceToPlayer < 1000.0f) { // If Mario is in range, move to rising action, make Mr. Blizzard visible, @@ -164,8 +164,8 @@ static void mr_blizzard_act_rise_from_ground(void) { static void mr_blizzard_act_rotate(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; s16 angleDiff; f32 prevDizziness; @@ -233,7 +233,7 @@ static void mr_blizzard_act_rotate(void) { static void mr_blizzard_act_death(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; cur_obj_become_intangible(); struct Object *cap; @@ -341,7 +341,7 @@ static void mr_blizzard_act_burrow(void) { static void mr_blizzard_act_jump(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (o->oMrBlizzardTimer != 0) { cur_obj_rotate_yaw_toward(o->oMrBlizzardTargetMoveYaw, 3400); @@ -449,7 +449,7 @@ static void mr_blizzard_snowball_act_0(void) { static void mr_blizzard_snowball_act_1(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; f32 marioDist; diff --git a/src/game/behaviors/mr_i.inc.c b/src/game/behaviors/mr_i.inc.c index 66a5c02bb..3202eefd1 100644 --- a/src/game/behaviors/mr_i.inc.c +++ b/src/game/behaviors/mr_i.inc.c @@ -132,8 +132,8 @@ void mr_i_act_3(void) { void mr_i_act_2(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; s16 sp1E; s16 sp1C; sp1E = o->oMoveAngleYaw; @@ -146,8 +146,10 @@ void mr_i_act_2(void) { o->oMrIUnk100 = 0; o->oMrIUnk104 = 0; } - obj_turn_toward_object(o, player, 0x10, 0x800); - obj_turn_toward_object(o, player, 0x0F, 0x400); + if (player) { + obj_turn_toward_object(o, player, 0x10, 0x800); + obj_turn_toward_object(o, player, 0x0F, 0x400); + } sp1C = sp1E - (s16)(o->oMoveAngleYaw); if (!sp1C) { o->oMrIUnkFC = 0; @@ -178,7 +180,7 @@ void mr_i_act_2(void) { if (o->oMrIUnk104 == o->oMrIUnk108) o->oMrIUnk110 = 1; if (o->oMrIUnk104 == o->oMrIUnk108 + 20) { - if (marioState->playerIndex == 0) { + if (marioState && marioState->playerIndex == 0) { spawn_mr_i_particle(); } o->oMrIUnk104 = 0; @@ -195,14 +197,14 @@ void mr_i_act_2(void) { void mr_i_act_1(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; s16 sp1E; s16 sp1C; s16 sp1A; - sp1E = obj_angle_to_object(o, player); - sp1C = abs_angle_diff(o->oMoveAngleYaw, sp1E); - sp1A = abs_angle_diff(o->oMoveAngleYaw, player->oFaceAngleYaw); + sp1E = player ? obj_angle_to_object(o, player) : 0; + sp1C = player ? abs_angle_diff(o->oMoveAngleYaw, sp1E) : 0; + sp1A = player ? abs_angle_diff(o->oMoveAngleYaw, player->oFaceAngleYaw) : 0; if (o->oTimer == 0) { cur_obj_become_tangible(); o->oMoveAnglePitch = 0; @@ -215,7 +217,7 @@ void mr_i_act_1(void) { } if (sp1C < 1024 && sp1A > 0x4000) { if (distanceToPlayer < 700.0f) { - if (marioState->playerIndex == 0) { + if (marioState && marioState->playerIndex == 0) { o->oAction = 2; network_send_object(o); } @@ -231,7 +233,7 @@ void mr_i_act_1(void) { if (o->oMrIUnk108 + 80 < o->oMrIUnk104) { o->oMrIUnk104 = 0; o->oMrIUnk108 = random_float() * 80.0f; - if (marioState->playerIndex == 0) { + if (marioState && marioState->playerIndex == 0) { spawn_mr_i_particle(); } } @@ -239,7 +241,7 @@ void mr_i_act_1(void) { void mr_i_act_0(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; #ifndef VERSION_JP obj_set_angle(o, 0, 0, 0); @@ -278,7 +280,7 @@ void bhv_mr_i_loop(void) { } struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; obj_set_hitbox(o, &sMrIHitbox); cur_obj_call_action_function(sMrIActions); diff --git a/src/game/behaviors/mushroom_1up.inc.c b/src/game/behaviors/mushroom_1up.inc.c index 1f8e6fd53..92d5c3dd6 100644 --- a/src/game/behaviors/mushroom_1up.inc.c +++ b/src/game/behaviors/mushroom_1up.inc.c @@ -2,7 +2,7 @@ void bhv_1up_interact(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - if (marioState->playerIndex == 0 && obj_check_if_collided_with_object(o, marioState->marioObj) == 1) { + if (marioState && marioState->playerIndex == 0 && obj_check_if_collided_with_object(o, marioState->marioObj) == 1) { play_sound(SOUND_GENERAL_COLLECT_1UP, gGlobalSoundSource); marioState->numLives++; o->activeFlags = ACTIVE_FLAG_DEACTIVATED; @@ -46,13 +46,15 @@ void one_up_loop_in_air(void) { void pole_1up_move_towards_mario(void) { struct Object* player = nearest_player_to_object(o); - f32 sp34 = player->header.gfx.pos[0] - o->oPosX; - f32 sp30 = player->header.gfx.pos[1] + 120.0f - o->oPosY; - f32 sp2C = player->header.gfx.pos[2] - o->oPosZ; - s16 sp2A = atan2s(sqrtf(sqr(sp34) + sqr(sp2C)), sp30); + if (player) { + f32 sp34 = player->header.gfx.pos[0] - o->oPosX; + f32 sp30 = player->header.gfx.pos[1] + 120.0f - o->oPosY; + f32 sp2C = player->header.gfx.pos[2] - o->oPosZ; + s16 sp2A = atan2s(sqrtf(sqr(sp34) + sqr(sp2C)), sp30); - obj_turn_toward_object(o, player, 16, 0x1000); - o->oMoveAnglePitch = approach_s16_symmetric(o->oMoveAnglePitch, sp2A, 0x1000); + obj_turn_toward_object(o, player, 16, 0x1000); + o->oMoveAnglePitch = approach_s16_symmetric(o->oMoveAnglePitch, sp2A, 0x1000); + } o->oVelY = sins(o->oMoveAnglePitch) * 30.0f; o->oForwardVel = coss(o->oMoveAnglePitch) * 30.0f; bhv_1up_interact(); @@ -60,7 +62,7 @@ void pole_1up_move_towards_mario(void) { void one_up_move_away_from_mario(s16 sp1A) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; o->oForwardVel = 8.0f; o->oMoveAngleYaw = angleToPlayer + 0x8000; @@ -285,7 +287,7 @@ void bhv_1up_hidden_trigger_loop(void) { } struct Object* player = nearest_player_to_object(o); - if (player == gMarioStates[0].marioObj && obj_check_if_collided_with_object(o, player) == 1) { + if (player && player == gMarioStates[0].marioObj && obj_check_if_collided_with_object(o, player) == 1) { struct Object *hiddenObj = cur_obj_nearest_object_with_behavior(bhvHidden1up); if (hiddenObj != NULL) { hiddenObj->o1UpHiddenUnkF4++; @@ -356,7 +358,7 @@ void bhv_1up_hidden_in_pole_trigger_loop(void) { } struct Object* player = nearest_player_to_object(o); - if (player == gMarioStates[0].marioObj && obj_check_if_collided_with_object(o, player) == 1) { + if (player && player == gMarioStates[0].marioObj && obj_check_if_collided_with_object(o, player) == 1) { struct Object *hiddenObj = cur_obj_nearest_object_with_behavior(bhvHidden1upInPole); if (hiddenObj != NULL) { hiddenObj->o1UpHiddenUnkF4++; @@ -378,8 +380,8 @@ void bhv_1up_hidden_in_pole_spawner_loop(void) { } struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - if (player == gMarioStates[0].marioObj && distanceToPlayer < 700) { + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + if (player && player == gMarioStates[0].marioObj && distanceToPlayer < 700) { struct Object* spawn_objects[3]; u32 models[3]; diff --git a/src/game/behaviors/piranha_bubbles.inc.c b/src/game/behaviors/piranha_bubbles.inc.c index 52d7bdb0c..b58dfca06 100644 --- a/src/game/behaviors/piranha_bubbles.inc.c +++ b/src/game/behaviors/piranha_bubbles.inc.c @@ -42,7 +42,7 @@ void bhv_piranha_plant_bubble_loop(void) { cur_obj_set_pos_relative(parent, 0, 72.0f, 180.0f); struct Object* parentPlayer = nearest_player_to_object(parent); - s32 distanceToParentPlayer = dist_between_objects(parent, parentPlayer); + s32 distanceToParentPlayer = parentPlayer ? dist_between_objects(parent, parentPlayer) : 10000; switch (o->oAction) { case PIRANHA_PLANT_BUBBLE_ACT_IDLE: diff --git a/src/game/behaviors/piranha_plant.inc.c b/src/game/behaviors/piranha_plant.inc.c index 249a2720b..e7db9cb0d 100644 --- a/src/game/behaviors/piranha_plant.inc.c +++ b/src/game/behaviors/piranha_plant.inc.c @@ -23,7 +23,7 @@ void piranha_plant_act_idle(void) { #endif struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (distanceToPlayer < 1200.0f) { o->oAction = PIRANHA_PLANT_ACT_SLEEPING; if (sync_object_is_owned_locally(o->oSyncID)) { network_send_object(o); } @@ -91,7 +91,7 @@ void piranha_plant_act_sleeping(void) { #endif struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (distanceToPlayer < 400.0f) { if (mario_moving_fast_enough_to_make_piranha_plant_bite()) { o->oAction = PIRANHA_PLANT_ACT_WOKEN_UP; @@ -209,7 +209,7 @@ void piranha_plant_act_shrink_and_die(void) { */ void piranha_plant_act_wait_to_respawn(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (distanceToPlayer > 1200.0f) { o->oAction = PIRANHA_PLANT_ACT_RESPAWN; if (sync_object_is_owned_locally(o->oSyncID)) { network_send_object(o); } @@ -256,9 +256,9 @@ static s8 sPiranhaPlantBiteSoundFrames[] = { 12, 28, 50, 64, -1 }; */ void piranha_plant_act_biting(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; s32 frame = o->header.gfx.animInfo.animFrame; @@ -285,7 +285,7 @@ void piranha_plant_act_biting(void) { // If the player is wearing the Metal Cap and interacts with the Piranha // Plant, the Piranha Plant will die. if (o->oInteractStatus & INT_STATUS_INTERACTED) { - if (marioState->flags & MARIO_METAL_CAP) { + if (marioState && marioState->flags & MARIO_METAL_CAP) { o->oAction = PIRANHA_PLANT_ACT_ATTACKED; } } @@ -299,6 +299,7 @@ void piranha_plant_act_biting(void) { */ s32 mario_moving_fast_enough_to_make_piranha_plant_bite(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); + if (!marioState) { return FALSE; } if (marioState->vel[1] > 10.0f) return TRUE; if (marioState->forwardVel > 10.0f) @@ -313,7 +314,7 @@ s32 mario_moving_fast_enough_to_make_piranha_plant_bite(void) { */ void piranha_plant_act_stopped_biting(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; cur_obj_become_intangible(); cur_obj_init_animation_with_sound(6); diff --git a/src/game/behaviors/pokey.inc.c b/src/game/behaviors/pokey.inc.c index 713566083..6640f3e51 100644 --- a/src/game/behaviors/pokey.inc.c +++ b/src/game/behaviors/pokey.inc.c @@ -213,8 +213,8 @@ static void pokey_act_uninitialized(void) { */ static void pokey_act_wander(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; s32 targetAngleOffset; struct Object *bodyPart; diff --git a/src/game/behaviors/racing_penguin.inc.c b/src/game/behaviors/racing_penguin.inc.c index 95408dc9f..8052016f5 100644 --- a/src/game/behaviors/racing_penguin.inc.c +++ b/src/game/behaviors/racing_penguin.inc.c @@ -84,6 +84,7 @@ void bhv_racing_penguin_init(void) { static void racing_penguin_act_wait_for_mario(void) { struct Object* player = nearest_player_to_object(o); + if (!player) { return; } if (o->oTimer > o->oRacingPenguinInitTextCooldown && o->oPosY - player->oPosY <= 0.0f && cur_obj_can_mario_activate_textbox_2(&gMarioStates[0], 400.0f, 400.0f)) { o->oAction = RACING_PENGUIN_ACT_SHOW_INIT_TEXT; @@ -93,6 +94,7 @@ static void racing_penguin_act_wait_for_mario(void) { u8 racing_penguin_act_show_init_text_continue_dialog(void) { return o->oAction == RACING_PENGUIN_ACT_SHOW_INIT_TEXT; } static void racing_penguin_act_show_init_text(void) { + if (!gMarioStates[0].visibleToEnemies) { return; } s32 response = obj_update_race_proposition_dialog(&gMarioStates[0], *sRacingPenguinData[o->oBehParams2ndByte].text, racing_penguin_act_show_init_text_continue_dialog); if (response == 1) { @@ -152,7 +154,7 @@ static void racing_penguin_act_race(void) { if (sync_object_is_owned_locally(o->oSyncID)) { network_send_object(o); } } else { struct Object* player = nearest_player_to_object(o); - targetSpeed = o->oPosY - player->oPosY; + targetSpeed = player ? (o->oPosY - player->oPosY) : o->oPosY; minSpeed = 70.0f; cur_obj_play_sound_1(SOUND_AIR_ROUGH_SLIDE); @@ -292,10 +294,10 @@ void bhv_racing_penguin_update(void) { void bhv_penguin_race_finish_line_update(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (o->parentObj->oRacingPenguinReachedBottom - || (distanceToPlayer < 1000.0f && player->oPosZ - o->oPosZ < 0.0f)) { + || (player && distanceToPlayer < 1000.0f && player->oPosZ - o->oPosZ < 0.0f)) { if (!o->parentObj->oRacingPenguinReachedBottom && !o->parentObj->oRacingPenguinMarioWon) { o->parentObj->oRacingPenguinMarioWon = TRUE; network_send_object(o->parentObj); @@ -305,7 +307,7 @@ void bhv_penguin_race_finish_line_update(void) { void bhv_penguin_race_shortcut_check_update(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (distanceToPlayer < 500.0f && !o->parentObj->oRacingPenguinMarioCheated) { o->parentObj->oRacingPenguinMarioCheated = TRUE; network_send_object(o->parentObj); diff --git a/src/game/behaviors/recovery_heart.inc.c b/src/game/behaviors/recovery_heart.inc.c index 08feda480..ef312b5d4 100644 --- a/src/game/behaviors/recovery_heart.inc.c +++ b/src/game/behaviors/recovery_heart.inc.c @@ -17,6 +17,7 @@ void bhv_recovery_heart_loop(void) { for (s32 i = 0; i < MAX_PLAYERS; i++) { if (!is_player_active(&gMarioStates[i])) { continue; } + if (!gMarioStates[i].visibleToEnemies) { continue; } if (obj_check_if_collided_with_object(o, gMarioStates[i].marioObj)) { collided = TRUE; } } @@ -27,7 +28,9 @@ void bhv_recovery_heart_loop(void) { } struct MarioState* marioState = nearest_mario_state_to_object(o); - o->oAngleVelYaw = (s32)(200.0f * marioState->forwardVel) + 1000; + if (marioState) { + o->oAngleVelYaw = (s32)(200.0f * marioState->forwardVel) + 1000; + } } else { o->oSpinningHeartPlayedSound = 0; @@ -41,6 +44,7 @@ void bhv_recovery_heart_loop(void) { struct MarioState* nearestState = nearest_mario_state_to_object(o); for (s32 i = 0; i < MAX_PLAYERS; i++) { + if (!gMarioStates[i].visibleToEnemies) { continue; } if (!is_player_active(&gMarioStates[i])) { continue; } if (&gMarioStates[i] == nearestState || dist_between_objects(o, gMarioStates[i].marioObj) < 1000) { gMarioStates[i].healCounter += 4; diff --git a/src/game/behaviors/scuttlebug.inc.c b/src/game/behaviors/scuttlebug.inc.c index 99c1548c0..ddaa69cc6 100644 --- a/src/game/behaviors/scuttlebug.inc.c +++ b/src/game/behaviors/scuttlebug.inc.c @@ -38,7 +38,7 @@ void bhv_scuttlebug_loop(void) { } struct Object *player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; cur_obj_update_floor_and_walls(); if (o->oSubAction != 0 @@ -60,12 +60,14 @@ void bhv_scuttlebug_loop(void) { break; case 1: o->oForwardVel = 5.0f; - if (cur_obj_lateral_dist_from_obj_to_home(player) > 1000.0f) { + if (player && cur_obj_lateral_dist_from_obj_to_home(player) > 1000.0f) { angleToPlayer = cur_obj_angle_to_home(); } else { if (o->oScuttlebugUnkF8 == 0) { o->oScuttlebugUnkFC = 0; - angleToPlayer = obj_angle_to_object(o, player); + if (player) { + angleToPlayer = obj_angle_to_object(o, player); + } if (abs_angle_diff(angleToPlayer, o->oMoveAngleYaw) < 0x800) { o->oScuttlebugUnkF8 = 1; o->oVelY = 20.0f; @@ -147,10 +149,10 @@ void bhv_scuttlebug_spawn_loop(void) { } struct MarioState* marioState = nearest_mario_state_to_object(o); - if (marioState->playerIndex != 0) { return; } + if (marioState && marioState->playerIndex != 0) { return; } - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (o->oAction == 0) { if (o->oTimer > 30 && 500.0f < distanceToPlayer && distanceToPlayer < 1500.0f) { diff --git a/src/game/behaviors/skeeter.inc.c b/src/game/behaviors/skeeter.inc.c index 76b83d4b2..83e6ba21b 100644 --- a/src/game/behaviors/skeeter.inc.c +++ b/src/game/behaviors/skeeter.inc.c @@ -156,8 +156,8 @@ void bhv_skeeter_update(void) { o->oDeathSound = SOUND_OBJ_SNUFIT_SKEETER_DEATH; struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; treat_far_home_as_mario(1000.0f, &distanceToPlayer, &angleToPlayer); o->oDistanceToMario = distanceToPlayer; o->oAngleToMario = angleToPlayer; diff --git a/src/game/behaviors/sl_snowman_wind.inc.c b/src/game/behaviors/sl_snowman_wind.inc.c index 8b316851b..3af531658 100644 --- a/src/game/behaviors/sl_snowman_wind.inc.c +++ b/src/game/behaviors/sl_snowman_wind.inc.c @@ -14,8 +14,8 @@ void bhv_sl_snowman_wind_loop(void) { } struct Object *player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; s16 marioAngleFromWindSource; Vec3f tempPos; @@ -36,13 +36,13 @@ void bhv_sl_snowman_wind_loop(void) { // Mario has come close, begin dialog. } else if (o->oSubAction == SL_SNOWMAN_WIND_ACT_TALKING) { - if (cur_obj_update_dialog(&gMarioStates[0], 2, 2, gBehaviorValues.dialogs.SnowmanWindDialog, 0, bhv_sl_snowman_wind_loop_continue_dialog)) { + if (gMarioStates[0].visibleToEnemies && cur_obj_update_dialog(&gMarioStates[0], 2, 2, gBehaviorValues.dialogs.SnowmanWindDialog, 0, bhv_sl_snowman_wind_loop_continue_dialog)) { o->oSubAction++; network_send_object(o); } // Blowing, spawn wind particles (SL_SNOWMAN_WIND_ACT_BLOWING) - } else if (distanceToPlayer < 1500.0f && absf(player->oPosY - o->oHomeY) < 500.0f) { + } else if (distanceToPlayer < 1500.0f && player && absf(player->oPosY - o->oHomeY) < 500.0f) { // Point towards Mario, but only within 0x1500 angle units of the original angle. if ((marioAngleFromWindSource = angleToPlayer - o->oSLSnowmanWindOriginalYaw) > 0) { if (marioAngleFromWindSource < 0x1500) diff --git a/src/game/behaviors/snow_mound.inc.c b/src/game/behaviors/snow_mound.inc.c index a523d6b54..20993d072 100644 --- a/src/game/behaviors/snow_mound.inc.c +++ b/src/game/behaviors/snow_mound.inc.c @@ -44,7 +44,7 @@ void bhv_snow_mound_spawn_loop(void) { } if (!is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 6000) - || o->oPosY + 1000.0f < player->header.gfx.pos[1]) + || (player && (o->oPosY + 1000.0f < player->header.gfx.pos[1]))) return; if (o->oTimer == 64 || o->oTimer == 128 || o->oTimer == 192 || o->oTimer == 224 || o->oTimer == 256) { diff --git a/src/game/behaviors/snowman.inc.c b/src/game/behaviors/snowman.inc.c index 15b47a939..3a10e81a1 100644 --- a/src/game/behaviors/snowman.inc.c +++ b/src/game/behaviors/snowman.inc.c @@ -56,7 +56,7 @@ void adjust_rolling_face_pitch(f32 f12) { void snowmans_bottom_act_1(void) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; UNUSED s16 sp26; s32 sp20 = 0; @@ -137,7 +137,8 @@ void bhv_snowmans_bottom_loop(void) { switch (o->oAction) { case 0: - if (should_start_or_continue_dialog(marioState, o) + if (marioState + && should_start_or_continue_dialog(marioState, o) && (is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 400) == 1) && set_mario_npc_dialog(&gMarioStates[0], 1, bhv_snowmans_bottom_loop_continue_dialog) == 2) { sp1E = cutscene_object_with_dialog(CUTSCENE_DIALOG, o, gBehaviorValues.dialogs.SnowmanHeadBodyDialog); diff --git a/src/game/behaviors/snufit.inc.c b/src/game/behaviors/snufit.inc.c index 8e005e215..9ba80d40e 100644 --- a/src/game/behaviors/snufit.inc.c +++ b/src/game/behaviors/snufit.inc.c @@ -72,7 +72,7 @@ Gfx *geo_snufit_scale_body(s32 callContext, struct GraphNode *node, UNUSED Mat4 */ void snufit_act_idle(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; s32 marioDist; // This line would could cause a crash in certain PU situations, @@ -147,9 +147,9 @@ void bhv_snufit_loop(void) { } struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; // Only update if Mario is in the current room. if (!(o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM)) { @@ -157,7 +157,9 @@ void bhv_snufit_loop(void) { // Face Mario if he is within range. if (distanceToPlayer < 800.0f) { - obj_turn_pitch_toward_mario(marioState, 120.0f, 2000); + if (marioState) { + obj_turn_pitch_toward_mario(marioState, 120.0f, 2000); + } if ((s16) o->oMoveAnglePitch > 0x2000) { o->oMoveAnglePitch = 0x2000; diff --git a/src/game/behaviors/sparkle_spawn_star.inc.c b/src/game/behaviors/sparkle_spawn_star.inc.c index 488cbccdb..55b260bc9 100644 --- a/src/game/behaviors/sparkle_spawn_star.inc.c +++ b/src/game/behaviors/sparkle_spawn_star.inc.c @@ -54,9 +54,11 @@ void set_home_to_mario(void) { o->oHomeY = o->parentObj->oPosY; } else { struct Object* player = nearest_player_to_object(o); - o->oHomeX = player->oPosX; - o->oHomeZ = player->oPosZ; - o->oHomeY = player->oPosY; + if (player) { + o->oHomeX = player->oPosX; + o->oHomeZ = player->oPosZ; + o->oHomeY = player->oPosY; + } } o->oHomeY += 250.0f; o->oPosY = o->oHomeY; diff --git a/src/game/behaviors/spindrift.inc.c b/src/game/behaviors/spindrift.inc.c index 273ffbee0..77accd221 100644 --- a/src/game/behaviors/spindrift.inc.c +++ b/src/game/behaviors/spindrift.inc.c @@ -19,8 +19,8 @@ void bhv_spindrift_loop(void) { } struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; o->activeFlags |= ACTIVE_FLAG_UNK10; if (cur_obj_set_hitbox_and_die_if_attacked(&sSpindriftHitbox, SOUND_OBJ_DYING_ENEMY1, 0)) diff --git a/src/game/behaviors/spiny.inc.c b/src/game/behaviors/spiny.inc.c index 9dc763578..2816576d4 100644 --- a/src/game/behaviors/spiny.inc.c +++ b/src/game/behaviors/spiny.inc.c @@ -74,7 +74,7 @@ static void bhv_spiny_on_sent_pre(void) { */ static s32 spiny_check_active(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (o->parentObj == NULL || o->parentObj->behavior != smlua_override_behavior(bhvEnemyLakitu)) { obj_mark_for_deletion(o); diff --git a/src/game/behaviors/sushi.inc.c b/src/game/behaviors/sushi.inc.c index a1052c6e0..a6245c35f 100644 --- a/src/game/behaviors/sushi.inc.c +++ b/src/game/behaviors/sushi.inc.c @@ -17,7 +17,7 @@ void bhv_sushi_shark_loop(void) { o->oPosY = sp1C + o->oHomeY + sins(o->oSushiSharkUnkF4) * 200.0f; o->oMoveAngleYaw = o->oSushiSharkUnkF4 + 0x4000; o->oSushiSharkUnkF4 += 0x80; - if (player->oPosY - sp1C > -500.0f) + if (player && player->oPosY - sp1C > -500.0f) if (o->oPosY - sp1C > -200.0f) spawn_object_with_scale(o, MODEL_WAVE_TRAIL, bhvObjectWaveTrail, 4.0f); if ((o->oTimer & 0xF) == 0) diff --git a/src/game/behaviors/swoop.inc.c b/src/game/behaviors/swoop.inc.c index 72a8d61a6..ba455570e 100644 --- a/src/game/behaviors/swoop.inc.c +++ b/src/game/behaviors/swoop.inc.c @@ -25,8 +25,8 @@ static struct ObjectHitbox sSwoopHitbox = { */ static void swoop_act_idle(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; cur_obj_init_animation_with_sound(1); @@ -47,7 +47,7 @@ static void swoop_act_idle(void) { */ static void swoop_act_move(void) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; cur_obj_init_animation_with_accel_and_sound(0, 2.0f); if (cur_obj_check_if_near_animation_end()) { @@ -73,7 +73,7 @@ static void swoop_act_move(void) { // If we're not done swooping, turn toward mario. When between // 0 and 200 units above mario, increase speed and stop swooping o->oSwoopTargetYaw = angleToPlayer; - if (o->oPosY < player->oPosY + 200.0f) { + if (player && o->oPosY < player->oPosY + 200.0f) { if (obj_y_vel_approach(0.0f, 0.5f)) { o->oForwardVel *= 2.0f; } diff --git a/src/game/behaviors/thi_top.inc.c b/src/game/behaviors/thi_top.inc.c index 9f32b3106..151cf4b5a 100644 --- a/src/game/behaviors/thi_top.inc.c +++ b/src/game/behaviors/thi_top.inc.c @@ -25,13 +25,13 @@ void bhv_thi_tiny_island_top_loop(void) { } struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (!(gTHIWaterDrained & 1)) { if (o->oAction == 0) { if (distanceToPlayer < 500.0f) - if (marioState->action == ACT_GROUND_POUND_LAND) { + if (marioState && marioState->action == ACT_GROUND_POUND_LAND) { o->oAction++; cur_obj_spawn_particles(&D_8032F134); spawn_triangle_break_particles(20, 138, 0.3f, 3); diff --git a/src/game/behaviors/tree_particles.inc.c b/src/game/behaviors/tree_particles.inc.c index a7422b28f..ad704fc37 100644 --- a/src/game/behaviors/tree_particles.inc.c +++ b/src/game/behaviors/tree_particles.inc.c @@ -39,7 +39,9 @@ void bhv_snow_leaf_particle_spawn_init(void) { f32 scale; UNUSED s32 unused2; struct Object* player = nearest_player_to_object(o); - player->oActiveParticleFlags &= ~0x2000; + if (player) { + player->oActiveParticleFlags &= ~0x2000; + } if (isSnow) { if (random_float() < 0.5) { obj = spawn_object(o, MODEL_WHITE_PARTICLE_DL, bhvTreeSnow); diff --git a/src/game/behaviors/tumbling_bridge.inc.c b/src/game/behaviors/tumbling_bridge.inc.c index 231985829..7e2b21520 100644 --- a/src/game/behaviors/tumbling_bridge.inc.c +++ b/src/game/behaviors/tumbling_bridge.inc.c @@ -123,8 +123,9 @@ void tumbling_bridge_act_1(void) { } void tumbling_bridge_act_2(void) { - struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + struct MarioState* marioState = nearest_possible_mario_state_to_object(o); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; cur_obj_hide(); if (cur_obj_has_behavior(bhvLllTumblingBridge)) @@ -141,8 +142,9 @@ void tumbling_bridge_act_3(void) { } void tumbling_bridge_act_0(void) { - struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + struct MarioState* marioState = nearest_possible_mario_state_to_object(o); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (cur_obj_has_behavior(bhvLllTumblingBridge) || distanceToPlayer < 1000.0f) o->oAction = 1; diff --git a/src/game/behaviors/tuxie.inc.c b/src/game/behaviors/tuxie.inc.c index d67ae226f..fe696cde8 100644 --- a/src/game/behaviors/tuxie.inc.c +++ b/src/game/behaviors/tuxie.inc.c @@ -113,7 +113,7 @@ u8 tuxies_mother_act_0_continue_dialog(void) { return (o->oAction == 0 && o->oSu void tuxies_mother_act_0(void) { // only local can interact with mother struct MarioState* marioState = &gMarioStates[0]; - s32 distanceToPlayer = dist_between_objects(o, marioState->marioObj); + s32 distanceToPlayer = marioState->visibleToEnemies ? dist_between_objects(o, marioState->marioObj) : 10000; s32 sp2C; f32 sp28; @@ -136,7 +136,7 @@ void tuxies_mother_act_0(void) { o->oSubAction++; break; case 1: - if (cur_obj_update_dialog_with_cutscene(marioState, 2, 1, CUTSCENE_DIALOG, gBehaviorValues.dialogs.TuxieMotherDialog, tuxies_mother_act_0_continue_dialog)) + if (marioState->visibleToEnemies && cur_obj_update_dialog_with_cutscene(marioState, 2, 1, CUTSCENE_DIALOG, gBehaviorValues.dialogs.TuxieMotherDialog, tuxies_mother_act_0_continue_dialog)) o->oSubAction++; break; case 2: @@ -175,8 +175,8 @@ void small_penguin_dive_with_mario(void) { void small_penguin_act_2(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; s32 sp1C = 0; if (o->oTimer == 0) @@ -194,8 +194,8 @@ void small_penguin_act_2(void) { void small_penguin_act_1(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; cur_obj_init_animation_with_sound(0); o->oForwardVel = o->oSmallPenguinUnk104 + 3.0f; @@ -229,7 +229,7 @@ void small_penguin_act_4(void) { void small_penguin_act_0(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; s32 sp1C; @@ -255,7 +255,7 @@ void small_penguin_act_0(void) { void small_penguin_act_5(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; f32 sp24; s16 sp22; diff --git a/src/game/behaviors/tweester.inc.c b/src/game/behaviors/tweester.inc.c index 73a794c76..0f97a9fed 100644 --- a/src/game/behaviors/tweester.inc.c +++ b/src/game/behaviors/tweester.inc.c @@ -44,7 +44,7 @@ void tweester_scale_and_move(f32 preScale) { */ void tweester_act_idle(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (o->oSubAction == TWEESTER_SUB_ACT_WAIT) { cur_obj_become_tangible(); @@ -73,16 +73,17 @@ void tweester_act_idle(void) { */ void tweester_act_chase(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; f32 activationRadius = o->oBehParams2ndByte * 100; o->oAngleToHome = cur_obj_angle_to_home(); cur_obj_play_sound_1(SOUND_ENV_WIND1); - if (cur_obj_lateral_dist_from_obj_to_home(player) < activationRadius + if (player + && cur_obj_lateral_dist_from_obj_to_home(player) < activationRadius && o->oSubAction == TWEESTER_SUB_ACT_CHASE) { o->oForwardVel = 20.0f; @@ -123,7 +124,7 @@ void tweester_act_hide(void) { tweester_scale_and_move(shrinkTimer / 60.0f); else { cur_obj_become_intangible(); - if (cur_obj_lateral_dist_from_obj_to_home(player) > 2500.0f) + if (player && cur_obj_lateral_dist_from_obj_to_home(player) > 2500.0f) o->oAction = TWEESTER_ACT_IDLE; if (o->oTimer > 360) o->oAction = TWEESTER_ACT_IDLE; diff --git a/src/game/behaviors/ukiki.inc.c b/src/game/behaviors/ukiki.inc.c index 0b04b4f8b..1762672fc 100644 --- a/src/game/behaviors/ukiki.inc.c +++ b/src/game/behaviors/ukiki.inc.c @@ -125,8 +125,8 @@ void idle_ukiki_taunt(void) { */ void ukiki_act_idle(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; idle_ukiki_taunt(); @@ -147,7 +147,7 @@ void ukiki_act_idle(void) { } // Jump away from Mario after stealing his cap. - if (o->oUkikiTextState == UKIKI_TEXT_STOLE_CAP) { + if (player && o->oUkikiTextState == UKIKI_TEXT_STOLE_CAP) { o->oMoveAngleYaw = player->oMoveAngleYaw + 0x8000; if (check_if_moving_over_floor(50.0f, 150.0f)) { @@ -213,7 +213,7 @@ void ukiki_act_wait_to_respawn(void) { */ void ukiki_act_unused_turn(void) { struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; idle_ukiki_taunt(); if (o->oSubAction == UKIKI_SUB_ACT_TAUNT_JUMP_CLAP) { @@ -226,8 +226,8 @@ void ukiki_act_unused_turn(void) { */ void ukiki_act_turn_to_mario(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; s32 facingMario; // Initialize the action with a random fVel from 2-5. @@ -257,9 +257,9 @@ void ukiki_act_turn_to_mario(void) { */ void ukiki_act_run(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; s32 fleeMario = TRUE; s16 goalYaw = angleToPlayer + 0x8000; @@ -278,7 +278,9 @@ void ukiki_act_run(void) { //! @bug (Ukikispeedia) This function sets forward speed to 0.9 * Mario's //! forward speed, which means ukiki can move at hyperspeed rates. - cur_obj_set_vel_from_mario_vel(marioState, 20.0f, 0.9f); + if (marioState) { + cur_obj_set_vel_from_mario_vel(marioState, 20.0f, 0.9f); + } if (fleeMario) { if (distanceToPlayer > o->oUkikiChaseFleeRange) { @@ -357,8 +359,8 @@ u8 ukiki_act_go_to_cage_continue_dialog(void) { return o->oAction == UKIKI_ACT_G */ void ukiki_act_go_to_cage(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; struct Object* obj; f32 latDistToCage = 0.0f; @@ -405,7 +407,7 @@ void ukiki_act_go_to_cage(void) { case UKIKI_SUB_ACT_CAGE_TALK_TO_MARIO: cur_obj_init_animation_with_sound(UKIKI_ANIM_HANDSTAND); - if (should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 3, 1, CUTSCENE_DIALOG, gBehaviorValues.dialogs.UkikiCageDialog, ukiki_act_go_to_cage_continue_dialog)) { + if (marioState && should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 3, 1, CUTSCENE_DIALOG, gBehaviorValues.dialogs.UkikiCageDialog, ukiki_act_go_to_cage_continue_dialog)) { o->oSubAction++; network_send_object_reliability(o, TRUE); } diff --git a/src/game/behaviors/unagi.inc.c b/src/game/behaviors/unagi.inc.c index 41c4a4acb..5971ce2e8 100644 --- a/src/game/behaviors/unagi.inc.c +++ b/src/game/behaviors/unagi.inc.c @@ -50,7 +50,7 @@ void bhv_unagi_init(void) { void unagi_act_0(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (distanceToPlayer > 4500.0f && o->oSubAction != 0) { o->oAction = 1; o->oPosX = o->oPathedStartWaypoint->pos[0]; @@ -162,7 +162,7 @@ void bhv_unagi_loop(void) { s32 val04; struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (o->oUnagiUnk1B2 == 0) { o->oUnagiUnk1AC = 99999.0f; @@ -198,7 +198,7 @@ void bhv_unagi_subobject_loop(void) { f32 val04; struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; if (o->parentObj->oUnagiUnk1B2 == 0) { obj_mark_for_deletion(o); diff --git a/src/game/behaviors/water_bomb.inc.c b/src/game/behaviors/water_bomb.inc.c index 0e3fbd75f..706a2c6ec 100644 --- a/src/game/behaviors/water_bomb.inc.c +++ b/src/game/behaviors/water_bomb.inc.c @@ -46,6 +46,7 @@ void bhv_water_bomb_spawner_update(void) { for (s32 i = 0; i < MAX_PLAYERS; i++) { if (!is_player_active(&gMarioStates[i])) { continue; } + if (!gMarioStates[0].visibleToEnemies) { continue; } f32 latDist = lateral_dist_between_objects(o, gMarioStates[i].marioObj); if (latDist < latDistToMario) { latDistToMario = latDist; @@ -165,7 +166,7 @@ static void water_bomb_act_drop(void) { // Move toward mario struct Object* player = nearest_player_to_object(o); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; o->oMoveAngleYaw = angleToPlayer; o->oForwardVel = 10.0f; o->oWaterBombStretchSpeed = -40.0f; diff --git a/src/game/behaviors/water_ring.inc.c b/src/game/behaviors/water_ring.inc.c index 46f0fd37f..5647a1d66 100644 --- a/src/game/behaviors/water_ring.inc.c +++ b/src/game/behaviors/water_ring.inc.c @@ -2,6 +2,7 @@ f32 water_ring_calc_mario_dist(void) { struct Object* player = nearest_player_to_object(o); + if (!player) { return 10000; } f32 marioDistX = o->oPosX - player->header.gfx.pos[0]; f32 marioDistY = o->oPosY - (player->header.gfx.pos[1] + 80.0f); @@ -48,6 +49,7 @@ void bhv_jet_stream_water_ring_init(void) { void water_ring_check_collection(f32 avgScale, struct Object *ringManager) { struct Object* player = nearest_player_to_object(o); + if (!player) { return; } f32 marioDistInFront = water_ring_calc_mario_dist(); struct Object *ringSpawner; diff --git a/src/game/behaviors/wdw_water_level.inc.c b/src/game/behaviors/wdw_water_level.inc.c index 08f8e0dd9..66579f5af 100644 --- a/src/game/behaviors/wdw_water_level.inc.c +++ b/src/game/behaviors/wdw_water_level.inc.c @@ -35,7 +35,7 @@ void bhv_init_changing_water_level_loop(void) { void bhv_water_level_diamond_loop(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; + struct Object* player = marioState ? marioState->marioObj : NULL; struct Object* manager = cur_obj_nearest_object_with_behavior(bhvInitializeChangingWaterLevel); @@ -52,7 +52,7 @@ void bhv_water_level_diamond_loop(void) { o->oAction++; // Sets to WATER_LEVEL_DIAMOND_ACT_IDLE break; case WATER_LEVEL_DIAMOND_ACT_IDLE: - if (marioState == &gMarioStates[0] && obj_check_if_collided_with_object(o, player)) { + if (marioState == &gMarioStates[0] && player && obj_check_if_collided_with_object(o, player)) { if (gWDWWaterLevelChanging == 0) { o->oAction++; // Sets to WATER_LEVEL_DIAMOND_ACT_CHANGE_WATER_LEVEL gWDWWaterLevelChanging = 1; diff --git a/src/game/behaviors/whomp.inc.c b/src/game/behaviors/whomp.inc.c index 5807bca85..67468d559 100644 --- a/src/game/behaviors/whomp.inc.c +++ b/src/game/behaviors/whomp.inc.c @@ -18,8 +18,8 @@ u8 whomp_act_0_continue_dialog(void) { return o->oAction == 0; } void whomp_act_0(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 distanceToPlayer = dist_between_objects(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; cur_obj_init_animation_with_accel_and_sound(0, 1.0f); cur_obj_set_pos_to_home(); @@ -34,7 +34,7 @@ void whomp_act_0(void) { cur_obj_set_pos_to_home(); o->oHealth = gBehaviorValues.KingWhompHealth; } - } else if (should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 1, CUTSCENE_DIALOG, gBehaviorValues.dialogs.KingWhompDialog, whomp_act_0_continue_dialog)) { + } else if (marioState && should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 1, CUTSCENE_DIALOG, gBehaviorValues.dialogs.KingWhompDialog, whomp_act_0_continue_dialog)) { o->oAction = 2; network_send_object(o); } @@ -61,8 +61,8 @@ void whomp_act_7(void) { void whomp_act_1(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; s16 sp26; f32 sp20; @@ -90,8 +90,8 @@ void whomp_act_1(void) { void whomp_act_2(void) { struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; s16 sp1E; cur_obj_init_animation_with_accel_and_sound(0, 1.0f); @@ -161,7 +161,9 @@ void king_whomp_on_ground(void) { o->oAction = 8; else { vec3f_copy_2(pos, &o->oPosX); - vec3f_copy_2(&o->oPosX, &player->oPosX); + if (player) { + vec3f_copy_2(&o->oPosX, &player->oPosX); + } spawn_mist_particles_variable(0, 0, 100.0f); spawn_triangle_break_particles(20, 138, 3.0f, 4); cur_obj_shake_screen(SHAKE_POS_SMALL); @@ -192,7 +194,9 @@ void whomp_on_ground(void) { o->oAction = 8; } else { struct MarioState* marioState = nearest_mario_state_to_object(o); - cur_obj_spawn_loot_coin_at_mario_pos(marioState); + if (marioState) { + cur_obj_spawn_loot_coin_at_mario_pos(marioState); + } o->oSubAction++; } } @@ -211,7 +215,7 @@ void whomp_act_6(void) { else whomp_on_ground(); struct MarioState* marioState = nearest_mario_state_to_object(o); - if (o->oTimer > 100 || (marioState->action == ACT_SQUISHED && o->oTimer > 30)) + if (o->oTimer > 100 || (marioState && marioState->action == ACT_SQUISHED && o->oTimer > 30)) o->oSubAction = 10; } else { if (o->oFaceAnglePitch > 0) { @@ -233,7 +237,7 @@ u8 whomp_act_8_continue_dialog(void) { return o->oAction == 8; } void whomp_act_8(void) { if (o->oBehParams2ndByte != 0) { struct MarioState* marioState = nearest_mario_state_to_object(o); - if (should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 2, CUTSCENE_DIALOG, gBehaviorValues.dialogs.KingWhompDefeatDialog, whomp_act_8_continue_dialog)) { + if (marioState && should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 2, CUTSCENE_DIALOG, gBehaviorValues.dialogs.KingWhompDefeatDialog, whomp_act_8_continue_dialog)) { obj_set_angle(o, 0, 0, 0); cur_obj_hide(); cur_obj_become_intangible(); diff --git a/src/game/behaviors/wiggler.inc.c b/src/game/behaviors/wiggler.inc.c index 62e6f3cb7..24e6412f1 100644 --- a/src/game/behaviors/wiggler.inc.c +++ b/src/game/behaviors/wiggler.inc.c @@ -211,9 +211,9 @@ void wiggler_update_segments(void) { */ static void wiggler_act_walk(void) { struct MarioState *marioState = nearest_mario_state_to_object(o); - struct Object *player = marioState->marioObj; - s32 distanceToPlayer = o->oDistanceToMario; - s32 angleToPlayer = o->oAngleToMario; + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; o->oWigglerWalkAnimSpeed = 0.06f * o->oForwardVel; @@ -226,7 +226,7 @@ static void wiggler_act_walk(void) { // If Mario is positioned below the wiggler, assume he entered through the // lower cave entrance, so don't display text. - if (player->oPosY < o->oPosY || (cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 0, CUTSCENE_DIALOG, gBehaviorValues.dialogs.WigglerDialog, wiggler_act_walk_continue_dialog) != 0)) { + if ((player && player->oPosY < o->oPosY) || (cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 0, CUTSCENE_DIALOG, gBehaviorValues.dialogs.WigglerDialog, wiggler_act_walk_continue_dialog) != 0)) { o->oWigglerTextStatus = WIGGLER_TEXT_STATUS_COMPLETED_DIALOG; network_send_object_reliability(o, TRUE); } @@ -314,7 +314,7 @@ static void wiggler_act_jumped_on(void) { s16 dialogIndex = (o->oHealth - 2); if (o->header.gfx.scale[1] >= 4.0f) { if (o->oTimer > 30) { - if ((dialogIndex >= 0 && dialogIndex <= 2) && should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(marioState, 2, 0, CUTSCENE_DIALOG, *attackText[dialogIndex], wiggler_act_jumped_on_continue_dialog) != 0) { + if ((dialogIndex >= 0 && dialogIndex <= 2) && marioState && should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(marioState, 2, 0, CUTSCENE_DIALOG, *attackText[dialogIndex], wiggler_act_jumped_on_continue_dialog) != 0) { // Because we don't want the wiggler to disappear after being // defeated, we leave its health at 1 if (--o->oHealth <= 1) { @@ -472,8 +472,8 @@ void bhv_wiggler_update(void) { } struct Object* player = nearest_player_to_object(o); - s32 distanceToPlayer = dist_between_objects(o, player); - s32 angleToPlayer = obj_angle_to_object(o, player); + s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; o->oDistanceToMario = distanceToPlayer; o->oAngleToMario = angleToPlayer; diff --git a/src/game/behaviors/yoshi.inc.c b/src/game/behaviors/yoshi.inc.c index 08ced5b46..26be83bf7 100644 --- a/src/game/behaviors/yoshi.inc.c +++ b/src/game/behaviors/yoshi.inc.c @@ -91,8 +91,8 @@ void yoshi_idle_loop(void) { void yoshi_talk_loop(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); - struct Object* player = marioState->marioObj; - s32 angleToPlayer = obj_angle_to_object(o, player); + struct Object* player = marioState ? marioState->marioObj : NULL; + s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; if (marioState != &gMarioStates[0]) { return; diff --git a/src/game/interaction.c b/src/game/interaction.c index 477dc72e2..8c1f2802c 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -2275,6 +2275,7 @@ void check_lava_boost(struct MarioState *m) { } void pss_begin_slide(UNUSED struct MarioState *m) { + if (!m->visibleToEnemies) { return; } if (!(gHudDisplay.flags & HUD_DISPLAY_FLAG_TIMER)) { level_control_timer(TIMER_CONTROL_SHOW); level_control_timer(TIMER_CONTROL_START); diff --git a/src/game/mario.c b/src/game/mario.c index 04a51e053..c6bd9557b 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -400,10 +400,12 @@ bool mario_can_bubble(struct MarioState* m) { if (!gServerSettings.bubbleDeath) { return false; } if (m->playerIndex != 0) { return false; } if (m->action == ACT_BUBBLED) { return false; } + if (!m->visibleToEnemies) { return false; } u8 allInBubble = TRUE; for (s32 i = 1; i < MAX_PLAYERS; i++) { if (!is_player_active(&gMarioStates[i])) { continue; } + if (!gMarioStates[i].visibleToEnemies) { continue; } if (gMarioStates[i].action != ACT_BUBBLED && gMarioStates[i].health >= 0x100) { allInBubble = FALSE; break; @@ -2142,6 +2144,7 @@ void init_single_mario(struct MarioState* m) { m->framesSinceB = 0xFF; m->invincTimer = 0; + m->visibleToEnemies = TRUE; // always put the cap on head /*if (save_file_get_flags() & (SAVE_FLAG_CAP_ON_GROUND | SAVE_FLAG_CAP_ON_KLEPTO | SAVE_FLAG_CAP_ON_UKIKI | SAVE_FLAG_CAP_ON_MR_BLIZZARD)) { diff --git a/src/game/mario_actions_automatic.c b/src/game/mario_actions_automatic.c index d14d4283c..ecea74043 100644 --- a/src/game/mario_actions_automatic.c +++ b/src/game/mario_actions_automatic.c @@ -938,6 +938,10 @@ s32 act_bubbled(struct MarioState* m) { set_camera_mode(m->area->camera, CAMERA_MODE_FREE_ROAM, 1); } struct MarioState* targetMarioState = nearest_mario_state_to_object(m->marioObj); + if (targetMarioState == NULL) { + targetMarioState = &gMarioStates[0]; + } + struct Object* target = targetMarioState->marioObj; s32 angleToPlayer = obj_angle_to_object(m->marioObj, target); s32 pitchToPlayer = obj_pitch_to_object(m->marioObj, target); @@ -948,6 +952,7 @@ s32 act_bubbled(struct MarioState* m) { u8 allInBubble = TRUE; for (s32 i = 0; i < MAX_PLAYERS; i++) { if (!is_player_active(&gMarioStates[i])) { continue; } + if (!gMarioStates[i].visibleToEnemies) { continue; } if (gMarioStates[i].action != ACT_BUBBLED && gMarioStates[i].health >= 0x100) { allInBubble = FALSE; break; diff --git a/src/game/mario_actions_cutscene.c b/src/game/mario_actions_cutscene.c index bdbc8a0e4..68c5a0e0f 100644 --- a/src/game/mario_actions_cutscene.c +++ b/src/game/mario_actions_cutscene.c @@ -367,6 +367,7 @@ s32 mario_ready_to_speak(struct MarioState* m) { } u8 should_start_or_continue_dialog(struct MarioState* m, struct Object* object) { + if (!m->visibleToEnemies) { return FALSE; } if (m->playerIndex == 0) { return TRUE; } return (gContinueDialogFunctionObject == object); } diff --git a/src/game/obj_behaviors.c b/src/game/obj_behaviors.c index 116cc54d6..f959dd8dc 100644 --- a/src/game/obj_behaviors.c +++ b/src/game/obj_behaviors.c @@ -518,6 +518,24 @@ void obj_move_xyz_using_fvel_and_yaw(struct Object *obj) { * Checks if a point is within distance from Mario's graphical position. Test is exclusive. */ s8 is_point_within_radius_of_mario(f32 x, f32 y, f32 z, s32 dist) { + for (s32 i = 0; i < MAX_PLAYERS; i++) { + if (!is_player_active(&gMarioStates[i])) { continue; } + if (!gMarioStates[i].visibleToEnemies) { continue; } + struct Object* player = gMarioStates[i].marioObj; + f32 mGfxX = player->header.gfx.pos[0]; + f32 mGfxY = player->header.gfx.pos[1]; + f32 mGfxZ = player->header.gfx.pos[2]; + + if ((x - mGfxX) * (x - mGfxX) + (y - mGfxY) * (y - mGfxY) + (z - mGfxZ) * (z - mGfxZ) + < (f32)(dist * dist)) { + return TRUE; + } + } + + return FALSE; +} + +s8 is_point_within_radius_of_any_player(f32 x, f32 y, f32 z, s32 dist) { for (s32 i = 0; i < MAX_PLAYERS; i++) { if (!is_player_active(&gMarioStates[i])) { continue; } struct Object* player = gMarioStates[i].marioObj; @@ -586,23 +604,32 @@ struct MarioState* nearest_mario_state_to_object(struct Object *obj) { if (!obj) { return NULL; } struct MarioState* nearest = NULL; f32 nearestDist = 0; - u8 checkActive = TRUE; - do { - for (s32 i = 0; i < MAX_PLAYERS; i++) { - if (gMarioStates[i].marioObj == obj) { continue; } - if (checkActive && !is_player_active(&gMarioStates[i])) { continue; } - float dist = dist_between_objects(obj, gMarioStates[i].marioObj); - if (nearest == NULL || dist < nearestDist) { - nearest = &gMarioStates[i]; - nearestDist = dist; - } + for (s32 i = 0; i < MAX_PLAYERS; i++) { + if (gMarioStates[i].marioObj == obj) { continue; } + if (!gMarioStates[i].visibleToEnemies) { continue; } + if (!is_player_active(&gMarioStates[i])) { continue; } + float dist = dist_between_objects(obj, gMarioStates[i].marioObj); + if (nearest == NULL || dist < nearestDist) { + nearest = &gMarioStates[i]; + nearestDist = dist; } - if (!checkActive) { break; } - checkActive = FALSE; - } while (nearest == NULL); + } - if (nearest == NULL) { - nearest = &gMarioStates[0]; + return nearest; +} + +struct MarioState* nearest_possible_mario_state_to_object(struct Object *obj) { + if (!obj) { return NULL; } + struct MarioState* nearest = NULL; + f32 nearestDist = 0; + for (s32 i = 0; i < MAX_PLAYERS; i++) { + if (gMarioStates[i].marioObj == obj) { continue; } + if (!is_player_active(&gMarioStates[i])) { continue; } + float dist = dist_between_objects(obj, gMarioStates[i].marioObj); + if (nearest == NULL || dist < nearestDist) { + nearest = &gMarioStates[i]; + nearestDist = dist; + } } return nearest; @@ -625,21 +652,18 @@ struct MarioState *nearest_interacting_mario_state_to_object(struct Object *obj) if (!obj) { return NULL; } struct MarioState *nearest = NULL; f32 nearestDist = 0; - u8 checkActive = TRUE; - do { - for (s32 i = 0; i < MAX_PLAYERS; i++) { - if (gMarioStates[i].marioObj == obj) { continue; } - if (gMarioStates[i].interactObj != obj) { continue; } - if (checkActive && !is_player_active(&gMarioStates[i])) { continue; } - float dist = dist_between_objects(obj, gMarioStates[i].marioObj); - if (nearest == NULL || dist < nearestDist) { - nearest = &gMarioStates[i]; - nearestDist = dist; - } + + for (s32 i = 0; i < MAX_PLAYERS; i++) { + if (gMarioStates[i].marioObj == obj) { continue; } + if (gMarioStates[i].interactObj != obj) { continue; } + if (!gMarioStates[i].visibleToEnemies) { continue; } + if (!is_player_active(&gMarioStates[i])) { continue; } + float dist = dist_between_objects(obj, gMarioStates[i].marioObj); + if (nearest == NULL || dist < nearestDist) { + nearest = &gMarioStates[i]; + nearestDist = dist; } - if (!checkActive) { break; } - checkActive = FALSE; - } while (nearest == NULL); + } if (nearest == NULL) { nearest = &gMarioStates[0]; diff --git a/src/game/obj_behaviors.h b/src/game/obj_behaviors.h index 39b78a292..485ae20af 100644 --- a/src/game/obj_behaviors.h +++ b/src/game/obj_behaviors.h @@ -166,6 +166,7 @@ u8 is_player_active(struct MarioState* m); u8 is_other_player_active(void); u8 is_player_in_local_area(struct MarioState* m); struct MarioState* nearest_mario_state_to_object(struct Object* obj); +struct MarioState* nearest_possible_mario_state_to_object(struct Object *obj); struct Object* nearest_player_to_object(struct Object* obj); struct MarioState *nearest_interacting_mario_state_to_object(struct Object *obj); struct Object *nearest_interacting_player_to_object(struct Object *obj); diff --git a/src/game/obj_behaviors_2.c b/src/game/obj_behaviors_2.c index ba4f0c60f..15b1f74be 100644 --- a/src/game/obj_behaviors_2.c +++ b/src/game/obj_behaviors_2.c @@ -383,6 +383,7 @@ s32 cur_obj_play_sound_at_anim_range(s8 arg0, s8 arg1, u32 sound) { } s16 obj_turn_pitch_toward_mario(struct MarioState* m, f32 targetOffsetY, s16 turnAmount) { + if (!m) { return 0; } s16 targetPitch; o->oPosY -= targetOffsetY; @@ -673,7 +674,9 @@ void obj_set_knockback_action(s32 attackType) { o->oFlags &= ~OBJ_FLAG_SET_FACE_YAW_TO_MOVE_YAW; struct Object* player = nearest_player_to_object(o); - o->oMoveAngleYaw = obj_angle_to_object(player, o); + if (player) { + o->oMoveAngleYaw = obj_angle_to_object(player, o); + } } void obj_set_squished_action(void) { @@ -900,12 +903,19 @@ void treat_far_home_as_mario(f32 threshold, s32* distanceToPlayer, s32* angleToP } } else { struct Object* player = nearest_player_to_object(o); - dx = o->oHomeX - player->oPosX; - dy = o->oHomeY - player->oPosY; - dz = o->oHomeZ - player->oPosZ; - distance = sqrtf(dx * dx + dy * dy + dz * dz); + if (player) { + dx = o->oHomeX - player->oPosX; + dy = o->oHomeY - player->oPosY; + dz = o->oHomeZ - player->oPosZ; + distance = sqrtf(dx * dx + dy * dy + dz * dz); - if (distance > threshold) { + if (distance > threshold) { + o->oDistanceToMario = 20000.0f; + if (distanceToPlayer != NULL) { + *distanceToPlayer = o->oDistanceToMario; + } + } + } else { o->oDistanceToMario = 20000.0f; if (distanceToPlayer != NULL) { *distanceToPlayer = o->oDistanceToMario; diff --git a/src/game/object_helpers.c b/src/game/object_helpers.c index cb82eebe0..9afd262d0 100644 --- a/src/game/object_helpers.c +++ b/src/game/object_helpers.c @@ -1693,6 +1693,7 @@ f32 cur_obj_lateral_dist_from_obj_to_home(struct Object *obj) { f32 cur_obj_lateral_dist_from_mario_to_home(void) { struct Object* player = nearest_player_to_object(o); + if (!player) { return 10000; } f32 dist; f32 dx = o->oHomeX - player->oPosX; f32 dz = o->oHomeZ - player->oPosZ; @@ -2628,6 +2629,10 @@ s32 cur_obj_mario_far_away(void) { s32 is_mario_moving_fast_or_in_air(s32 speedThreshold) { struct MarioState* marioState = nearest_mario_state_to_object(o); + if (!marioState) { + return FALSE; + } + if (marioState->forwardVel > speedThreshold) { return TRUE; } @@ -2830,6 +2835,7 @@ void clear_time_stop_flags(s32 flags) { } s32 cur_obj_can_mario_activate_textbox(struct MarioState* m, f32 radius, f32 height, UNUSED s32 unused) { + if (!m->visibleToEnemies) { return FALSE; } if (o->oDistanceToMario < 1500.0f) { f32 latDistToMario = lateral_dist_between_objects(o, m->marioObj); UNUSED s16 angleFromMario = obj_angle_to_object(m->marioObj, o); @@ -2944,6 +2950,7 @@ s32 cur_obj_update_dialog_with_cutscene(struct MarioState* m, s32 actionArg, s32 s32 doneTurning = TRUE; if (m->playerIndex != 0) { return 0; } + if (!m->visibleToEnemies) { return FALSE; } switch (o->oDialogState) { #ifdef VERSION_JP diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index 8531f4daf..a05d42802 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -786,7 +786,7 @@ static struct LuaObjectField sMarioBodyStateFields[LUA_MARIO_BODY_STATE_FIELD_CO { "wingFlutter", LVT_S8, offsetof(struct MarioBodyState, wingFlutter), false, LOT_NONE }, }; -#define LUA_MARIO_STATE_FIELD_COUNT 75 +#define LUA_MARIO_STATE_FIELD_COUNT 76 static struct LuaObjectField sMarioStateFields[LUA_MARIO_STATE_FIELD_COUNT] = { { "action", LVT_U32, offsetof(struct MarioState, action), false, LOT_NONE }, { "actionArg", LVT_U32, offsetof(struct MarioState, actionArg), false, LOT_NONE }, @@ -859,6 +859,7 @@ static struct LuaObjectField sMarioStateFields[LUA_MARIO_STATE_FIELD_COUNT] = { { "unkC4", LVT_F32, offsetof(struct MarioState, unkC4), false, LOT_NONE }, { "usedObj", LVT_COBJECT_P, offsetof(struct MarioState, usedObj), false, LOT_OBJECT }, { "vel", LVT_COBJECT, offsetof(struct MarioState, vel), true, LOT_VEC3F }, + { "visibleToEnemies", LVT_U8, offsetof(struct MarioState, visibleToEnemies), false, LOT_NONE }, { "wall", LVT_COBJECT_P, offsetof(struct MarioState, wall), false, LOT_SURFACE }, { "wallKickTimer", LVT_U8, offsetof(struct MarioState, wallKickTimer), false, LOT_NONE }, { "wallNormal", LVT_COBJECT, offsetof(struct MarioState, wallNormal), true, LOT_VEC3F }, diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index 67510b0bf..bf0a656f3 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -1046,7 +1046,7 @@ char gSmluaConstants[] = "" "SKIN = 5\n" "CAP = 6\n" "PLAYER_PART_MAX = 7\n" -"METAL = 6\n" +"METAL = CAP\n" "CT_MARIO = 0\n" "CT_LUIGI = 1\n" "CT_TOAD = 2\n" diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index f9dcf190a..56df0295e 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -12138,6 +12138,24 @@ int smlua_func_is_point_close_to_object(lua_State* L) { return 1; } +int smlua_func_is_point_within_radius_of_any_player(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 4)) { return 0; } + + f32 x = smlua_to_number(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1 for function 'is_point_within_radius_of_any_player'"); return 0; } + f32 y = smlua_to_number(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2 for function 'is_point_within_radius_of_any_player'"); return 0; } + f32 z = smlua_to_number(L, 3); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 3 for function 'is_point_within_radius_of_any_player'"); return 0; } + s32 dist = smlua_to_integer(L, 4); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 4 for function 'is_point_within_radius_of_any_player'"); return 0; } + + extern s8 is_point_within_radius_of_any_player(f32 x, f32 y, f32 z, s32 dist); + lua_pushinteger(L, is_point_within_radius_of_any_player(x, y, z, dist)); + + return 1; +} + int smlua_func_is_point_within_radius_of_mario(lua_State* L) { if(!smlua_functions_valid_param_count(L, 4)) { return 0; } @@ -12204,6 +12222,18 @@ int smlua_func_nearest_player_to_object(lua_State* L) { return 1; } +int smlua_func_nearest_possible_mario_state_to_object(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 1)) { return 0; } + + struct Object* obj = (struct Object*)smlua_to_cobject(L, 1, LOT_OBJECT); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1 for function 'nearest_possible_mario_state_to_object'"); return 0; } + + extern struct MarioState* nearest_possible_mario_state_to_object(struct Object *obj); + smlua_push_object(L, LOT_MARIOSTATE, nearest_possible_mario_state_to_object(obj)); + + return 1; +} + int smlua_func_obj_check_floor_death(lua_State* L) { if(!smlua_functions_valid_param_count(L, 2)) { return 0; } @@ -19317,11 +19347,13 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "is_player_active", smlua_func_is_player_active); smlua_bind_function(L, "is_player_in_local_area", smlua_func_is_player_in_local_area); smlua_bind_function(L, "is_point_close_to_object", smlua_func_is_point_close_to_object); + smlua_bind_function(L, "is_point_within_radius_of_any_player", smlua_func_is_point_within_radius_of_any_player); smlua_bind_function(L, "is_point_within_radius_of_mario", smlua_func_is_point_within_radius_of_mario); smlua_bind_function(L, "nearest_interacting_mario_state_to_object", smlua_func_nearest_interacting_mario_state_to_object); smlua_bind_function(L, "nearest_interacting_player_to_object", smlua_func_nearest_interacting_player_to_object); smlua_bind_function(L, "nearest_mario_state_to_object", smlua_func_nearest_mario_state_to_object); smlua_bind_function(L, "nearest_player_to_object", smlua_func_nearest_player_to_object); + smlua_bind_function(L, "nearest_possible_mario_state_to_object", smlua_func_nearest_possible_mario_state_to_object); smlua_bind_function(L, "obj_check_floor_death", smlua_func_obj_check_floor_death); smlua_bind_function(L, "obj_check_if_facing_toward_angle", smlua_func_obj_check_if_facing_toward_angle); smlua_bind_function(L, "obj_find_wall", smlua_func_obj_find_wall);