Add ability for mods to signal that a player will not be seen by enemies

This commit is contained in:
MysterD 2022-11-11 19:02:11 -08:00
parent 06f801afe9
commit b6b5b4f4e3
105 changed files with 734 additions and 450 deletions

View file

@ -2715,7 +2715,7 @@ CAP = 6
PLAYER_PART_MAX = 7
--- @type PlayerParts
METAL = 6
METAL = CAP
--- @class DialogId

View file

@ -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

View file

@ -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

View file

@ -887,7 +887,7 @@
| SKIN | 5 |
| CAP | 6 |
| PLAYER_PART_MAX | 7 |
| METAL | 6 |
| METAL | CAP |
[:arrow_up_small:](#)

View file

@ -7702,6 +7702,29 @@
<br />
## [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:](#)
<br />
## [is_point_within_radius_of_mario](#is_point_within_radius_of_mario)
### Lua Example
@ -7805,6 +7828,26 @@
<br />
## [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:](#)
<br />
## [obj_check_floor_death](#obj_check_floor_death)
### Lua Example

View file

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

View file

@ -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 |

View file

@ -393,6 +393,7 @@ struct MarioState
/*????*/ u8 knockbackTimer;
/*????*/ u8 specialTripleJump;
/*????*/ Vec3f wallNormal;
/*????*/ u8 visibleToEnemies;
};
struct TextureInfo

View file

@ -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

View file

@ -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,6 +133,7 @@ static void homing_amp_chase_loop(void) {
// while curving towards him.
o->oForwardVel = 10.0f;
if (player) {
obj_turn_toward_object(o, player, 16, 0x400);
// The amp's average Y will approach Mario's graphical Y position + 250
@ -138,6 +143,7 @@ static void homing_amp_chase_loop(void) {
o->oHomingAmpAvgY += 10.0f;
}
}
}
// The amp's position will sinusoidally oscillate 40 units around its average Y.
o->oPosY = o->oHomingAmpAvgY + sins(o->oAmpYPhase * 0x400) * 20.0f;
@ -287,6 +293,7 @@ static void fixed_circling_amp_idle_loop(void) {
struct Object* player = nearest_player_to_object(o);
// Turn towards Mario, in both yaw and pitch.
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;
@ -294,6 +301,7 @@ static void fixed_circling_amp_idle_loop(void) {
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.

View file

@ -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) {

View file

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

View file

@ -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;
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,6 +517,7 @@ static void boo_act_4(void) {
}
struct MarioState* marioState = nearest_mario_state_to_object(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);
@ -522,6 +526,7 @@ static void boo_act_4(void) {
play_puzzle_jingle();
}
}
}
}
static void (*sBooActions[])(void) = {
@ -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);
}

View file

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

View file

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

View file

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

View file

@ -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();
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) {
if (player) {
o->oMoveAngleYaw = obj_angle_to_object(o, player);
}
o->oBlueFlameNextScale = 5.0f;
}
if (o->oTimer < 16) {

View file

@ -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();
}

View file

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

View file

@ -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);
if (player) {
o->oCheepCheepUnkF8 = player->oPosY + o->oCheepCheepUnkFC;
}
o->oWallHitboxRadius = 30.0f;
cur_obj_update_floor_and_walls();
cur_obj_call_action_function(sCheepCheepActions);

View file

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

View file

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

View file

@ -122,8 +122,10 @@ void bully_check_mario_collision(void) {
// Get the player who interacted with us.
struct MarioState *player = nearest_interacting_mario_state_to_object(o);
if (player) {
o->oBullyLastNetworkPlayerIndex = gNetworkPlayers[player->playerIndex].globalIndex;
}
}
}
void bully_act_chase_mario(void) {
@ -135,7 +137,9 @@ void bully_act_chase_mario(void) {
if (o->oTimer < 10) {
o->oForwardVel = 3.0;
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;
if (player) {
obj_turn_toward_object(o, player, 16, 1280);
}
} else {
o->header.gfx.animInfo.animFrame = 0;
}

View file

@ -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,8 +61,10 @@ void butterfly_act_rest(void) {
o->oAction = BUTTERFLY_ACT_FOLLOW_MARIO;
struct Object* player = nearest_player_to_object(o);
if (player) {
o->oMoveAngleYaw = player->header.gfx.angle[1];
}
}
}
void butterfly_act_follow_mario(void) {

View file

@ -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
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;
}
}

View file

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

View file

@ -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; }
}

View file

@ -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

View file

@ -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) {

View file

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

View file

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

View file

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

View file

@ -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 {
}
}

View file

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

View file

@ -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; }

View file

@ -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) {

View file

@ -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,9 +78,11 @@ static void enemy_lakitu_update_speed_and_angle(void) {
}
// Move faster the farther away mario is and the faster mario is moving
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);
}

View file

@ -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,15 +133,17 @@ 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;
if (player) {
sp1C->oMoveAngleYaw = player->oMoveAngleYaw;
sp1C->globalPlayerIndex = player->globalPlayerIndex;
}
}
o->oBehParams |= a0->unk2 << 24;
if (a0->model == 122)
o->oFlags |= 0x4000;

View file

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

View file

@ -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.
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)

View file

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

View file

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

View file

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

View file

@ -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) {

View file

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

View file

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

View file

@ -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) {
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) {

View file

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

View file

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

View file

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

View file

@ -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) {

View file

@ -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,6 +53,7 @@ void bhv_kickable_board_loop(void) {
o->oFaceAnglePitch = 0;
load_object_collision_model();
o->oFaceAnglePitch = -sins(o->oKickableBoardF4) * o->oKickableBoardF8;
if (marioState) {
if (o->oTimer > 30 && (sp24 = check_mario_attacking(marioState))) {
if (marioState->marioObj->oPosY > o->oPosY + 160.0f && sp24 == 2) {
o->oAction++;
@ -61,6 +62,7 @@ void bhv_kickable_board_loop(void) {
} else
o->oTimer = 0;
}
}
if (o->oTimer != 0) {
o->oKickableBoardF8 -= 8;
if (o->oKickableBoardF8 < 0) {

View file

@ -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;
}

View file

@ -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) {
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();

View file

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

View file

@ -70,15 +70,19 @@ void bhv_koopa_shell_loop(void) {
cur_obj_if_hit_wall_bounce_away();
if (o->oInteractStatus & INT_STATUS_INTERACTED) {
o->oAction++;
if (marioState) {
o->heldByPlayerIndex = marioState->playerIndex;
}
}
o->oFaceAngleYaw += 0x1000;
cur_obj_move_standard(-20);
koopa_shell_spawn_sparkles(10.0f);
break;
case 1:
player = gMarioStates[o->heldByPlayerIndex].marioObj;
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);
if (player) {
o->oFaceAngleYaw = player->oMoveAngleYaw;
}
if (o->oInteractStatus & INT_STATUS_STOP_RIDING) {
o->heldByPlayerIndex = 0;
obj_mark_for_deletion(o);

View file

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

View file

@ -31,13 +31,14 @@ 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) {
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);
@ -47,5 +48,6 @@ void bhv_pushable_loop(void) {
}
}
}
}
cur_obj_move_using_fvel_and_gravity();
}

View file

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

View file

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

View file

@ -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;
}

View file

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

View file

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

View file

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

View file

@ -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,6 +46,7 @@ void one_up_loop_in_air(void) {
void pole_1up_move_towards_mario(void) {
struct Object* player = nearest_player_to_object(o);
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;
@ -53,6 +54,7 @@ void pole_1up_move_towards_mario(void) {
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];

View file

@ -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:

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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) {

View file

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

View file

@ -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) {
if (marioState) {
obj_turn_pitch_toward_mario(marioState, 120.0f, 2000);
}
if ((s16) o->oMoveAnglePitch > 0x2000) {
o->oMoveAnglePitch = 0x2000;

View file

@ -54,10 +54,12 @@ void set_home_to_mario(void) {
o->oHomeY = o->parentObj->oPosY;
} else {
struct Object* player = nearest_player_to_object(o);
if (player) {
o->oHomeX = player->oPosX;
o->oHomeZ = player->oPosZ;
o->oHomeY = player->oPosY;
}
}
o->oHomeY += 250.0f;
o->oPosY = o->oHomeY;
f32 sp1C = o->oHomeX - o->oPosX;

View file

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

View file

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

View file

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

View file

@ -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;
}

View file

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

View file

@ -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);
if (player) {
player->oActiveParticleFlags &= ~0x2000;
}
if (isSnow) {
if (random_float() < 0.5) {
obj = spawn_object(o, MODEL_WHITE_PARTICLE_DL, bhvTreeSnow);

View file

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

View file

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

View file

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

View file

@ -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.
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);
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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)) {

View file

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

View file

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

View file

@ -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; }
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; }
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];

View file

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

Some files were not shown because too many files have changed in this diff Show more