#include "common.h"
#include "world/partners.h"
#include "effects.h"
#include "sprite/npc/WorldBombette.h"

BSS s32 D_802BE920;
BSS s32 D_802BE924;
BSS s32 D_802BE928;
BSS s32 D_802BE92C;
BSS s32 D_802BE930;
BSS s32 D_802BE934;
BSS s32 D_802BE938;
BSS s32 D_802BE93C;
BSS TweesterPhysics BombetteTweesterPhysics;

void entity_try_partner_interaction_trigger(s32 arg0);

void func_802BD100_317E50(Npc* npc) {
    f32 x, y, z;
    f32 angle = 0.0f;

    while (angle < 360.0f) {
        x = npc->pos.x;
        y = npc->pos.y;
        z = npc->pos.z;
        if (npc_test_move_taller_with_slipping(0x100000, &x, &y, &z, 30.0f, clamp_angle(npc->yaw + angle),
                                               npc->collisionHeight, npc->collisionRadius) != 0) {
            break;
        } else {
            angle += 45.0f;
        }
    }

    if (angle >= 360.0f) {
        angle = 0.0f;

        while (angle < 360.0f) {
            x = npc->pos.x;
            y = npc->pos.y;
            z = npc->pos.z;
            if (npc_test_move_taller_with_slipping(0x40000, &x, &y, &z, 30.0f, clamp_angle(npc->yaw + angle),
                                                   npc->collisionHeight, npc->collisionRadius) != 0) {
                break;
            } else {
                angle += 45.0f;
            }
        }

        if (!(angle >= 360.0f)) {
            if (NpcHitQueryColliderID >= 0 && (NpcHitQueryColliderID & COLLISION_WITH_ENTITY_BIT) != 0) {
                entity_try_partner_interaction_trigger(NpcHitQueryColliderID & ~COLLISION_WITH_ENTITY_BIT);
            }
        }
    } else {
        if (NpcHitQueryColliderID >= 0 && (NpcHitQueryColliderID & COLLISION_WITH_ENTITY_BIT) != 0) {
            entity_try_partner_interaction_trigger(NpcHitQueryColliderID & ~COLLISION_WITH_ENTITY_BIT);
        }
    }
}

void world_bombette_init(Npc* bombette) {
    bombette->collisionHeight = 28;
    bombette->collisionRadius = 24;
    D_802BE928 = 0;
    D_802BE924 = 0;
}

ApiStatus func_802BD300_318050(Evt* script, s32 isInitialCall) {
    Npc* bombette = script->owner2.npc;

    if (isInitialCall) {
        partner_init_get_out(bombette);
    }

    return partner_get_out(bombette) ? ApiStatus_DONE1 : ApiStatus_BLOCK;
}

EvtScript world_bombette_take_out = {
    EVT_CALL(func_802BD300_318050)
    EVT_RETURN
    EVT_END
};

TweesterPhysics* BombetteTweesterPhysicsPtr = &BombetteTweesterPhysics;

ApiStatus func_802BD338_318088(Evt* script, s32 isInitialCall) {
    PlayerData* playerData = &gPlayerData;
    Npc* bombette = script->owner2.npc;
    f32 sinAngle, cosAngle, liftoffVelocity;
    Entity* entity;

    if (isInitialCall) {
        partner_walking_enable(bombette, 1);
        mem_clear(BombetteTweesterPhysicsPtr, sizeof(TweesterPhysics));
        TweesterTouchingPartner = NULL;
    }

    playerData->partnerUsedTime[PARTNER_BOMBETTE]++;
    bombette->flags |= NPC_FLAG_DIRTY_SHADOW;
    entity = TweesterTouchingPartner;

    if (entity == NULL) {
        partner_walking_update_player_tracking(bombette);
        partner_walking_update_motion(bombette);
        return ApiStatus_BLOCK;
    }

    switch (BombetteTweesterPhysicsPtr->state) {
        case TWEESTER_PARTNER_INIT:
            BombetteTweesterPhysicsPtr->state++;
            BombetteTweesterPhysicsPtr->prevFlags = bombette->flags;
            BombetteTweesterPhysicsPtr->radius = fabsf(dist2D(bombette->pos.x, bombette->pos.z,
                                                     entity->position.x, entity->position.z));
            BombetteTweesterPhysicsPtr->angle = atan2(entity->position.x, entity->position.z,
                                              bombette->pos.x, bombette->pos.z);
            BombetteTweesterPhysicsPtr->angularVelocity = 6.0f;
            BombetteTweesterPhysicsPtr->liftoffVelocityPhase = 50.0f;
            BombetteTweesterPhysicsPtr->countdown = 120;
            bombette->flags |= NPC_FLAG_IGNORE_CAMERA_FOR_YAW | NPC_FLAG_IGNORE_PLAYER_COLLISION | NPC_FLAG_IGNORE_WORLD_COLLISION | NPC_FLAG_8;
            bombette->flags &= ~NPC_FLAG_GRAVITY;
        case TWEESTER_PARTNER_ATTRACT:
            sin_cos_rad(DEG_TO_RAD(BombetteTweesterPhysicsPtr->angle), &sinAngle, &cosAngle);
            bombette->pos.x = entity->position.x + (sinAngle * BombetteTweesterPhysicsPtr->radius);
            bombette->pos.z = entity->position.z - (cosAngle * BombetteTweesterPhysicsPtr->radius);
            BombetteTweesterPhysicsPtr->angle = clamp_angle(BombetteTweesterPhysicsPtr->angle - BombetteTweesterPhysicsPtr->angularVelocity);

            if (BombetteTweesterPhysicsPtr->radius > 20.0f) {
                BombetteTweesterPhysicsPtr->radius--;
            } else if (BombetteTweesterPhysicsPtr->radius < 19.0f) {
                BombetteTweesterPhysicsPtr->radius++;
            }

            liftoffVelocity = sin_rad(DEG_TO_RAD(BombetteTweesterPhysicsPtr->liftoffVelocityPhase)) * 3.0f;
            BombetteTweesterPhysicsPtr->liftoffVelocityPhase += 3.0f;

            if (BombetteTweesterPhysicsPtr->liftoffVelocityPhase > 150.0f) {
                BombetteTweesterPhysicsPtr->liftoffVelocityPhase = 150.0f;
            }

            bombette->pos.y += liftoffVelocity;
            bombette->renderYaw = clamp_angle(360.0f - BombetteTweesterPhysicsPtr->angle);
            BombetteTweesterPhysicsPtr->angularVelocity += 0.8;

            if (BombetteTweesterPhysicsPtr->angularVelocity > 40.0f) {
                BombetteTweesterPhysicsPtr->angularVelocity = 40.0f;
            }

            if (--BombetteTweesterPhysicsPtr->countdown == 0) {
                BombetteTweesterPhysicsPtr->state++;
            }
            break;
        case TWEESTER_PARTNER_HOLD:
            bombette->flags = BombetteTweesterPhysicsPtr->prevFlags;
            BombetteTweesterPhysicsPtr->countdown = 30;
            BombetteTweesterPhysicsPtr->state++;
            break;
        case TWEESTER_PARTNER_RELEASE:
            partner_walking_update_player_tracking(bombette);
            partner_walking_update_motion(bombette);

            if (--BombetteTweesterPhysicsPtr->countdown == 0) {
                BombetteTweesterPhysicsPtr->state = TWEESTER_PARTNER_INIT;
                TweesterTouchingPartner = NULL;
            }
            break;
    }
    return ApiStatus_BLOCK;
}

EvtScript world_bombette_update = {
    EVT_CALL(func_802BD338_318088)
    EVT_RETURN
    EVT_END
};

void func_802BD6DC_31842C(Npc* npc) {
    if (TweesterTouchingPartner != NULL) {
        TweesterTouchingPartner = NULL;
        npc->flags = BombetteTweesterPhysicsPtr->prevFlags;
        BombetteTweesterPhysicsPtr->state = TWEESTER_PARTNER_INIT;
        partner_clear_player_tracking(npc);
    }
}

s32 world_bombette_can_use_ability(Npc* npc) {
    if (gPartnerActionStatus.partnerActionState != PARTNER_ACTION_NONE) {
        D_802BE934 = 1;
        return FALSE;
    }
    return TRUE;
}

s32 world_bombette_can_player_pause(Npc* npc) {
    return gPartnerActionStatus.partnerActionState == PARTNER_ACTION_NONE;
}

ApiStatus func_802BD758_3184A8(Evt* evt, s32 isInitialCall);

ApiStatus func_802BD758_3184A8(Evt *evt, s32 isInitialCall) {
    PlayerStatus* playerStatus = &gPlayerStatus;
    CollisionStatus* collisionStatus = &gCollisionStatus;
    PartnerActionStatus* partnerActionStatus = &gPartnerActionStatus;
    Camera* camera = &gCameras[CAM_DEFAULT];
    Npc* npc = evt->owner2.npc;
    u16 temp_ret = ApiStatus_BLOCK;
    f32 x;
    f32 y;
    f32 z;
    f32 hitDepth;
    f32* zPtr;
    f32* xPtr;
    f32 temp_f0;
    f32 temp_f0_2;
    f32 temp_f0_5;
    s32 var_v0_5;
    f32 temp1;

    if (gCurrentEncounter.unk_08 != 0) {
        return ApiStatus_BLOCK;
    }

    if (isInitialCall) {
        func_802BD6DC_31842C(npc);
        evt->functionTemp[0] = 20;
    }

    switch (evt->functionTemp[0]) {
        case 20:
            if ((playerStatus->inputDisabledCount != 0) || (playerStatus->flags & PS_FLAG_JUMPING) || !(npc->flags & NPC_FLAG_GROUNDED)) {
                return ApiStatus_DONE2;
            }
            disable_player_input();
            evt->functionTemp[3] = playerStatus->inputDisabledCount;
            D_802BE92C = 1;
            D_802BE928 = 0;
            D_802BE930 = 0;
            D_802BE934 = 0;
            npc->flags &= ~(NPC_FLAG_JUMPING | NPC_FLAG_GRAVITY | NPC_FLAG_IGNORE_WORLD_COLLISION | NPC_FLAG_8);
            partnerActionStatus->partnerActionState = PARTNER_ACTION_USE;
            partnerActionStatus->actingPartner = PARTNER_BOMBETTE;
            D_802BE920 = partner_force_player_flip_done();
            enable_npc_blur(npc);
            npc->duration = 4;
            npc->yaw = atan2(npc->pos.x, npc->pos.z, playerStatus->position.x, playerStatus->position.z);
            suggest_player_anim_allow_backward(ANIM_Mario1_Idle);
            evt->functionTemp[0] = 21;
        case 21:
            if (playerStatus->actionState == ACTION_STATE_HIT_FIRE || playerStatus->actionState == ACTION_STATE_KNOCKBACK) {
                disable_npc_blur(npc);
                evt->functionTemp[0] = 7;
                break;
            }
            if (playerStatus->flags & PS_FLAG_JUMPING) {
                evt->functionTemp[0] = 7;
                break;
            }
            npc->moveToPos.x = playerStatus->position.x;
            npc->moveToPos.y = playerStatus->position.y;
            npc->moveToPos.z = playerStatus->position.z;
            npc->currentAnim = ANIM_WorldBombette_Run;
            add_vec2D_polar(&npc->moveToPos.x, &npc->moveToPos.z, 0.0f, playerStatus->targetYaw);
            temp_f0 = clamp_angle(playerStatus->targetYaw + ((D_802BE920 != 0) ? (-90.0f) : (90.0f)));
            add_vec2D_polar(&npc->moveToPos.x, &npc->moveToPos.z, playerStatus->colliderDiameter / 4, temp_f0);
            npc->pos.x += (npc->moveToPos.x - npc->pos.x) / npc->duration;
            npc->pos.y += (npc->moveToPos.y - npc->pos.y) / npc->duration;
            npc->pos.z += (npc->moveToPos.z - npc->pos.z) / npc->duration;
            npc->duration--;
            if (npc->duration != 0) {
                break;
            }
            if (evt->functionTemp[3] < playerStatus->inputDisabledCount) {
                disable_npc_blur(npc);
                temp_f0 = 0;
                evt->functionTemp[(u8)temp_f0] = 7;
                break;
            }
            npc->pos.x = npc->moveToPos.x;
            npc->pos.y = npc->moveToPos.y;
            npc->pos.z = npc->moveToPos.z;
            disable_npc_blur(npc);
            suggest_player_anim_allow_backward(ANIM_MarioW1_Lift);
            npc->yaw = playerStatus->targetYaw;
            npc->currentAnim = ANIM_WorldBombette_Walk;
            evt->functionTemp[0] = 1;
            evt->functionTemp[1] = 10;
        case 1:
            if (playerStatus->actionState == ACTION_STATE_HIT_FIRE || playerStatus->actionState == ACTION_STATE_KNOCKBACK) {
                evt->functionTemp[0] = 7;
                break;
            }
            npc->pos.y = playerStatus->position.y + playerStatus->colliderHeight;
            npc->yaw = playerStatus->targetYaw;
            if (evt->functionTemp[1] == 1) {
                suggest_player_anim_allow_backward(ANIM_MarioW1_PlaceItem);
            }
            if (evt->functionTemp[1] != 0) {
                evt->functionTemp[1]--;
                break;
            }
            sfx_play_sound_at_npc(SOUND_80000000, SOUND_SPACE_MODE_0, NPC_PARTNER);
            D_802BE924 = 1;
            add_vec2D_polar(&npc->pos.x, &npc->pos.z, 0.0f, npc->yaw);
            npc->currentAnim = ANIM_WorldBombette_WalkLit;
            npc->jumpVelocity = 0.0f;
            D_802BE938 = 0;
            npc->flags |= NPC_FLAG_GRAVITY;
            npc->flags &= ~NPC_FLAG_IGNORE_PLAYER_COLLISION;
            npc->moveSpeed = 1.0f;
            evt->functionTemp[0] = 2;
            evt->functionTemp[1] = 50;
        case 2:
            if ((playerStatus->animFlags & PA_FLAG_INTERRUPT_USE_PARTNER) || (playerStatus->actionState == ACTION_STATE_HIT_FIRE || playerStatus->actionState == ACTION_STATE_KNOCKBACK)) {
                evt->functionTemp[0] = 7;
                break;
            }
            if (evt->functionTemp[1] < 45) {
                if (!(npc->flags & NPC_FLAG_COLLDING_WITH_WORLD) && (D_802BE938 == 0)) {
                    npc_move_heading(npc, npc->moveSpeed, npc->yaw);
                    spawn_surface_effects(npc, SURFACE_INTERACT_WALK);
                } else {
                    D_802BE938 = 1;
                }
            }
            x = npc->pos.x;
            y = npc->pos.y + 14.0f;
            z = npc->pos.z;
            hitDepth = 16.0f;
            if ((npc_raycast_down_around(COLLISION_CHANNEL_10000, &x, &y, &z, &hitDepth, npc->yaw, npc->collisionRadius) != 0) && (((u32) ((get_collider_flags(NpcHitQueryColliderID) & 0xFF) - 2)) < 2U)) {
                if (playerStatus->actionState == ACTION_STATE_IDLE) {
                    suggest_player_anim_allow_backward(ANIM_Mario1_Idle);
                }
                npc->currentAnim = ANIM_WorldBombette_AboutToExplode;
                npc->flags &= ~NPC_FLAG_GRAVITY;
                evt->functionTemp[1] = 2;
                evt->functionTemp[0] = 3;
                if (D_802BE92C != 0) {
                    D_802BE92C = 0;
                    enable_player_input();
                }
            } else {
                if (!(evt->functionTemp[1] & 3)) {
                    if (gGameStatusPtr->frameCounter & 1) {
                        sfx_play_sound_at_npc(SOUND_STEP_NORMAL1, SOUND_SPACE_MODE_0, NPC_PARTNER);
                    } else {
                        sfx_play_sound_at_npc(SOUND_STEP_NORMAL2, SOUND_SPACE_MODE_0, NPC_PARTNER);
                    }
                }
                if (evt->functionTemp[1] == 40) {
                    if (playerStatus->actionState == ACTION_STATE_IDLE) {
                        suggest_player_anim_allow_backward(ANIM_Mario1_Idle);
                    }
                    enable_player_input();
                    D_802BE92C = 0;
                }
                npc_do_other_npc_collision(npc);
                if (npc->flags & NPC_FLAG_COLLIDING_WITH_NPC) {
                    if (D_802BE92C != 0) {
                        D_802BE92C = 0;
                        enable_player_input();
                    }
                } else if (D_802BE934 == 0) {
                    if (evt->functionTemp[1] != 0) {
                        evt->functionTemp[1]--;
                        break;
                    }
                }
                npc->currentAnim = ANIM_WorldBombette_AboutToExplode;
                evt->functionTemp[1] = 20;
                evt->functionTemp[0] = 3;
                if (playerStatus->actionState == ACTION_STATE_IDLE) {
                    suggest_player_anim_allow_backward(ANIM_Mario1_Idle);
                }
            }
    }

    switch (evt->functionTemp[0]) {
        case 3:
            if (evt->functionTemp[1] != 0) {
                evt->functionTemp[1]--;
                break;
            }
            if (D_802BE924 != 0) {
                D_802BE924 = 0;
                sfx_stop_sound(SOUND_80000000);
            }
            fx_explosion(gPlayerData.partners[gPlayerData.currentPartner].level, npc->pos.x, npc->pos.y + (npc->collisionHeight * 0.5f), npc->pos.z);
            switch (gPlayerData.partners[gPlayerData.currentPartner].level) {
                case 0:
                    sfx_play_sound_at_npc(SOUND_CANNON1, SOUND_SPACE_MODE_0, NPC_PARTNER);
                    break;
                case 1:
                    sfx_play_sound_at_npc(SOUND_CANNON2, SOUND_SPACE_MODE_0, NPC_PARTNER);
                    break;
                case 2:
                    sfx_play_sound_at_npc(SOUND_CANNON3, SOUND_SPACE_MODE_0, NPC_PARTNER);
                    break;
            }
            exec_ShakeCam1(0, 0, 20);
            spawn_surface_effects(npc, SURFACE_INTERACT_LAND);
            collisionStatus->bombetteExploded = 0;
            collisionStatus->bombetteExplosionPos.x = npc->pos.x;
            collisionStatus->bombetteExplosionPos.y = npc->pos.y;
            collisionStatus->bombetteExplosionPos.z = npc->pos.z;
            func_802BD100_317E50(npc);
            D_802BE928 = 1;
            partnerActionStatus->partnerActionState = PARTNER_ACTION_BOMBETTE_2;
            evt->functionTemp[1] = 3;
            evt->functionTemp[0]++;
            break;
        case 4:
            if (evt->functionTemp[1] != 0) {
                evt->functionTemp[1]--;
                break;
            }
            partnerActionStatus->partnerActionState = PARTNER_ACTION_BOMBETTE_3;
            D_802BE928 = 0;
            npc->jumpVelocity = ((playerStatus->position.y - npc->pos.y) / 20.0f) + 30.0;
            npc->moveSpeed = 0.8f;
            npc->yaw = rand_int(360);
            npc->jumpScale = 0.8f;
            npc->pos.y += 10.0f;
            npc->moveToPos.y = npc->pos.y;
            collisionStatus->bombetteExploded = -1;
            collisionStatus->bombetteExplosionPos.x = npc->pos.x;
            collisionStatus->bombetteExplosionPos.y = npc->pos.y;
            collisionStatus->bombetteExplosionPos.z = npc->pos.z;
            npc->currentAnim = ANIM_WorldBombette_Aftermath;
            temp1 = atan2(npc->pos.x, npc->pos.z, playerStatus->position.x, playerStatus->position.z);
            if (!(get_clamped_angle_diff(camera->currentYaw, temp1) < 0.0f)) {
                evt->functionTemp[2] = 1;
            } else {
                evt->functionTemp[2] = -1;
            }
            evt->functionTemp[1] = 10;
            evt->functionTemp[0] = 5;
            break;
        case 5:
            npc->pos.y += npc->jumpVelocity;
            npc->jumpVelocity -= npc->jumpScale;
            npc->rotation.z -= (evt->functionTemp[2] * 79) / 2;
            npc->rotation.x -= (evt->functionTemp[2] * 67) / 2;
            if (evt->functionTemp[1] != 0) {
                evt->functionTemp[1]--;
                break;
            }
            if (D_802BE930 == 0) {
                npc->pos.x = playerStatus->position.x;
                npc->pos.z = playerStatus->position.z;
            }
            npc->yaw = clamp_angle(gCameras[CAM_DEFAULT].currentYaw + playerStatus->spriteFacingAngle);
            add_vec2D_polar(&npc->pos.x, &npc->pos.z, 10.0f, npc->yaw);
            npc->jumpVelocity = 0.0f;
            npc->currentAnim = ANIM_WorldBombette_Aftermath;
            npc->flags |= NPC_FLAG_JUMPING;
            evt->functionTemp[0] = 6;
            break;
        case 6:
            if (npc->pos.y + 10.0f < playerStatus->position.y + playerStatus->colliderHeight) {
                npc->flags &= ~NPC_FLAG_JUMPING;
                if (fabsf(playerStatus->position.y - npc->pos.y) < 500.0) {
                    evt->functionTemp[0] = 8;
                    break;
                } else if (npc_try_snap_to_ground(npc, npc->jumpVelocity)) {
                    evt->functionTemp[0] = 7;
                    break;
                }
            }
            npc->pos.y += npc->jumpVelocity;
            npc->jumpVelocity -= npc->jumpScale;
            if (npc->jumpVelocity < -8.0) {
                npc->jumpVelocity = -8.0f;
            }
            npc->rotation.z -= (evt->functionTemp[2] * 79) / 2;
            npc->rotation.x -= (evt->functionTemp[2] * 67) / 2;
            break;
    }

    switch (evt->functionTemp[0]) {
        case 7:
            if (playerStatus->actionState == ACTION_STATE_IDLE) {
                suggest_player_anim_allow_backward(ANIM_Mario1_Idle);
            }
            if (D_802BE92C != 0) {
                D_802BE92C = 0;
                enable_player_input();
            }
            partnerActionStatus->partnerActionState = ACTION_STATE_IDLE;
            partnerActionStatus->actingPartner = PARTNER_NONE;
            npc->jumpVelocity = 0.0f;
            D_802BE928 = 0;
            D_802BE934 = 0;
            npc->pos.y = playerStatus->position.y;
            npc->rotation.x = 0.0f;
            npc->rotation.z = 0.0f;
            npc->currentAnim = ANIM_WorldBombette_Idle;
            partner_clear_player_tracking(npc);
            if (D_802BE924 != 0) {
                D_802BE924 = 0;
                sfx_stop_sound(SOUND_80000000);
            }
            temp_ret = ApiStatus_DONE2;
            return temp_ret;
        case 8:
            if (D_802BE92C != 0) {
                D_802BE92C = 0;
                enable_player_input();
            }
            partnerActionStatus->partnerActionState = PARTNER_ACTION_NONE;
            partnerActionStatus->actingPartner = PARTNER_NONE;
            npc->jumpVelocity = 0.0f;
            npc->pos.y = playerStatus->position.y;
            npc->rotation.x = 0.0f;
            npc->rotation.z = 0.0f;
            npc->currentAnim = ANIM_WorldBombette_Idle;
            npc->pos.x = playerStatus->position.x;
            npc->pos.y = playerStatus->position.y;
            npc->pos.z = playerStatus->position.z;
            D_802BE928 = 0;
            D_802BE934 = 0;
            xPtr = &npc->pos.x;
            zPtr = &npc->pos.z;
            if (D_802BE920 == 0) {
                add_vec2D_polar(xPtr, zPtr, playerStatus->colliderDiameter / 4, clamp_angle(playerStatus->targetYaw + 90.0f));
            } else {
                add_vec2D_polar(xPtr, zPtr, playerStatus->colliderDiameter / 4, clamp_angle(playerStatus->targetYaw - 90.0f));
            }
            npc->jumpVelocity = 0.0f;
            partner_clear_player_tracking(npc);
            temp_ret = ApiStatus_DONE2;
            if (D_802BE924 != 0) {
                D_802BE924 = 0;
                sfx_stop_sound(SOUND_80000000);
            }
            temp_ret = ApiStatus_DONE2;
            break;
        default:
            return ApiStatus_BLOCK;
    }

    return temp_ret;
}

EvtScript world_bombette_use_ability = {
    EVT_CALL(func_802BD758_3184A8)
    EVT_RETURN
    EVT_END
};

ApiStatus func_802BE4E8_319238(Evt* script, s32 isInitialCall) {
    Npc* bombette = script->owner2.npc;

    if (isInitialCall) {
        partner_init_put_away(bombette);
    }

    return partner_put_away(bombette) ? ApiStatus_DONE1 : ApiStatus_BLOCK;
}

EvtScript world_bombette_put_away = {
    EVT_CALL(func_802BE4E8_319238)
    EVT_RETURN
    EVT_END
};

s32 world_bombette_test_first_strike(Npc* bombette, Npc* enemy) {
    f32 adjustedDistanceX, adjustedDistanceY, adjustedDistanceZ;
    f32 temp_f6, temp_f20, npcZPos, bombetteZPos, npcXPos, bombetteXPos;
    s32 slippingResult;
    f32 distance;
    s32 ret;
    f32 temp2;
    f32 height;

    if (D_802BE928 == 0) {
        return FALSE;
    }

    npcXPos = enemy->pos.x;
    bombetteXPos = bombette->pos.x;
    adjustedDistanceX = enemy->pos.x - bombette->pos.x;

    adjustedDistanceY = (enemy->pos.y + (f32)(enemy->collisionHeight * 0.5) - bombette->pos.y);

    npcZPos = enemy->pos.z;
    bombetteZPos = bombette->pos.z;
    adjustedDistanceZ = npcZPos - bombetteZPos;

    temp_f6 = enemy->collisionRadius * 0.55;
    height = 35.0f;
    temp2 = sqrtf(SQ(adjustedDistanceX) + SQ(adjustedDistanceY) + SQ(adjustedDistanceZ));
    ret = FALSE;

    if (temp2 < (temp_f6 + height)) {
        ret = TRUE;
    }

    temp_f20 = atan2(npcXPos, npcZPos, bombetteXPos, bombetteZPos);
    distance = dist2D(npcXPos, npcZPos, bombetteXPos, bombetteZPos);

    adjustedDistanceX = bombette->pos.x;
    adjustedDistanceY = bombette->pos.y;
    adjustedDistanceZ = bombette->pos.z;

    slippingResult = npc_test_move_taller_with_slipping(0, &adjustedDistanceX, &adjustedDistanceY, &adjustedDistanceZ,
                                                        distance, temp_f20, height, 2.0f);

    if (slippingResult) {
        return FALSE;
    }

    return ret;
}

void world_bombette_pre_battle(Npc* bombette) {
    PlayerStatus* playerStatus = &gPlayerStatus;
    PartnerActionStatus* bombetteActionStatus = &gPartnerActionStatus;

    if (bombetteActionStatus->partnerActionState != PARTNER_ACTION_NONE) {
        if (D_802BE92C) {
            enable_player_input();
        }

        D_802BE928 = 0;
        playerStatus->flags &= ~PS_FLAG_JUMPING;
        bombette->jumpVelocity = 0.0f;
        bombette->flags &= ~NPC_FLAG_JUMPING;

        set_action_state(ACTION_STATE_IDLE);
        partner_clear_player_tracking(bombette);

        bombetteActionStatus->partnerActionState = PARTNER_ACTION_NONE;
        bombetteActionStatus->actingPartner = 0;

        bombette->pos.x = playerStatus->position.x;
        bombette->pos.y = playerStatus->position.y;
        bombette->pos.z = playerStatus->position.z;

        if (D_802BE920 == 0) {
            add_vec2D_polar(&bombette->pos.x, &bombette->pos.z,
                            playerStatus->colliderDiameter / 4, clamp_angle(playerStatus->targetYaw + 90.0f));
        } else {
            add_vec2D_polar(&bombette->pos.x, &bombette->pos.z,
                            playerStatus->colliderDiameter / 4, clamp_angle(playerStatus->targetYaw - 90.0f));
        }

        bombette->jumpVelocity = 0.0f;
        bombette->pos.y = playerStatus->position.y;
        bombette->rotation.x = 0.0f;
        bombette->rotation.z = 0.0f;
        bombette->currentAnim = ANIM_WorldBombette_Idle;
        partner_clear_player_tracking(bombette);
        disable_npc_blur(bombette);

        if (D_802BE924) {
            D_802BE924 = 0;
            sfx_stop_sound(SOUND_80000000);
        }
    }
}
