Fixed ~240 possible crashes

This commit is contained in:
MysterD 2023-05-05 23:59:58 -07:00
parent f06a422ff9
commit 1ee3fd1d13
100 changed files with 620 additions and 331 deletions

View file

@ -11543,13 +11543,13 @@ MAX_LOCAL_VERSION_LENGTH = 36
MAX_VERSION_LENGTH = 32
--- @type integer
MINOR_VERSION_NUMBER = 1
MINOR_VERSION_NUMBER = 0
--- @type integer
PATCH_VERSION_NUMBER = 0
--- @type integer
VERSION_NUMBER = 34
VERSION_NUMBER = 35
--- @type string
VERSION_REGION = "JP"

View file

@ -7187,6 +7187,12 @@ function get_object_list_from_behavior(behavior)
-- ...
end
--- @param trajectory Pointer_Trajectory
--- @return integer
function get_trajectory_length(trajectory)
-- ...
end
--- @param value number
--- @param center number
--- @param zeroThreshold number
@ -9000,8 +9006,9 @@ function cur_obj_play_sound_2(soundMagic)
end
--- @param soundStates SoundState
--- @param maxSoundStates integer
--- @return nil
function exec_anim_sound_state(soundStates)
function exec_anim_sound_state(soundStates, maxSoundStates)
-- ...
end
@ -9076,5 +9083,5 @@ end
--- @class Pointer_number
--- @class Pointer_Vec4s
--- @class Pointer_Mtx
--- @class Pointer_Collision
--- @class Pointer_Trajectory
--- @class Pointer_Collision

View file

@ -908,10 +908,12 @@ s16 *DynOS_Level_GetWarp(s32 aLevel, s32 aArea, u8 aWarpId) {
}
DynOS_Level_Init();
for (const auto &_Warp : sDynosLevelWarps[aLevel]) {
if (_Warp.mArea == aArea) {
if (_Warp.mId == aWarpId) {
return (s16 *) &_Warp;
if (aLevel < LEVEL_COUNT) {
for (const auto &_Warp : sDynosLevelWarps[aLevel]) {
if (_Warp.mArea == aArea) {
if (_Warp.mId == aWarpId) {
return (s16 *) &_Warp;
}
}
}
}

View file

@ -4650,6 +4650,26 @@
<br />
## [get_trajectory_length](#get_trajectory_length)
### Lua Example
`local integerValue = get_trajectory_length(trajectory)`
### Parameters
| Field | Type |
| ----- | ---- |
| trajectory | `Pointer` <`Trajectory`> |
### Returns
- `integer`
### C Prototype
`s32 get_trajectory_length(Trajectory* trajectory);`
[:arrow_up_small:](#)
<br />
## [increment_velocity_toward_range](#increment_velocity_toward_range)
### Lua Example

View file

@ -2569,18 +2569,19 @@
## [exec_anim_sound_state](#exec_anim_sound_state)
### Lua Example
`exec_anim_sound_state(soundStates)`
`exec_anim_sound_state(soundStates, maxSoundStates)`
### Parameters
| Field | Type |
| ----- | ---- |
| soundStates | [SoundState](structs.md#SoundState) |
| maxSoundStates | `integer` |
### Returns
- None
### C Prototype
`void exec_anim_sound_state(struct SoundState *soundStates);`
`void exec_anim_sound_state(struct SoundState *soundStates, u16 maxSoundStates);`
[:arrow_up_small:](#)

View file

@ -1348,6 +1348,7 @@
- [find_unimportant_object](functions-4.md#find_unimportant_object)
- [geo_offset_klepto_debug](functions-4.md#geo_offset_klepto_debug)
- [get_object_list_from_behavior](functions-4.md#get_object_list_from_behavior)
- [get_trajectory_length](functions-4.md#get_trajectory_length)
- [increment_velocity_toward_range](functions-4.md#increment_velocity_toward_range)
- [is_item_in_array](functions-4.md#is_item_in_array)
- [is_mario_moving_fast_or_in_air](functions-4.md#is_mario_moving_fast_or_in_air)

View file

@ -130,6 +130,7 @@ void obj_update_gfx_pos_and_angle(struct Object *obj) {
static void cur_obj_bhv_stack_push(uintptr_t bhvAddr) {
gCurrentObject->bhvStack[gCurrentObject->bhvStackIndex] = bhvAddr;
gCurrentObject->bhvStackIndex++;
if (gCurrentObject->bhvStackIndex >= 8) { gCurrentObject->bhvStackIndex = 8 - 1; }
}
// Retrieve the last behavior command address from the object's behavior stack.
@ -137,6 +138,7 @@ static uintptr_t cur_obj_bhv_stack_pop(void) {
uintptr_t bhvAddr;
gCurrentObject->bhvStackIndex--;
if (gCurrentObject->bhvStackIndex >= 8) { gCurrentObject->bhvStackIndex = 0; }
bhvAddr = gCurrentObject->bhvStack[gCurrentObject->bhvStackIndex];
return bhvAddr;
@ -858,7 +860,9 @@ static s32 bhv_cmd_parent_bit_clear(void) {
s32 value = BHV_CMD_GET_U32(1);
value = value ^ 0xFFFFFFFF;
obj_and_int(gCurrentObject->parentObj, field, value);
if (gCurrentObject->parentObj) {
obj_and_int(gCurrentObject->parentObj, field, value);
}
gCurBhvCommand += 2;
return BHV_PROC_CONTINUE;
@ -1337,6 +1341,7 @@ cur_obj_update_begin:;
if (!skipBehavior) {
do {
if (!gCurBhvCommand) { break; }
bhvCmdProc = BehaviorCmdTable[*gCurBhvCommand >> 24];
bhvProcResult = bhvCmdProc();
} while (bhvProcResult == BHV_PROC_CONTINUE);

View file

@ -488,7 +488,7 @@ struct GraphNodeBackground *init_graph_node_background(struct AllocOnlyPool *poo
if (graphNode != NULL) {
init_scene_graph_node_links(&graphNode->fnNode.node, GRAPH_NODE_TYPE_BACKGROUND);
if (background > BACKGROUND_CUSTOM) {
if (backgroundFunc && background > BACKGROUND_CUSTOM) {
LOG_ERROR("invalid background id");
background = BACKGROUND_OCEAN_SKY;
}

View file

@ -66,6 +66,7 @@ static s32 sRegister;
static struct LevelCommand *sCurrentCmd;
static u8 sLevelOwnedGraphNodes[MAX_LOADED_GRAPH_NODES] = { 0 };
static u8 sFinishedLoadingPerm = false;
static s32 eval_script_area(s32 arg) {
return (sWarpDest.areaIdx == arg);
@ -389,6 +390,7 @@ static void level_cmd_alloc_level_pool(void) {
// reset level graph node ownership
for (s32 i = 0; i < MAX_LOADED_GRAPH_NODES; i++) {
if (sLevelOwnedGraphNodes[i]) {
gLoadedGraphNodes[i] = NULL;
sLevelOwnedGraphNodes[i] = false;
}
}
@ -455,7 +457,7 @@ static void level_cmd_load_model_from_dl(void) {
if (val1 < MAX_LOADED_GRAPH_NODES) {
gLoadedGraphNodes[val1] = (struct GraphNode *) init_graph_node_display_list(sLevelPool, 0, val2, val3);
sLevelOwnedGraphNodes[val1] = true;
if (sFinishedLoadingPerm) { sLevelOwnedGraphNodes[val1] = true; }
smlua_model_util_remember(val1, val2, val3, 1);
}
@ -468,8 +470,11 @@ static void level_cmd_load_model_from_geo(void) {
if (arg0 < MAX_LOADED_GRAPH_NODES) {
gLoadedGraphNodes[arg0] = process_geo_layout(sLevelPool, arg1);
sLevelOwnedGraphNodes[arg0] = true;
if (sFinishedLoadingPerm) { sLevelOwnedGraphNodes[arg0] = true; }
smlua_model_util_remember(arg0, LAYER_OPAQUE, arg1, 0);
if (arg0 == MODEL_ERROR_MODEL) {
sFinishedLoadingPerm = true;
}
}
sCurrentCmd = CMD_NEXT;
@ -491,7 +496,7 @@ static void level_cmd_23(void) {
// GraphNodeScale has a GraphNode at the top. This
// is being stored to the array, so cast the pointer.
gLoadedGraphNodes[model] = (struct GraphNode *) init_graph_node_scale(sLevelPool, 0, arg0H, arg1, arg2.f);
sLevelOwnedGraphNodes[model] = true;
if (sFinishedLoadingPerm) { sLevelOwnedGraphNodes[model] = true; }
smlua_model_util_remember(model, arg0H, arg1, 1);
}

View file

@ -1,6 +1,9 @@
#ifndef BEHAVIOR_ACTIONS_H
#define BEHAVIOR_ACTIONS_H
#define BHV_ARR_CHECK(_arr, _idx, _arritem) (((size_t)_idx) < (sizeof(_arr) / sizeof(_arritem)))
#define BHV_ARR(_arr, _idx, _arritem) (BHV_ARR_CHECK(_arr, _idx, _arritem) ? _arr[_idx] : 0)
void spawn_mist_particles_variable(s32 count, s32 offsetY, f32 size);
void bhv_spawn_star_no_level_exit(struct Object* object, u32 params, u8 networkSendEvent);
void bhv_star_door_loop_2(void);

View file

@ -35,7 +35,9 @@ void bhv_alpha_boo_key_loop(void) {
// Another theory is that the boo key was intended to be spawned by a
// spawner that used object field 0x00 for something else. This
// is elaborated on more in beta_boo_key_dropped_loop.
o->parentObj->oBooDeathStatus = BOO_DEATH_STATUS_DYING;
if (o->parentObj) {
o->parentObj->oBooDeathStatus = BOO_DEATH_STATUS_DYING;
}
// Delete the object and spawn sparkles
obj_mark_for_deletion(o);
@ -94,7 +96,7 @@ static void beta_boo_key_dropped_loop(void) {
// One theory about this code is that there was a boo spawner, which
// spawned "false" boos and one "true" boo with the key, and the player
// was intended to find the one with the key to progress.
o->parentObj->oInteractStatus = INT_STATUS_HOOT_GRABBED_BY_MARIO;
if (o->parentObj) { o->parentObj->oInteractStatus = INT_STATUS_HOOT_GRABBED_BY_MARIO; }
// Delete the object and spawn sparkles
obj_mark_for_deletion(o);
@ -120,7 +122,9 @@ static void beta_boo_key_drop(void) {
// which stops this function from running again.
if (o->oTimer == 0) {
// Separate from the parent boo
o->parentObj = parent->parentObj;
if (parent) {
o->parentObj = parent->parentObj;
}
o->oAction = BETA_BOO_KEY_ACT_DROPPED;
@ -154,7 +158,7 @@ static void beta_boo_key_inside_boo_loop(void) {
o->oPosY += 40.0f;
// If the boo is dying/dead, set the action to BETA_BOO_KEY_ACT_DROPPING.
if (parent->oBooDeathStatus != BOO_DEATH_STATUS_ALIVE) {
if (parent && parent->oBooDeathStatus != BOO_DEATH_STATUS_ALIVE) {
o->oAction = BETA_BOO_KEY_ACT_DROPPING;
}

View file

@ -63,7 +63,7 @@ static void bird_act_fly(void) {
// A spawned bird's parent is its spawner bird. A spawner bird's parent
// is itself. In other words, when a group of birds has its spawner bird
// fly past Y=8000, they will all despawn simultaneously. Otherwise, fly.
if (o->parentObj->oPosY > 8000.0f) {
if (!o->parentObj || o->parentObj->oPosY > 8000.0f) {
obj_mark_for_deletion(o);
} else {
// If the bird is a spawner bird, fly towards its home; otherwise,

View file

@ -28,7 +28,7 @@ void bhv_hidden_blue_coin_loop(void) {
// Wait until the blue coin switch starts ticking to activate.
blueCoinSwitch = o->oHiddenBlueCoinSwitch;
if (blueCoinSwitch->oAction == BLUE_COIN_SWITCH_ACT_TICKING) {
if (blueCoinSwitch && blueCoinSwitch->oAction == BLUE_COIN_SWITCH_ACT_TICKING) {
o->oAction++; // Set to HIDDEN_BLUE_COIN_ACT_ACTIVE
}
@ -107,8 +107,10 @@ void bhv_blue_coin_number_loop(void) {
*/
void bhv_blue_coin_switch_init(void) {
struct Object *blueCoinNumber = spawn_object(o, MODEL_NUMBER, bhvBlueCoinNumber);
blueCoinNumber->activeFlags |= ACTIVE_FLAG_INITIATED_TIME_STOP; // to make sure it's updated even during time stop
blueCoinNumber->oHiddenBlueCoinSwitch = o;
if (blueCoinNumber) {
blueCoinNumber->activeFlags |= ACTIVE_FLAG_INITIATED_TIME_STOP; // to make sure it's updated even during time stop
blueCoinNumber->oHiddenBlueCoinSwitch = o;
}
o->oHomeY = o->oPosY;
}

View file

@ -85,7 +85,7 @@ void bhv_blue_fish_movement_loop(void) {
cur_obj_move_using_fvel_and_gravity();
// Deletes object if the parent has oAction set to BLUE_FISH_ACT_DUPLICATE.
if (o->parentObj->oAction == BLUE_FISH_ACT_DUPLICATE) {
if (!o->parentObj || o->parentObj->oAction == BLUE_FISH_ACT_DUPLICATE) {
obj_mark_for_deletion(o);
}
}

View file

@ -266,7 +266,7 @@ void bhv_bob_pit_bowling_ball_loop(void) {
UNUSED s16 collisionFlags = object_step();
find_floor_height_and_data(o->oPosX, o->oPosY, o->oPosZ, &sp1c);
if ((sp1c->normalX == 0) && (sp1c->normalZ == 0))
if (sp1c && (sp1c->normalX == 0) && (sp1c->normalZ == 0))
o->oForwardVel = 28.0f;
bowling_ball_set_hitbox();

View file

@ -48,6 +48,7 @@ s16 D_8032F520[][3] = { { 1, 10, 40 }, { 0, 0, 74 }, { -1, -10, 114 }, { 1
{ -1, 80, 184 }, { 1, 160, 186 }, { -1, -160, 186 }, { 1, 0, 0 }, };
void bhv_bowser_tail_anchor_init(void) {
if (!o->parentObj) { mark_obj_for_deletion(o); return; }
sync_object_init_field(o->parentObj, &o->oAction);
sync_object_init_field(o->parentObj, &o->oPrevAction);
sync_object_init_field(o->parentObj, &o->oTimer);
@ -59,6 +60,7 @@ void bhv_bowser_tail_anchor_init(void) {
}
void bhv_bowser_tail_anchor_loop(void) {
if (!o->parentObj) { return; }
CUR_OBJ_CALL_ACTION_FUNCTION(sBowserTailAnchorActions);
o->oParentRelativePosX = 90.0f;
if (o->parentObj->oAction == 4)
@ -71,6 +73,7 @@ void bhv_bowser_flame_spawn_loop(void) {
sync_object_init(o, SYNC_DISTANCE_ONLY_EVENTS);
}
struct Object *bowser = o->parentObj;
if (!bowser) { return; }
s32 sp30;
f32 sp2C;
f32 sp28;
@ -79,8 +82,9 @@ void bhv_bowser_flame_spawn_loop(void) {
s16 *sp1C = segmented_to_virtual(bowser_seg6_unkmoveshorts_060576FC);
if (bowser->oSoundStateID == 6) {
sp30 = bowser->header.gfx.animInfo.animFrame + 1.0f;
if (bowser->header.gfx.animInfo.curAnim->loopEnd == sp30)
if (bowser->header.gfx.animInfo.curAnim && bowser->header.gfx.animInfo.curAnim->loopEnd == sp30) {
sp30 = 0;
}
if (sp30 > 45 && sp30 < 85) {
cur_obj_play_sound_1(SOUND_AIR_BOWSER_SPIT_FIRE);
sp2C = sp1C[5 * sp30];
@ -106,6 +110,7 @@ void bhv_bowser_flame_spawn_loop(void) {
}
void bhv_bowser_body_anchor_init(void) {
if (!o->parentObj) { mark_obj_for_deletion(o); return; }
sync_object_init_field(o->parentObj, &o->oInteractType);
sync_object_init_field(o->parentObj, &o->oInteractStatus);
sync_object_init_field(o->parentObj, &o->oIntangibleTimer);
@ -113,6 +118,7 @@ void bhv_bowser_body_anchor_init(void) {
}
void bhv_bowser_body_anchor_loop(void) {
if (!o->parentObj) { return; }
obj_copy_pos_and_angle(o, o->parentObj);
if (o->parentObj->oAction == 4) {
#ifndef VERSION_JP
@ -1213,7 +1219,7 @@ void bowser_free_update(void) {
o->platform = floor->object;
else
o->platform = NULL;
exec_anim_sound_state(D_8032F5B8);
exec_anim_sound_state(D_8032F5B8, sizeof(D_8032F5B8) / sizeof(struct SoundState));
}
void bowser_held_update(void) {
@ -1262,9 +1268,11 @@ void bowser_thrown_dropped_update(void) {
o->oForwardVel = coss(o->oBowserHeldAnglePitch) * sp1C;
o->oVelY = -sins(o->oBowserHeldAnglePitch) * sp1C;
cur_obj_become_intangible();
o->prevObj->oAction = 1; // not sure what prevObj is
o->prevObj->oTimer = 0;
o->prevObj->oSubAction = 0;
if (o->prevObj) {
o->prevObj->oAction = 1; // not sure what prevObj is
o->prevObj->oTimer = 0;
o->prevObj->oSubAction = 0;
}
o->oTimer = 0;
o->oSubAction = 0;
@ -1549,7 +1557,9 @@ Gfx *geo_bits_bowser_coloring(s32 run, struct GraphNode *node, UNUSED s32 a2) {
void falling_bowser_plat_act_0(void) {
o->oPlatformUnkF8 = cur_obj_nearest_object_with_behavior(bhvBowser);
obj_set_collision_data(o, D_8032F698[o->oBehParams2ndByte].unk0);
if (BHV_ARR_CHECK(D_8032F698, o->oBehParams2ndByte, struct Struct8032F698)) {
obj_set_collision_data(o, D_8032F698[o->oBehParams2ndByte].unk0);
}
if (o->oPlatformUnkF8 != 0)
o->oAction = 1;
}
@ -1558,13 +1568,13 @@ void falling_bowser_plat_act_1(void) {
u8 doSend = FALSE;
UNUSED s32 unused;
struct Object *sp0 = o->oPlatformUnkF8;
if (sp0->platform == o) {
if (sp0 && sp0->platform == o) {
if (sp0->oAction == 13 && sp0->oBowserUnkF4 & 0x10000) {
o->oAction = 2;
doSend = TRUE;
}
}
if (sp0->oHealth == 1 && (sp0->oAction == 3 || sp0->oHeldState != HELD_FREE))
if (sp0 && sp0->oHealth == 1 && (sp0->oAction == 3 || sp0->oHeldState != HELD_FREE))
o->oSubAction = 1;
if (o->oSubAction == 0)
o->oPlatformUnkFC = 0;
@ -1594,7 +1604,7 @@ void falling_bowser_plat_act_2(void) {
o->oGravity = 0.0f;
} else
o->oGravity = -4.0f;
if ((o->oTimer & 1) == 0 && o->oTimer < 14) {
if ((o->oTimer & 1) == 0 && o->oTimer < 14 && BHV_ARR_CHECK(D_8032F698, o->oBehParams2ndByte, struct Struct8032F698)) {
sp22 = D_8032F698[o->oBehParams2ndByte].unk3 + (gDebugInfo[4][1] << 8);
sp1C = -(o->oTimer / 2) * 290 + 1740;
vec3f_copy_2(sp24, &o->oPosX);
@ -1779,10 +1789,16 @@ void bhv_flame_floating_landing_loop(void) {
cur_obj_update_floor_and_walls();
cur_obj_move_standard(0x4e);
bowser_flame_move();
if (bowser_flame_should_despawn(900))
if (bowser_flame_should_despawn(900)) {
obj_mark_for_deletion(o);
if (o->oVelY < D_8032F748[o->oBehParams2ndByte])
o->oVelY = D_8032F748[o->oBehParams2ndByte];
}
if (BHV_ARR_CHECK(D_8032F748, o->oBehParams2ndByte, f32)) {
if (o->oVelY < D_8032F748[o->oBehParams2ndByte]) {
o->oVelY = D_8032F748[o->oBehParams2ndByte];
}
}
if (o->oMoveFlags & OBJ_MOVE_LANDED) {
if (o->oBehParams2ndByte == 0)
spawn_object(o, MODEL_RED_FLAME, bhvFlameLargeBurningOut);

View file

@ -8,6 +8,7 @@
void bub_spawner_act_0(void) {
s32 i;
s32 sp18 = o->oBirdChirpChirpUnkF4;
if (sp18 > 20) { sp18 = 20; }
for (i = 0; i < sp18; i++)
spawn_object(o, MODEL_BUB, bhvBub);
o->oAction = 1;
@ -138,6 +139,6 @@ void bhv_bub_loop(void) {
cur_obj_update_floor_and_walls();
CUR_OBJ_CALL_ACTION_FUNCTION(sCheepCheepActions);
cur_obj_move_using_fvel_and_gravity();
if (o->parentObj->oAction == 2)
if (!o->parentObj || o->parentObj->oAction == 2)
obj_mark_for_deletion(o);
}

View file

@ -53,9 +53,9 @@ void opened_cannon_act_4(void) {
o->oPosZ += (f32)((o->oTimer / 2 & 1) - 0.5) * 4;
o->oAction = 6;
}
if (o->oCannonPlayerIndex != 0) {
if (o->oCannonPlayerIndex != 0 && o->oCannonPlayerIndex < MAX_PLAYERS) {
struct MarioState* controlledBy = &gMarioStates[o->oCannonPlayerIndex];
if (controlledBy->marioObj != NULL) {
if (controlledBy && controlledBy->marioObj != NULL) {
controlledBy->marioObj->oMarioCannonObjectYaw = o->oMoveAngleYaw;
controlledBy->marioObj->oMarioCannonInputYaw = 0;
}
@ -75,9 +75,9 @@ void opened_cannon_act_6(void) {
o->oMoveAngleYaw = sins(o->oCannonUnkF4) * 0x4000 + ((s16)(o->oBehParams2ndByte << 8));
o->oCannonUnkF4 += 0x400;
} else if (o->oTimer < 26) {
} else {
} else if (o->oCannonPlayerIndex < MAX_PLAYERS) {
struct MarioState* controlledBy = &gMarioStates[o->oCannonPlayerIndex];
if (controlledBy->marioObj != NULL) {
if (controlledBy && controlledBy->marioObj != NULL) {
controlledBy->marioObj->oMarioCannonObjectYaw = o->oMoveAngleYaw;
controlledBy->marioObj->oMarioCannonInputYaw = 0;
}
@ -110,7 +110,7 @@ void opened_cannon_act_1(void) {
if (o->oCannonPlayerIndex == 0) {
cur_obj_become_intangible();
cur_obj_disable_rendering();
} else {
} else if (o->oCannonPlayerIndex < MAX_PLAYERS) {
struct MarioState* controlledBy = &gMarioStates[o->oCannonPlayerIndex];
o->oMoveAnglePitch = 14563 + controlledBy->faceAngle[0] * -0.5f;
if (controlledBy->marioObj != NULL) {
@ -245,7 +245,7 @@ void bhv_cannon_base_loop(void) {
void bhv_cannon_barrel_loop(void) {
struct Object *parent = o->parentObj;
if (parent->header.gfx.node.flags & GRAPH_RENDER_ACTIVE) {
if (parent && parent->header.gfx.node.flags & GRAPH_RENDER_ACTIVE) {
cur_obj_enable_rendering();
obj_copy_pos(o, o->parentObj);
o->oMoveAngleYaw = o->parentObj->oMoveAngleYaw;

View file

@ -8,7 +8,7 @@ void cap_switch_act_0(void) {
o->oPosY += 71.0f;
spawn_object_relative_with_scale(0, 0, -71, 0, 0.5f, o, MODEL_CAP_SWITCH_BASE, bhvCapSwitchBase);
if (gCurrLevelNum != LEVEL_UNKNOWN_32) {
if (save_file_get_flags() & D_8032F0C0[o->oBehParams2ndByte]) {
if (save_file_get_flags() & BHV_ARR(D_8032F0C0, o->oBehParams2ndByte, s32)) {
o->oAction = 3;
o->header.gfx.scale[1] = 0.1f;
} else
@ -19,7 +19,7 @@ void cap_switch_act_0(void) {
void cap_switch_act_1(void) {
if (capSwitchForcePress || cur_obj_is_mario_on_platform()) {
save_file_set_flags(D_8032F0C0[o->oBehParams2ndByte]);
save_file_set_flags(BHV_ARR(D_8032F0C0, o->oBehParams2ndByte, s32));
o->oAction = 2;
cur_obj_play_sound_2(SOUND_GENERAL_ACTIVATE_CAP_SWITCH);
if (!capSwitchForcePress) {

View file

@ -6,9 +6,12 @@ void bhv_floor_trap_in_castle_loop(void) {
if (!is_player_active(&gMarioStates[i])) { continue; }
onPlatform = onPlatform || (gMarioStates[i].marioObj->platform == o);
}
if (onPlatform)
o->parentObj->oInteractStatus |= INT_STATUS_TRAP_TURN;
o->oFaceAngleRoll = o->parentObj->oFaceAngleRoll;
if (o->parentObj) {
if (onPlatform) {
o->parentObj->oInteractStatus |= INT_STATUS_TRAP_TURN;
}
o->oFaceAngleRoll = o->parentObj->oFaceAngleRoll;
}
}
void bhv_castle_floor_trap_init(void) {

View file

@ -1,10 +1,12 @@
// celebration_star.c.inc
void bhv_celebration_star_init(void) {
o->oHomeX = o->parentObj->header.gfx.pos[0];
o->oPosY = o->parentObj->header.gfx.pos[1] + 30.0f;
o->oHomeZ = o->parentObj->header.gfx.pos[2];
o->oMoveAngleYaw = o->parentObj->header.gfx.angle[1] + 0x8000;
if (o->parentObj) {
o->oHomeX = o->parentObj->header.gfx.pos[0];
o->oPosY = o->parentObj->header.gfx.pos[1] + 30.0f;
o->oHomeZ = o->parentObj->header.gfx.pos[2];
o->oMoveAngleYaw = o->parentObj->header.gfx.angle[1] + 0x8000;
}
o->oCelebStarDiameterOfRotation = 100;
#if BUGFIX_STAR_BOWSER_KEY
if (gCurrLevelNum == LEVEL_BOWSER_1 || gCurrLevelNum == LEVEL_BOWSER_2) {
@ -57,7 +59,7 @@ void celeb_star_act_face_camera(void) {
cur_obj_scale((f32) o->oTimer / 10.0);
#endif
o->oFaceAngleYaw += 0x1000;
} else {
} else if (o->parentObj) {
o->oFaceAngleYaw = o->parentObj->header.gfx.angle[1];
}

View file

@ -38,13 +38,17 @@ void bhv_chain_chomp_chain_part_update(void) {
obj_mark_for_deletion(o);
network_send_object(o);
} else if (o->oBehParams2ndByte != CHAIN_CHOMP_CHAIN_PART_BP_PIVOT) {
struct ChainSegment *segment = &o->parentObj->oChainChompSegments[o->oBehParams2ndByte];
struct ChainSegment *segment = (o->oBehParams2ndByte <= 4 && o->parentObj)
? &o->parentObj->oChainChompSegments[o->oBehParams2ndByte]
: NULL;
// Set position relative to the pivot
if (segment) {
o->oPosX = o->parentObj->parentObj->oPosX + segment->posX;
o->oPosY = o->parentObj->parentObj->oPosY + segment->posY;
o->oPosZ = o->parentObj->parentObj->oPosZ + segment->posZ;
if (segment && o->parentObj && o->parentObj->parentObj) {
if (o->parentObj->oChainChompSegments) {
o->oPosX = o->parentObj->parentObj->oPosX + segment->posX;
o->oPosY = o->parentObj->parentObj->oPosY + segment->posY;
o->oPosZ = o->parentObj->parentObj->oPosZ + segment->posZ;
}
}
} else if (o->parentObj->oChainChompReleaseStatus != CHAIN_CHOMP_NOT_RELEASED) {
cur_obj_update_floor_and_walls();
@ -379,6 +383,10 @@ static void chain_chomp_act_move(void) {
chain_chomp_act_uninitialized();
}
if (!o->parentObj) {
return;
}
// Segment 0 connects the pivot to the chain chomp itself
o->oChainChompSegments[0].posX = o->oPosX - o->parentObj->oPosX;
o->oChainChompSegments[0].posY = o->oPosY - o->parentObj->oPosY;
@ -447,8 +455,10 @@ static void chain_chomp_act_unload_chain(void) {
o->oAction = CHAIN_CHOMP_ACT_UNINITIALIZED;
if (o->oChainChompReleaseStatus != CHAIN_CHOMP_NOT_RELEASED) {
for (u8 i = 0; i < 5; i++) {
obj_mark_for_deletion((struct Object*)&o->oChainChompSegments[i]);
if (o->oChainChompSegments) {
for (u8 i = 0; i < 5; i++) {
obj_mark_for_deletion((struct Object*)&o->oChainChompSegments[i]);
}
}
obj_mark_for_deletion(o);
obj_mark_for_deletion(o->parentObj);

View file

@ -57,7 +57,7 @@ static void bhv_checkerboard_platform_run_once(void) {
}
void bhv_checkerboard_platform_init(void) {
o->oCheckerBoardPlatformUnkFC = o->parentObj->oBehParams2ndByte;
o->oCheckerBoardPlatformUnkFC = o->parentObj ? o->parentObj->oBehParams2ndByte : 0;
o->areaTimerType = AREA_TIMER_TYPE_LOOP;
o->areaTimer = 0;
o->areaTimerDuration = 132 + o->oCheckerBoardPlatformUnkFC * 2;

View file

@ -115,7 +115,7 @@ static void cloud_act_main(void) {
localOffsetPhase = 0x800 * gGlobalTimer;
if (o->parentObj != o) {
if (o->parentObj && o->parentObj != o) {
// Despawn if the parent lakitu does
if (o->parentObj->activeFlags == ACTIVE_FLAG_DEACTIVATED) {
o->oAction = CLOUD_ACT_UNLOAD;
@ -180,7 +180,7 @@ void bhv_cloud_update(void) {
* Update function for bhvCloudPart. Follow the parent cloud with some oscillation.
*/
void bhv_cloud_part_update(void) {
if (o->parentObj->oAction == CLOUD_ACT_UNLOAD) {
if (!o->parentObj || o->parentObj->oAction == CLOUD_ACT_UNLOAD) {
obj_mark_for_deletion(o);
} else {
f32 size = 2.0f / 3.0f * o->parentObj->header.gfx.scale[0];
@ -206,8 +206,7 @@ void bhv_cloud_part_update(void) {
o->oPosX = o->parentObj->oCloudCenterX + cloudRadius * sins(angleFromCenter) + localOffset;
o->oPosY =
o->parentObj->oCloudCenterY + localOffset + size * sCloudPartHeights[o->oBehParams2ndByte];
o->oPosY = o->parentObj->oCloudCenterY + localOffset + size * BHV_ARR(sCloudPartHeights, o->oBehParams2ndByte, s8);
o->oPosZ = o->parentObj->oPosZ + cloudRadius * coss(angleFromCenter) + localOffset;

View file

@ -156,7 +156,7 @@ void coffin_act_stand_up(void) {
*/
void bhv_coffin_loop(void) {
// Gotta save those 6 object slots
if (o->parentObj->oAction == COFFIN_SPAWNER_ACT_COFFINS_UNLOADED) {
if (o->parentObj && o->parentObj->oAction == COFFIN_SPAWNER_ACT_COFFINS_UNLOADED) {
obj_mark_for_deletion(o);
} else {
// Scale the coffin vertically? Must have thought it was too short?

View file

@ -133,11 +133,12 @@ void bhv_coin_formation_spawn_loop(void) {
cur_obj_set_model(smlua_model_util_load(E_MODEL_YELLOW_COIN_NO_SHADOW));
}
} else {
if (bhv_coin_sparkles_init())
if (o->parentObj && bhv_coin_sparkles_init()) {
o->parentObj->oCoinUnkF4 |= bit_shift_left(o->oBehParams2ndByte);
}
o->oAnimState++;
}
if (o->parentObj->oAction == 2)
if (!o->parentObj || o->parentObj->oAction == 2)
obj_mark_for_deletion(o);
}

View file

@ -31,11 +31,11 @@ void bhv_controllable_platform_sub_loop(void) {
if (gMarioStates[0].marioObj->platform == o) {
D_80331694 = o->oBehParams2ndByte;
#ifdef VERSION_SH
o->parentObj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
if (o->parentObj) { o->parentObj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE; }
#endif
o->oAction = 1;
cur_obj_play_sound_2(SOUND_GENERAL_MOVING_PLATFORM_SWITCH);
network_send_object(o->parentObj);
if (o->parentObj) { network_send_object(o->parentObj); }
}
break;
@ -48,11 +48,13 @@ void bhv_controllable_platform_sub_loop(void) {
break;
}
o->oVelX = o->parentObj->oVelX;
o->oVelZ = o->parentObj->oVelZ;
if (o->parentObj) {
o->oVelX = o->parentObj->oVelX;
o->oVelZ = o->parentObj->oVelZ;
if (o->parentObj->activeFlags == ACTIVE_FLAG_DEACTIVATED)
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
if (o->parentObj->activeFlags == ACTIVE_FLAG_DEACTIVATED)
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
}
}
static void bhv_controllable_platform_on_received_post(UNUSED u8 localIndex) {
@ -279,6 +281,7 @@ void bhv_controllable_platform_loop(void) {
D_80331694 = 0;
o->oTimer = 0;
for (s32 i = 0; i < 4; i++) {
if (!controllablePlatformSubs[i]) { continue; }
controllablePlatformSubs[i]->oParentRelativePosY = 51.0f;
controllablePlatformSubs[i]->oAction = 0;
controllablePlatformSubs[i]->oTimer = 0;

View file

@ -122,15 +122,15 @@ void elevator_act_3(void) // nearly identical to action 2
}
void bhv_elevator_init(void) {
s32 sp1C = D_8032F38C[o->oBehParams2ndByte * 3 + 2];
s32 sp1C = BHV_ARR(D_8032F38C, o->oBehParams2ndByte * 3 + 2, s16);
if (sp1C == 0) {
o->oElevatorUnkF4 = D_8032F38C[o->oBehParams2ndByte * 3];
o->oElevatorUnkF4 = BHV_ARR(D_8032F38C, o->oBehParams2ndByte * 3, s16);
o->oElevatorUnkF8 = o->oHomeY;
o->oElevatorUnkFC = (o->oElevatorUnkF4 + o->oElevatorUnkF8) / 2;
o->oElevatorUnk100 = cur_obj_has_behavior(bhvRrElevatorPlatform);
} else {
o->oElevatorUnkF4 = D_8032F38C[o->oBehParams2ndByte * 3];
o->oElevatorUnkF8 = D_8032F38C[o->oBehParams2ndByte * 3 + 1];
o->oElevatorUnkF4 = BHV_ARR(D_8032F38C, o->oBehParams2ndByte * 3, s16);
o->oElevatorUnkF8 = BHV_ARR(D_8032F38C, o->oBehParams2ndByte * 3 + 1, s16);
o->oElevatorUnkFC = (o->oElevatorUnkF4 + o->oElevatorUnkF8) / 2;
o->oElevatorUnk100 = 2;
}

View file

@ -31,7 +31,7 @@ struct Struct802C0DF0 sExclamationBoxContents[] = { { 0, 0, 0, MODEL_MARIOS_WING
{ 99, 0, 0, 0, NULL } };
void bhv_rotating_exclamation_box_loop(void) {
if (o->parentObj->oAction != 1)
if (!o->parentObj || o->parentObj->oAction != 1)
obj_mark_for_deletion(o);
}
@ -39,7 +39,7 @@ void exclamation_box_act_0(void) {
o->oExclamationBoxForce = FALSE;
if (o->oBehParams2ndByte < 3) {
o->oAnimState = o->oBehParams2ndByte;
if ((save_file_get_flags() & D_8032F0C0[o->oBehParams2ndByte])
if ((save_file_get_flags() & BHV_ARR(D_8032F0C0, o->oBehParams2ndByte, s32))
|| ((o->oBehParams >> 24) & 0xFF) != 0)
o->oAction = 2;
else
@ -56,7 +56,7 @@ void exclamation_box_act_1(void) {
spawn_object(o, smlua_model_util_load(E_MODEL_EXCLAMATION_POINT), bhvRotatingExclamationMark);
cur_obj_set_model(smlua_model_util_load(E_MODEL_EXCLAMATION_BOX_OUTLINE));
}
if ((save_file_get_flags() & D_8032F0C0[o->oBehParams2ndByte])
if ((save_file_get_flags() & BHV_ARR(D_8032F0C0, o->oBehParams2ndByte, s32))
|| ((o->oBehParams >> 24) & 0xFF) != 0) {
o->oAction = 2;
cur_obj_set_model(smlua_model_util_load(E_MODEL_EXCLAMATION_BOX));

View file

@ -208,6 +208,7 @@ static void eyerok_boss_act_die(void) {
}
void bhv_eyerok_boss_loop(void) {
if (!o->parentObj) { return; }
if (o->oAction == EYEROK_BOSS_ACT_DEAD) {
return;
}
@ -232,7 +233,7 @@ void bhv_eyerok_boss_loop(void) {
}
if (o->oAction != oldAction) {
if (sync_object_is_owned_locally(o->parentObj->oSyncID)) {
if (o->parentObj && sync_object_is_owned_locally(o->parentObj->oSyncID)) {
eyerokBossImmediateUpdate = TRUE;
} else {
o->oAction = EYEROK_BOSS_ACT_PAUSE;
@ -246,6 +247,7 @@ void bhv_eyerok_boss_loop(void) {
}
static s32 eyerok_hand_check_attacked(void) {
if (!o->parentObj) { return FALSE; }
struct Object* player = nearest_player_to_object(o);
s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0;
if (o->oEyerokReceivedAttack != 0 && abs_angle_diff(angleToPlayer, o->oFaceAngleYaw) < 0x3000) {
@ -279,7 +281,8 @@ static void eyerok_hand_pound_ground(void) {
}
static void eyerok_hand_act_sleep(void) {
if (o->parentObj->oAction != EYEROK_BOSS_ACT_SLEEP
if (!o->parentObj) { return; }
if (o->parentObj && o->parentObj->oAction != EYEROK_BOSS_ACT_SLEEP
&& ++o->oEyerokHandWakeUpTimer > -3 * o->oBehParams2ndByte) {
if (cur_obj_check_if_near_animation_end()) {
o->parentObj->oEyerokBossNumHands += 1;
@ -305,6 +308,7 @@ static void eyerok_hand_act_sleep(void) {
}
static void eyerok_hand_act_idle(void) {
if (!o->parentObj) { return; }
struct Object* player = nearest_player_to_object(o);
s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0;
cur_obj_init_animation_with_sound(2);
@ -342,6 +346,7 @@ static void eyerok_hand_act_idle(void) {
}
static void eyerok_hand_act_open(void) {
if (!o->parentObj) { return; }
struct Object* player = nearest_player_to_object(o);
s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0;
o->parentObj->oEyerokBossUnk1AC = o->oBehParams2ndByte;
@ -365,6 +370,7 @@ static void eyerok_hand_act_open(void) {
}
static void eyerok_hand_act_show_eye(void) {
if (!o->parentObj) { return; }
struct Object* player = nearest_player_to_object(o);
s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0;
UNUSED s16 val06;
@ -373,7 +379,7 @@ static void eyerok_hand_act_show_eye(void) {
cur_obj_play_sound_at_anim_range(0, 0, SOUND_OBJ_EYEROK_SHOW_EYE);
if (!eyerok_hand_check_attacked()) {
if (o->parentObj->oEyerokBossActiveHand == 0) {
if (o->parentObj && o->parentObj->oEyerokBossActiveHand == 0) {
if (o->oAnimState < 3) {
o->oAnimState += 1;
} else if (cur_obj_check_if_near_animation_end()) {
@ -385,13 +391,13 @@ static void eyerok_hand_act_show_eye(void) {
if (o->oEyerokHandUnkFC != 0) {
o->oEyerokHandUnkFC -= 1;
}
o->oAnimState = D_80331BA4[o->oEyerokHandUnkFC];
o->oAnimState = BHV_ARR(D_80331BA4, o->oEyerokHandUnkFC, s8);
} else {
o->oEyerokHandUnkFC = 5;
o->oEyerokHandUnk100 = random_linear_offset(20, 50);
}
if (o->parentObj->oEyerokBossNumHands != 2) {
if (o->parentObj && o->parentObj->oEyerokBossNumHands != 2) {
obj_face_yaw_approach(o->oMoveAngleYaw, 0x800);
if (o->oTimer > 10
&& ((player && o->oPosZ - player->oPosZ > 0.0f) || (o->oMoveFlags & OBJ_MOVE_HIT_EDGE))) {
@ -404,6 +410,7 @@ static void eyerok_hand_act_show_eye(void) {
}
static void eyerok_hand_act_close(void) {
if (!o->parentObj) { return; }
if (cur_obj_init_anim_check_frame(7, 1)) {
o->collisionData = segmented_to_virtual(ssl_seg7_collision_07028274);
@ -435,6 +442,7 @@ static void eyerok_hand_act_recover(void) {
}
static void eyerok_hand_act_become_active(void) {
if (!o->parentObj) { return; }
if (o->parentObj->oEyerokBossActiveHand == 0 || o->parentObj->oEyerokBossNumHands != 2) {
o->oAction = EYEROK_HAND_ACT_RETREAT;
o->parentObj->oEyerokBossActiveHand = o->oBehParams2ndByte;
@ -454,6 +462,7 @@ static void eyerok_hand_act_die_event(void) {
}
static void eyerok_hand_act_die(void) {
if (!o->parentObj) { return; }
if (cur_obj_init_anim_and_check_if_end(1)) {
o->parentObj->oEyerokBossUnk1AC = 0;
eyerok_hand_act_die_event();
@ -490,6 +499,7 @@ static void eyerok_hand_act_retreat(void) {
}
static void eyerok_hand_act_target_mario(void) {
if (!o->parentObj) { return; }
struct Object* player = nearest_player_to_object(o);
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)
@ -553,6 +563,7 @@ static void eyerok_hand_act_fist_push(void) {
}
static void eyerok_hand_act_fist_sweep(void) {
if (!o->parentObj) { return; }
if (o->oPosZ - o->parentObj->oPosZ < 1000.0f || (o->oMoveFlags & OBJ_MOVE_HIT_EDGE)) {
o->oAction = EYEROK_HAND_ACT_RETREAT;
o->oForwardVel = 0.0f;
@ -564,6 +575,7 @@ static void eyerok_hand_act_fist_sweep(void) {
}
static void eyerok_hand_act_begin_double_pound(void) {
if (!o->parentObj) { return; }
f32 sp4;
if (o->parentObj->oEyerokBossUnk104 < 0
@ -582,6 +594,7 @@ static void eyerok_hand_act_begin_double_pound(void) {
}
static void eyerok_hand_act_double_pound(void) {
if (!o->parentObj) { return; }
if (o->parentObj->oEyerokBossNumHands != 2) {
o->parentObj->oEyerokBossActiveHand = o->oBehParams2ndByte;
}
@ -608,6 +621,7 @@ static void eyerok_hand_act_double_pound(void) {
}
void bhv_eyerok_hand_loop(void) {
if (!o->parentObj) { return; }
if (o->oAction == EYEROK_HAND_ACT_DEAD) {
eyerok_hand_act_die_event();
return;
@ -679,7 +693,7 @@ void bhv_eyerok_hand_loop(void) {
o->header.gfx.scale[0] = 1.5f * o->oBehParams2ndByte;
if (o->oAction != oldAction) {
if (sync_object_is_owned_locally(o->parentObj->oSyncID)) {
if (o->parentObj && sync_object_is_owned_locally(o->parentObj->oSyncID)) {
eyerokBossImmediateUpdate = TRUE;
} else {
o->oAction = EYEROK_HAND_ACT_PAUSE;

View file

@ -129,6 +129,7 @@ void bhv_falling_pillar_loop(void) {
* Main loop for the invisible hitboxes.
*/
void bhv_falling_pillar_hitbox_loop(void) {
if (!o->parentObj) { return; }
// Get the state of the pillar.
s32 pitch = o->parentObj->oFaceAnglePitch;
s32 yaw = o->parentObj->oFaceAngleYaw;

View file

@ -31,6 +31,10 @@ void bhv_ferris_wheel_axle_init(void) {
struct Object *platform;
s32 i;
if (!BHV_ARR_CHECK(sFerrisWheelProperties, o->oBehParams2ndByte, struct FerrisWheelProperties)) {
return;
}
o->collisionData = segmented_to_virtual(sFerrisWheelProperties[o->oBehParams2ndByte].axleCollision);
for (i = 0; i < 4; i++) {
@ -60,6 +64,8 @@ void bhv_ferris_wheel_platform_update(void) {
f32 offsetXZ;
s16 offsetAngle;
if (!o->parentObj) { return; }
obj_perform_position_op(POS_OP_SAVE_POSITION);
offsetAngle = o->parentObj->oFaceAngleRoll + o->oBehParams2ndByte * 0x4000;

View file

@ -8,10 +8,10 @@
* These settings are animations, colour, and spawn quantity.
*/
static void fish_spawner_act_spawn(void) {
s32 i;
s32 schoolQuantity;
s16 model;
const struct Animation * const *fishAnimation;
s32 i = 0;
s32 schoolQuantity = 0;
s16 model = MODEL_ERROR_MODEL;
const struct Animation * const *fishAnimation = NULL;
struct Object *fishObject;
switch (o->oBehParams2ndByte) {
@ -280,7 +280,7 @@ void bhv_fish_loop(void)
cur_obj_move_using_fvel_and_gravity();
// If the parent object has action set to two, then delete the fish object.
if (o->parentObj->oAction == FISH_SPAWNER_ACT_RESPAWN) {
if (!o->parentObj || o->parentObj->oAction == FISH_SPAWNER_ACT_RESPAWN) {
obj_mark_for_deletion(o);
}
}

View file

@ -20,9 +20,9 @@ void bhv_flamethrower_flame_loop(void) {
o->oVelY = 0;
o->oPosY = o->oFloorHeight + 25.0f * size;
}
sp18 = o->parentObj->oFlameThowerFlameUnk110 / 1.2;
sp18 = o->parentObj ? o->parentObj->oFlameThowerFlameUnk110 / 1.2 : 0;
} else
sp18 = o->parentObj->oFlameThowerFlameUnk110;
sp18 = o->parentObj ? o->parentObj->oFlameThowerFlameUnk110 : 0;
cur_obj_scale(size);
if (o->oBehParams2ndByte == 4)
o->oPosY += o->oForwardVel; // weird?

View file

@ -336,6 +336,7 @@ void bhv_book_switch_loop(void) {
o->header.gfx.scale[0] = 2.0f;
o->header.gfx.scale[1] = 0.9f;
if (!o->parentObj) { return; }
if (o->parentObj->oAction == 4) {
obj_mark_for_deletion(o);

View file

@ -138,12 +138,9 @@ static void goomba_begin_jump(void) {
* comes back.
*/
void mark_goomba_as_dead(void) {
if (o->parentObj != o) {
set_object_respawn_info_bits(o->parentObj,
(o->oBehParams2ndByte & GOOMBA_BP_TRIPLET_FLAG_MASK) >> 2);
o->parentObj->oBehParams =
o->parentObj->oBehParams | (o->oBehParams2ndByte & GOOMBA_BP_TRIPLET_FLAG_MASK) << 6;
if (o->parentObj && o->parentObj != o) {
set_object_respawn_info_bits(o->parentObj, (o->oBehParams2ndByte & GOOMBA_BP_TRIPLET_FLAG_MASK) >> 2);
o->parentObj->oBehParams = o->parentObj->oBehParams | (o->oBehParams2ndByte & GOOMBA_BP_TRIPLET_FLAG_MASK) << 6;
}
}
@ -282,7 +279,7 @@ void bhv_goomba_update(void) {
if (obj_update_standard_actions(o->oGoombaScale)) {
// If this goomba has a spawner and mario moved away from the spawner,
// unload
if (o->parentObj != o) {
if (o->parentObj && o->parentObj != o) {
if (o->parentObj->oAction == GOOMBA_TRIPLET_SPAWNER_ACT_UNLOADED) {
obj_mark_for_deletion(o);
}

View file

@ -5,7 +5,7 @@ struct OpenableGrill gOpenableGrills[] = { { 320, MODEL_BOB_BARS_GRILLS, bob_seg
void bhv_openable_cage_door_loop(void) {
if (gCurrentObject->oAction == 0) {
if (gCurrentObject->parentObj->oOpenableGrillUnk88 != 0)
if (gCurrentObject->parentObj && gCurrentObject->parentObj->oOpenableGrillUnk88 != 0)
gCurrentObject->oAction++;
} else if (gCurrentObject->oAction == 1) {
if (gCurrentObject->oTimer < 64)
@ -21,18 +21,20 @@ void bhv_openable_grill_loop(void) {
switch (o->oAction) {
case 0:
grillIdx = o->oBehParams2ndByte;
grillObj = spawn_object_relative(-1, gOpenableGrills[grillIdx].halfWidth, 0, 0, o, gOpenableGrills[grillIdx].modelID,
bhvOpenableCageDoor);
if (grillObj != NULL) {
grillObj->oMoveAngleYaw += 0x8000;
obj_set_collision_data(grillObj, gOpenableGrills[grillIdx].collision);
if (BHV_ARR_CHECK(gOpenableGrills, grillIdx, struct OpenableGrill)) {
grillObj = spawn_object_relative(-1, gOpenableGrills[grillIdx].halfWidth, 0, 0, o, gOpenableGrills[grillIdx].modelID,
bhvOpenableCageDoor);
if (grillObj != NULL) {
grillObj->oMoveAngleYaw += 0x8000;
obj_set_collision_data(grillObj, gOpenableGrills[grillIdx].collision);
}
grillObj = spawn_object_relative(1, -gOpenableGrills[grillIdx].halfWidth, 0, 0, o, gOpenableGrills[grillIdx].modelID,
bhvOpenableCageDoor);
if (grillObj != NULL) {
obj_set_collision_data(grillObj, gOpenableGrills[grillIdx].collision);
}
o->oAction++;
}
grillObj = spawn_object_relative(1, -gOpenableGrills[grillIdx].halfWidth, 0, 0, o, gOpenableGrills[grillIdx].modelID,
bhvOpenableCageDoor);
if (grillObj != NULL) {
obj_set_collision_data(grillObj, gOpenableGrills[grillIdx].collision);
}
o->oAction++;
break;
case 1:
if ((o->oOpenableGrillUnkF4 = cur_obj_nearest_object_with_behavior(bhvFloorSwitchGrills))
@ -41,7 +43,7 @@ void bhv_openable_grill_loop(void) {
break;
case 2:
grillObj = o->oOpenableGrillUnkF4;
if (grillObj->oAction == 2) {
if (grillObj && grillObj->oAction == 2) {
o->oOpenableGrillUnk88 = 2;
cur_obj_play_sound_2(SOUND_GENERAL_CAGE_OPEN);
o->oAction++;

View file

@ -25,7 +25,9 @@ void spawn_smoke_with_velocity(void) {
// TODO Fix name
void clear_particle_flags(u32 flags) {
o->parentObj->oActiveParticleFlags &= flags ^ -1; // Clear the flags given (could just be ~flags)
if (o->parentObj) {
o->parentObj->oActiveParticleFlags &= flags ^ -1; // Clear the flags given (could just be ~flags)
}
}
void bhv_ground_snow_init(void) {

View file

@ -11,24 +11,26 @@ void bhv_heave_ho_throw_mario_loop(void) {
o->oParentRelativePosX = 200.0f;
o->oParentRelativePosY = -50.0f;
o->oParentRelativePosZ = 0.0f;
o->oMoveAngleYaw = o->parentObj->oMoveAngleYaw;
switch (o->parentObj->oHeaveHoUnk88) {
case 0:
break;
case 1:
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;
if (o->parentObj) {
o->oMoveAngleYaw = o->parentObj->oMoveAngleYaw;
switch (o->parentObj->oHeaveHoUnk88) {
case 0:
break;
case 1:
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;
}
}
}

View file

@ -366,7 +366,7 @@ void king_bobomb_move(void) {
else
cur_obj_move_using_fvel_and_gravity();
CUR_OBJ_CALL_ACTION_FUNCTION(sKingBobombActions);
exec_anim_sound_state(sKingBobombSoundStates);
exec_anim_sound_state(sKingBobombSoundStates, sizeof(sKingBobombSoundStates) / sizeof(struct SoundState));
s32 distanceToPlayer = dist_between_objects(o, gMarioStates[0].marioObj);
if (distanceToPlayer < 5000.0f * draw_distance_scalar())
cur_obj_enable_rendering();

View file

@ -587,7 +587,7 @@ s32 obj_begin_race(s32 noTimer) {
level_control_timer(TIMER_CONTROL_SHOW);
level_control_timer(TIMER_CONTROL_START);
o->parentObj->oKoopaRaceEndpointRaceBegun = TRUE;
if (o->parentObj) { o->parentObj->oKoopaRaceEndpointRaceBegun = TRUE; }
}
// Unfreeze mario and disable time stop to begin the race
@ -630,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 (marioState && should_start_or_continue_dialog(marioState, o)) {
if (marioState && should_start_or_continue_dialog(marioState, o) && BHV_ARR_CHECK(sKoopaTheQuickProperties, o->oKoopaTheQuickRaceIndex, struct KoopaTheQuickProperties)) {
response = obj_update_race_proposition_dialog(&gMarioStates[0], *sKoopaTheQuickProperties[o->oKoopaTheQuickRaceIndex].initText, koopa_the_quick_act_show_init_text_continue_dialog);
}
@ -738,7 +738,7 @@ static void koopa_the_quick_act_race(void) {
struct Object* player = nearest_player_to_object(o);
s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000;
if (o->parentObj->oKoopaRaceEndpointRaceStatus != 0 && distanceToPlayer > 1500.0f
if (o->parentObj && o->parentObj->oKoopaRaceEndpointRaceStatus != 0 && distanceToPlayer > 1500.0f
&& (o->oPathedPrevWaypointFlags & WAYPOINT_MASK_00FF) < 28) {
// Move faster if mario has already finished the race or
// cheated by shooting from cannon
@ -840,6 +840,7 @@ static void koopa_the_quick_act_after_race(void) {
cur_obj_init_animation_with_sound(7);
struct MarioState* marioState = nearest_mario_state_to_object(o);
if (!o->parentObj) { return; }
if (o->parentObj->oKoopaRaceEndpointUnk100 == 0) {
if (marioState == &gMarioStates[0] && cur_obj_can_mario_activate_textbox_2(&gMarioStates[0], 400.0f, 400.0f)) {
@ -913,7 +914,7 @@ static void koopa_the_quick_update(void) {
break;
}
if (o->parentObj != o) {
if (o->parentObj != o && o->parentObj) {
if (dist_between_objects(o, o->parentObj) < 400.0f) {
o->parentObj->oKoopaRaceEndpointKoopaFinished = TRUE;
}

View file

@ -10,7 +10,7 @@ void bhv_lll_wood_piece_loop(void) {
o->oPosY -= 100.0f;
o->oPosY += sins(o->oLllWoodPieceOscillationTimer) * 3.0f;
o->oLllWoodPieceOscillationTimer += 0x400;
if (o->parentObj->oAction == 2)
if (o->parentObj && o->parentObj->oAction == 2)
obj_mark_for_deletion(o);
}

View file

@ -8,6 +8,7 @@ s16 *D_8032F8C8[] = { D_8032F860, D_8032F894 };
s32 lll_octagonal_mesh_move(s16 *a0, s32 a1) {
if (!BHV_ARR_CHECK(D_8032F860, a1, s16)) { return 0; }
switch (a0[a1]) {
case 4:
o->oMoveAngleYaw = a0[a1 + 2];
@ -70,9 +71,9 @@ void bhv_lll_moving_octagonal_mesh_platform_loop(void) {
if (o->oAction == 0) {
o->oHorizontalMovementUnkF8 = 0;
o->oAction++;
} else
o->oHorizontalMovementUnkF8 =
lll_octagonal_mesh_move(D_8032F8C8[o->oBehParams2ndByte], o->oHorizontalMovementUnkF8);
} else if (BHV_ARR_CHECK(D_8032F8C8, o->oBehParams2ndByte, s16*)) {
o->oHorizontalMovementUnkF8 = lll_octagonal_mesh_move(D_8032F8C8[o->oBehParams2ndByte], o->oHorizontalMovementUnkF8);
}
print_debug_top_down_objectinfo("number %d\n", o->oHorizontalMovementUnkF8);
cur_obj_move_using_fvel_and_gravity();
if (lll_octagonal_mesh_find_y_offset(&o->oHorizontalMovementUnk104, &o->oHorizontalMovementUnk108, 0x400, -80)) {

View file

@ -4,10 +4,15 @@ void bhv_lll_rotating_hex_flame_loop(void) {
f32 sp24 = o->oLllRotatingHexFlameUnkF4;
f32 sp20 = o->oLllRotatingHexFlameUnkF8;
f32 sp1C = o->oLllRotatingHexFlameUnkFC;
cur_obj_set_pos_relative(o->parentObj, sp24, sp20, sp1C);
o->oPosY = o->parentObj->oPosY + 100.0f;
if (o->parentObj->oAction == 3)
if (o->parentObj) {
cur_obj_set_pos_relative(o->parentObj, sp24, sp20, sp1C);
o->oPosY = o->parentObj->oPosY + 100.0f;
if (o->parentObj->oAction == 3)
obj_mark_for_deletion(o);
} else {
obj_mark_for_deletion(o);
}
}
void fire_bar_spawn_flames(s16 a0) {

View file

@ -146,12 +146,14 @@ void bhv_mips_act_wait_for_nearby_mario(void) {
void bhv_mips_act_follow_path(void) {
s16 collisionFlags = 0;
s32 followStatus = 0;
struct Waypoint ***pathBase;
struct Waypoint **pathBase;
struct Waypoint *waypoint;
// Retrieve current waypoint.
pathBase = segmented_to_virtual(sMipsPaths);
waypoint = segmented_to_virtual(*(*pathBase + o->oMipsStartWaypointIndex));
pathBase = segmented_to_virtual(sMipsPaths[0]);
s32 length = get_trajectory_length((Trajectory*)pathBase);
if (o->oMipsStartWaypointIndex >= length) { return; }
waypoint = segmented_to_virtual(pathBase[o->oMipsStartWaypointIndex]);
// Set start waypoint and follow the path from there.
o->oPathedStartWaypoint = waypoint;

View file

@ -2,8 +2,10 @@
void bhv_invisible_objects_under_bridge_init(void) {
if (save_file_get_flags() & SAVE_FLAG_MOAT_DRAINED) {
gEnvironmentRegions[6] = -800;
gEnvironmentRegions[12] = -800;
if (gEnvironmentRegions) {
gEnvironmentRegions[6] = -800;
gEnvironmentRegions[12] = -800;
}
o->oAction = 2;
} else {
o->oAction = 0;
@ -18,12 +20,14 @@ void bhv_invisible_objects_under_bridge_loop(void) {
break;
case 1:
// approach -800
gEnvironmentRegions[6] = (s16)approach_f32_symmetric(gEnvironmentRegions[6], -800, 5.0f);
gEnvironmentRegions[12] = (s16)approach_f32_symmetric(gEnvironmentRegions[12], -800, 5.0f);
if (gEnvironmentRegions[6] <= -795 && gEnvironmentRegions[12] <= -795) {
gEnvironmentRegions[6] = -800;
gEnvironmentRegions[12] = -800;
o->oAction = 2;
if (gEnvironmentRegions) {
gEnvironmentRegions[6] = (s16)approach_f32_symmetric(gEnvironmentRegions[6], -800, 5.0f);
gEnvironmentRegions[12] = (s16)approach_f32_symmetric(gEnvironmentRegions[12], -800, 5.0f);
if (gEnvironmentRegions[6] <= -795 && gEnvironmentRegions[12] <= -795) {
gEnvironmentRegions[6] = -800;
gEnvironmentRegions[12] = -800;
o->oAction = 2;
}
}
break;
case 2:

View file

@ -196,7 +196,9 @@ void bhv_moneybag_loop(void) {
o->oOpacity += 12;
if (o->oOpacity >= 256) {
o->oOpacity = 255;
o->parentObj->activeFlags = ACTIVE_FLAG_DEACTIVATED;
if (o->parentObj) {
o->parentObj->activeFlags = ACTIVE_FLAG_DEACTIVATED;
}
o->oAction = MONEYBAG_ACT_MOVE_AROUND;
}
break;

View file

@ -64,6 +64,7 @@ static struct Object *monty_mole_select_available_hole(f32 minDistToMario) {
struct Object *hole = sMontyMoleHoleList;
s32 numAvailableHoles = 0;
s32 sanity = 0;
while (hole != NULL) {
player = nearest_player_to_object(hole);
@ -74,6 +75,8 @@ static struct Object *monty_mole_select_available_hole(f32 minDistToMario) {
}
}
if (sanity++ > 100) { break; }
if (hole == hole->parentObj) { break; }
hole = hole->parentObj;
}

View file

@ -436,7 +436,7 @@ void bhv_mr_blizzard_update(void) {
static void mr_blizzard_snowball_act_0(void) {
cur_obj_move_using_fvel_and_gravity();
if (o->parentObj->prevObj == o) {
if (o->parentObj && o->parentObj->prevObj == o) {
o->oAction = 1;
o->oParentRelativePosX = 190.0f;
o->oParentRelativePosY = o->oParentRelativePosZ = -38.0f;
@ -453,7 +453,7 @@ static void mr_blizzard_snowball_act_1(void) {
f32 marioDist;
if (o->parentObj->prevObj == NULL) {
if (o->parentObj && o->parentObj->prevObj == NULL) {
if (o->parentObj->oAction == MR_BLIZZARD_ACT_THROW_SNOWBALL) {
marioDist = distanceToPlayer;
if (marioDist > 800.0f) {

View file

@ -54,6 +54,10 @@ void spawn_mr_i_particle(void) {
}
void bhv_mr_i_body_loop(void) {
if (!o->parentObj) {
obj_mark_for_deletion(o);
return;
}
obj_copy_pos_and_angle(o, o->parentObj);
if (!(o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM)) {
obj_copy_scale(o, o->parentObj);

View file

@ -93,10 +93,13 @@ void bhv_platform_on_track_init(void) {
o->oPlatformOnTrackIsNotSkiLift = o->oPlatformOnTrackType - PLATFORM_ON_TRACK_TYPE_SKI_LIFT;
o->collisionData =
segmented_to_virtual(sPlatformOnTrackCollisionModels[o->oPlatformOnTrackType]);
if (BHV_ARR_CHECK(sPlatformOnTrackCollisionModels, o->oPlatformOnTrackType, void const *)) {
o->collisionData = segmented_to_virtual(sPlatformOnTrackCollisionModels[o->oPlatformOnTrackType]);
}
o->oPlatformOnTrackStartWaypoint = segmented_to_virtual(*sPlatformOnTrackPaths[pathIndex]);
if (BHV_ARR_CHECK(sPlatformOnTrackPaths, pathIndex, Trajectory**)) {
o->oPlatformOnTrackStartWaypoint = segmented_to_virtual(*sPlatformOnTrackPaths[pathIndex]);
}
o->oPlatformOnTrackIsNotHMC = pathIndex - 4;
@ -353,8 +356,9 @@ void bhv_platform_on_track_update(void) {
*/
void bhv_track_ball_update(void) {
// Despawn after the elevator passes this ball
s16 relativeIndex =
(s16) o->oBehParams2ndByte - (s16) o->parentObj->oPlatformOnTrackBaseBallIndex - 1;
s16 relativeIndex = o->parentObj ?
((s16) o->oBehParams2ndByte - (s16) o->parentObj->oPlatformOnTrackBaseBallIndex - 1)
: 0;
if (relativeIndex < 1 || relativeIndex > 5) {
obj_mark_for_deletion(o);
}

View file

@ -157,7 +157,9 @@ void bhv_pyramid_pillar_touch_detector_loop(void) {
cur_obj_become_tangible();
if ((o->oInteractStatus & INT_STATUS_INTERACTED) || obj_check_if_collided_with_object(o, gMarioStates[0].marioObj) == 1) {
// Increase the pyramid top's count of pillars touched.
o->parentObj->oPyramidTopPillarsTouched++;
if (o->parentObj) {
o->parentObj->oPyramidTopPillarsTouched++;
}
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
if (!(o->oInteractStatus & INT_STATUS_INTERACTED)) {
network_send_collect_item(o);

View file

@ -31,9 +31,11 @@ void bhv_racing_penguin_the_quick_override_ownership(u8* shouldOverride, u8* sho
void bhv_racing_penguin_run_once(void) {
cur_obj_align_gfx_with_floor();
cur_obj_push_mario_away_from_cylinder(
*sRacingPenguinData[o->oBehParams2ndByte].radius,
*sRacingPenguinData[o->oBehParams2ndByte].height);
if (BHV_ARR_CHECK(sRacingPenguinData, o->oBehParams2ndByte, struct RacingPenguinData)) {
cur_obj_push_mario_away_from_cylinder(
*sRacingPenguinData[o->oBehParams2ndByte].radius,
*sRacingPenguinData[o->oBehParams2ndByte].height);
}
}
void bhv_racing_penguin_init(void) {
@ -44,10 +46,10 @@ void bhv_racing_penguin_init(void) {
}
struct Object* objFinishLine = cur_obj_nearest_object_with_behavior(bhvPenguinRaceFinishLine);
objFinishLine->parentObj = o;
if (objFinishLine) { objFinishLine->parentObj = o; }
struct Object* objShortcutCheck = cur_obj_nearest_object_with_behavior(bhvPenguinRaceShortcutCheck);
objShortcutCheck->parentObj = o;
if (objShortcutCheck) { objShortcutCheck->parentObj = o; }
struct SyncObject* so = sync_object_init(o, SYNC_DISTANCE_ONLY_EVENTS);
if (so) {
@ -95,6 +97,7 @@ u8 racing_penguin_act_show_init_text_continue_dialog(void) { return o->oAction =
static void racing_penguin_act_show_init_text(void) {
if (!gMarioStates[0].visibleToEnemies) { return; }
if (!BHV_ARR_CHECK(sRacingPenguinData, o->oBehParams2ndByte, struct RacingPenguinData)) { 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) {
@ -136,12 +139,12 @@ static void racing_penguin_act_race(void) {
// prevent segfault / error state
if (o->oPathedStartWaypoint == NULL) {
struct Object* child;
struct Object* child = NULL;
child = cur_obj_nearest_object_with_behavior(bhvPenguinRaceFinishLine);
child->parentObj = o;
if (child) { child->parentObj = o; }
child = cur_obj_nearest_object_with_behavior(bhvPenguinRaceShortcutCheck);
child->parentObj = o;
if (child) { child->parentObj = o; }
o->oPathedStartWaypoint = o->oPathedPrevWaypoint = segmented_to_virtual(gBehaviorValues.trajectories.RacingPenguinTrajectory);
o->oPathedPrevWaypointFlags = 0;
@ -295,6 +298,9 @@ void bhv_racing_penguin_update(void) {
void bhv_penguin_race_finish_line_update(void) {
struct Object* player = nearest_player_to_object(o);
s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000;
if (!o->parentObj) {
return;
}
if (o->parentObj->oRacingPenguinReachedBottom
|| (player && distanceToPlayer < 1000.0f && player->oPosZ - o->oPosZ < 0.0f)) {
@ -308,7 +314,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 = player ? dist_between_objects(o, player) : 10000;
if (distanceToPlayer < 500.0f && !o->parentObj->oRacingPenguinMarioCheated) {
if (distanceToPlayer < 500.0f && o->parentObj && !o->parentObj->oRacingPenguinMarioCheated) {
o->parentObj->oRacingPenguinMarioCheated = TRUE;
network_send_object(o->parentObj);
}

View file

@ -8,8 +8,10 @@ void const *D_80331A44[] = {
s16 D_80331A4C[] = { 300, -300, 600, -600 };
void bhv_rotating_octagonal_plat_init(void) {
o->collisionData = segmented_to_virtual(D_80331A44[(u8)(o->oBehParams >> 16)]);
o->oAngleVelYaw = D_80331A4C[(u8)(o->oBehParams >> 24)];
if (BHV_ARR_CHECK(D_80331A44, (u8)(o->oBehParams >> 16), void const*)) {
o->collisionData = segmented_to_virtual(D_80331A44[(u8)(o->oBehParams >> 16)]);
}
o->oAngleVelYaw = BHV_ARR(D_80331A4C, (u8)(o->oBehParams >> 24), s16);
}
void bhv_rotating_octagonal_plat_loop(void) {

View file

@ -39,7 +39,7 @@ void bhv_wf_rotating_wooden_platform_loop(void) {
void bhv_rotating_platform_loop(void) {
s8 sp1F = o->oBehParams >> 24;
if (o->oTimer == 0) {
if (o->oTimer == 0 && BHV_ARR_CHECK(sWFRotatingPlatformData, o->oBehParams2ndByte, struct WFRotatingPlatformData)) {
obj_set_collision_data(o, sWFRotatingPlatformData[o->oBehParams2ndByte].collisionData);
o->oCollisionDistance = sWFRotatingPlatformData[o->oBehParams2ndByte].collisionDistance;
cur_obj_scale(sWFRotatingPlatformData[o->oBehParams2ndByte].scale * 0.01f);

View file

@ -129,7 +129,7 @@ void bhv_scuttlebug_loop(void) {
if (o->parentObj != o) {
if (obj_is_hidden(o))
obj_mark_for_deletion(o);
if (o->activeFlags == ACTIVE_FLAG_DEACTIVATED) {
if (o->activeFlags == ACTIVE_FLAG_DEACTIVATED && o->parentObj) {
o->parentObj->oScuttlebugSpawnerUnk88 = 1;
network_send_object(o->parentObj);
}

View file

@ -16,7 +16,9 @@ static void const *sSeesawPlatformCollisionModels[] = {
* Init function for bhvSeesawPlatform.
*/
void bhv_seesaw_platform_init(void) {
o->collisionData = segmented_to_virtual(sSeesawPlatformCollisionModels[o->oBehParams2ndByte]);
if (BHV_ARR_CHECK(sSeesawPlatformCollisionModels, o->oBehParams2ndByte, void const*)) {
o->collisionData = segmented_to_virtual(sSeesawPlatformCollisionModels[o->oBehParams2ndByte]);
}
// The S-shaped seesaw platform in BitS is large, so increase its collision
// distance

View file

@ -22,11 +22,11 @@ static s32 sl_walking_penguin_turn(void) {
// Stay still and use walking animation for the turn.
o->oForwardVel = 0.0f;
cur_obj_init_animation_with_accel_and_sound(PENGUIN_ANIM_WALK, 1.0f);
// Turn around.
o->oAngleVelYaw = 0x400;
o->oMoveAngleYaw += o->oAngleVelYaw;
if (o->oTimer == 31)
return TRUE; // Finished turning
else
@ -52,7 +52,7 @@ void bhv_sl_walking_penguin_loop(void) {
o->oAngleVelYaw = 0;
cur_obj_update_floor_and_walls();
switch (o->oAction) {
// Walk erratically across the ice bridge using preset steps.
case SL_WALKING_PENGUIN_ACT_MOVING_FORWARDS:
@ -61,68 +61,69 @@ void bhv_sl_walking_penguin_loop(void) {
o->oSLWalkingPenguinCurStep = 0;
o->oSLWalkingPenguinCurStepTimer = 0;
}
if (o->oSLWalkingPenguinCurStepTimer < sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].stepLength)
o->oSLWalkingPenguinCurStepTimer++;
else {
// Move to next step
o->oSLWalkingPenguinCurStepTimer = 0;
o->oSLWalkingPenguinCurStep++;
if (sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].stepLength < 0)
// Reached the end of the list, go back to the start
o->oSLWalkingPenguinCurStep = 0;
}
if (o->oPosX < 300.0f)
o->oAction++; // If reached the end of the bridge, turn around and head back.
else {
// Move and animate the penguin
o->oForwardVel = sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].speed;
cur_obj_init_animation_with_accel_and_sound(
sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].anim,
sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].animSpeed
);
if (BHV_ARR_CHECK(sSLWalkingPenguinErraticSteps, o->oSLWalkingPenguinCurStep, struct SLWalkingPenguinStep)) {
if (o->oSLWalkingPenguinCurStepTimer < sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].stepLength)
o->oSLWalkingPenguinCurStepTimer++;
else {
// Move to next step
o->oSLWalkingPenguinCurStepTimer = 0;
o->oSLWalkingPenguinCurStep++;
if (sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].stepLength < 0)
// Reached the end of the list, go back to the start
o->oSLWalkingPenguinCurStep = 0;
}
if (o->oPosX < 300.0f)
o->oAction++; // If reached the end of the bridge, turn around and head back.
else {
// Move and animate the penguin
o->oForwardVel = sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].speed;
cur_obj_init_animation_with_accel_and_sound(
sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].anim,
sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].animSpeed
);
}
}
break;
// At the end, turn around and prepare to head back across the bridge.
case SL_WALKING_PENGUIN_ACT_TURNING_BACK:
if (sl_walking_penguin_turn())
o->oAction++; // Finished turning
break;
// Walk back across the bridge at a constant speed.
case SL_WALKING_PENGUIN_ACT_RETURNING:
// Move and animate the penguin
o->oForwardVel = 12.0f;
cur_obj_init_animation_with_accel_and_sound(PENGUIN_ANIM_WALK, 2.0f);
if (o->oPosX > 1700.0f)
o->oAction++; // If reached the start of the bridge, turn around.
break;
// At the start, turn around and prepare to walk erratically across the bridge.
case SL_WALKING_PENGUIN_ACT_TURNING_FORWARDS:
if (sl_walking_penguin_turn())
o->oAction = SL_WALKING_PENGUIN_ACT_MOVING_FORWARDS; // Finished turning
break;
}
cur_obj_move_standard(-78);
if (!cur_obj_hide_if_mario_far_away_y(1000.0f))
play_penguin_walking_sound(PENGUIN_WALK_BIG);
// Adjust the position to get a point better lined up with the visual model, for stopping the wind.
// The new point is 60 units behind the penguin and 100 units perpedicularly, away from the snowman.
adjustedXPos = o->oPosX + sins(0xDBB0) * 60.0f; // 0xDBB0 = -51 degrees, the angle the penguin is facing
adjustedZPos = o->oPosZ + coss(0xDBB0) * 60.0f;
adjustedXPos += perpendicularOffset * sins(0x1BB0); // 0x1BB0 = 39 degrees, perpendicular to the penguin
adjustedZPos += perpendicularOffset * coss(0x1BB0);
o->oSLWalkingPenguinWindCollisionXPos = adjustedXPos;
o->oSLWalkingPenguinWindCollisionZPos = adjustedZPos;
print_debug_bottom_up("x %d", o->oPosX);
print_debug_bottom_up("z %d", o->oPosZ);
}

View file

@ -256,6 +256,10 @@ void bhv_snowmans_head_loop(void) {
}
void bhv_snowmans_body_checkpoint_loop(void) {
if (!o->parentObj) {
return;
}
if (is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 800)) {
o->parentObj->oSnowmansBottomUnk1AC++;
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;

View file

@ -13,8 +13,9 @@ struct ObjectHitbox sSparkleSpawnStarHitbox = {
};
void bhv_spawned_star_init(void) {
if (!(o->oInteractionSubtype & INT_SUBTYPE_NO_EXIT))
if (!(o->oInteractionSubtype & INT_SUBTYPE_NO_EXIT) && o->parentObj) {
o->oBehParams = o->parentObj->oBehParams;
}
s32 sp24 = (o->oBehParams >> 24) & 0xFF;
if (bit_shift_left(sp24) & save_file_get_star_flags(gCurrSaveFileNum - 1, gCurrCourseNum - 1))
cur_obj_set_model(smlua_model_util_load(E_MODEL_TRANSPARENT_STAR));

View file

@ -41,7 +41,7 @@ void bhv_thi_tiny_island_top_loop(void) {
}
} else {
if (o->oTimer < 50) {
gEnvironmentRegions[18]--;
if (gEnvironmentRegions) { gEnvironmentRegions[18]--; }
cur_obj_play_sound_1(SOUND_ENV_WATER_DRAIN);
} else {
gTHIWaterDrained |= 1;
@ -50,8 +50,9 @@ void bhv_thi_tiny_island_top_loop(void) {
}
}
} else {
if (o->oTimer == 0)
gEnvironmentRegions[18] = 700;
if (o->oTimer == 0) {
if (gEnvironmentRegions) { gEnvironmentRegions[18] = 700; }
}
cur_obj_hide();
}
}

View file

@ -1,6 +1,7 @@
// tower_platform.c.inc
void bhv_wf_solid_tower_platform_loop(void) {
if (!o->parentObj) { return; }
if (o->parentObj->oAction == 1) {
cur_obj_become_tangible();
o->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
@ -45,12 +46,14 @@ void bhv_wf_elevator_tower_platform_loop(void) {
break;
}
if (o->parentObj->oAction == 1) {
cur_obj_become_tangible();
o->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
} else if (o->parentObj->oAction > 1) {
cur_obj_become_intangible();
o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
if (o->parentObj) {
if (o->parentObj->oAction == 1) {
cur_obj_become_tangible();
o->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
} else if (o->parentObj->oAction > 1) {
cur_obj_become_intangible();
o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
}
}
}
@ -73,12 +76,14 @@ void bhv_wf_sliding_tower_platform_loop(void) {
o->oPosX += o->oVelX;
o->oPosZ += o->oVelZ;
if (o->parentObj->oAction == 1) {
cur_obj_become_tangible();
o->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
} else if (o->parentObj->oAction > 1) {
cur_obj_become_intangible();
o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
if (o->parentObj) {
if (o->parentObj->oAction == 1) {
cur_obj_become_tangible();
o->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
} else if (o->parentObj->oAction > 1) {
cur_obj_become_intangible();
o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
}
}
}

View file

@ -66,6 +66,7 @@ void tox_box_act_3(void) {
}
void tox_box_act_0(void) {
if (!BHV_ARR_CHECK(D_8032F96C, o->oBehParams2ndByte, s8*)) { return; }
s8 *sp1C = D_8032F96C[o->oBehParams2ndByte];
o->oAction = cur_obj_set_direction_table(sp1C);
}

View file

@ -17,6 +17,10 @@ static struct ObjectHitbox sTreasureChestBottomHitbox = {
void bhv_treasure_chest_top_loop(void) {
if (!o->parentObj || !o->parentObj->parentObj) {
obj_mark_for_deletion(o);
return;
}
struct Object *rootParent = o->parentObj->parentObj;
switch (o->oAction) {
@ -67,6 +71,7 @@ void bhv_treasure_chest_bottom_init(void) {
}
void bhv_treasure_chest_bottom_loop(void) {
if (!o->parentObj) { return; }
if (o->parentObj != NULL && o->parentObj->oTreasureChestSound != 0) {
switch (o->parentObj->oTreasureChestSound) {
case 1: play_sound(SOUND_GENERAL2_RIGHT_ANSWER, gGlobalSoundSource); break;

View file

@ -36,10 +36,12 @@ static void triplet_butterfly_act_init(void) {
}
//! TODO: Describe this glitch
if (o->parentObj->oTripletButterflySelectedButterfly == o->oBehParams2ndByte) {
o->oTripletButterflyType = TRIPLET_BUTTERFLY_TYPE_SPAWN_1UP;
} else if (o->parentObj->oBehParams2ndByte & TRIPLET_BUTTERFLY_BP_NO_BOMBS) {
o->oTripletButterflyType = TRIPLET_BUTTERFLY_TYPE_NORMAL;
if (o->parentObj) {
if (o->parentObj->oTripletButterflySelectedButterfly == o->oBehParams2ndByte) {
o->oTripletButterflyType = TRIPLET_BUTTERFLY_TYPE_SPAWN_1UP;
} else if (o->parentObj->oBehParams2ndByte & TRIPLET_BUTTERFLY_BP_NO_BOMBS) {
o->oTripletButterflyType = TRIPLET_BUTTERFLY_TYPE_NORMAL;
}
}
// Default butterfly type is TRIPLET_BUTTERFLY_TYPE_EXPLODES
@ -82,6 +84,7 @@ static void triplet_butterfly_act_wander(void) {
}
static void triplet_butterfly_act_activate(void) {
if (!BHV_ARR_CHECK(sTripletButterflyActivationData, o->oTripletButterflyType, struct TripletButterflyActivationData)) { return; }
if (o->oTimer > 20) {
if (o->oTripletButterflyModel == 0) {
spawn_object_relative_with_scale(0, 0, -40, 0, 1.5f, o, MODEL_SMOKE, bhvWhitePuffSmoke2);
@ -90,8 +93,7 @@ static void triplet_butterfly_act_activate(void) {
obj_set_billboard(o);
o->oTripletButterflyScale = 0.0f;
o->oHomeY = o->oPosY;
} else if (o->oTripletButterflyScale
>= sTripletButterflyActivationData[o->oTripletButterflyType].scale) {
} else if (o->oTripletButterflyScale >= sTripletButterflyActivationData[o->oTripletButterflyType].scale) {
if (o->oTripletButterflyType != TRIPLET_BUTTERFLY_TYPE_EXPLODES) {
spawn_object(o, o->oTripletButterflyModel,
sTripletButterflyActivationData[o->oTripletButterflyType].behavior);
@ -102,8 +104,7 @@ static void triplet_butterfly_act_activate(void) {
}
}
o->oTripletButterflyScale +=
sTripletButterflyActivationData[o->oTripletButterflyType].scale / 30.0f;
o->oTripletButterflyScale += sTripletButterflyActivationData[o->oTripletButterflyType].scale / 30.0f;
if (o->oTripletButterflyType == TRIPLET_BUTTERFLY_TYPE_EXPLODES) {
o->oGraphYOffset = 250.0f * o->oTripletButterflyScale;
o->oPosY = o->oHomeY - o->oGraphYOffset;

View file

@ -37,9 +37,10 @@ static s16 sTTC2DRotatorTimeBetweenTurns[][4] = {
* Init function for bhvTTC2DRotator.
*/
void bhv_ttc_2d_rotator_init(void) {
o->oTTC2DRotatorMinTimeUntilNextTurn =
sTTC2DRotatorTimeBetweenTurns[o->oBehParams2ndByte][gTTCSpeedSetting];
o->oTTC2DRotatorIncrement = o->oTTC2DRotatorSpeed = sTTC2DRotatorSpeeds[o->oBehParams2ndByte];
if (o->oBehParams2ndByte < 2 && gTTCSpeedSetting < 4) {
o->oTTC2DRotatorMinTimeUntilNextTurn = sTTC2DRotatorTimeBetweenTurns[o->oBehParams2ndByte][gTTCSpeedSetting];
o->oTTC2DRotatorIncrement = o->oTTC2DRotatorSpeed = sTTC2DRotatorSpeeds[o->oBehParams2ndByte];
}
struct SyncObject* so = sync_object_init(o, 4000.0f);
if (so) {

View file

@ -37,7 +37,9 @@ static struct TTCPitBlockProperties sTTCPitBlockProperties[][2] = {
* Init function for bhvTTCPitBlock.
*/
void bhv_ttc_pit_block_init(void) {
o->collisionData = segmented_to_virtual(sTTCPitBlockCollisionModels[o->oBehParams2ndByte]);
if (BHV_ARR_CHECK(sTTCPitBlockCollisionModels, o->oBehParams2ndByte, Collision const *)) {
o->collisionData = segmented_to_virtual(sTTCPitBlockCollisionModels[o->oBehParams2ndByte]);
}
o->oTTCPitBlockPeakY = o->oPosY + 330.0f;
@ -65,13 +67,15 @@ void bhv_ttc_pit_block_update(void) {
if (clamp_f32(&o->oPosY, o->oHomeY, o->oTTCPitBlockPeakY)) {
o->oTTCPitBlockDir = o->oTTCPitBlockDir ^ 0x1;
if ((o->oTTCPitBlockWaitTime =
sTTCPitBlockProperties[gTTCSpeedSetting][o->oTTCPitBlockDir & 0x1].waitTime)
< 0) {
o->oTTCPitBlockWaitTime = random_mod_offset(10, 20, 6);
}
if (gTTCSpeedSetting < 4) {
if ((o->oTTCPitBlockWaitTime = sTTCPitBlockProperties[gTTCSpeedSetting][o->oTTCPitBlockDir & 0x1].waitTime) < 0) {
o->oTTCPitBlockWaitTime = random_mod_offset(10, 20, 6);
}
o->oVelY = sTTCPitBlockProperties[gTTCSpeedSetting][o->oTTCPitBlockDir].speed;
if (o->oTTCPitBlockDir < 2) {
o->oVelY = sTTCPitBlockProperties[gTTCSpeedSetting][o->oTTCPitBlockDir].speed;
}
}
o->oTimer = 0;
}
}

View file

@ -26,7 +26,9 @@ static u8 sTTCRotatingSolidInitialDelays[] = {
* Init function for bhvTTCRotatingSolid.
*/
void bhv_ttc_rotating_solid_init(void) {
o->collisionData = segmented_to_virtual(sTTCRotatingSolidCollisionModels[o->oBehParams2ndByte]);
if (BHV_ARR_CHECK(sTTCRotatingSolidCollisionModels, o->oBehParams2ndByte, void const*)) {
o->collisionData = segmented_to_virtual(sTTCRotatingSolidCollisionModels[o->oBehParams2ndByte]);
}
o->oTTCRotatingSolidNumSides = o->oBehParams2ndByte == TTC_ROTATING_SOLID_BP_CUBE ? 4 : 3;
@ -68,8 +70,9 @@ void bhv_ttc_rotating_solid_update(void) {
if (o->oAngleVelRoll == 0) {
cur_obj_play_sound_2(SOUND_GENERAL2_ROTATING_BLOCK_CLICK);
o->oTTCRotatingSolidNumTurns =
(o->oTTCRotatingSolidNumTurns + 1) % o->oTTCRotatingSolidNumSides;
if (o->oTTCRotatingSolidNumSides) {
o->oTTCRotatingSolidNumTurns = (o->oTTCRotatingSolidNumTurns + 1) % o->oTTCRotatingSolidNumSides;
}
o->oTimer = 0;
if (gTTCSpeedSetting == TTC_SPEED_RANDOM) {

View file

@ -31,7 +31,7 @@ void bhv_tumbling_bridge_platform_loop(void) {
}
}
if (o->parentObj != NULL && gCurrCourseNum == COURSE_LLL) {
if (o->parentObj && gCurrCourseNum == COURSE_LLL) {
if (o->parentObj->oIntangibleTimer == -1) {
cur_obj_hide();
o->oIntangibleTimer = o->parentObj->oIntangibleTimer;
@ -74,12 +74,12 @@ void bhv_tumbling_bridge_platform_loop(void) {
case 3:
break;
}
if (o->parentObj->oAction == 3) {
if (o->parentObj && o->parentObj->oAction == 3) {
obj_mark_for_deletion(o);
if (isLLL) { network_send_object(o); }
}
if (o->parentObj != NULL && o->parentObj->oIntangibleTimer != -1) {
if (o->parentObj && o->parentObj->oIntangibleTimer != -1) {
load_object_collision_model();
} else if (gCurrCourseNum != COURSE_LLL) {
load_object_collision_model();
@ -94,6 +94,7 @@ void tumbling_bridge_act_1(void) {
s32 relativePlatformZ;
s32 relativePlatformY = 0;
s32 relativeInitialPlatformY = 0;
if (!BHV_ARR_CHECK(sTumblingBridgeParams, bridgeID, struct Struct8032F34C)) { return; }
for (i = 0; i < sTumblingBridgeParams[bridgeID].numBridgeSections; i++) {
relativePlatformX = 0;

View file

@ -57,7 +57,7 @@ void tuxies_mother_act_1(void) {
cur_obj_init_animation_with_sound(3);
if (!cur_obj_is_mario_on_platform()) {
sp2C = (o->oBehParams >> 0x10) & 0xFF;
sp28 = (o->prevObj->oBehParams >> 0x10) & 0xFF;
sp28 = o->prevObj ? ((o->prevObj->oBehParams >> 0x10) & 0xFF) : 0;
if (sp2C == sp28) {
dialogID = gBehaviorValues.dialogs.TuxieMotherBabyFoundDialog;
} else {
@ -75,7 +75,7 @@ void tuxies_mother_act_1(void) {
cur_obj_init_animation_with_sound(0);
break;
case 1:
if (o->prevObj->oHeldState == HELD_FREE) {
if (o->prevObj && o->prevObj->oHeldState == HELD_FREE) {
//! This line is was almost certainly supposed to be something
// like o->prevObj->oInteractionSubtype &= ~INT_SUBTYPE_DROP_IMMEDIATELY;
// however, this code uses the value of o->oInteractionSubtype
@ -98,7 +98,7 @@ void tuxies_mother_act_1(void) {
}
break;
case 2:
if (o->prevObj->oHeldState == HELD_FREE) {
if (o->prevObj && o->prevObj->oHeldState == HELD_FREE) {
//! Same bug as above
o->prevObj->OBJECT_FIELD_S32(o->oInteractionSubtype) &= ~INT_SUBTYPE_DROP_IMMEDIATELY;
obj_set_behavior(o->prevObj, bhvPenguinBaby);

View file

@ -516,7 +516,7 @@ void ukiki_free_loop(void) {
handle_cap_ukiki_reset();
if(!(o->oMoveFlags & OBJ_MOVE_MASK_IN_WATER)) {
exec_anim_sound_state(sUkikiSoundStates);
exec_anim_sound_state(sUkikiSoundStates, sizeof(sUkikiSoundStates) / sizeof(struct SoundState));
}
}

View file

@ -29,7 +29,7 @@ void bhv_ukiki_cage_star_loop(void) {
obj_copy_behavior_params(o, o->parentObj);
// When they cage hides itself, spawn particles and the star.
if (o->parentObj->oAction == UKIKI_CAGE_ACT_HIDE) {
if (o->parentObj && o->parentObj->oAction == UKIKI_CAGE_ACT_HIDE) {
o->oAction++;
}
break;

View file

@ -53,9 +53,11 @@ void unagi_act_0(void) {
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];
o->oPosY = o->oPathedStartWaypoint->pos[1];
o->oPosZ = o->oPathedStartWaypoint->pos[2];
if (o->oPathedStartWaypoint) {
o->oPosX = o->oPathedStartWaypoint->pos[0];
o->oPosY = o->oPathedStartWaypoint->pos[1];
o->oPosZ = o->oPathedStartWaypoint->pos[2];
}
} else if (o->oUnagiUnk1AC < 700.0f) {
o->oSubAction = 1;
}
@ -200,7 +202,7 @@ void bhv_unagi_subobject_loop(void) {
struct Object* player = nearest_player_to_object(o);
s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000;
if (o->parentObj->oUnagiUnk1B2 == 0) {
if (!o->parentObj || o->parentObj->oUnagiUnk1B2 == 0) {
obj_mark_for_deletion(o);
} else {
val04 = 300.0f * o->oBehParams2ndByte;

View file

@ -54,12 +54,12 @@ void bhv_water_bomb_spawner_update(void) {
marioState = &gMarioStates[i];
}
}
if (!player) { return; }
spawnerRadius = 50 * (u16)(o->oBehParams >> 16) + 200.0f;
// When mario is in range and a water bomb isn't already active
if (!o->oWaterBombSpawnerBombActive && latDistToMario < spawnerRadius
&& player->oPosY - o->oPosY < 1000.0f) {
if (!o->oWaterBombSpawnerBombActive && latDistToMario < spawnerRadius && player->oPosY - o->oPosY < 1000.0f) {
if (o->oWaterBombSpawnerTimeToSpawn != 0) {
o->oWaterBombSpawnerTimeToSpawn -= 1;
} else if (sync_object_is_owned_locally(o->oSyncID)) {
@ -206,7 +206,9 @@ static void water_bomb_act_drop(void) {
*/
static void water_bomb_act_explode(void) {
water_bomb_spawn_explode_particles(25, 60, 10);
o->parentObj->oWaterBombSpawnerBombActive = FALSE;
if (o->parentObj) {
o->parentObj->oWaterBombSpawnerBombActive = FALSE;
}
obj_mark_for_deletion(o);
}
@ -278,7 +280,7 @@ void bhv_water_bomb_update(void) {
* Despawn when the parent water bomb does.
*/
void bhv_water_bomb_shadow_update(void) {
if (o->parentObj->oAction == WATER_BOMB_ACT_EXPLODE) {
if (!o->parentObj || o->parentObj->oAction == WATER_BOMB_ACT_EXPLODE) {
obj_mark_for_deletion(o);
} else {
// TODO: What is happening here

View file

@ -3,7 +3,7 @@
void bhv_bubble_cannon_barrel_loop(void) {
struct Object *val04;
if (o->parentObj->oAction == 2) {
if (!o->parentObj || o->parentObj->oAction == 2) {
obj_mark_for_deletion(o);
} else {
o->oMoveAngleYaw = o->parentObj->oFaceAngleYaw;

View file

@ -81,6 +81,8 @@ void bhv_water_level_pillar_loop(void) {
water_level_pillar_drained();
else
water_level_pillar_undrained();
gEnvironmentRegions[18] = gEnvironmentLevels[2];
gEnvironmentRegions[6] = gEnvironmentLevels[0];
if (gEnvironmentRegions) {
gEnvironmentRegions[18] = gEnvironmentLevels[2];
gEnvironmentRegions[6] = gEnvironmentLevels[0];
}
}

View file

@ -116,7 +116,9 @@ void water_ring_act_not_collected(void) {
//! In this case ringSpawner and ringManager are the same object,
// because the Jet Stream Ring Spawner is its own parent object.
struct Object *ringSpawner = o->parentObj;
if (!ringSpawner) { return; }
struct Object *ringManager = ringSpawner->parentObj;
if (!ringManager) { return; }
if (o->oTimer >= 226) {
o->oOpacity -= 2;
@ -160,7 +162,8 @@ void water_ring_spawner_act_inactive(void) {
// from the Manta Ray, which spawns rings but also has a Ring Manager object as its
// parent. The Jet Stream Ring Spawner functions as both a spawner and a Ring Manager.
struct Object *currentObj = o->parentObj;
struct Object *waterRing;
struct Object *waterRing = NULL;
if (!currentObj) { return; }
//! Because the index counter overflows at 10000, it's possible to wait
// for about 4 hours and 38 minutes if you miss a ring, and the index will
@ -217,7 +220,9 @@ void bhv_manta_ray_water_ring_init(void) {
void manta_water_ring_act_not_collected(void) {
f32 avgScale = (f32) o->oTimer / 50.0f * 1.3 + 0.1;
struct Object *ringSpawner = o->parentObj;
if (!ringSpawner) { return; }
struct Object *ringManager = ringSpawner->parentObj;
if (!ringManager) { return; }
if (avgScale > 1.3)
avgScale = 1.3;

View file

@ -22,9 +22,10 @@ void bhv_init_changing_water_level_loop(void) {
}
}
if (!gEnvironmentRegions) { return; }
if (gCurrentObject->oAction == 0) {
if (gEnvironmentRegions != NULL)
gCurrentObject->oAction++;
gCurrentObject->oAction++;
} else if (gCurrentObject->oTimer < 10)
*gEnvironmentLevels = gEnvironmentRegions[6];
else {

View file

@ -72,6 +72,7 @@ void bhv_wiggler_body_part_update(void) {
// This should never be higher then 3
// in normal circumstances.
if (o->oBehParams2ndByte > 3 || o->oBehParams2ndByte < 0) { return; }
if (!parent->oWigglerSegments) { return; }
struct ChainSegment *segment = &parent->oWigglerSegments[o->oBehParams2ndByte];
@ -126,11 +127,13 @@ void bhv_wiggler_body_part_update(void) {
*/
void wiggler_init_segments(void) {
struct ChainSegment *segments = mem_pool_alloc(gObjectMemoryPool, 4 * sizeof(struct ChainSegment));
// Each segment represents the global position and orientation of each
// object. Segment 0 represents the wiggler's head, and segment i>0
// represents body part i.
o->oWigglerSegments = segments;
if (segments != NULL) {
// Each segment represents the global position and orientation of each
// object. Segment 0 represents the wiggler's head, and segment i>0
// represents body part i.
o->oWigglerSegments = segments;
for (s32 i = 0; i <= 3; i++) {
chain_segment_init(segments + i);
@ -171,11 +174,12 @@ void wiggler_init_segments(void) {
*/
void wiggler_update_segments(void) {
f32 segmentLength = 35.0f * o->header.gfx.scale[0];
if (!o->oWigglerSegments) { return; }
for (s32 i = 1; i <= 3; i++) {
struct ChainSegment *prevBodyPart = &o->oWigglerSegments[i - 1];
struct ChainSegment *bodyPart = &o->oWigglerSegments[i];
if (!prevBodyPart || !bodyPart) { continue; }
f32 dx = bodyPart->posX - prevBodyPart->posX;
f32 dy = bodyPart->posY - prevBodyPart->posY;
f32 dz = bodyPart->posZ - prevBodyPart->posZ;
@ -235,7 +239,7 @@ static void wiggler_act_walk(void) {
// to 4 until after this runs the first time. It indexes out of bounds
// and uses the value 113762.3 for one frame on US. This is fixed up
// in wiggler_init_segments if AVOID_UB is defined.
obj_forward_vel_approach(sWigglerSpeeds[o->oHealth - 1], 1.0f);
obj_forward_vel_approach(BHV_ARR(sWigglerSpeeds, o->oHealth - 1, f32), 1.0f);
if (o->oWigglerWalkAwayFromWallTimer != 0) {
o->oWigglerWalkAwayFromWallTimer -= 1;
@ -522,11 +526,13 @@ void bhv_wiggler_update(void) {
}
// Update segment 0 with data from the wiggler object
o->oWigglerSegments[0].posX = o->oPosX;
o->oWigglerSegments[0].posY = o->oPosY;
o->oWigglerSegments[0].posZ = o->oPosZ;
o->oWigglerSegments[0].pitch = o->oFaceAnglePitch;
o->oWigglerSegments[0].yaw = o->oFaceAngleYaw;
if (o->oWigglerSegments) {
o->oWigglerSegments[0].posX = o->oPosX;
o->oWigglerSegments[0].posY = o->oPosY;
o->oWigglerSegments[0].posZ = o->oPosZ;
o->oWigglerSegments[0].pitch = o->oFaceAnglePitch;
o->oWigglerSegments[0].yaw = o->oFaceAngleYaw;
}
// Update the rest of the segments to follow segment 0
wiggler_update_segments();

View file

@ -3658,24 +3658,28 @@ void stub_camera_3(UNUSED struct Camera *c) {
}
void vec3f_sub(Vec3f dst, Vec3f src) {
if (!dst || !src) { return; }
dst[0] -= src[0];
dst[1] -= src[1];
dst[2] -= src[2];
}
void object_pos_to_vec3f(Vec3f dst, struct Object *o) {
if (!dst || !o) { return; }
dst[0] = o->oPosX;
dst[1] = o->oPosY;
dst[2] = o->oPosZ;
}
void vec3f_to_object_pos(struct Object *o, Vec3f src) {
if (!o || !src) { return; }
o->oPosX = src[0];
o->oPosY = src[1];
o->oPosZ = src[2];
}
void unused_object_angle_to_vec3s(Vec3s dst, struct Object *o) {
if (!dst || !o) { return; }
dst[0] = o->oMoveAnglePitch;
dst[1] = o->oMoveAngleYaw;
dst[2] = o->oMoveAngleRoll;

View file

@ -1479,7 +1479,7 @@ void handle_dialog_text_and_pages(s8 colorMode, struct DialogEntry *dialog, s8 l
while (pageState == DIALOG_PAGE_STATE_NONE) {
change_and_flash_dialog_text_color_lines(colorMode, lineNum);
strChar = str[strIdx];
strChar = str ? str[strIdx] : DIALOG_CHAR_TERMINATOR;
switch (strChar) {
case DIALOG_CHAR_TERMINATOR:
@ -1932,6 +1932,10 @@ void render_dialog_entries(void) {
break;
}
#else
if (gDialogID >= DIALOG_COUNT || gDialogID < 0) {
gDialogID = -1;
return;
}
dialogTable = segmented_to_virtual(seg2_dialog_table);
#endif
dialog = segmented_to_virtual(dialogTable[gDialogID]);

View file

@ -2239,7 +2239,7 @@ void mario_process_interactions(struct MarioState *m) {
m->collidedObjInteractTypes &= ~interactType;
if (!(object->oInteractStatus & INT_STATUS_INTERACTED)) {
if (object && !(object->oInteractStatus & INT_STATUS_INTERACTED)) {
bool allow = true;
smlua_call_event_hooks_interact_params_ret_bool(HOOK_ALLOW_INTERACT, m, object, interactType, &allow);
if (allow) {

View file

@ -677,6 +677,7 @@ s16 music_changed_through_warp(s16 arg) {
}
struct ObjectWarpNode *warpNode = area_get_warp_node(arg);
if (!warpNode) { return FALSE; }
s16 levelNum = warpNode->node.destLevel & 0x7F;
#if BUGFIX_KOOPA_RACE_MUSIC

View file

@ -2313,9 +2313,11 @@ static void end_peach_cutscene_summon_jumbo_star(struct MarioState *m) {
advance_cutscene_step(m);
}
sEndJumboStarObj->oFaceAngleYaw += 0x0400;
generate_yellow_sparkles(0, 2528, -1800, 250.0f);
play_sound(SOUND_AIR_PEACH_TWINKLE, sEndJumboStarObj->header.gfx.cameraToObject);
if (sEndJumboStarObj) {
sEndJumboStarObj->oFaceAngleYaw += 0x0400;
generate_yellow_sparkles(0, 2528, -1800, 250.0f);
play_sound(SOUND_AIR_PEACH_TWINKLE, sEndJumboStarObj->header.gfx.cameraToObject);
}
}
#if defined(VERSION_EU)
@ -2344,7 +2346,7 @@ static void end_peach_cutscene_spawn_peach(struct MarioState *m) {
play_transition(WARP_TRANSITION_FADE_FROM_COLOR, 192, 255, 255, 255);
}
if (m->actionTimer == 40) {
obj_mark_for_deletion(sEndJumboStarObj);
if (sEndJumboStarObj) { obj_mark_for_deletion(sEndJumboStarObj); }
sEndPeachObj = spawn_object_abs_with_rot(gCurrentObject, 0, MODEL_PEACH, bhvEndPeach, 0, 2428,
-1300, 0, 0, 0);

View file

@ -287,6 +287,8 @@ void *alloc_only_pool_alloc(struct AllocOnlyPool *pool, s32 size) {
}
if (addr == NULL) {
LOG_ERROR("Allocate only pool failed to allocate memory of size 0x%X on at pool %p.", size, pool);
} else {
memset(addr, 0, size);
}
return addr;
}
@ -374,6 +376,7 @@ void *mem_pool_alloc(struct MemoryPool *pool, u32 size) {
* Free a block that was allocated using mem_pool_alloc.
*/
void mem_pool_free(struct MemoryPool *pool, void *addr) {
if (!addr) { return; }
struct MemoryBlock *block = (struct MemoryBlock *) ((u8 *) addr - sizeof(struct MemoryBlock));
struct MemoryBlock *freeList = pool->freeList.next;
@ -419,6 +422,7 @@ void *alloc_display_list(u32 size) {
if (gGfxPoolEnd - size >= (u8 *) gDisplayListHead) {
gGfxPoolEnd -= size;
ptr = gGfxPoolEnd;
memset(ptr, 0, size);
} else {
LOG_ERROR("Failed to allocate display list of size 0x%X!", size);
}

View file

@ -319,8 +319,10 @@ Gfx *geo_wdw_set_initial_water_level(s32 callContext, UNUSED struct GraphNode *n
} else {
wdwWaterHeight = 1024;
}
for (i = 0; i < *gEnvironmentRegions; i++) {
gEnvironmentRegions[i * 6 + 6] = wdwWaterHeight;
if (gEnvironmentRegions) {
for (i = 0; i < *gEnvironmentRegions; i++) {
gEnvironmentRegions[i * 6 + 6] = wdwWaterHeight;
}
}
gWdwWaterLevelSet = TRUE;
}

View file

@ -178,6 +178,7 @@ void platform_on_track_update_pos_or_spawn_ball(s32 ballIndex, f32 x, f32 y, f32
do {
prevWaypoint = nextWaypoint;
if (!prevWaypoint) { break; }
nextWaypoint += 1;
if (nextWaypoint->flags == WAYPOINT_FLAGS_END) {

View file

@ -219,7 +219,7 @@ Gfx *geo_switch_area(s32 callContext, struct GraphNode *node) {
if (door == NULL) { continue; }
if (door->oInteractType != INTERACT_DOOR) { continue; }
if (door->oAction == 0) { continue; }
if (gDoorAdjacentRooms[door->oDoorUnkF8][0] != gMarioCurrentRoom && gDoorAdjacentRooms[door->oDoorUnkF8][1] != gMarioCurrentRoom) { continue; }
if (door->oDoorUnkF8 < 60 && gDoorAdjacentRooms[door->oDoorUnkF8][0] != gMarioCurrentRoom && gDoorAdjacentRooms[door->oDoorUnkF8][1] != gMarioCurrentRoom) { continue; }
find_floor(door->oHomeX, door->oHomeY, door->oHomeZ, &sp20);
if (!sp20) { continue; }
@ -755,6 +755,7 @@ void cur_obj_move_using_vel(void) {
}
void obj_copy_graph_y_offset(struct Object *dst, struct Object *src) {
if (!dst || !src) { return; }
dst->oGraphYOffset = src->oGraphYOffset;
}
@ -764,12 +765,14 @@ void obj_copy_pos_and_angle(struct Object *dst, struct Object *src) {
}
void obj_copy_pos(struct Object *dst, struct Object *src) {
if (!dst || !src) { return; }
dst->oPosX = src->oPosX;
dst->oPosY = src->oPosY;
dst->oPosZ = src->oPosZ;
}
void obj_copy_angle(struct Object *dst, struct Object *src) {
if (!dst || !src) { return; }
dst->oMoveAnglePitch = src->oMoveAnglePitch;
dst->oMoveAngleYaw = src->oMoveAngleYaw;
dst->oMoveAngleRoll = src->oMoveAngleRoll;
@ -780,6 +783,7 @@ void obj_copy_angle(struct Object *dst, struct Object *src) {
}
void obj_set_gfx_pos_from_pos(struct Object *obj) {
if (!obj) { return; }
obj->header.gfx.pos[0] = obj->oPosX;
obj->header.gfx.pos[1] = obj->oPosY;
obj->header.gfx.pos[2] = obj->oPosZ;
@ -1211,15 +1215,15 @@ BAD_RETURN(s16) cur_obj_reverse_animation(void) {
BAD_RETURN(s32) cur_obj_extend_animation_if_at_end(void) {
s32 sp4 = o->header.gfx.animInfo.animFrame;
s32 sp0 = o->header.gfx.animInfo.curAnim->loopEnd - 2;
s32 sp0 = o->header.gfx.animInfo.curAnim ? o->header.gfx.animInfo.curAnim->loopEnd - 2 : 0;
if (sp4 == sp0) o->header.gfx.animInfo.animFrame--;
}
s32 cur_obj_check_if_near_animation_end(void) {
u32 animFlags = (s32) o->header.gfx.animInfo.curAnim->flags;
u32 animFlags = o->header.gfx.animInfo.curAnim ? (s32) o->header.gfx.animInfo.curAnim->flags : 0;
s32 animFrame = o->header.gfx.animInfo.animFrame;
s32 nearLoopEnd = o->header.gfx.animInfo.curAnim->loopEnd - 2;
s32 nearLoopEnd = o->header.gfx.animInfo.curAnim ? o->header.gfx.animInfo.curAnim->loopEnd - 2 : 0;
s32 isNearEnd = FALSE;
if (animFlags & ANIM_FLAG_NOLOOP && nearLoopEnd + 1 == animFrame) {
@ -1235,7 +1239,7 @@ s32 cur_obj_check_if_near_animation_end(void) {
s32 cur_obj_check_if_at_animation_end(void) {
s32 animFrame = o->header.gfx.animInfo.animFrame;
s32 lastFrame = o->header.gfx.animInfo.curAnim->loopEnd - 1;
s32 lastFrame = o->header.gfx.animInfo.curAnim ? o->header.gfx.animInfo.curAnim->loopEnd - 1 : 0;
if (animFrame == lastFrame) {
return TRUE;
@ -1732,6 +1736,7 @@ s32 cur_obj_has_behavior(const BehaviorScript *behavior) {
}
s32 obj_has_behavior(struct Object *obj, const BehaviorScript *behavior) {
if (!obj || !behavior) { return FALSE; }
behavior = smlua_override_behavior(behavior);
if (obj->behavior == segmented_to_virtual(behavior)) {
return TRUE;
@ -2242,6 +2247,7 @@ void obj_set_throw_matrix_from_transform(struct Object *obj) {
void obj_build_transform_relative_to_parent(struct Object *obj) {
if (obj == NULL) { return; }
struct Object *parent = obj->parentObj;
if (!parent) { return; }
obj_build_transform_from_pos_and_angle(obj, O_PARENT_RELATIVE_POS_INDEX, O_FACE_ANGLE_INDEX);
obj_apply_scale_to_transform(obj);
@ -2305,6 +2311,8 @@ s32 cur_obj_follow_path(UNUSED s32 unusedArg) {
startWaypoint = o->oPathedStartWaypoint;
lastWaypoint = o->oPathedPrevWaypoint;
if (!startWaypoint) { return PATH_NONE; }
// sanity check waypoints
if (lastWaypoint == NULL) { lastWaypoint = startWaypoint; }
struct Waypoint* tmpWaypoint = (lastWaypoint + 1);
@ -2593,6 +2601,7 @@ s32 cur_obj_progress_direction_table(void) {
s8 spF;
s8 *sp8 = o->oToxBoxMovementPattern;
s32 sp4 = o->oToxBoxMovementStep + 1;
if (!sp8) { return 0; }
if (sp8[sp4] != -1) {
spF = sp8[sp4];
@ -2701,7 +2710,7 @@ void spawn_base_star_with_no_lvl_exit(void) {
}
s32 bit_shift_left(s32 a0) {
return D_8032F0A4[a0];
return BHV_ARR(D_8032F0A4, a0, s16);
}
s32 cur_obj_mario_far_away(void) {
@ -3297,4 +3306,15 @@ void cur_obj_set_home_once(void) {
o->oHomeX = o->oPosX;
o->oHomeY = o->oPosY;
o->oHomeZ = o->oPosZ;
}
s32 get_trajectory_length(Trajectory* trajectory) {
if (!trajectory) { return 0; }
s32 count = 0;
s16* c = trajectory;
while (*c != -1) {
count++;
c += 4;
}
return count;
}

View file

@ -326,5 +326,6 @@ void cur_obj_spawn_star_at_y_offset(f32 targetX, f32 targetY, f32 targetZ, f32 o
#endif
void cur_obj_set_home_once(void);
s32 get_trajectory_length(Trajectory* trajectory);
#endif // OBJECT_HELPERS_H

View file

@ -275,6 +275,7 @@ void bhv_mario_update(void) {
// set mario state to the current player
s32 stateIndex = (gCurrentObject->oBehParams - 1);
if (stateIndex > MAX_PLAYERS) { return; }
gMarioState = &gMarioStates[stateIndex];
// sanity check torsoPos, it isn't updated off-screen otherwise
@ -465,6 +466,7 @@ void set_object_respawn_info_bits(struct Object *obj, u8 bits) {
u16 *info16;
u8 oldRespawnInfoBits = 0;
u8 newRespawnInfoBits = 0;
if (!obj) { return; }
switch (obj->respawnInfoType) {
case RESPAWN_INFO_TYPE_32:

View file

@ -109,11 +109,14 @@ struct Object *try_allocate_object(struct ObjectNode *destList, struct ObjectNod
geo_remove_child(&nextObj->gfx.node);
geo_add_child(&gObjParentGraphNode, &nextObj->gfx.node);
((struct Object *)nextObj)->ctx = 0
struct Object* ret = (struct Object *) nextObj;
ret->ctx = 0
| ((u8)CTX_WITHIN(CTX_LEVEL_SCRIPT) << 0)
| ((u8)CTX_WITHIN(CTX_HOOK) << 1);
return (struct Object *) nextObj;
ret->header.gfx.sharedChild = NULL;
return ret;
}
/**

View file

@ -15,8 +15,9 @@
* of sound states. Used for the stepping sounds of various
* objects. (King Bobomb, Bowser, King Whomp)
*/
void exec_anim_sound_state(struct SoundState *soundStates) {
void exec_anim_sound_state(struct SoundState *soundStates, u16 maxSoundStates) {
s32 stateIdx = gCurrentObject->oSoundStateID;
if (stateIdx >= maxSoundStates) { return; }
switch (soundStates[stateIdx].playSound) {
// since we have an array of sound states corresponding to

View file

@ -19,6 +19,6 @@ struct SoundState
void cur_obj_play_sound_1(s32 soundMagic);
void cur_obj_play_sound_2(s32 soundMagic);
void create_sound_spawner(s32 soundMagic);
void exec_anim_sound_state(struct SoundState *soundStates);
void exec_anim_sound_state(struct SoundState *soundStates, u16 maxSoundStates);
#endif // SPAWN_SOUND_H

View file

@ -577,7 +577,7 @@ void render_score_menu_buttons(struct Object *scoreButton) {
spawn_object_rel_with_rot(scoreButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, 711,
311, -100, 0, -0x8000, 0);
}
sMainMenuButtons[MENU_BUTTON_SCORE_FILE_A]->oMenuButtonScale = 0.11111111f;
if (sMainMenuButtons[MENU_BUTTON_SCORE_FILE_A]) { sMainMenuButtons[MENU_BUTTON_SCORE_FILE_A]->oMenuButtonScale = 0.11111111f; }
// File B
if (save_file_exists(SAVE_FILE_B) == TRUE) {
sMainMenuButtons[MENU_BUTTON_SCORE_FILE_B] =
@ -588,7 +588,7 @@ void render_score_menu_buttons(struct Object *scoreButton) {
spawn_object_rel_with_rot(scoreButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton,
-166, 311, -100, 0, -0x8000, 0);
}
sMainMenuButtons[MENU_BUTTON_SCORE_FILE_B]->oMenuButtonScale = 0.11111111f;
if (sMainMenuButtons[MENU_BUTTON_SCORE_FILE_B]) { sMainMenuButtons[MENU_BUTTON_SCORE_FILE_B]->oMenuButtonScale = 0.11111111f; }
// File C
if (save_file_exists(SAVE_FILE_C) == TRUE) {
sMainMenuButtons[MENU_BUTTON_SCORE_FILE_C] = spawn_object_rel_with_rot(
@ -597,7 +597,7 @@ void render_score_menu_buttons(struct Object *scoreButton) {
sMainMenuButtons[MENU_BUTTON_SCORE_FILE_C] = spawn_object_rel_with_rot(
scoreButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, 711, 0, -100, 0, -0x8000, 0);
}
sMainMenuButtons[MENU_BUTTON_SCORE_FILE_C]->oMenuButtonScale = 0.11111111f;
if (sMainMenuButtons[MENU_BUTTON_SCORE_FILE_C]) { sMainMenuButtons[MENU_BUTTON_SCORE_FILE_C]->oMenuButtonScale = 0.11111111f; }
// File D
if (save_file_exists(SAVE_FILE_D) == TRUE) {
sMainMenuButtons[MENU_BUTTON_SCORE_FILE_D] =
@ -607,19 +607,19 @@ void render_score_menu_buttons(struct Object *scoreButton) {
sMainMenuButtons[MENU_BUTTON_SCORE_FILE_D] = spawn_object_rel_with_rot(
scoreButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, -166, 0, -100, 0, -0x8000, 0);
}
sMainMenuButtons[MENU_BUTTON_SCORE_FILE_D]->oMenuButtonScale = 0.11111111f;
if (sMainMenuButtons[MENU_BUTTON_SCORE_FILE_D]) { sMainMenuButtons[MENU_BUTTON_SCORE_FILE_D]->oMenuButtonScale = 0.11111111f; }
// Return to main menu button
sMainMenuButtons[MENU_BUTTON_SCORE_RETURN] = spawn_object_rel_with_rot(
scoreButton, MODEL_MAIN_MENU_YELLOW_FILE_BUTTON, bhvMenuButton, 711, -388, -100, 0, -0x8000, 0);
sMainMenuButtons[MENU_BUTTON_SCORE_RETURN]->oMenuButtonScale = 0.11111111f;
if (sMainMenuButtons[MENU_BUTTON_SCORE_RETURN]) { sMainMenuButtons[MENU_BUTTON_SCORE_RETURN]->oMenuButtonScale = 0.11111111f; }
// Switch to copy menu button
sMainMenuButtons[MENU_BUTTON_SCORE_COPY_FILE] = spawn_object_rel_with_rot(
scoreButton, MODEL_MAIN_MENU_BLUE_COPY_BUTTON, bhvMenuButton, 0, -388, -100, 0, -0x8000, 0);
sMainMenuButtons[MENU_BUTTON_SCORE_COPY_FILE]->oMenuButtonScale = 0.11111111f;
if (sMainMenuButtons[MENU_BUTTON_SCORE_COPY_FILE]) { sMainMenuButtons[MENU_BUTTON_SCORE_COPY_FILE]->oMenuButtonScale = 0.11111111f; }
// Switch to erase menu button
sMainMenuButtons[MENU_BUTTON_SCORE_ERASE_FILE] = spawn_object_rel_with_rot(
scoreButton, MODEL_MAIN_MENU_RED_ERASE_BUTTON, bhvMenuButton, -711, -388, -100, 0, -0x8000, 0);
sMainMenuButtons[MENU_BUTTON_SCORE_ERASE_FILE]->oMenuButtonScale = 0.11111111f;
if (sMainMenuButtons[MENU_BUTTON_SCORE_ERASE_FILE]) { sMainMenuButtons[MENU_BUTTON_SCORE_ERASE_FILE]->oMenuButtonScale = 0.11111111f; }
}
#ifdef VERSION_EU
@ -1325,7 +1325,7 @@ void bhv_menu_button_manager_init(void) {
spawn_object_rel_with_rot(gCurrentObject, MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE,
bhvMenuButton, -6400, 2800, 0, 0, 0, 0);
}
sMainMenuButtons[MENU_BUTTON_PLAY_FILE_A]->oMenuButtonScale = 1.0f;
if (sMainMenuButtons[MENU_BUTTON_PLAY_FILE_A]) { sMainMenuButtons[MENU_BUTTON_PLAY_FILE_A]->oMenuButtonScale = 1.0f; }
// File B
if (save_file_exists(SAVE_FILE_B) == TRUE) {
sMainMenuButtons[MENU_BUTTON_PLAY_FILE_B] =
@ -1336,7 +1336,7 @@ void bhv_menu_button_manager_init(void) {
spawn_object_rel_with_rot(gCurrentObject, MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE,
bhvMenuButton, 1500, 2800, 0, 0, 0, 0);
}
sMainMenuButtons[MENU_BUTTON_PLAY_FILE_B]->oMenuButtonScale = 1.0f;
if (sMainMenuButtons[MENU_BUTTON_PLAY_FILE_B]) { sMainMenuButtons[MENU_BUTTON_PLAY_FILE_B]->oMenuButtonScale = 1.0f; }
// File C
if (save_file_exists(SAVE_FILE_C) == TRUE) {
sMainMenuButtons[MENU_BUTTON_PLAY_FILE_C] =
@ -1346,7 +1346,7 @@ void bhv_menu_button_manager_init(void) {
sMainMenuButtons[MENU_BUTTON_PLAY_FILE_C] = spawn_object_rel_with_rot(
gCurrentObject, MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE, bhvMenuButton, -6400, 0, 0, 0, 0, 0);
}
sMainMenuButtons[MENU_BUTTON_PLAY_FILE_C]->oMenuButtonScale = 1.0f;
if (sMainMenuButtons[MENU_BUTTON_PLAY_FILE_C]) { sMainMenuButtons[MENU_BUTTON_PLAY_FILE_C]->oMenuButtonScale = 1.0f; }
// File D
if (save_file_exists(SAVE_FILE_D) == TRUE) {
sMainMenuButtons[MENU_BUTTON_PLAY_FILE_D] = spawn_object_rel_with_rot(
@ -1355,23 +1355,23 @@ void bhv_menu_button_manager_init(void) {
sMainMenuButtons[MENU_BUTTON_PLAY_FILE_D] = spawn_object_rel_with_rot(
gCurrentObject, MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE, bhvMenuButton, 1500, 0, 0, 0, 0, 0);
}
sMainMenuButtons[MENU_BUTTON_PLAY_FILE_D]->oMenuButtonScale = 1.0f;
if (sMainMenuButtons[MENU_BUTTON_PLAY_FILE_D]) { sMainMenuButtons[MENU_BUTTON_PLAY_FILE_D]->oMenuButtonScale = 1.0f; }
// Score menu button
sMainMenuButtons[MENU_BUTTON_SCORE] = spawn_object_rel_with_rot(
gCurrentObject, MODEL_MAIN_MENU_GREEN_SCORE_BUTTON, bhvMenuButton, -6400, -3500, 0, 0, 0, 0);
sMainMenuButtons[MENU_BUTTON_SCORE]->oMenuButtonScale = 1.0f;
if (sMainMenuButtons[MENU_BUTTON_SCORE]) { sMainMenuButtons[MENU_BUTTON_SCORE]->oMenuButtonScale = 1.0f; }
// Copy menu button
sMainMenuButtons[MENU_BUTTON_COPY] = spawn_object_rel_with_rot(
gCurrentObject, MODEL_MAIN_MENU_BLUE_COPY_BUTTON, bhvMenuButton, -2134, -3500, 0, 0, 0, 0);
sMainMenuButtons[MENU_BUTTON_COPY]->oMenuButtonScale = 1.0f;
if (sMainMenuButtons[MENU_BUTTON_COPY]) { sMainMenuButtons[MENU_BUTTON_COPY]->oMenuButtonScale = 1.0f; }
// Erase menu button
sMainMenuButtons[MENU_BUTTON_ERASE] = spawn_object_rel_with_rot(
gCurrentObject, MODEL_MAIN_MENU_RED_ERASE_BUTTON, bhvMenuButton, 2134, -3500, 0, 0, 0, 0);
sMainMenuButtons[MENU_BUTTON_ERASE]->oMenuButtonScale = 1.0f;
if (sMainMenuButtons[MENU_BUTTON_ERASE]) { sMainMenuButtons[MENU_BUTTON_ERASE]->oMenuButtonScale = 1.0f; }
// Sound mode menu button (Option Mode in EU)
sMainMenuButtons[MENU_BUTTON_SOUND_MODE] = spawn_object_rel_with_rot(
gCurrentObject, MODEL_MAIN_MENU_PURPLE_SOUND_BUTTON, bhvMenuButton, 6400, -3500, 0, 0, 0, 0);
sMainMenuButtons[MENU_BUTTON_SOUND_MODE]->oMenuButtonScale = 1.0f;
if (sMainMenuButtons[MENU_BUTTON_SOUND_MODE]) { sMainMenuButtons[MENU_BUTTON_SOUND_MODE]->oMenuButtonScale = 1.0f; }
sTextBaseAlpha = 0;
}
@ -1392,7 +1392,7 @@ void check_main_menu_clicked_buttons(void) {
#endif
// Sound mode menu is handled separately because the button ID for it
// is not grouped with the IDs of the other submenus.
if (check_clicked_button(sMainMenuButtons[MENU_BUTTON_SOUND_MODE]->oPosX,
if (sMainMenuButtons[MENU_BUTTON_SOUND_MODE] && check_clicked_button(sMainMenuButtons[MENU_BUTTON_SOUND_MODE]->oPosX,
sMainMenuButtons[MENU_BUTTON_SOUND_MODE]->oPosY, 200.0f) == TRUE) {
sMainMenuButtons[MENU_BUTTON_SOUND_MODE]->oMenuButtonState = MENU_BUTTON_STATE_GROWING;
sSelectedButtonID = MENU_BUTTON_SOUND_MODE;
@ -1401,6 +1401,7 @@ void check_main_menu_clicked_buttons(void) {
s8 buttonID;
// Configure Main Menu button group
for (buttonID = MENU_BUTTON_MAIN_MIN; buttonID < MENU_BUTTON_MAIN_MAX; buttonID++) {
if (!sMainMenuButtons[buttonID]) { continue; }
s16 buttonX = sMainMenuButtons[buttonID]->oPosX;
s16 buttonY = sMainMenuButtons[buttonID]->oPosY;
@ -1415,7 +1416,9 @@ void check_main_menu_clicked_buttons(void) {
#ifdef VERSION_EU
// Open Options Menu if sOpenLangSettings is TRUE (It's TRUE when there's no saves)
if (sOpenLangSettings == TRUE) {
sMainMenuButtons[MENU_BUTTON_SOUND_MODE]->oMenuButtonState = MENU_BUTTON_STATE_GROWING;
if (sMainMenuButtons[MENU_BUTTON_SOUND_MODE]) {
sMainMenuButtons[MENU_BUTTON_SOUND_MODE]->oMenuButtonState = MENU_BUTTON_STATE_GROWING;
}
sSelectedButtonID = MENU_BUTTON_SOUND_MODE;
sOpenLangSettings = FALSE;
}

View file

@ -34,20 +34,20 @@
*/
// Star Selector count models printed in the act selector menu.
static struct Object *sStarSelectorModels[8];
static struct Object *sStarSelectorModels[8] = { 0 };
// The act the course is loaded as, affects whether some objects spawn.
s8 sLoadedActNum;
s8 sLoadedActNum = 0;
s8 sReceivedLoadedActNum = 0;
// Number of obtained stars, excluding the coin star.
static u8 sObtainedStars;
static u8 sObtainedStars = 0;
// Total number of stars that appear in the act selector menu.
static s8 sVisibleStars;
static s8 sVisibleStars = 0;
// Act selected when the act menu is first opened.
static u8 sInitSelectedActNum;
static u8 sInitSelectedActNum = 0;
// Index value of the act selected in the act menu.
s8 sSelectedActIndex = 0;
@ -96,7 +96,7 @@ void bhv_act_selector_star_type_loop(void) {
* Renders the 100 coin star with an special star selector type.
*/
void render_100_coin_star(u8 stars) {
if (stars & (1 << 6)) {
if ((stars & (1 << 6)) && sStarSelectorModels[6]) {
// If the 100 coin star has been collected, create a new star selector next to the coin score.
sStarSelectorModels[6] = spawn_object_abs_with_rot(gCurrentObject, 0, MODEL_STAR,
bhvActSelectorStarType, 370, 24, -300, 0, 0, 0);
@ -205,6 +205,7 @@ void bhv_act_selector_loop(void) {
// Star selector type handler
for (i = 0; i < sVisibleStars; i++) {
if (!sStarSelectorModels[i]) { continue; }
if (sSelectedActIndex == i) {
sStarSelectorModels[i]->oStarSelectorType = STAR_SELECTOR_SELECTED;
} else {

View file

@ -4022,8 +4022,8 @@ char gSmluaConstants[] = ""
"COOP_OBJ_FLAG_NON_SYNC = (1 << 2)\n"
"COOP_OBJ_FLAG_INITIALIZED = (1 << 3)\n"
"VERSION_TEXT = 'beta'\n"
"VERSION_NUMBER = 34\n"
"MINOR_VERSION_NUMBER = 1\n"
"VERSION_NUMBER = 35\n"
"MINOR_VERSION_NUMBER = 0\n"
"PATCH_VERSION_NUMBER = 0\n"
"VERSION_REGION = 'JP'\n"
"VERSION_REGION = 'EU'\n"

View file

@ -23663,6 +23663,24 @@ int smlua_func_get_object_list_from_behavior(lua_State* L) {
return 1;
}
int smlua_func_get_trajectory_length(lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 1) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "get_trajectory_length", 1, top);
return 0;
}
Trajectory* trajectory = (Trajectory*)smlua_to_cpointer(L, 1, LVT_TRAJECTORY_P);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "get_trajectory_length"); return 0; }
extern s32 get_trajectory_length(Trajectory* trajectory);
lua_pushinteger(L, get_trajectory_length(trajectory));
return 1;
}
int smlua_func_increment_velocity_toward_range(lua_State* L) {
if (L == NULL) { return 0; }
@ -29058,16 +29076,18 @@ int smlua_func_exec_anim_sound_state(lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 1) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "exec_anim_sound_state", 1, top);
if (top != 2) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "exec_anim_sound_state", 2, top);
return 0;
}
struct SoundState* soundStates = (struct SoundState*)smlua_to_cobject(L, 1, LOT_SOUNDSTATE);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "exec_anim_sound_state"); return 0; }
u16 maxSoundStates = smlua_to_integer(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "exec_anim_sound_state"); return 0; }
extern void exec_anim_sound_state(struct SoundState *soundStates);
exec_anim_sound_state(soundStates);
extern void exec_anim_sound_state(struct SoundState *soundStates, u16 maxSoundStates);
exec_anim_sound_state(soundStates, maxSoundStates);
return 1;
}
@ -30685,6 +30705,7 @@ void smlua_bind_functions_autogen(void) {
//smlua_bind_function(L, "geo_update_layer_transparency", smlua_func_geo_update_layer_transparency); <--- UNIMPLEMENTED
//smlua_bind_function(L, "geo_update_projectile_pos_from_parent", smlua_func_geo_update_projectile_pos_from_parent); <--- UNIMPLEMENTED
smlua_bind_function(L, "get_object_list_from_behavior", smlua_func_get_object_list_from_behavior);
smlua_bind_function(L, "get_trajectory_length", smlua_func_get_trajectory_length);
smlua_bind_function(L, "increment_velocity_toward_range", smlua_func_increment_velocity_toward_range);
smlua_bind_function(L, "is_item_in_array", smlua_func_is_item_in_array);
smlua_bind_function(L, "is_mario_moving_fast_or_in_air", smlua_func_is_mario_moving_fast_or_in_air);

View file

@ -585,6 +585,11 @@ u16 smlua_model_util_load_with_pool_and_cache_id(enum ModelExtendedId extId, str
}
}
if (pickLoadedId >= MAX_LOADED_GRAPH_NODES) {
LOG_ERROR("Could not find slot for extId - %u", extId);
return UNLOADED_ID;
}
// load
bool resizePool = false;
if (pool == NULL) {

View file

@ -404,3 +404,23 @@ void set_whirlpools(f32 x, f32 y, f32 z, s16 strength, s16 area, s32 index) {
gAreas[area].whirlpools[index]->pos[2] = z;
gAreas[area].whirlpools[index]->strength = strength;
}
#ifdef DEVELOPMENT
void obj_randomize(struct Object* o) {
for (int i = 0; i < 80; i++) {
if (rand() % 10 < 5) {
o->rawData.asU32[i] = rand() % 10;
} else {
o->rawData.asU32[i] = rand();
}
}
struct Object* objs[] = { NULL, gMarioStates[0].marioObj, o };
if (rand()%4 > 0) { o->parentObj = objs[rand()%3]; }
if (rand()%4 > 0) { o->prevObj = objs[rand()%3]; }
if (rand()%4 > 0) { o->usingObj = objs[rand()%3]; }
if (rand() % 10 < 5) {
o->oAction = rand() % 10;
}
}
#endif

View file

@ -103,7 +103,7 @@ void network_send_area(struct NetworkPlayer* toNp) {
// TODO: move find model to a utility file/function
// find model
u32 model = 0;
for (s32 j = 0; j < 256; j++) {
for (s32 j = 0; j < MAX_LOADED_GRAPH_NODES; j++) {
if (so->o->header.gfx.sharedChild == gLoadedGraphNodes[j]) {
model = j;
break;