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);