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

    SetObjAnimation(1);
    if (sp24 == 0 || sp24 == 15)
        PlaySound2(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 = RandomFloat() * 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;
    }

    SetObjAnimation(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) {
        SetObjAnimation(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 {
        SetObjAnimation(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();
    SetObjAnimation(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)) {
        SetObjAnimation(2);
        PlaySound2(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) {
        PlaySound2(SOUND_GENERAL_YOSHI_WALK);
    }
}

void yoshi_finish_jumping_and_despawn_loop(void) {
    func_8029F728();
    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 BehYoshiLoop(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:
            SetObjAnimation(0);
            break;
    }

    ObjRandomBlink(&o->oYoshiUnkF4);
}
