Merge branch 'unstable' of github.com:sm64ex-coop-dev/sm64ex-coop into unstable

This commit is contained in:
MysterD 2022-03-30 19:26:06 -07:00
commit 0e50998a39
10 changed files with 210 additions and 67 deletions

View file

@ -1469,4 +1469,4 @@ MAKEFLAGS += --no-builtin-rules
-include $(DEP_FILES)
print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true
print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true

View file

@ -301,25 +301,26 @@ void bhv_bobomb_buddy_init(void) {
}
void bobomb_buddy_act_idle(void) {
UNUSED u8 filler[4];
s16 sp1a = o->header.gfx.animInfo.animFrame;
UNUSED s16 collisionFlags = 0;
s16 animFrame = o->header.gfx.animInfo.animFrame;
o->oBobombBuddyPosXCopy = o->oPosX;
o->oBobombBuddyPosYCopy = o->oPosY;
o->oBobombBuddyPosZCopy = o->oPosZ;
collisionFlags = object_step();
object_step();
if ((sp1a == 5) || (sp1a == 16))
if ((animFrame == 5) || (animFrame == 16)) {
cur_obj_play_sound_2(SOUND_OBJ_BOBOMB_WALK);
}
struct Object* player = nearest_player_to_object(o);
if (dist_between_objects(o, player) < 1000.0f)
if (dist_between_objects(o, player) < 1000.0f) {
o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, obj_angle_to_object(o, player), 0x140);
}
if (o->oInteractStatus == INT_STATUS_INTERACTED)
if (o->oInteractStatus == INT_STATUS_INTERACTED) {
o->oAction = BOBOMB_BUDDY_ACT_TURN_TO_TALK;
}
}
/**
@ -345,24 +346,27 @@ void bobomb_buddy_cannon_dialog(s16 dialogFirstText, s16 dialogSecondText) {
forceCannonOpen = FALSE;
cannonClosed = cur_obj_nearest_object_with_behavior(bhvCannonClosed);
if (cannonClosed != 0)
if (cannonClosed != 0) {
o->oBobombBuddyCannonStatus = BOBOMB_BUDDY_CANNON_OPENING;
else
} else {
o->oBobombBuddyCannonStatus = BOBOMB_BUDDY_CANNON_STOP_TALKING;
}
}
break;
case BOBOMB_BUDDY_CANNON_OPENING:
cannonClosed = cur_obj_nearest_object_with_behavior(bhvCannonClosed);
cutscene = cutscene_object(CUTSCENE_PREPARE_CANNON, cannonClosed);
if (cutscene == -1)
if (cutscene == -1) {
o->oBobombBuddyCannonStatus = BOBOMB_BUDDY_CANNON_OPENED;
}
break;
case BOBOMB_BUDDY_CANNON_OPENED:
buddyText = cutscene_object_with_dialog(CUTSCENE_DIALOG, o, dialogSecondText);
if (buddyText != 0)
if (buddyText != 0) {
o->oBobombBuddyCannonStatus = BOBOMB_BUDDY_CANNON_STOP_TALKING;
}
break;
case BOBOMB_BUDDY_CANNON_STOP_TALKING:
@ -400,25 +404,28 @@ void bobomb_buddy_act_talk(void) {
break;
case BOBOMB_BUDDY_ROLE_CANNON:
if (gCurrCourseNum == COURSE_BOB)
if (gCurrCourseNum == COURSE_BOB) {
bobomb_buddy_cannon_dialog(DIALOG_004, DIALOG_105);
else
} else {
bobomb_buddy_cannon_dialog(DIALOG_047, DIALOG_106);
}
break;
}
}
}
void bobomb_buddy_act_turn_to_talk(void) {
s16 sp1e = o->header.gfx.animInfo.animFrame;
if ((sp1e == 5) || (sp1e == 16))
s16 animFrame = o->header.gfx.animInfo.animFrame;
if ((animFrame == 5) || (animFrame == 16)) {
cur_obj_play_sound_2(SOUND_OBJ_BOBOMB_WALK);
}
struct Object* player = nearest_player_to_object(o);
struct Object *player = nearest_interacting_player_to_object(o);
s32 angleToPlayer = obj_angle_to_object(o, player);
o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, angleToPlayer, 0x1000);
if ((s16) o->oMoveAngleYaw == (s16) angleToPlayer)
if ((s16) o->oMoveAngleYaw == (s16) angleToPlayer) {
o->oAction = BOBOMB_BUDDY_ACT_TALK;
}
cur_obj_play_sound_2(SOUND_ACTION_READ_SIGN);
}

View file

@ -1,19 +1,22 @@
// bowser.c.inc
static u32 networkBowserAnimationIndex = 0;
static u8 bowserIsDying = FALSE;
static u8 bowserCutscenePlayed = FALSE;
static u8 bowserIsCutscenePlayer = FALSE;
void bowser_tail_anchor_act_0(void) {
struct Object* bowser = o->parentObj;
struct Object* player = nearest_player_to_object(o);
cur_obj_become_tangible();
cur_obj_scale(1.0f);
if (bowser->oAction == 19)
if (bowser->oAction == 5 || bowser->oAction == 6 || bowser->oAction == 19 || bowser->oAction == 20) {
bowser->oIntangibleTimer = -1;
else if (obj_check_if_collided_with_object(o, player)) {
} else if (obj_check_if_collided_with_object(o, player)) {
bowser->oIntangibleTimer = 0;
o->oAction = 2;
} else
} else {
bowser->oIntangibleTimer = -1;
}
}
void bowser_tail_anchor_act_1(void) {
@ -177,31 +180,37 @@ s32 bowser_set_anim_look_up_and_walk(void) {
s32 bowser_set_anim_slow_gait(void) {
o->oForwardVel = 3.0f;
cur_obj_init_animation_with_sound(13);
if (cur_obj_check_if_near_animation_end())
if (cur_obj_check_if_near_animation_end()) {
return 1;
else
return 0;
}
return 0;
}
s32 bowser_set_anim_look_down(void) {
cur_obj_init_animation_with_sound(14);
if (cur_obj_check_anim_frame(20))
if (cur_obj_check_anim_frame(20)) {
o->oForwardVel = 0.0f;
if (cur_obj_check_if_near_animation_end())
}
if (cur_obj_check_if_near_animation_end()) {
return 1;
else
return 0;
}
return 0;
}
void bowser_initialize_action(void) {
if (o->oBowserUnk88 == 0)
if (o->oBowserUnk88 == 0 && !bowserCutscenePlayed) {
o->oAction = 5;
else if (o->oBowserUnk88 == 1)
} else if (o->oBowserUnk88 == 1 && !bowserCutscenePlayed) {
o->oAction = 6;
else if (o->oBehParams2ndByte == 1)
} else if (o->oBehParams2ndByte == 1) {
bowserCutscenePlayed = TRUE;
o->oAction = 13;
else
if (bowserIsCutscenePlayer) { network_send_object_reliability(o, TRUE); }
} else {
bowserCutscenePlayed = TRUE;
o->oAction = 0;
if (bowserIsCutscenePlayer) { network_send_object_reliability(o, TRUE); }
}
}
void bowser_act_text_wait(void) // not much
@ -374,12 +383,13 @@ void bowser_act_default(void) // only lasts one frame
o->oAngleVelYaw = 0;
o->oForwardVel = 0.0f;
o->oVelY = 0.0f;
if (BITDW)
if (BITDW) {
bowser_bitdw_act_controller();
else if (BITFS)
} else if (BITFS) {
bowser_bitfs_act_controller();
else
} else {
bowser_bits_act_controller();
}
// Action 14 commonly follows
}
@ -850,12 +860,14 @@ void bowser_spawn_grand_star_key(void) {
reward = (prevReward != NULL) ? prevReward : spawn_object(o, MODEL_STAR, bhvGrandStar);
gSecondCameraFocus = reward;
if (prevReward == NULL && reward != NULL) {
if (network_owns_object(o) && prevReward == NULL && reward != NULL) {
// set the home position
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);
@ -921,7 +933,6 @@ s32 bowser_dead_wait_for_mario(void) {
s32 bowser_dead_twirl_into_trophy(void) {
bowserIsDying = TRUE;
s32 ret = 0;
if (o->header.gfx.scale[0] < 0.8)
o->oAngleVelYaw += 0x80;
if (o->header.gfx.scale[0] > 0.2) {
@ -933,11 +944,11 @@ s32 bowser_dead_twirl_into_trophy(void) {
o->oGravity = 0.0f;
}
if (o->header.gfx.scale[1] < 0.5)
ret = 1;
return 1;
o->oMoveAngleYaw += o->oAngleVelYaw;
if (o->oOpacity >= 3)
o->oOpacity -= 2;
return ret;
return 0;
}
void bowser_dead_hide(void) {
@ -1094,6 +1105,9 @@ void bowser_act_ride_tilting_platform(void) {
cur_obj_extend_animation_if_at_end();
}
void bowser_act_nothing(void) {
}
s32 bowser_check_fallen_off_stage(void) // bowser off stage?
{
@ -1114,7 +1128,8 @@ void (*sBowserActions[])(void) = { bowser_act_default, bowser_act_thrown_droppe
bowser_act_dead, bowser_act_text_wait, bowser_act_intro_walk, bowser_act_charge_mario,
bowser_act_spit_fire_into_sky, bowser_act_spit_fire_onto_floor, bowser_act_hit_edge, bowser_act_turn_from_edge,
bowser_act_hit_mine, bowser_act_jump, bowser_act_walk_to_mario, bowser_act_breath_fire,
bowser_act_teleport, bowser_act_jump_towards_mario, bowser_act_unused_slow_walk, bowser_act_ride_tilting_platform };
bowser_act_teleport, bowser_act_jump_towards_mario, bowser_act_unused_slow_walk, bowser_act_ride_tilting_platform,
bowser_act_nothing, };
struct SoundState D_8032F5B8[] = { { 0, 0, 0, NO_SOUND },
{ 0, 0, 0, NO_SOUND },
{ 0, 0, 0, NO_SOUND },
@ -1257,8 +1272,13 @@ void bhv_bowser_loop(void) {
geo_obj_init_animation(&o->header.gfx, &anim);
}
}
// If Bowser isn't in a cutscene, It's been played already.
if (!bowserCutscenePlayed && (o->oAction != 5 && o->oAction != 6 && o->oAction != 20)) {
bowserCutscenePlayed = TRUE;
}
s16 angleToMario; // AngleToMario from Bowser's perspective
s16 angleToMario; // AngleToMario from Bowser's perspective
s16 angleToCentre; // AngleToCentre from Bowser's perspective
o->oBowserDistToCentre = sqrtf(o->oPosX * o->oPosX + o->oPosZ * o->oPosZ);
@ -1314,6 +1334,13 @@ void bhv_bowser_loop(void) {
}
void bhv_bowser_override_ownership(u8* shouldOverride, u8* shouldOwn) {
// Nothing state sanity check.
if (o->oAction == 20) {
*shouldOverride = TRUE;
*shouldOwn = FALSE;
return;
}
// tilting platform
static u8 tiltingTimer = 0;
if (o->oAction == 19) { tiltingTimer = 5; }
@ -1327,6 +1354,7 @@ void bhv_bowser_override_ownership(u8* shouldOverride, u8* shouldOwn) {
static u8 bhv_bowser_ignore_if_true(void) {
if (bowserIsDying) { return TRUE; }
if (o->oAction == 19) { return TRUE; } // let the platform get to a stable state
if (bowserIsCutscenePlayer && (o->oAction == 5 || o->oAction == 6)) { return TRUE; } // Ignore updates till our cutscene is done.
return FALSE;
}
@ -1346,21 +1374,32 @@ void bhv_bowser_init(void) {
o->oBowserUnk1B2 = D_8032F690[level];
o->oHealth = D_8032F694[level];
cur_obj_start_cam_event(o, CAM_EVENT_BOWSER_INIT);
o->oAction = 5;
o->oBowserUnk1AE = 0;
o->oBowserEyesShut = 0;
struct SyncObject* so = network_init_object(o, 8000.0f);
if (so) {
so->override_ownership = bhv_bowser_override_ownership;
so->ignore_if_true = bhv_bowser_ignore_if_true;
so->fullObjectSync = TRUE;
network_init_object_field_with_size(o, &o->header.gfx.node.flags, 16);
network_init_object_field_with_size(o, &o->header.gfx.animInfo.animFrame, 16);
network_init_object_field(o, &networkBowserAnimationIndex);
network_init_object_field(o, &o->header.gfx.scale[0]);
network_init_object_field(o, &o->header.gfx.scale[1]);
network_init_object_field(o, &o->header.gfx.scale[2]);
bowserCutscenePlayed = FALSE;
// Make sure we're the first to trigger Bowser.
if (!is_other_player_active()) {
bowserIsCutscenePlayer = TRUE;
o->oAction = 5; // bowser_act_text_wait
} else { // If we aren't do nothing till we get our sync.
bowserIsCutscenePlayer = FALSE;
o->oAction = 20; // bowser_act_nothing
}
if (!network_sync_object_initialized(o)) {
struct SyncObject* so = network_init_object(o, 8000.0f);
if (so) {
so->override_ownership = bhv_bowser_override_ownership;
so->ignore_if_true = bhv_bowser_ignore_if_true;
so->fullObjectSync = TRUE;
network_init_object_field_with_size(o, &o->header.gfx.node.flags, 16);
network_init_object_field_with_size(o, &o->header.gfx.animInfo.animFrame, 16);
network_init_object_field(o, &networkBowserAnimationIndex);
network_init_object_field(o, &o->header.gfx.scale[0]);
network_init_object_field(o, &o->header.gfx.scale[1]);
network_init_object_field(o, &o->header.gfx.scale[2]);
}
}
}

View file

@ -1,8 +1,8 @@
// grand_star.c.inc
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];
s32 arc_to_goal_pos(Vec3f empty, Vec3f pos, f32 yVel, f32 gravity) {
f32 dx = empty[0] - pos[0];
f32 dz = empty[2] - pos[2];
f32 planarDist = sqrtf(dx * dx + dz * dz);
o->oMoveAngleYaw = atan2s(dz, dx);
o->oVelY = yVel;
@ -22,12 +22,15 @@ void bhv_grand_star_init(void) {
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);
struct SyncObject *so = network_init_object(o, 4000.0f);
if (so) {
network_init_object_field_with_size(o, &o->activeFlags, 16);
network_init_object_field(o, &o->header.gfx.scale[0]);
network_init_object_field(o, &o->header.gfx.scale[1]);
network_init_object_field(o, &o->header.gfx.scale[2]);
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->oInteractStatus);
network_init_object_field(o, &o->oTimer);
network_init_object_field(o, &o->oHomeX);
network_init_object_field(o, &o->oHomeY);
@ -41,7 +44,7 @@ void bhv_grand_star_init(void) {
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);
network_init_object_field(o, &o->oGraphYOffset);
}
}
return;
@ -66,12 +69,12 @@ void bhv_grand_star_loop(void) {
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;
Vec3f empty;
empty[0] = empty[1] = empty[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);
o->oGrandStarUnk108 = arc_to_goal_pos(empty, &o->oPosX, 80.0f, -2.0f);
}
cur_obj_move_using_fvel_and_gravity();
if (o->oSubAction == 0) {
@ -92,13 +95,25 @@ void bhv_grand_star_loop(void) {
cur_obj_play_sound_2(SOUND_GENERAL_GRAND_STAR_JUMP);
}
spawn_sparkle_particles(3, 200, 80, -60);
} else {
} else if (o->oAction == 2) {
// Make our object tangible.
cur_obj_become_tangible();
// Check for if the jumbo star has been collected.
if (o->oInteractStatus & INT_STATUS_INTERACTED) {
// Make sure we're in the jumbo star cutscene.
if (gMarioStates[0].action != ACT_JUMBO_STAR_CUTSCENE) {
set_mario_action(&gMarioStates[0], ACT_JUMBO_STAR_CUTSCENE, 0);
}
// Increment our action, The star despawns next action.
o->oAction++;
}
} else {
// The star cutscene has started, Make sure the star is deleted
// if it isn't already deactivated.
if (o->activeFlags != ACTIVE_FLAG_DEACTIVATED) {
// Mark our object for deletion.
obj_mark_for_deletion(o);
// Reset our interactive status.
o->oInteractStatus = 0;
}
}
@ -108,4 +123,4 @@ void bhv_grand_star_loop(void) {
o->oFaceAngleYaw += o->oAngleVelYaw;
cur_obj_scale(2.0f);
o->oGraphYOffset = 110.0f;
}
}

View file

@ -327,4 +327,4 @@ void bhv_treasure_chest_loop(void) {
case 2:
break;
}
}
}

View file

@ -3336,7 +3336,8 @@ void reset_camera(struct Camera *c) {
}
void init_camera(struct Camera *c) {
struct Surface *floor = 0;
struct Surface *floor = NULL;
struct Object *obj = NULL;
Vec3f marioOffset;
s32 i;
@ -3391,18 +3392,34 @@ void init_camera(struct Camera *c) {
case LEVEL_BOWSER_1:
#ifndef VERSION_JP
if (gCurrDemoInput == NULL) {
// Make sure Bowser is in a state that we'd start speaking to him in.
obj = find_object_with_behavior(bhvBowser);
if (obj != NULL && obj->oAction != 5) { break; }
start_cutscene(c, CUTSCENE_ENTER_BOWSER_ARENA);
} else if (gSecondCameraFocus != NULL) {
gSecondCameraFocus->oBowserUnk88 = 2;
}
#else
// Make sure Bowser is in a state that we'd start speaking to him in.
obj = find_object_with_behavior(bhvBowser);
if (obj != NULL && obj->oAction != 5) { break; }
start_cutscene(c, CUTSCENE_ENTER_BOWSER_ARENA);
#endif
break;
case LEVEL_BOWSER_2:
// Make sure Bowser is in a state that we'd start speaking to him in.
obj = find_object_with_behavior(bhvBowser);
if (obj != NULL && obj->oAction != 5) { break; }
start_cutscene(c, CUTSCENE_ENTER_BOWSER_ARENA);
break;
case LEVEL_BOWSER_3:
// Make sure Bowser is in a state that we'd start speaking to him in.
obj = find_object_with_behavior(bhvBowser);
if (obj != NULL && obj->oAction != 5) { break; }
start_cutscene(c, CUTSCENE_ENTER_BOWSER_ARENA);
break;

View file

@ -536,6 +536,14 @@ u8 is_player_active(struct MarioState* m) {
return TRUE;
}
u8 is_other_player_active(void) {
for (s32 i = 1; i < MAX_PLAYERS; i++) {
struct MarioState *m = &gMarioStates[i];
if (is_player_active(m)) { return TRUE; }
}
return FALSE;
}
u8 is_player_in_local_area(struct MarioState* m) {
if (gNetworkType == NT_NONE && m == &gMarioStates[0]) { return TRUE; }
struct NetworkPlayer* np = &gNetworkPlayers[m->playerIndex];
@ -589,6 +597,43 @@ struct Object* nearest_player_to_object(struct Object *obj) {
return nearest->marioObj;
}
/**
* Returns closest MarioState that's interacting with the object.
*/
struct MarioState *nearest_interacting_mario_state_to_object(struct Object *obj) {
struct MarioState *nearest = NULL;
f32 nearestDist = 0;
u8 checkActive = TRUE;
do {
for (s32 i = 0; i < MAX_PLAYERS; i++) {
if (gMarioStates[i].marioObj == obj) { continue; }
if (gMarioStates[i].interactObj != obj) { continue; }
if (checkActive && !is_player_active(&gMarioStates[i])) { continue; }
float dist = dist_between_objects(obj, gMarioStates[i].marioObj);
if (nearest == NULL || dist < nearestDist) {
nearest = &gMarioStates[i];
nearestDist = dist;
}
}
if (!checkActive) { break; }
checkActive = FALSE;
} while (nearest == NULL);
if (nearest == NULL) {
nearest = &gMarioStates[0];
}
return nearest;
}
/**
* Returns closest marioObj that's interacting with the object.
*/
struct Object *nearest_interacting_player_to_object(struct Object *obj) {
struct MarioState *nearest = nearest_interacting_mario_state_to_object(obj);
return nearest->marioObj;
}
/**
* Returns whether or not the MarioState is the closet MarioState
* to the object.

View file

@ -163,9 +163,12 @@ void bhv_rr_cruiser_wing_init(void);
void bhv_rr_cruiser_wing_loop(void);
struct Object* spawn_default_star(f32 sp20, f32 sp24, f32 sp28);
u8 is_player_active(struct MarioState* m);
u8 is_other_player_active(void);
u8 is_player_in_local_area(struct MarioState* m);
struct MarioState* nearest_mario_state_to_object(struct Object* obj);
struct Object* nearest_player_to_object(struct Object* obj);
struct MarioState *nearest_interacting_mario_state_to_object(struct Object *obj);
struct Object *nearest_interacting_player_to_object(struct Object *obj);
u8 is_nearest_mario_state_to_object(struct MarioState* m, struct Object* obj);
u8 is_nearest_player_to_object(struct Object* m, struct Object* obj);
#endif // OBJ_BEHAVIORS_H

View file

@ -1036,6 +1036,22 @@ s32 count_objects_with_behavior(const BehaviorScript *behavior) {
return count;
}
struct Object *find_object_with_behavior(const BehaviorScript *behavior) {
uintptr_t *behaviorAddr = segmented_to_virtual(behavior);
struct ObjectNode *listHead = &gObjectLists[get_object_list_from_behavior(behaviorAddr)];
struct ObjectNode *obj = listHead->next;
while (listHead != obj) {
if (((struct Object *) obj)->behavior == behaviorAddr) {
return (struct Object *)obj;
}
obj = obj->next;
}
return NULL;
}
struct Object *cur_obj_find_nearby_held_actor(const BehaviorScript *behavior, f32 maxDist) {
const BehaviorScript *behaviorAddr = segmented_to_virtual(behavior);
struct ObjectNode *listHead;

View file

@ -146,6 +146,7 @@ f32 cur_obj_dist_to_nearest_object_with_behavior(const BehaviorScript* behavior)
struct Object* cur_obj_find_nearest_pole(void);
struct Object *cur_obj_find_nearest_object_with_behavior(const BehaviorScript * behavior, f32 *dist);
u16 cur_obj_count_objects_with_behavior(const BehaviorScript* behavior, f32 dist);
struct Object *find_object_with_behavior(const BehaviorScript *behavior);
struct Object *find_unimportant_object(void);
s32 count_unimportant_objects(void);
s32 count_objects_with_behavior(const BehaviorScript *behavior);