Fix star cutscene playing for everybody with Klepto plus some cleanup. (#32)

* Fix star cutscene playing for everybody with Klepto plus some cleanup.

* Fix compile error.

* Fix pyramid elevator syncing, Hopefully fix pyramid top syncing, Grand Star partial working sync.

* Fix up the Grand Star code.
This commit is contained in:
Prince Frizzy 2022-03-16 03:05:28 -04:00 committed by GitHub
parent a50b154bdb
commit bb8ead8681
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 126 additions and 105 deletions

View file

@ -744,7 +744,8 @@
#define PYRAMID_ELEVATOR_IDLE 0
#define PYRAMID_ELEVATOR_START_MOVING 1
#define PYRAMID_ELEVATOR_CONSTANT_VELOCITY 2
#define PYRAMID_ELEVATOR_AT_BOTTOM 3
#define PYRAMID_ELEVATOR_END_MOVING 3
#define PYRAMID_ELEVATOR_AT_BOTTOM 4
/* Pyramid top */
#define PYRAMID_TOP_ACT_CHECK_IF_SOLVED 0

View file

@ -855,6 +855,7 @@ void bowser_spawn_grand_star_key(void) {
reward->oHomeX = reward->oPosX;
reward->oHomeY = reward->oPosY;
reward->oHomeZ = reward->oPosZ;
network_set_sync_id(reward);
struct Object* spawn_objects[] = { reward };
u32 models[] = { MODEL_STAR };
network_send_spawn_objects(spawn_objects, models, 1);
@ -951,7 +952,6 @@ u8 bowser_dead_not_bits_end_continue_dialog(void) { return o->oAction == 4 && o-
s32 bowser_dead_not_bits_end(void) {
struct MarioState* marioState = nearest_mario_state_to_object(o);
s32 ret = 0;
if (o->oBowserUnkF8 < 2) {
if (o->oBowserUnkF8 == 0) {
seq_player_lower_volume(SEQ_PLAYER_LEVEL, 60, 40);
@ -970,23 +970,21 @@ s32 bowser_dead_not_bits_end(void) {
spawn_triangle_break_particles(20, 116, 1.0f, 0);
bowser_spawn_grand_star_key();
set_mario_npc_dialog(&gMarioStates[0], 0, NULL);
ret = 1;
return 1;
}
return ret;
return 0;
}
u8 bowser_dead_bits_end_continue_dialog(void) { return o->oAction == 4 && o->oBowserUnkF8 < 2; }
s32 bowser_dead_bits_end(void) {
struct MarioState* marioState = nearest_mario_state_to_object(o);
UNUSED s32 unused;
s32 ret = 0;
s32 dialogID;
struct MarioState *marioState = nearest_mario_state_to_object(o);
if (o->oBowserUnkF8 < 2) {
if (gHudDisplay.stars < 120)
s32 dialogID = DIALOG_163;
if (gHudDisplay.stars < 120) {
dialogID = DIALOG_121;
else
dialogID = DIALOG_163;
}
if (o->oBowserUnkF8 == 0) {
seq_player_lower_volume(SEQ_PLAYER_LEVEL, 60, 40);
o->oBowserUnkF8++;
@ -1002,9 +1000,9 @@ s32 bowser_dead_bits_end(void) {
o->oOpacity -= 4;
else {
bowser_dead_hide();
ret = 1;
return 1;
}
return ret;
return 0;
}
void bowser_act_dead(void) {

View file

@ -14,7 +14,7 @@ struct ObjectHitbox sClamShellHitbox = {
void clam_act_0(void) {
struct Object* player = nearest_player_to_object(o);
int distanceToPlayer = dist_between_objects(o, player);
s32 distanceToPlayer = dist_between_objects(o, player);
if (cur_obj_init_anim_check_frame(0, 25)) {
cur_obj_play_sound_2(SOUND_GENERAL_CLAM_SHELL3);

View file

@ -4,11 +4,10 @@ s32 arc_to_goal_pos(Vec3f a0, Vec3f a1, f32 yVel, f32 gravity) {
f32 dx = a0[0] - a1[0];
f32 dz = a0[2] - a1[2];
f32 planarDist = sqrtf(dx * dx + dz * dz);
s32 time;
o->oMoveAngleYaw = atan2s(dz, dx);
o->oVelY = yVel;
o->oGravity = gravity;
time = -2.0f / o->oGravity * yVel - 1.0f;
s32 time = -2.0f / o->oGravity * yVel - 1.0f;
o->oForwardVel = planarDist / time;
return time;
}
@ -20,28 +19,56 @@ void grand_star_zero_velocity(void) {
}
void bhv_grand_star_init(void) {
struct Object* other = cur_obj_nearest_object_with_behavior(bhvGrandStar);
if (other == NULL) { return; }
struct Object *other = cur_obj_nearest_object_with_behavior(bhvGrandStar);
if (other == NULL) {
if (!network_sync_object_initialized(o)) {
struct SyncObject *so = network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
if (so) {
network_init_object_field(o, &o->activeFlags);
network_init_object_field(o, &o->oPrevAction);
network_init_object_field(o, &o->oAction);
network_init_object_field(o, &o->oSubAction);
network_init_object_field(o, &o->oTimer);
network_init_object_field(o, &o->oHomeX);
network_init_object_field(o, &o->oHomeY);
network_init_object_field(o, &o->oHomeZ);
network_init_object_field(o, &o->oPosX);
network_init_object_field(o, &o->oPosY);
network_init_object_field(o, &o->oPosZ);
network_init_object_field(o, &o->oGravity);
network_init_object_field(o, &o->oVelY);
network_init_object_field(o, &o->oForwardVel);
network_init_object_field(o, &o->oAngleVelYaw);
network_init_object_field(o, &o->oMoveAngleYaw);
network_init_object_field(o, &o->oFaceAngleYaw);
network_init_object_field(o, &o->oGrandStarUnk108);
}
}
return;
}
obj_mark_for_deletion(o);
if (gSecondCameraFocus == o) { gSecondCameraFocus = other; }
}
void bhv_grand_star_loop(void) {
if (o->activeFlags == ACTIVE_FLAG_DEACTIVATED) { return; }
UNUSED s32 unused;
Vec3f sp28;
sp28[0] = sp28[1] = sp28[2] = 0.0f;
if (o->oAction == 0) {
if (o->oTimer == 0) {
obj_set_angle(o, 0, 0, 0);
o->oAngleVelYaw = 0x400;
cur_obj_play_sound_2(SOUND_GENERAL2_STAR_APPEARS);
}
if (o->oTimer > 70)
if (o->oTimer > 70) {
o->oAction++;
}
spawn_sparkle_particles(3, 200, 80, -60);
} else if (o->oAction == 1) {
if (o->oTimer == 0) {
Vec3f sp28;
sp28[0] = sp28[1] = sp28[2] = 0.0f;
cur_obj_play_sound_2(SOUND_GENERAL_GRAND_STAR);
cutscene_object(CUTSCENE_STAR_SPAWN, o);
o->oGrandStarUnk108 = arc_to_goal_pos(sp28, &o->oPosX, 80.0f, -2.0f);
@ -75,8 +102,9 @@ void bhv_grand_star_loop(void) {
o->oInteractStatus = 0;
}
}
if (o->oAngleVelYaw > 0x400)
if (o->oAngleVelYaw > 0x400) {
o->oAngleVelYaw -= 0x100;
}
o->oFaceAngleYaw += o->oAngleVelYaw;
cur_obj_scale(2.0f);
o->oGraphYOffset = 110.0f;

View file

@ -21,7 +21,7 @@ static u8 sKleptoAttackHandlers[] = { 2, 2, 5, 5, 2, 2 };
static void klepto_target_mario(void) {
struct MarioState* marioState = nearest_mario_state_to_object(o);
struct Object* player = marioState->marioObj;
int angleToPlayer = obj_angle_to_object(o, player);
s32 angleToPlayer = obj_angle_to_object(o, player);
o->oKleptoDistanceToTarget = lateral_dist_between_objects(player, o);
o->oKleptoUnk1B0 = obj_turn_pitch_toward_mario(marioState, 250.0f, 0);
o->oKleptoYawToTarget = angleToPlayer;
@ -129,23 +129,18 @@ void bhv_klepto_init(void) {
static void klepto_change_target(void) {
s32 newTarget = 0;
s32 i;
f32 dx;
f32 dz;
f32 targetDist;
f32 minTargetDist;
struct Object* player = nearest_player_to_object(o);
int distanceToPlayer = dist_between_objects(o, player);
s32 distanceToPlayer = dist_between_objects(o, player);
if (distanceToPlayer > 2000.0f) {
minTargetDist = 99999.0f;
f32 minTargetDist = 99999.0f;
for (i = 0; i < 3; i++) {
dx = player->oPosX - sKleptoTargetPositions[i][0];
dz = player->oPosZ - sKleptoTargetPositions[i][2];
for (s32 i = 0; i < 3; i++) {
f32 dx = player->oPosX - sKleptoTargetPositions[i][0];
f32 dz = player->oPosZ - sKleptoTargetPositions[i][2];
targetDist = sqrtf(dx * dx + dz * dz);
f32 targetDist = sqrtf(dx * dx + dz * dz);
if (targetDist < minTargetDist) {
minTargetDist = targetDist;
newTarget = i;
@ -166,11 +161,8 @@ static void klepto_change_target(void) {
}
static void klepto_circle_target(f32 radius, f32 targetSpeed) {
s16 turnAmount;
f32 accel;
struct Object* player = nearest_player_to_object(o);
int distanceToPlayer = dist_between_objects(o, player);
s32 distanceToPlayer = dist_between_objects(o, player);
if (o->oAnimState != KLEPTO_ANIM_STATE_HOLDING_NOTHING
&& ((o->oTimer > 60 && distanceToPlayer > 2000.0f)
@ -179,8 +171,8 @@ static void klepto_circle_target(f32 radius, f32 targetSpeed) {
o->oKleptoTimeUntilTargetChange = random_linear_offset(300, 300);
o->oAction = KLEPTO_ACT_APPROACH_TARGET_HOLDING;
} else {
turnAmount = 0x4000 - atan2s(radius, o->oKleptoDistanceToTarget - radius);
accel = 0.05f;
s16 turnAmount = 0x4000 - atan2s(radius, o->oKleptoDistanceToTarget - radius);
f32 accel = 0.05f;
if ((s16)(o->oMoveAngleYaw - o->oKleptoYawToTarget) < 0) {
turnAmount = -turnAmount;
}
@ -235,7 +227,7 @@ static void klepto_act_turn_toward_mario(void) {
klepto_target_mario();
struct Object* player = nearest_player_to_object(o);
int angleToPlayer = obj_angle_to_object(o, player);
s32 angleToPlayer = obj_angle_to_object(o, player);
if (klepto_set_and_check_if_anim_at_end() && cur_obj_check_if_at_animation_end() && o->oKleptoDistanceToTarget > 800.0f
&& abs_angle_diff(angleToPlayer, o->oFaceAngleYaw) < 0x800 && o->oKleptoUnk1B0 < 0x400) {
@ -254,8 +246,8 @@ static void klepto_act_turn_toward_mario(void) {
static void klepto_act_dive_at_mario(void) {
struct MarioState* marioState = nearest_mario_state_to_object(o);
struct Object* player = marioState->marioObj;
int distanceToPlayer = dist_between_objects(o, player);
int angleToPlayer = obj_angle_to_object(o, player);
s32 distanceToPlayer = dist_between_objects(o, player);
s32 angleToPlayer = obj_angle_to_object(o, player);
approach_f32_ptr(&o->oKleptoSpeed, 60.0f, 10.0f);
if (o->oSoundStateID == 2) {
@ -373,11 +365,9 @@ void obj_set_speed_to_zero(void) {
}
void bhv_klepto_update(void) {
struct MarioState* marioState = nearest_mario_state_to_object(o);
struct Object* player = marioState->marioObj;
int angleToPlayer = obj_angle_to_object(o, player);
UNUSED s32 unused;
struct MarioState *marioState = nearest_mario_state_to_object(o);
struct Object *player = marioState->marioObj;
s32 angleToPlayer = obj_angle_to_object(o, player);
cur_obj_update_floor_and_walls();
@ -437,7 +427,13 @@ void bhv_klepto_update(void) {
}
} else if (o->oAnimState == KLEPTO_ANIM_STATE_HOLDING_STAR) {
spawn_default_star(-5550.0f, 300.0f, -930.0f);
struct Object *star = spawn_default_star(-5550.0f, 300.0f, -930.0f);
// If we're not the closet to Klepto,
// Don't play the cutscene!
if (star != NULL && marioState != &gMarioStates[0]) {
star->oStarSpawnExtCutsceneFlags = 0;
}
}
if (network_owns_object(o)) {

View file

@ -5,31 +5,26 @@
* well as the small marker balls that demarcate its trajactory.
*/
u8 bhv_pyramid_elevator_ignore_if_true(void) {
return (o->oAction != PYRAMID_ELEVATOR_IDLE);
}
/**
* Generate the ten trajectory marker balls that indicate where the elevator
* moves.
*/
void bhv_pyramid_elevator_init(void) {
s32 i;
struct Object *ball;
for (i = 0; i < 10; i++) {
ball = spawn_object(o, MODEL_TRAJECTORY_MARKER_BALL, bhvPyramidElevatorTrajectoryMarkerBall);
for (s32 i = 0; i < 10; i++) {
struct Object *ball = spawn_object(o, MODEL_TRAJECTORY_MARKER_BALL, bhvPyramidElevatorTrajectoryMarkerBall);
if (ball == NULL) { continue; }
ball->oPosY = 4600 - i * 460;
}
struct SyncObject* so = network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
if (so) {
so->ignore_if_true = bhv_pyramid_elevator_ignore_if_true;
network_init_object_field(o, &o->oAction);
network_init_object_field(o, &o->oPrevAction);
network_init_object_field(o, &o->oTimer);
network_init_object_field(o, &o->oPosY);
if (!network_sync_object_initialized(o)) {
struct SyncObject* so = network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
if (so) {
network_init_object_field(o, &o->oPrevAction);
network_init_object_field(o, &o->oAction);
network_init_object_field(o, &o->oTimer);
network_init_object_field(o, &o->oPosY);
network_init_object_field(o, &o->oVelY);
}
}
}
@ -52,8 +47,10 @@ void bhv_pyramid_elevator_loop(void) {
*/
case PYRAMID_ELEVATOR_START_MOVING:
o->oPosY = o->oHomeY - sins(o->oTimer * 0x1000) * 10.0f;
if (o->oTimer == 8)
if (o->oTimer == 8) {
o->oAction = PYRAMID_ELEVATOR_CONSTANT_VELOCITY;
if (cur_obj_is_mario_on_platform()) { network_send_object(o); }
}
break;
/**
@ -65,7 +62,8 @@ void bhv_pyramid_elevator_loop(void) {
o->oPosY += o->oVelY;
if (o->oPosY < 128.0f) {
o->oPosY = 128.0f;
o->oAction = PYRAMID_ELEVATOR_AT_BOTTOM;
o->oAction = PYRAMID_ELEVATOR_END_MOVING;
if (cur_obj_is_mario_on_platform()) { network_send_object(o); }
}
break;
@ -73,13 +71,22 @@ void bhv_pyramid_elevator_loop(void) {
* Use a sine wave to stop the elevator's movement with a small jolt.
* Then, remain at the bottom of the track.
*/
case PYRAMID_ELEVATOR_AT_BOTTOM:
case PYRAMID_ELEVATOR_END_MOVING:
o->oPosY = sins(o->oTimer * 0x1000) * 10.0f + 128.0f;
if (o->oTimer >= 8) {
o->oVelY = 0;
o->oPosY = 128.0f;
o->oAction = PYRAMID_ELEVATOR_AT_BOTTOM;
network_send_object(o);
}
break;
/**
* The elevator is now at the bottom and finished it's moving
* We will no longer move from this point.
*/
case PYRAMID_ELEVATOR_AT_BOTTOM:
o->oVelY = 0;
o->oPosY = 128.0f;
break;
}
}
@ -88,10 +95,8 @@ void bhv_pyramid_elevator_loop(void) {
* Otherwise, set their scale.
*/
void bhv_pyramid_elevator_trajectory_marker_ball_loop(void) {
struct Object *elevator;
cur_obj_scale(0.15f);
elevator = cur_obj_nearest_object_with_behavior(bhvPyramidElevator);
struct Object *elevator = cur_obj_nearest_object_with_behavior(bhvPyramidElevator);
if (elevator != NULL) {
if (elevator->oAction != PYRAMID_ELEVATOR_IDLE) {

View file

@ -14,14 +14,10 @@
* Spawn the four pillars' touch detectors.
*/
void bhv_pyramid_top_init(void) {
spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvPyramidPillarTouchDetector, 1789, 1024, 764, 0, 0,
0);
spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvPyramidPillarTouchDetector, 1789, 896, -2579, 0, 0,
0);
spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvPyramidPillarTouchDetector, -5883, 1024, -2579, 0, 0,
0);
spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvPyramidPillarTouchDetector, -5883, 1024, 764, 0, 0,
0);
spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvPyramidPillarTouchDetector, 1789, 1024, 764, 0, 0, 0);
spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvPyramidPillarTouchDetector, 1789, 896, -2579, 0, 0, 0);
spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvPyramidPillarTouchDetector, -5883, 1024, -2579, 0, 0, 0);
spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvPyramidPillarTouchDetector, -5883, 1024, 764, 0, 0, 0);
}
/**
@ -71,16 +67,11 @@ void bhv_pyramid_top_spinning(void) {
* Explode the pyramid top, generating dust and pyramid fragments.
*/
void bhv_pyramid_top_explode(void) {
struct Object *pyramidFragment;
s16 i;
spawn_mist_particles_variable(0, 0, 690);
// Generate 30 pyramid fragments with random properties.
for (i = 0; i < 30; i++) {
pyramidFragment = spawn_object(
o, MODEL_DIRT_ANIMATION, bhvPyramidTopFragment
);
for (s16 i = 0; i < 30; i++) {
struct Object *pyramidFragment = spawn_object(o, MODEL_DIRT_ANIMATION, bhvPyramidTopFragment);
if (pyramidFragment != NULL) {
pyramidFragment->oForwardVel = random_float() * 50 + 80;
pyramidFragment->oVelY = random_float() * 80 + 20;
@ -92,22 +83,21 @@ void bhv_pyramid_top_explode(void) {
// Deactivate the pyramid top.
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
}
static u8 bhv_pyramid_top_ignore_if_true(void) {
return (o->oAction != PYRAMID_TOP_ACT_SPINNING);
// Make sure the object is set to be disabled for others.
network_send_object(o);
}
void bhv_pyramid_top_loop(void) {
if (!network_sync_object_initialized(o)) {
struct SyncObject* so = network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
struct SyncObject *so = network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
if (so) {
so->ignore_if_true = bhv_pyramid_top_ignore_if_true;
network_init_object_field(o, &o->activeFlags);
network_init_object_field(o, &o->oAction);
network_init_object_field(o, &o->oPrevAction);
network_init_object_field(o, &o->oTimer);
}
}
switch (o->oAction) {
case PYRAMID_TOP_ACT_CHECK_IF_SOLVED:
if (o->oPyramidTopPillarsTouched == 4) {

View file

@ -11,7 +11,6 @@
* positions.
*/
void bhv_ssl_moving_pyramid_wall_init(void) {
switch (o->oBehParams2ndByte) {
case PYRAMID_WALL_BP_POSITION_HIGH:
break;
@ -26,12 +25,17 @@ void bhv_ssl_moving_pyramid_wall_init(void) {
o->oAction = PYRAMID_WALL_ACT_MOVING_UP;
break;
}
network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
network_init_object_field(o, &o->oPrevAction);
network_init_object_field(o, &o->oAction);
network_init_object_field(o, &o->oTimer);
network_init_object_field(o, &o->oVelY);
network_init_object_field(o, &o->oPosY);
if (!network_sync_object_initialized(o)) {
struct SyncObject *so = network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
if (so) {
network_init_object_field(o, &o->oPrevAction);
network_init_object_field(o, &o->oAction);
network_init_object_field(o, &o->oTimer);
network_init_object_field(o, &o->oVelY);
network_init_object_field(o, &o->oPosY);
}
}
}
/**

View file

@ -2462,9 +2462,8 @@ void stub_obj_helpers_4(void) {
s32 cur_obj_is_mario_on_platform(void) {
if (gMarioObject->platform == o) {
return TRUE;
} else {
return FALSE;
}
return FALSE;
}
s32 cur_obj_is_any_player_on_platform(void) {