sm64pc/src/game/behaviors/yoshi.inc.c

181 lines
5.3 KiB
C

// yoshi.c.inc
// X/Z coordinates of Yoshi's homes that he switches between.
// Note that this doesn't contain the Y coordinate since the castle roof is flat,
// so o->oHomeY is never updated.
static s16 sYoshiHomeLocations[] = { 0, -5625, -1364, -5912, -1403, -4609, -1004, -5308 };
void bhv_yoshi_init(void) {
o->oGravity = 2.0f;
o->oFriction = 0.9f;
o->oBuoyancy = 1.3f;
o->oInteractionSubtype = INT_SUBTYPE_NPC;
if (save_file_get_total_star_count(gCurrSaveFileNum - 1, 0, 24) < 120 || sYoshiDead == TRUE) {
o->activeFlags = 0;
}
}
void yoshi_walk_loop(void) {
UNUSED s16 sp26;
s16 sp24 = o->header.gfx.unk38.animFrame;
o->oForwardVel = 10.0f;
sp26 = object_step();
o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, o->oYoshiTargetYaw, 0x500);
if (is_point_close_to_object(o, o->oHomeX, 3174.0f, o->oHomeZ, 200))
o->oAction = YOSHI_ACT_IDLE;
cur_obj_init_animation(1);
if (sp24 == 0 || sp24 == 15)
cur_obj_play_sound_2(SOUND_GENERAL_YOSHI_WALK);
if (o->oInteractStatus == INT_STATUS_INTERACTED)
o->oAction = YOSHI_ACT_TALK;
if (o->oPosY < 2100.0f) {
create_respawner(MODEL_YOSHI, bhvYoshi, 3000);
o->activeFlags = 0;
}
}
void yoshi_idle_loop(void) {
s16 chosenHome;
UNUSED s16 sp1C = o->header.gfx.unk38.animFrame;
if (o->oTimer > 90) {
chosenHome = random_float() * 3.99;
if (o->oYoshiChosenHome == chosenHome) {
return;
} else {
o->oYoshiChosenHome = chosenHome;
}
o->oHomeX = sYoshiHomeLocations[o->oYoshiChosenHome * 2];
o->oHomeZ = sYoshiHomeLocations[o->oYoshiChosenHome * 2 + 1];
o->oYoshiTargetYaw = atan2s(o->oHomeZ - o->oPosZ, o->oHomeX - o->oPosX);
o->oAction = YOSHI_ACT_WALK;
}
cur_obj_init_animation(0);
if (o->oInteractStatus == INT_STATUS_INTERACTED)
o->oAction = YOSHI_ACT_TALK;
// Credits; Yoshi appears at this position overlooking the castle near the end of the credits
if (gPlayerCameraState->cameraEvent == CAM_EVENT_START_ENDING ||
gPlayerCameraState->cameraEvent == CAM_EVENT_START_END_WAVING) {
o->oAction = YOSHI_ACT_CREDITS;
o->oPosX = -1798.0f;
o->oPosY = 3174.0f;
o->oPosZ = -3644.0f;
}
}
void yoshi_talk_loop(void) {
if ((s16) o->oMoveAngleYaw == (s16) o->oAngleToMario) {
cur_obj_init_animation(0);
if (set_mario_npc_dialog(1) == 2) {
o->activeFlags |= 0x20;
if (cutscene_object_with_dialog(CUTSCENE_DIALOG, o, DIALOG_161)) {
o->activeFlags &= ~0x20;
o->oInteractStatus = 0;
o->oHomeX = sYoshiHomeLocations[2];
o->oHomeZ = sYoshiHomeLocations[3];
o->oYoshiTargetYaw = atan2s(o->oHomeZ - o->oPosZ, o->oHomeX - o->oPosX);
o->oAction = YOSHI_ACT_GIVE_PRESENT;
}
}
} else {
cur_obj_init_animation(1);
play_puzzle_jingle();
o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, o->oAngleToMario, 0x500);
}
}
void yoshi_walk_and_jump_off_roof_loop(void) {
s16 sp26 = o->header.gfx.unk38.animFrame;
o->oForwardVel = 10.0f;
object_step();
cur_obj_init_animation(1);
if (o->oTimer == 0)
cutscene_object(CUTSCENE_STAR_SPAWN, o);
o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, o->oYoshiTargetYaw, 0x500);
if (is_point_close_to_object(o, o->oHomeX, 3174.0f, o->oHomeZ, 200)) {
cur_obj_init_animation(2);
cur_obj_play_sound_2(SOUND_GENERAL_ENEMY_ALERT1);
o->oForwardVel = 50.0f;
o->oVelY = 40.0f;
o->oMoveAngleYaw = -0x3FFF;
o->oAction = YOSHI_ACT_FINISH_JUMPING_AND_DESPAWN;
}
if (sp26 == 0 || sp26 == 15) {
cur_obj_play_sound_2(SOUND_GENERAL_YOSHI_WALK);
}
}
void yoshi_finish_jumping_and_despawn_loop(void) {
cur_obj_extend_animation_if_at_end();
obj_move_xyz_using_fvel_and_yaw(o);
o->oVelY -= 2.0;
if (o->oPosY < 2100.0f) {
set_mario_npc_dialog(0);
gObjCutsceneDone = TRUE;
sYoshiDead = 1;
o->activeFlags = 0;
}
}
void yoshi_give_present_loop(void) {
s32 sp1C = gGlobalTimer;
if (gHudDisplay.lives == 100) {
play_sound(SOUND_GENERAL_COLLECT_1UP, gDefaultSoundArgs);
gSpecialTripleJump = 1;
o->oAction = YOSHI_ACT_WALK_JUMP_OFF_ROOF;
return;
}
if ((sp1C & 0x03) == 0) {
play_sound(SOUND_MENU_YOSHI_GAIN_LIVES, gDefaultSoundArgs);
gMarioState->numLives++;
}
}
void bhv_yoshi_loop(void) {
switch (o->oAction) {
case YOSHI_ACT_IDLE:
yoshi_idle_loop();
break;
case YOSHI_ACT_WALK:
yoshi_walk_loop();
break;
case YOSHI_ACT_TALK:
yoshi_talk_loop();
break;
case YOSHI_ACT_WALK_JUMP_OFF_ROOF:
yoshi_walk_and_jump_off_roof_loop();
break;
case YOSHI_ACT_FINISH_JUMPING_AND_DESPAWN:
yoshi_finish_jumping_and_despawn_loop();
break;
case YOSHI_ACT_GIVE_PRESENT:
yoshi_give_present_loop();
break;
case YOSHI_ACT_CREDITS:
cur_obj_init_animation(0);
break;
}
curr_obj_random_blink(&o->oYoshiUnkF4);
}