// IW6 GSC SOURCE
// Generated by https://github.com/xensik/gsc-tool

main()
{
    if ( maps\mp\_utility::is_aliens() )
        return;

    if ( isdefined( level.createfx_enabled ) && level.createfx_enabled )
        return;

    if ( level.script == "mp_character_room" )
        return;

    setup_callbacks();
    maps\mp\bots\_bots_personality::setup_personalities();
    level.badplace_cylinder_func = ::badplace_cylinder;
    level.badplace_delete_func = ::badplace_delete;
    maps\mp\bots\_bots_ks::bot_killstreak_setup();
    maps\mp\bots\_bots_loadout::init();
    level thread init();
}

setup_callbacks()
{
    level.bot_funcs = [];
    level.bot_funcs["bots_spawn"] = ::spawn_bots;
    level.bot_funcs["bots_add_scavenger_bag"] = ::bot_add_scavenger_bag;
    level.bot_funcs["bots_add_to_level_targets"] = maps\mp\bots\_bots_util::bot_add_to_bot_level_targets;
    level.bot_funcs["bots_remove_from_level_targets"] = maps\mp\bots\_bots_util::bot_remove_from_bot_level_targets;
    level.bot_funcs["bots_make_entity_sentient"] = ::bot_make_entity_sentient;
    level.bot_funcs["think"] = ::bot_think;
    level.bot_funcs["on_killed"] = ::on_bot_killed;
    level.bot_funcs["should_do_killcam"] = ::bot_should_do_killcam;
    level.bot_funcs["get_attacker_ent"] = maps\mp\bots\_bots_util::bot_get_known_attacker;
    level.bot_funcs["should_pickup_weapons"] = ::bot_should_pickup_weapons;
    level.bot_funcs["on_damaged"] = ::bot_damage_callback;
    level.bot_funcs["gametype_think"] = ::default_gametype_think;
    level.bot_funcs["leader_dialog"] = maps\mp\bots\_bots_util::bot_leader_dialog;
    level.bot_funcs["player_spawned"] = ::bot_player_spawned;
    level.bot_funcs["should_start_cautious_approach"] = maps\mp\bots\_bots_strategy::should_start_cautious_approach_default;
    level.bot_funcs["know_enemies_on_start"] = ::bot_know_enemies_on_start;
    level.bot_funcs["bot_get_rank_xp"] = ::bot_get_rank_xp;
    level.bot_funcs["ai_3d_sighting_model"] = ::bot_3d_sighting_model;
    level.bot_funcs["dropped_weapon_think"] = ::bot_think_seek_dropped_weapons;
    level.bot_funcs["dropped_weapon_cancel"] = ::should_stop_seeking_weapon;
    level.bot_funcs["crate_can_use"] = ::crate_can_use_always;
    level.bot_funcs["crate_low_ammo_check"] = ::crate_low_ammo_check;
    level.bot_funcs["crate_should_claim"] = ::crate_should_claim;
    level.bot_funcs["crate_wait_use"] = ::crate_wait_use;
    level.bot_funcs["crate_in_range"] = ::crate_in_range;
    level.bot_funcs["post_teleport"] = ::bot_post_teleport;
    level.bot_random_path_function = [];
    level.bot_random_path_function["allies"] = maps\mp\bots\_bots_personality::bot_random_path_default;
    level.bot_random_path_function["axis"] = maps\mp\bots\_bots_personality::bot_random_path_default;
    level.bot_can_use_box_by_type["deployable_vest"] = ::bot_should_use_ballistic_vest_crate;
    level.bot_can_use_box_by_type["deployable_ammo"] = ::bot_should_use_ammo_crate;
    level.bot_can_use_box_by_type["scavenger_bag"] = ::bot_should_use_scavenger_bag;
    level.bot_can_use_box_by_type["deployable_grenades"] = ::bot_should_use_grenade_crate;
    level.bot_can_use_box_by_type["deployable_juicebox"] = ::bot_should_use_juicebox_crate;
    level.bot_pre_use_box_of_type["deployable_ammo"] = ::bot_pre_use_ammo_crate;
    level.bot_post_use_box_of_type["deployable_ammo"] = ::bot_post_use_ammo_crate;
    level.bot_find_defend_node_func["capture"] = maps\mp\bots\_bots_strategy::find_defend_node_capture;
    level.bot_find_defend_node_func["capture_zone"] = maps\mp\bots\_bots_strategy::find_defend_node_capture_zone;
    level.bot_find_defend_node_func["protect"] = maps\mp\bots\_bots_strategy::find_defend_node_protect;
    level.bot_find_defend_node_func["bodyguard"] = maps\mp\bots\_bots_strategy::find_defend_node_bodyguard;
    level.bot_find_defend_node_func["patrol"] = maps\mp\bots\_bots_strategy::find_defend_node_patrol;
    maps\mp\bots\_bots_gametype_war::setup_callbacks();

    if ( maps\mp\_utility::bot_is_fireteam_mode() )
        maps\mp\bots\_bots_fireteam::bot_fireteam_setup_callbacks();
}

codecallback_leaderdialog( var_0, var_1 )
{
    if ( isdefined( level.bot_funcs ) && isdefined( level.bot_funcs["leader_dialog"] ) )
        self [[ level.bot_funcs["leader_dialog"] ]]( var_0, var_1 );
}

init()
{
    thread monitor_smoke_grenades();
    thread bot_triggers();
    initbotlevelvariables();

    if ( !shouldspawnbots() )
        return;

    refresh_existing_bots();
    var_0 = botautoconnectenabled();

    if ( var_0 > 0 )
    {
        setmatchdata( "hasBots", 1 );

        if ( maps\mp\_utility::bot_is_fireteam_mode() )
        {
            level thread maps\mp\bots\_bots_fireteam::bot_fireteam_init();
            level thread maps\mp\bots\_bots_fireteam_commander::init();
        }
        else
            level thread bot_connect_monitor();
    }
}

initbotlevelvariables()
{
    if ( !isdefined( level.crateownerusetime ) )
        level.crateownerusetime = 500;

    if ( !isdefined( level.cratenonownerusetime ) )
        level.cratenonownerusetime = 3000;

    level.bot_out_of_combat_time = 3000;
    level.bot_respawn_launcher_name = "iw6_panzerfaust3";
    level.bot_fallback_weapon = "iw6_knifeonly";
    level.zonecount = getzonecount();
    initbotmapextents();
}

initbotmapextents()
{
    if ( isdefined( level.teleportgetactivenodesfunc ) )
        var_0 = [[ level.teleportgetactivenodesfunc ]]();
    else
        var_0 = getallnodes();

    level.bot_map_min_x = 0;
    level.bot_map_max_x = 0;
    level.bot_map_min_y = 0;
    level.bot_map_max_y = 0;
    level.bot_map_min_z = 0;
    level.bot_map_max_z = 0;

    if ( var_0.size > 1 )
    {
        level.bot_map_min_x = var_0[0].origin[0];
        level.bot_map_max_x = var_0[0].origin[0];
        level.bot_map_min_y = var_0[0].origin[1];
        level.bot_map_max_y = var_0[0].origin[1];
        level.bot_map_min_z = var_0[0].origin[2];
        level.bot_map_max_z = var_0[0].origin[2];

        for ( var_1 = 1; var_1 < var_0.size; var_1++ )
        {
            var_2 = var_0[var_1].origin;

            if ( var_2[0] < level.bot_map_min_x )
                level.bot_map_min_x = var_2[0];

            if ( var_2[0] > level.bot_map_max_x )
                level.bot_map_max_x = var_2[0];

            if ( var_2[1] < level.bot_map_min_y )
                level.bot_map_min_y = var_2[1];

            if ( var_2[1] > level.bot_map_max_y )
                level.bot_map_max_y = var_2[1];

            if ( var_2[2] < level.bot_map_min_z )
                level.bot_map_min_z = var_2[2];

            if ( var_2[2] > level.bot_map_max_z )
                level.bot_map_max_z = var_2[2];
        }
    }

    level.bot_map_center = ( ( level.bot_map_min_x + level.bot_map_max_x ) / 2, ( level.bot_map_min_y + level.bot_map_max_y ) / 2, ( level.bot_map_min_z + level.bot_map_max_z ) / 2 );
    level.bot_variables_initialized = 1;
}

bot_post_teleport()
{
    level.bot_variables_initialized = undefined;
    level.bot_initialized_remote_vehicles = undefined;
    initbotmapextents();
    maps\mp\bots\_bots_ks_remote_vehicle::remote_vehicle_setup();
}

shouldspawnbots()
{
    return 1;
}

refresh_existing_bots()
{
    wait 1;

    foreach ( var_1 in level.players )
    {
        if ( isbot( var_1 ) )
        {
            var_1.equipment_enabled = 1;
            var_1.bot_team = var_1.team;
            var_1.bot_spawned_before = 1;
            var_1 thread [[ level.bot_funcs["think"] ]]();
        }
    }
}

bot_player_spawned()
{
    bot_set_loadout_class();

    if ( isdefined( self.prev_personality ) )
    {
        maps\mp\bots\_bots_util::bot_set_personality( self.prev_personality );
        self.prev_personality = undefined;
    }
}

bot_set_loadout_class()
{
    if ( !isdefined( self.bot_class ) )
    {
        if ( !bot_gametype_chooses_class() )
        {
            while ( !isdefined( level.bot_loadouts_initialized ) )
                wait 0.05;

            if ( isdefined( self.override_class_function ) )
                self.bot_class = [[ self.override_class_function ]]();
            else
                self.bot_class = maps\mp\bots\_bots_personality::bot_setup_callback_class();
        }
        else
            self.bot_class = self.class;
    }
}

watch_players_connecting()
{
    for (;;)
    {
        level waittill( "connected", var_0 );

        if ( !isai( var_0 ) && level.players.size > 0 )
        {
            level.players_waiting_to_join = common_scripts\utility::array_add( level.players_waiting_to_join, var_0 );
            childthread bots_notify_on_spawn( var_0 );
            childthread bots_notify_on_disconnect( var_0 );
            childthread bots_remove_from_array_on_notify( var_0 );
        }
    }
}

bots_notify_on_spawn( var_0 )
{
    var_0 endon( "bots_human_disconnected" );

    while ( !common_scripts\utility::array_contains( level.players, var_0 ) )
        wait 0.05;

    var_0 notify( "bots_human_spawned" );
}

bots_notify_on_disconnect( var_0 )
{
    var_0 endon( "bots_human_spawned" );
    var_0 waittill( "disconnect" );
    var_0 notify( "bots_human_disconnected" );
}

bots_remove_from_array_on_notify( var_0 )
{
    var_0 common_scripts\utility::waittill_any( "bots_human_spawned", "bots_human_disconnected" );
    level.players_waiting_to_join = common_scripts\utility::array_remove( level.players_waiting_to_join, var_0 );
}

monitor_pause_spawning()
{
    level.players_waiting_to_join = [];
    childthread watch_players_connecting();

    for (;;)
    {
        if ( level.players_waiting_to_join.size > 0 )
            level.pausing_bot_connect_monitor = 1;
        else
            level.pausing_bot_connect_monitor = 0;

        wait 0.5;
    }
}

bot_can_join_team( var_0 )
{
    if ( maps\mp\_utility::matchmakinggame() )
        return 1;

    if ( getdvar( "squad_vs_squad" ) == "1" )
        return 1;

    if ( !level.teambased )
        return 1;

    if ( maps\mp\gametypes\_teams::getjointeampermissions( var_0 ) )
        return 1;

    return 0;
}

bot_connect_monitor( var_0, var_1 )
{
    level endon( "game_ended" );
    self notify( "bot_connect_monitor" );
    self endon( "bot_connect_monitor" );
    level.pausing_bot_connect_monitor = 0;
    childthread monitor_pause_spawning();
    maps\mp\gametypes\_hostmigration::waitlongdurationwithhostmigrationpause( 0.5 );
    var_2 = 1.5;

    if ( !isdefined( level.bot_cm_spawned_bots ) )
        level.bot_cm_spawned_bots = 0;

    if ( !isdefined( level.bot_cm_waited_players_time ) )
        level.bot_cm_waited_players_time = 0;

    if ( !isdefined( level.bot_cm_human_picked ) )
        level.bot_cm_human_picked = 0;

    if ( getdvar( "squad_vs_squad" ) == "1" )
    {
        while ( !( isdefined( level.squad_vs_squad_allies_client ) && isdefined( level.squad_vs_squad_axis_client ) ) )
            wait 0.05;

        wait 2.0;
    }

    if ( getdvar( "squad_match" ) == "1" )
    {
        while ( !isdefined( level.squad_match_client ) )
            wait 0.05;

        wait 2.0;
    }

    if ( getdvar( "squad_use_hosts_squad" ) == "1" )
    {
        while ( !isdefined( level.wargame_client ) )
            wait 0.05;

        wait 2.0;
    }

    for (;;)
    {
        if ( level.pausing_bot_connect_monitor )
        {
            maps\mp\gametypes\_hostmigration::waitlongdurationwithhostmigrationpause( var_2 );
            continue;
        }

        var_3 = isdefined( level.bots_ignore_team_balance ) || !level.teambased;
        var_4 = botgetteamlimit( 0 );
        var_5 = botgetteamlimit( 1 );
        var_6 = botgetteamdifficulty( 0 );
        var_7 = botgetteamdifficulty( 1 );
        var_8 = "allies";
        var_9 = "axis";
        var_10 = bot_client_counts();
        var_11 = cat_array_get( var_10, "humans" );

        if ( var_11 > 1 )
        {
            var_12 = bot_get_host_team();

            if ( !maps\mp\_utility::matchmakinggame() && isdefined( var_12 ) && var_12 != "spectator" )
            {
                var_8 = var_12;
                var_9 = maps\mp\_utility::getotherteam( var_12 );
            }
            else
            {
                var_13 = cat_array_get( var_10, "humans_allies" );
                var_14 = cat_array_get( var_10, "humans_axis" );

                if ( var_14 > var_13 )
                {
                    var_8 = "axis";
                    var_9 = "allies";
                }
            }
        }
        else
        {
            var_15 = get_human_player();

            if ( isdefined( var_15 ) )
            {
                var_16 = var_15 bot_get_player_team();

                if ( isdefined( var_16 ) && var_16 != "spectator" )
                {
                    var_8 = var_16;
                    var_9 = maps\mp\_utility::getotherteam( var_16 );
                }
            }
        }

        var_17 = maps\mp\bots\_bots_util::bot_get_team_limit();
        var_18 = maps\mp\bots\_bots_util::bot_get_team_limit();

        if ( var_17 + var_18 < maps\mp\bots\_bots_util::bot_get_client_limit() )
        {
            if ( var_17 < var_4 )
                var_17++;
            else if ( var_18 < var_5 )
                var_18++;
        }

        var_19 = cat_array_get( var_10, "humans_" + var_8 );
        var_20 = cat_array_get( var_10, "humans_" + var_9 );
        var_21 = var_19 + var_20;
        var_22 = cat_array_get( var_10, "spectator" );
        var_23 = 0;

        for ( var_24 = 0; var_22 > 0; var_22-- )
        {
            var_25 = var_19 + var_23 + 1 <= var_17;
            var_26 = var_20 + var_24 + 1 <= var_18;

            if ( var_25 && !var_26 )
            {
                var_23++;
                continue;
            }

            if ( !var_25 && var_26 )
            {
                var_24++;
                continue;
            }

            if ( var_25 && var_26 )
            {
                if ( var_22 % 2 == 1 )
                {
                    var_23++;
                    continue;
                }

                var_24++;
            }
        }

        var_27 = cat_array_get( var_10, "bots_" + var_8 );
        var_28 = cat_array_get( var_10, "bots_" + var_9 );
        var_29 = var_27 + var_28;

        if ( var_29 > 0 )
            level.bot_cm_spawned_bots = 1;

        var_30 = 0;

        if ( !level.bot_cm_human_picked )
        {
            var_30 = !bot_get_human_picked_team();

            if ( !var_30 )
                level.bot_cm_human_picked = 1;
        }

        if ( var_30 )
        {
            var_31 = !getdvarint( "systemlink" ) && !getdvarint( "onlinegame" );
            var_32 = !var_3 && var_5 != var_4 && !level.bot_cm_spawned_bots && ( level.bot_cm_waited_players_time < 10 || !maps\mp\_utility::gameflag( "prematch_done" ) );

            if ( var_31 || var_32 )
            {
                level.bot_cm_waited_players_time = level.bot_cm_waited_players_time + var_2;
                maps\mp\gametypes\_hostmigration::waitlongdurationwithhostmigrationpause( var_2 );
                continue;
            }
        }

        var_33 = int( min( var_17 - var_19 - var_23, var_4 ) );
        var_34 = int( min( var_18 - var_20 - var_24, var_5 ) );
        var_35 = 1;
        var_36 = var_33 + var_34 + var_11;
        var_37 = var_4 + var_5 + var_11;

        for ( var_38 = [ -1, -1 ]; var_36 < maps\mp\bots\_bots_util::bot_get_client_limit() && var_36 < var_37; var_35 = !var_35 )
        {
            if ( var_35 && var_33 < var_4 && bot_can_join_team( var_8 ) )
                var_33++;
            else if ( !var_35 && var_34 < var_5 && bot_can_join_team( var_9 ) )
                var_34++;

            var_36 = var_33 + var_34 + var_11;

            if ( var_38[var_35] == var_36 )
                break;

            var_38[var_35] = var_36;
        }

        if ( var_4 == var_5 && !var_3 && var_23 == 1 && var_24 == 0 && var_34 > 0 )
        {
            if ( !isdefined( level.bot_prematchdonetime ) && maps\mp\_utility::gameflag( "prematch_done" ) )
                level.bot_prematchdonetime = gettime();

            if ( var_30 && ( !isdefined( level.bot_prematchdonetime ) || gettime() - level.bot_prematchdonetime < 10000 ) )
                var_34--;
        }

        var_39 = var_33 - var_27;
        var_40 = var_34 - var_28;
        var_41 = 1;

        if ( var_3 )
        {
            var_42 = var_17 + var_18;
            var_43 = var_4 + var_5;
            var_44 = var_19 + var_20;
            var_45 = var_27 + var_28;
            var_46 = int( min( var_42 - var_44, var_43 ) );
            var_47 = var_46 - var_45;

            if ( var_47 == 0 )
                var_41 = 0;
            else if ( var_47 > 0 )
            {
                var_39 = int( var_47 / 2 ) + var_47 % 2;
                var_40 = int( var_47 / 2 );
            }
            else if ( var_47 < 0 )
            {
                var_48 = var_47 * -1;
                var_39 = -1 * int( min( var_48, var_27 ) );
                var_40 = -1 * ( var_48 + var_39 );
            }
        }
        else if ( !maps\mp\_utility::matchmakinggame() && ( var_39 * var_40 < 0 && maps\mp\_utility::gameflag( "prematch_done" ) && !isdefined( level.bots_disable_team_switching ) ) )
        {
            var_49 = int( min( abs( var_39 ), abs( var_40 ) ) );

            if ( var_39 > 0 )
                move_bots_from_team_to_team( var_49, var_9, var_8, var_6 );
            else if ( var_40 > 0 )
                move_bots_from_team_to_team( var_49, var_8, var_9, var_7 );

            var_41 = 0;
        }

        if ( var_41 )
        {
            if ( var_40 < 0 )
                drop_bots( var_40 * -1, var_9 );

            if ( var_39 < 0 )
                drop_bots( var_39 * -1, var_8 );

            if ( var_40 > 0 )
                level thread spawn_bots( var_40, var_9, undefined, undefined, "spawned_enemies", var_7 );

            if ( var_39 > 0 )
                level thread spawn_bots( var_39, var_8, undefined, undefined, "spawned_allies", var_6 );

            if ( var_40 > 0 && var_39 > 0 )
                level common_scripts\utility::waittill_multiple( "spawned_enemies", "spawned_allies" );
            else if ( var_40 > 0 )
                level waittill( "spawned_enemies" );
            else if ( var_39 > 0 )
                level waittill( "spawned_allies" );
        }

        if ( var_7 != var_6 )
        {
            bots_update_difficulty( var_9, var_7 );
            bots_update_difficulty( var_8, var_6 );
        }

        maps\mp\gametypes\_hostmigration::waitlongdurationwithhostmigrationpause( var_2 );
    }
}

bot_get_player_team()
{
    if ( isdefined( self.team ) )
        return self.team;

    if ( isdefined( self.pers["team"] ) )
        return self.pers["team"];

    return undefined;
}

bot_get_host_team()
{
    foreach ( var_1 in level.players )
    {
        if ( !isai( var_1 ) && var_1 ishost() )
            return var_1 bot_get_player_team();
    }

    return "spectator";
}

bot_get_human_picked_team()
{
    var_0 = 0;
    var_1 = 0;
    var_2 = 0;

    foreach ( var_4 in level.players )
    {
        if ( !isai( var_4 ) )
        {
            if ( var_4 ishost() )
                var_0 = 1;

            if ( player_picked_team( var_4 ) )
            {
                var_1 = 1;

                if ( var_4 ishost() )
                    var_2 = 1;
            }
        }
    }

    return var_2 || var_1 && !var_0;
}

player_picked_team( var_0 )
{
    if ( isdefined( var_0.team ) && var_0.team != "spectator" )
        return 1;

    if ( isdefined( var_0.spectating_actively ) && var_0.spectating_actively )
        return 1;

    if ( var_0 ismlgspectator() && isdefined( var_0.team ) && var_0.team == "spectator" )
        return 1;

    return 0;
}

bot_client_counts()
{
    var_0 = [];

    for ( var_1 = 0; var_1 < level.players.size; var_1++ )
    {
        var_2 = level.players[var_1];

        if ( isdefined( var_2 ) && isdefined( var_2.team ) )
        {
            var_0 = cat_array_add( var_0, "all" );
            var_0 = cat_array_add( var_0, var_2.team );

            if ( isbot( var_2 ) )
            {
                var_0 = cat_array_add( var_0, "bots" );
                var_0 = cat_array_add( var_0, "bots_" + var_2.team );
                continue;
            }

            var_0 = cat_array_add( var_0, "humans" );
            var_0 = cat_array_add( var_0, "humans_" + var_2.team );
        }
    }

    return var_0;
}

cat_array_add( var_0, var_1 )
{
    if ( !isdefined( var_0 ) )
        var_0 = [];

    if ( !isdefined( var_0[var_1] ) )
        var_0[var_1] = 0;

    var_0[var_1] = var_0[var_1] + 1;
    return var_0;
}

cat_array_get( var_0, var_1 )
{
    if ( !isdefined( var_0 ) )
        return 0;

    if ( !isdefined( var_0[var_1] ) )
        return 0;

    return var_0[var_1];
}

move_bots_from_team_to_team( var_0, var_1, var_2, var_3 )
{
    foreach ( var_5 in level.players )
    {
        if ( !isdefined( var_5.team ) )
            continue;

        if ( isdefined( var_5.connected ) && var_5.connected && isbot( var_5 ) && var_5.team == var_1 )
        {
            var_5.bot_team = var_2;

            if ( isdefined( var_3 ) )
                var_5 maps\mp\bots\_bots_util::bot_set_difficulty( var_3 );

            var_5 notify( "luinotifyserver", "team_select", bot_lui_convert_team_to_int( var_2 ) );
            wait 0.05;
            var_5 notify( "luinotifyserver", "class_select", var_5.bot_class );
            var_0--;

            if ( var_0 <= 0 )
                break;
            else
                wait 0.1;
        }
    }
}

bots_update_difficulty( var_0, var_1 )
{
    foreach ( var_3 in level.players )
    {
        if ( !isdefined( var_3.team ) )
            continue;

        if ( isdefined( var_3.connected ) && var_3.connected && isbot( var_3 ) && var_3.team == var_0 )
        {
            if ( var_1 != var_3 botgetdifficulty() )
                var_3 maps\mp\bots\_bots_util::bot_set_difficulty( var_1 );
        }
    }
}

bot_drop()
{
    kick( self.entity_number, "EXE_PLAYERKICKED_BOT_BALANCE" );
    wait 0.1;
}

drop_bots( var_0, var_1 )
{
    var_2 = [];

    foreach ( var_4 in level.players )
    {
        if ( isdefined( var_4.connected ) && var_4.connected && isbot( var_4 ) && ( !isdefined( var_1 ) || isdefined( var_4.team ) && var_4.team == var_1 ) )
            var_2[var_2.size] = var_4;
    }

    for ( var_6 = var_2.size - 1; var_6 >= 0; var_6-- )
    {
        if ( var_0 <= 0 )
            break;

        if ( !maps\mp\_utility::isreallyalive( var_2[var_6] ) )
        {
            var_2[var_6] bot_drop();
            var_2 = common_scripts\utility::array_remove( var_2, var_2[var_6] );
            var_0--;
        }
    }

    for ( var_6 = var_2.size - 1; var_6 >= 0; var_6-- )
    {
        if ( var_0 <= 0 )
            break;

        var_2[var_6] bot_drop();
        var_0--;
    }
}

bot_lui_convert_team_to_int( var_0 )
{
    if ( var_0 == "axis" )
        return 0;
    else if ( var_0 == "allies" )
        return 1;
    else if ( var_0 == "autoassign" || var_0 == "random" )
        return 2;
    else
        return 3;
}

spawn_bot_latent( var_0, var_1, var_2 )
{
    var_3 = gettime() + 60000;

    while ( !self canspawntestclient() )
    {
        if ( gettime() >= var_3 )
        {
            kick( self.entity_number, "EXE_PLAYERKICKED_BOT_BALANCE" );
            var_2.abort = 1;
            return;
        }

        wait 0.05;

        if ( !isdefined( self ) )
        {
            var_2.abort = 1;
            return;
        }
    }

    maps\mp\gametypes\_hostmigration::waitlongdurationwithhostmigrationpause( randomfloatrange( 0.25, 2.0 ) );

    if ( !isdefined( self ) )
    {
        var_2.abort = 1;
        return;
    }

    self spawntestclient();
    self.pers["isBot"] = 1;
    self.equipment_enabled = 1;
    self.bot_team = var_0;

    if ( isdefined( var_2.difficulty ) )
        maps\mp\bots\_bots_util::bot_set_difficulty( var_2.difficulty );

    if ( isdefined( var_1 ) )
        self [[ var_1 ]]();

    self thread [[ level.bot_funcs["think"] ]]();
    var_2.ready = 1;
}

find_squad_member_index( var_0, var_1 )
{
    var_2 = var_0 getrankedplayerdata( "activeSquadMember" );
    var_3 = 0;
    var_4 = 0;

    while ( var_4 < 10 )
    {
        var_3 = 0;
        var_5 = var_0 getrankedplayerdata( "squadHQ", "aiSquadMembers", var_4 );

        if ( var_5 == var_2 )
        {
            var_4++;
            continue;
        }

        if ( !isdefined( level.human_team_bot_added ) || !isdefined( level.human_team_bot_added[var_5] ) || level.human_team_bot_added[var_5] == 0 )
            return var_5;

        var_4++;
    }

    return -1;
}

spawn_bots( var_0, var_1, var_2, var_3, var_4, var_5 )
{
    var_6 = gettime() + 10000;
    var_7 = [];
    var_8 = var_7.size;

    while ( level.players.size < maps\mp\bots\_bots_util::bot_get_client_limit() && var_7.size < var_0 && gettime() < var_6 )
    {
        maps\mp\gametypes\_hostmigration::waitlongdurationwithhostmigrationpause( 0.05 );
        var_9 = undefined;

        if ( getdvar( "squad_vs_squad" ) == "1" )
        {
            var_10 = level.squad_vs_squad_axis_client;

            if ( var_1 == "allies" )
                var_10 = level.squad_vs_squad_allies_client;

            if ( isdefined( var_10 ) )
            {
                var_11 = var_8;
                var_12 = var_10 getrankedplayerdata( "activeSquadMember" );
                var_13 = 0;
                var_14 = 0;

                for ( var_15 = 0; var_15 < maps\mp\bots\_bots_util::bot_get_team_limit(); var_15++ )
                {
                    var_14 = var_10 getrankedplayerdata( "squadHQ", "aiSquadMembers", var_15 );

                    if ( var_14 == var_12 )
                        continue;

                    if ( var_11 == var_13 )
                        break;

                    var_13++;
                }

                var_16 = var_10 getrankedplayerdata( "squadMembers", var_14, "name" );
                var_17 = var_10 getrankedplayerdata( "squadMembers", var_14, "head" );
                var_18 = var_10 getrankedplayerdata( "squadMembers", var_14, "body" );
                var_19 = var_10 getrankedplayerdata( "squadMembers", var_14, "helmet" );
                var_9 = addbot( var_16, var_17, var_18, var_19 );

                if ( isdefined( var_9 ) )
                    var_9.pers["squadSlot"] = var_14;
            }
            else if ( !isdefined( level.squad_vs_squad_has_forfeited ) )
            {
                if ( isdefined( level.squad_vs_squad_axis_client ) )
                {
                    level.finalkillcam_winner = "axis";
                    thread maps\mp\gametypes\_gamelogic::endgame( "axis", game["end_reason"]["allies_forfeited"] );
                }
                else
                {
                    level.finalkillcam_winner = "allies";
                    thread maps\mp\gametypes\_gamelogic::endgame( "allies", game["end_reason"]["axis_forfeited"] );
                }

                level.squad_vs_squad_has_forfeited = 1;
            }
        }
        else if ( getdvar( "squad_use_hosts_squad" ) == "1" )
        {
            if ( level.wargame_client.team == var_1 )
            {
                if ( maps\mp\_utility::matchmakinggame() )
                {
                    var_14 = find_squad_member_index( level.wargame_client, var_1 );
                    var_16 = level.wargame_client getrankedplayerdata( "squadMembers", var_14, "name" );
                    var_17 = level.wargame_client getrankedplayerdata( "squadMembers", var_14, "head" );
                    var_18 = level.wargame_client getrankedplayerdata( "squadMembers", var_14, "body" );
                    var_19 = level.wargame_client getrankedplayerdata( "squadMembers", var_14, "helmet" );
                    var_9 = addbot( var_16, var_17, var_18, var_19 );

                    if ( isdefined( var_9 ) )
                    {
                        level.human_team_bot_added[var_14] = 1;
                        var_9.pers["squadSlot"] = var_14;
                    }
                }
                else
                {
                    var_11 = var_8;
                    var_12 = level.wargame_client getprivateplayerdata( "privateMatchActiveSquadMember" );
                    var_13 = 0;
                    var_14 = 0;

                    for ( var_15 = 0; var_15 < maps\mp\bots\_bots_util::bot_get_team_limit(); var_15++ )
                    {
                        var_14 = var_15;

                        if ( var_15 == var_12 )
                            continue;

                        if ( var_11 == var_13 )
                            break;

                        var_13++;
                    }

                    var_16 = level.wargame_client getprivateplayerdata( "privateMatchSquadMembers", var_14, "name" );
                    var_17 = level.wargame_client getprivateplayerdata( "privateMatchSquadMembers", var_14, "head" );
                    var_18 = level.wargame_client getprivateplayerdata( "privateMatchSquadMembers", var_14, "body" );
                    var_19 = level.wargame_client getprivateplayerdata( "privateMatchSquadMembers", var_14, "helmet" );
                    var_9 = addbot( var_16, var_17, var_18, var_19 );

                    if ( isdefined( var_9 ) )
                        var_9.pers["squadSlot"] = var_14;
                }
            }
            else
                var_9 = addbot( "", 0, 0, 0 );
        }
        else if ( getdvar( "squad_match" ) == "1" )
        {
            if ( var_1 == "axis" )
            {
                var_14 = getenemysquaddata( "squadHQ", "aiSquadMembers", var_8 );
                var_16 = getenemysquaddata( "squadMembers", var_14, "name" );
                var_17 = getenemysquaddata( "squadMembers", var_14, "head" );
                var_18 = getenemysquaddata( "squadMembers", var_14, "body" );
                var_19 = getenemysquaddata( "squadMembers", var_14, "helmet" );
                var_9 = addbot( var_16, var_17, var_18, var_19 );

                if ( isdefined( var_9 ) )
                    var_9.pers["squadSlot"] = var_14;
            }
            else
            {
                var_14 = find_squad_member_index( level.squad_match_client, var_1 );

                if ( var_14 > -1 )
                {
                    var_16 = level.squad_match_client getrankedplayerdata( "squadMembers", var_14, "name" );
                    var_17 = level.squad_match_client getrankedplayerdata( "squadMembers", var_14, "head" );
                    var_18 = level.squad_match_client getrankedplayerdata( "squadMembers", var_14, "body" );
                    var_19 = level.squad_match_client getrankedplayerdata( "squadMembers", var_14, "helmet" );
                    var_9 = addbot( var_16, var_17, var_18, var_19 );

                    if ( isdefined( var_9 ) )
                    {
                        level.human_team_bot_added[var_14] = 1;
                        var_9.pers["squadSlot"] = var_14;
                    }
                }
            }
        }
        else
            var_9 = addbot( "", 0, 0, 0 );

        if ( !isdefined( var_9 ) )
        {
            if ( isdefined( var_3 ) && var_3 )
            {
                if ( isdefined( var_4 ) )
                    self notify( var_4 );

                return;
            }

            maps\mp\gametypes\_hostmigration::waitlongdurationwithhostmigrationpause( 1 );
            continue;
        }
        else
        {
            var_20 = spawnstruct();
            var_20.bot = var_9;
            var_20.ready = 0;
            var_20.abort = 0;
            var_20.index = var_8;
            var_20.difficulty = var_5;
            var_7[var_7.size] = var_20;
            var_20.bot thread spawn_bot_latent( var_1, var_2, var_20 );
            var_8++;
        }
    }

    var_21 = 0;
    var_6 = gettime() + 60000;

    while ( var_21 < var_7.size && gettime() < var_6 )
    {
        var_21 = 0;

        foreach ( var_20 in var_7 )
        {
            if ( var_20.ready || var_20.abort )
                var_21++;
        }

        wait 0.05;
    }

    if ( isdefined( var_4 ) )
        self notify( var_4 );
}

bot_gametype_chooses_team()
{
    if ( !level.teambased )
        return 1;

    if ( isdefined( level.bots_gametype_handles_team_choice ) && level.bots_gametype_handles_team_choice )
        return 1;

    return 0;
}

bot_gametype_chooses_class()
{
    return isdefined( level.bots_gametype_handles_class_choice ) && level.bots_gametype_handles_class_choice;
}

bot_think()
{
    self notify( "bot_think" );
    self endon( "bot_think" );
    self endon( "disconnect" );

    while ( !isdefined( self.pers["team"] ) )
        wait 0.05;

    level.hasbots = 1;

    if ( bot_gametype_chooses_team() )
        self.bot_team = self.pers["team"];

    var_0 = self.bot_team;

    if ( !isdefined( var_0 ) )
        var_0 = self.pers["team"];

    maps\mp\bots\_bots_ks::bot_killstreak_setup();
    self.entity_number = self getentitynumber();
    var_1 = 0;

    if ( !isdefined( self.bot_spawned_before ) )
    {
        var_1 = 1;
        self.bot_spawned_before = 1;

        if ( !bot_gametype_chooses_team() )
        {
            self notify( "luinotifyserver", "team_select", bot_lui_convert_team_to_int( var_0 ) );
            wait 0.5;

            if ( self.pers["team"] == "spectator" )
            {
                bot_drop();
                return;
            }
        }
    }

    for (;;)
    {
        maps\mp\bots\_bots_util::bot_set_difficulty( self botgetdifficulty() );
        var_2 = self botgetdifficultysetting( "advancedPersonality" );

        if ( var_1 && isdefined( var_2 ) && var_2 != 0 )
            maps\mp\bots\_bots_personality::bot_balance_personality();

        maps\mp\bots\_bots_personality::bot_assign_personality_functions();

        if ( var_1 )
        {
            bot_set_loadout_class();

            if ( !bot_gametype_chooses_class() )
                self notify( "luinotifyserver", "class_select", self.bot_class );

            if ( self.health == 0 )
                self waittill( "spawned_player" );

            if ( isdefined( level.bot_funcs ) && isdefined( level.bot_funcs["know_enemies_on_start"] ) )
                self thread [[ level.bot_funcs["know_enemies_on_start"] ]]();

            var_1 = 0;
        }

        bot_restart_think_threads();
        wait 0.1;
        self waittill( "death" );
        respawn_watcher();
        self waittill( "spawned_player" );
    }
}

respawn_watcher()
{
    self endon( "started_spawnPlayer" );

    while ( !self.waitingtospawn )
        wait 0.05;

    if ( maps\mp\gametypes\_playerlogic::needsbuttontorespawn() )
    {
        while ( self.waitingtospawn )
        {
            if ( self.sessionstate == "spectator" )
            {
                if ( getdvarint( "numlives" ) == 0 || self.pers["lives"] > 0 )
                    self botpressbutton( "use", 0.5 );
            }

            wait 1.0;
        }
    }
}

bot_get_rank_xp()
{
    if ( maps\mp\_utility::bot_israndom() == 0 )
    {
        if ( !isdefined( self.pers["rankxp"] ) )
            self.pers["rankxp"] = 0;

        return self.pers["rankxp"];
    }

    var_0 = self botgetdifficulty();
    var_1 = "bot_rank_" + var_0;

    if ( isdefined( self.pers[var_1] ) && self.pers[var_1] > 0 )
        return self.pers[var_1];

    var_2 = bot_random_ranks_for_difficulty( var_0 );
    var_3 = var_2["rank"];
    var_4 = var_2["prestige"];
    var_5 = maps\mp\gametypes\_rank::getrankinfominxp( var_3 );
    var_6 = var_5 + maps\mp\gametypes\_rank::getrankinfoxpamt( var_3 );
    var_7 = randomintrange( var_5, var_6 + 1 );
    self.pers[var_1] = var_7;
    return var_7;
}

bot_3d_sighting_model( var_0 )
{
    thread bot_3d_sighting_model_thread( var_0 );
}

bot_3d_sighting_model_thread( var_0 )
{
    var_0 endon( "disconnect" );
    self endon( "disconnect" );
    level endon( "game_ended" );

    for (;;)
    {
        if ( isalive( self ) && !self botcanseeentity( var_0 ) && common_scripts\utility::within_fov( self.origin, self.angles, var_0.origin, self botgetfovdot() ) )
            self botgetimperfectenemyinfo( var_0, var_0.origin );

        wait 0.1;
    }
}

bot_random_ranks_for_difficulty( var_0 )
{
    var_1 = [];
    var_1["rank"] = 0;
    var_1["prestige"] = 0;

    if ( var_0 == "default" )
        return var_1;

    if ( !isdefined( level.bot_rnd_rank ) )
    {
        level.bot_rnd_rank = [];
        level.bot_rnd_rank["recruit"][0] = 0;
        level.bot_rnd_rank["recruit"][1] = 7;
        level.bot_rnd_rank["regular"][0] = 9;
        level.bot_rnd_rank["regular"][1] = 37;
        level.bot_rnd_rank["hardened"][0] = 39;
        level.bot_rnd_rank["hardened"][1] = 57;
        level.bot_rnd_rank["veteran"][0] = 59;
        level.bot_rnd_rank["veteran"][1] = 59;
    }

    if ( !isdefined( level.bot_rnd_prestige ) )
    {
        level.bot_rnd_prestige = [];
        level.bot_rnd_prestige["recruit"][0] = 0;
        level.bot_rnd_prestige["recruit"][1] = 0;
        level.bot_rnd_prestige["regular"][0] = 0;
        level.bot_rnd_prestige["regular"][1] = 0;
        level.bot_rnd_prestige["hardened"][0] = 0;
        level.bot_rnd_prestige["hardened"][1] = 0;
        level.bot_rnd_prestige["veteran"][0] = 0;
        level.bot_rnd_prestige["veteran"][1] = 9;
    }

    if ( isdefined( level.bot_rnd_rank[var_0][0] ) && isdefined( level.bot_rnd_rank[var_0][1] ) )
        var_1["rank"] = randomintrange( level.bot_rnd_rank[var_0][0], level.bot_rnd_rank[var_0][1] + 1 );

    if ( isdefined( level.bot_rnd_prestige[var_0][0] ) && isdefined( level.bot_rnd_prestige[var_0][1] ) )
        var_1["prestige"] = randomintrange( level.bot_rnd_prestige[var_0][0], level.bot_rnd_prestige[var_0][1] + 1 );

    return var_1;
}

crate_can_use_always( var_0 )
{
    if ( isagent( self ) && !isdefined( var_0.boxtype ) )
        return 0;

    return 1;
}

get_human_player()
{
    var_0 = undefined;
    var_1 = getentarray( "player", "classname" );

    if ( isdefined( var_1 ) )
    {
        for ( var_2 = 0; var_2 < var_1.size; var_2++ )
        {
            if ( isdefined( var_1[var_2] ) && isdefined( var_1[var_2].connected ) && var_1[var_2].connected && !isai( var_1[var_2] ) && ( !isdefined( var_0 ) || var_0.team == "spectator" ) )
                var_0 = var_1[var_2];
        }
    }

    return var_0;
}

bot_damage_callback( var_0, var_1, var_2, var_3, var_4, var_5 )
{
    if ( !isdefined( self ) || !isalive( self ) )
        return;

    if ( var_2 == "MOD_FALLING" || var_2 == "MOD_SUICIDE" )
        return;

    if ( var_1 <= 0 )
        return;

    if ( !isdefined( var_4 ) )
    {
        if ( !isdefined( var_0 ) )
            return;

        var_4 = var_0;
    }

    if ( isdefined( var_4 ) )
    {
        if ( level.teambased )
        {
            if ( isdefined( var_4.team ) && var_4.team == self.team )
                return;
            else if ( isdefined( var_0 ) && isdefined( var_0.team ) && var_0.team == self.team )
                return;
        }

        var_6 = maps\mp\bots\_bots_util::bot_get_known_attacker( var_0, var_4 );

        if ( isdefined( var_6 ) )
            self botsetattacker( var_6 );
    }
}

on_bot_killed( var_0, var_1, var_2, var_3, var_4, var_5, var_6, var_7, var_8, var_9 )
{
    self botclearscriptenemy();
    self botclearscriptgoal();
    var_10 = maps\mp\bots\_bots_util::bot_get_known_attacker( var_1, var_0 );

    if ( !maps\mp\_utility::bot_is_fireteam_mode() && getdvar( "squad_match" ) != "1" && getdvar( "squad_vs_squad" ) != "1" && isdefined( var_10 ) && var_10.classname == "script_vehicle" && isdefined( var_10.helitype ) )
    {
        var_11 = self botgetdifficultysetting( "launcherRespawnChance" );

        if ( randomfloat( 1.0 ) < var_11 )
            self.respawn_with_launcher = 1;
    }
}

bot_should_do_killcam()
{
    if ( maps\mp\_utility::bot_is_fireteam_mode() )
        return 0;

    var_0 = 0.0;
    var_1 = self botgetdifficulty();

    if ( var_1 == "recruit" )
        var_0 = 0.1;
    else if ( var_1 == "regular" )
        var_0 = 0.4;
    else if ( var_1 == "hardened" )
        var_0 = 0.7;
    else if ( var_1 == "veteran" )
        var_0 = 1.0;

    return randomfloat( 1.0 ) < 1.0 - var_0;
}

bot_should_pickup_weapons()
{
    if ( maps\mp\_utility::isjuggernaut() )
        return 0;

    return 1;
}

bot_restart_think_threads()
{
    thread bot_think_watch_enemy();
    thread maps\mp\bots\_bots_strategy::bot_think_tactical_goals();
    self thread [[ level.bot_funcs["dropped_weapon_think"] ]]();
    thread bot_think_level_actions();
    thread bot_think_crate();
    thread bot_think_crate_blocking_path();
    thread maps\mp\bots\_bots_ks::bot_think_killstreak();
    thread maps\mp\bots\_bots_ks::bot_think_watch_aerial_killstreak();
    thread bot_think_gametype();
}

bot_think_watch_enemy( var_0 )
{
    var_1 = "spawned_player";

    if ( isdefined( var_0 ) && var_0 )
        var_1 = "death";

    self notify( "bot_think_watch_enemy" );
    self endon( "bot_think_watch_enemy" );
    self endon( var_1 );
    self endon( "disconnect" );
    level endon( "game_ended" );
    self.last_enemy_sight_time = gettime();

    for (;;)
    {
        if ( isdefined( self.enemy ) )
        {
            if ( self botcanseeentity( self.enemy ) )
                self.last_enemy_sight_time = gettime();
        }

        wait 0.05;
    }
}

bot_think_seek_dropped_weapons()
{
    self notify( "bot_think_seek_dropped_weapons" );
    self endon( "bot_think_seek_dropped_weapons" );
    self endon( "death" );
    self endon( "disconnect" );
    level endon( "game_ended" );
    var_0 = "throwingknife_mp";
    var_1 = "throwingknifejugg_mp";

    for (;;)
    {
        var_2 = 0;

        if ( maps\mp\bots\_bots_util::bot_out_of_ammo() && self [[ level.bot_funcs["should_pickup_weapons"] ]]() && !maps\mp\bots\_bots_util::bot_is_remote_or_linked() )
        {
            var_3 = getentarray( "dropped_weapon", "targetname" );
            var_4 = common_scripts\utility::get_array_of_closest( self.origin, var_3 );

            if ( var_4.size > 0 )
            {
                var_5 = var_4[0];
                bot_seek_dropped_weapon( var_5 );
            }
        }

        if ( !maps\mp\bots\_bots_util::bot_in_combat() && !maps\mp\bots\_bots_util::bot_is_remote_or_linked() && self botgetdifficultysetting( "strategyLevel" ) > 0 )
        {
            var_6 = self hasweapon( var_0 );
            var_7 = self hasweapon( var_1 );
            var_8 = var_6 && self getammocount( var_0 ) == 0 || var_7 && self getammocount( var_1 ) == 0;

            if ( var_8 )
            {
                if ( isdefined( self.going_for_knife ) )
                {
                    wait 5.0;
                    continue;
                }

                var_9 = getentarray( "dropped_knife", "targetname" );
                var_10 = common_scripts\utility::get_array_of_closest( self.origin, var_9 );

                foreach ( var_12 in var_10 )
                {
                    if ( !isdefined( var_12 ) )
                        continue;

                    if ( !isdefined( var_12.calculated_closest_point ) )
                    {
                        var_13 = maps\mp\bots\_bots_util::bot_queued_process( "BotGetClosestNavigablePoint", maps\mp\bots\_bots_util::func_bot_get_closest_navigable_point, var_12.origin, 32, self );

                        if ( isdefined( var_12 ) )
                        {
                            var_12.closest_point_on_grid = var_13;
                            var_12.calculated_closest_point = 1;
                        }
                        else
                            continue;
                    }

                    if ( isdefined( var_12.closest_point_on_grid ) )
                    {
                        self.going_for_knife = 1;
                        bot_seek_dropped_weapon( var_12 );
                    }
                }
            }
            else if ( var_6 || var_7 )
                self.going_for_knife = undefined;
        }

        wait( randomfloatrange( 0.25, 0.75 ) );
    }
}

bot_seek_dropped_weapon( var_0 )
{
    if ( maps\mp\bots\_bots_strategy::bot_has_tactical_goal( "seek_dropped_weapon", var_0 ) == 0 )
    {
        var_1 = undefined;

        if ( var_0.targetname == "dropped_weapon" )
        {
            var_2 = 1;
            var_3 = self getweaponslistprimaries();

            foreach ( var_5 in var_3 )
            {
                if ( var_0.model == getweaponmodel( var_5 ) )
                    var_2 = 0;
            }

            if ( var_2 )
                var_1 = ::bot_pickup_weapon;
        }

        var_7 = spawnstruct();
        var_7.object = var_0;
        var_7.script_goal_radius = 12;
        var_7.should_abort = level.bot_funcs["dropped_weapon_cancel"];
        var_7.action_thread = var_1;
        maps\mp\bots\_bots_strategy::bot_new_tactical_goal( "seek_dropped_weapon", var_0.origin, 100, var_7 );
    }
}

bot_pickup_weapon( var_0 )
{
    self botpressbutton( "use", 2 );
    wait 2;
}

should_stop_seeking_weapon( var_0 )
{
    if ( !isdefined( var_0.object ) )
        return 1;

    if ( var_0.object.targetname == "dropped_weapon" )
    {
        if ( maps\mp\bots\_bots_util::bot_get_total_gun_ammo() > 0 )
            return 1;
    }
    else if ( var_0.object.targetname == "dropped_knife" )
    {
        if ( maps\mp\bots\_bots_util::bot_in_combat() )
        {
            self.going_for_knife = undefined;
            return 1;
        }
    }

    return 0;
}

bot_think_level_actions( var_0 )
{
    self notify( "bot_think_level_actions" );
    self endon( "bot_think_level_actions" );
    self endon( "death" );
    self endon( "disconnect" );
    level endon( "game_ended" );

    for (;;)
    {
        common_scripts\utility::waittill_notify_or_timeout( "calculate_new_level_targets", randomfloatrange( 2, 10 ) );

        if ( !isdefined( level.level_specific_bot_targets ) || level.level_specific_bot_targets.size == 0 )
            continue;

        if ( maps\mp\bots\_bots_strategy::bot_has_tactical_goal( "map_interactive_object" ) )
            continue;

        if ( maps\mp\bots\_bots_util::bot_in_combat() || maps\mp\bots\_bots_util::bot_is_remote_or_linked() )
            continue;

        var_1 = undefined;

        foreach ( var_3 in level.level_specific_bot_targets )
        {
            if ( common_scripts\utility::array_contains( var_3.high_priority_for, self ) )
            {
                var_1 = var_3;
                break;
            }
        }

        if ( !isdefined( var_1 ) )
        {
            if ( randomint( 100 ) > 25 )
                continue;

            var_5 = common_scripts\utility::get_array_of_closest( self.origin, level.level_specific_bot_targets );
            var_6 = 256;

            if ( isdefined( var_0 ) )
                var_6 = var_0;
            else if ( self botgetscriptgoaltype() == "hunt" && self botpursuingscriptgoal() )
                var_6 = 512;

            if ( distancesquared( self.origin, var_5[0].origin ) > var_6 * var_6 )
                continue;

            var_1 = var_5[0];
        }

        var_7 = 0;

        if ( var_1.bot_interaction_type == "damage" )
        {
            var_7 = bot_should_melee_level_damage_target( var_1 );

            if ( var_7 )
            {
                var_8 = var_1.origin[2] - ( var_1.bot_targets[0].origin[2] + 55 );
                var_9 = var_1.origin[2] - ( var_1.bot_targets[1].origin[2] + 55 );

                if ( var_8 > 55 && var_9 > 55 )
                {
                    if ( common_scripts\utility::array_contains( var_1.high_priority_for, self ) )
                        var_1.high_priority_for = common_scripts\utility::array_remove( var_1.high_priority_for, self );

                    continue;
                }
            }

            var_10 = weaponclass( self getcurrentweapon() );

            if ( var_10 == "spread" )
            {
                var_11 = var_1.bot_targets[0].origin - var_1.origin;
                var_12 = var_1.bot_targets[1].origin - var_1.origin;
                var_13 = lengthsquared( var_11 );
                var_14 = lengthsquared( var_12 );

                if ( var_13 > 22500 && var_14 > 22500 )
                {
                    if ( common_scripts\utility::array_contains( var_1.high_priority_for, self ) )
                        var_1.high_priority_for = common_scripts\utility::array_remove( var_1.high_priority_for, self );

                    continue;
                }
            }
        }

        var_15 = spawnstruct();
        var_15.object = var_1;

        if ( var_1.bot_interaction_type == "damage" )
        {
            if ( var_7 )
                var_15.should_abort = ::level_trigger_should_abort_melee;
            else
                var_15.should_abort = ::level_trigger_should_abort_ranged;
        }

        if ( var_1.bot_interaction_type == "use" )
        {
            var_15.action_thread = ::use_use_trigger;
            var_15.should_abort = ::level_trigger_should_abort;
            var_15.script_goal_yaw = vectortoangles( var_1.origin - var_1.bot_target.origin )[1];
            maps\mp\bots\_bots_strategy::bot_new_tactical_goal( "map_interactive_object", var_1.bot_target.origin, 10, var_15 );
            continue;
        }

        if ( var_1.bot_interaction_type == "damage" )
        {
            if ( var_7 )
            {
                var_15.action_thread = ::melee_damage_trigger;
                var_15.script_goal_radius = 20;
            }
            else
            {
                var_15.action_thread = ::attack_damage_trigger;
                var_15.script_goal_radius = 50;
            }

            var_16 = undefined;
            var_17 = maps\mp\bots\_bots_util::bot_queued_process( "GetPathDistLevelAction", maps\mp\bots\_bots_util::func_get_path_dist, self.origin, var_1.bot_targets[0].origin );
            var_18 = maps\mp\bots\_bots_util::bot_queued_process( "GetPathDistLevelAction", maps\mp\bots\_bots_util::func_get_path_dist, self.origin, var_1.bot_targets[1].origin );

            if ( !isdefined( var_1 ) )
                continue;

            if ( var_17 <= 0 && var_18 <= 0 )
                continue;

            if ( var_17 > 0 )
            {
                if ( var_18 < 0 || var_17 <= var_18 )
                    var_16 = var_1.bot_targets[0];
            }

            if ( var_18 > 0 )
            {
                if ( var_17 < 0 || var_18 <= var_17 )
                    var_16 = var_1.bot_targets[1];
            }

            if ( !var_7 )
                childthread monitor_node_visible( var_16 );

            maps\mp\bots\_bots_strategy::bot_new_tactical_goal( "map_interactive_object", var_16.origin, 10, var_15 );
        }
    }
}

bot_should_melee_level_damage_target( var_0 )
{
    var_1 = self getcurrentweapon();
    var_2 = maps\mp\bots\_bots_util::bot_out_of_ammo() || self.hasriotshieldequipped || isdefined( self.isjuggernautmaniac ) && self.isjuggernautmaniac == 1 || weaponclass( var_1 ) == "grenade" || var_1 == "iw6_knifeonly_mp" || var_1 == "iw6_knifeonlyfast_mp";
    return var_2;
}

monitor_node_visible( var_0 )
{
    self endon( "goal" );
    wait 0.1;

    for (;;)
    {
        if ( weaponclass( self getcurrentweapon() ) == "spread" )
        {
            if ( distancesquared( self.origin, var_0.origin ) > 90000 )
            {
                wait 0.05;
                continue;
            }
        }

        var_1 = self getnearestnode();

        if ( isdefined( var_1 ) )
        {
            if ( nodesvisible( var_1, var_0 ) )
            {
                if ( sighttracepassed( self.origin + ( 0, 0, 55 ), var_0.origin + ( 0, 0, 55 ), 0, self ) )
                    self notify( "goal" );
            }
        }

        wait 0.05;
    }
}

attack_damage_trigger( var_0 )
{
    if ( var_0.object.origin[2] - self geteye()[2] > 55 )
    {
        if ( distance2dsquared( var_0.object.origin, self.origin ) < 225 )
            return;
    }

    self botsetflag( "disable_movement", 1 );
    look_at_damage_trigger( var_0.object, 0.3 );
    self botpressbutton( "ads", 0.3 );
    wait 0.25;
    var_1 = gettime();

    while ( isdefined( var_0.object ) && !isdefined( var_0.object.already_used ) && gettime() - var_1 < 5000 )
    {
        look_at_damage_trigger( var_0.object, 0.15 );
        self botpressbutton( "ads", 0.15 );
        self botpressbutton( "attack" );
        wait 0.1;
    }

    self botsetflag( "disable_movement", 0 );
}

melee_damage_trigger( var_0 )
{
    self botsetflag( "disable_movement", 1 );
    look_at_damage_trigger( var_0.object, 0.3 );
    wait 0.25;
    var_1 = gettime();

    while ( isdefined( var_0.object ) && !isdefined( var_0.object.already_used ) && gettime() - var_1 < 5000 )
    {
        look_at_damage_trigger( var_0.object, 0.15 );
        self botpressbutton( "melee" );
        wait 0.1;
    }

    self botsetflag( "disable_movement", 0 );
}

look_at_damage_trigger( var_0, var_1 )
{
    var_2 = var_0.origin;

    if ( distance2dsquared( self.origin, var_2 ) < 100 )
        var_2 = ( var_2[0], var_2[1], self geteye()[2] );

    self botlookatpoint( var_2, var_1, "script_forced" );
}

use_use_trigger( var_0 )
{
    if ( isagent( self ) )
    {
        common_scripts\utility::_enableusability();
        var_0.object enableplayeruse( self );
        wait 0.05;
    }

    var_1 = var_0.object.use_time;
    self botpressbutton( "use", var_1 );
    wait( var_1 );

    if ( isagent( self ) )
    {
        common_scripts\utility::_disableusability();

        if ( isdefined( var_0.object ) )
            var_0.object disableplayeruse( self );
    }
}

level_trigger_should_abort_melee( var_0 )
{
    if ( level_trigger_should_abort( var_0 ) )
        return 1;

    if ( !bot_should_melee_level_damage_target( var_0.object ) )
        return 1;

    return 0;
}

level_trigger_should_abort_ranged( var_0 )
{
    if ( level_trigger_should_abort( var_0 ) )
        return 1;

    if ( bot_should_melee_level_damage_target( var_0.object ) )
        return 1;

    return 0;
}

level_trigger_should_abort( var_0 )
{
    if ( !isdefined( var_0.object ) )
        return 1;

    if ( isdefined( var_0.object.already_used ) )
        return 1;

    if ( maps\mp\bots\_bots_util::bot_in_combat() )
        return 1;

    return 0;
}

crate_in_range( var_0 )
{
    if ( !isdefined( var_0.owner ) || var_0.owner != self )
    {
        if ( distancesquared( self.origin, var_0.origin ) > 4194304 )
            return 0;
    }

    return 1;
}

bot_crate_valid( var_0 )
{
    if ( !isdefined( var_0 ) )
        return 0;

    if ( !self [[ level.bot_funcs["crate_can_use"] ]]( var_0 ) )
        return 0;

    if ( !crate_landed_and_on_path_grid( var_0 ) )
        return 0;

    if ( level.teambased && isdefined( var_0.bomb ) && isdefined( var_0.team ) && var_0.team == self.team )
        return 0;

    if ( !self [[ level.bot_funcs["crate_in_range"] ]]( var_0 ) )
        return 0;

    if ( isdefined( var_0.boxtype ) )
    {
        if ( isdefined( level.boxsettings[var_0.boxtype] ) && ![[ level.boxsettings[var_0.boxtype].canusecallback ]]() )
            return 0;

        if ( isdefined( var_0.disabled_use_for ) && isdefined( var_0.disabled_use_for[self getentitynumber()] ) && var_0.disabled_use_for[self getentitynumber()] )
            return 0;

        if ( !self [[ level.bot_can_use_box_by_type[var_0.boxtype] ]]( var_0 ) )
            return 0;
    }

    return isdefined( var_0 );
}

crate_landed_and_on_path_grid( var_0 )
{
    if ( !crate_has_landed( var_0 ) )
        return 0;

    if ( !crate_is_on_path_grid( var_0 ) )
        return 0;

    return isdefined( var_0 );
}

crate_has_landed( var_0 )
{
    if ( isdefined( var_0.boxtype ) )
        return gettime() > var_0.birthtime + 1000;
    else
        return isdefined( var_0.droppingtoground ) && !var_0.droppingtoground;
}

crate_is_on_path_grid( var_0 )
{
    if ( !isdefined( var_0.on_path_grid ) )
        crate_calculate_on_path_grid( var_0 );

    return isdefined( var_0 ) && var_0.on_path_grid;
}

node_within_use_radius_of_crate( var_0, var_1 )
{
    if ( isdefined( var_1.boxtype ) && var_1.boxtype == "scavenger_bag" )
        return abs( var_0.origin[0] - var_1.origin[0] ) < 36 && abs( var_0.origin[0] - var_1.origin[0] ) < 36 && abs( var_0.origin[0] - var_1.origin[0] ) < 18;
    else
    {
        var_2 = getdvarfloat( "player_useRadius" );
        var_3 = distancesquared( var_1.origin, var_0.origin + ( 0, 0, 40 ) );
        return var_3 <= var_2 * var_2;
    }
}

crate_calculate_on_path_grid( var_0 )
{
    var_0 thread crate_monitor_position();
    var_0.on_path_grid = 0;
    var_1 = undefined;
    var_2 = undefined;

    if ( isdefined( var_0.forcedisconnectuntil ) )
    {
        var_1 = var_0.forcedisconnectuntil;
        var_2 = gettime() + 30000;
        var_0.forcedisconnectuntil = var_2;
        var_0 notify( "path_disconnect" );
    }

    wait 0.05;

    if ( !isdefined( var_0 ) )
        return;

    var_3 = crate_get_nearest_valid_nodes( var_0 );

    if ( !isdefined( var_0 ) )
        return;

    if ( isdefined( var_3 ) && var_3.size > 0 )
    {
        var_0.nearest_nodes = var_3;
        var_0.on_path_grid = 1;
    }
    else
    {
        var_4 = getdvarfloat( "player_useRadius" );
        var_5 = getnodesinradiussorted( var_0.origin, var_4 * 2, 0 )[0];
        var_6 = var_0 getpointinbounds( 0, 0, -1 );
        var_7 = undefined;

        if ( isdefined( var_0.boxtype ) && var_0.boxtype == "scavenger_bag" )
        {
            if ( maps\mp\bots\_bots_util::bot_point_is_on_pathgrid( var_0.origin ) )
                var_7 = var_0.origin;
        }
        else
            var_7 = botgetclosestnavigablepoint( var_0.origin, var_4 );

        if ( isdefined( var_5 ) && !var_5 nodeisdisconnected() && isdefined( var_7 ) && abs( var_5.origin[2] - var_6[2] ) < 30 )
        {
            var_0.nearest_points = [ var_7 ];
            var_0.nearest_nodes = [ var_5 ];
            var_0.on_path_grid = 1;
        }
    }

    if ( isdefined( var_0.forcedisconnectuntil ) )
    {
        if ( var_0.forcedisconnectuntil == var_2 )
            var_0.forcedisconnectuntil = var_1;
    }
}

crate_get_nearest_valid_nodes( var_0 )
{
    var_1 = getnodesinradiussorted( var_0.origin, 256, 0 );

    for ( var_2 = var_1.size; var_2 > 0; var_2-- )
        var_1[var_2] = var_1[var_2 - 1];

    var_1[0] = getclosestnodeinsight( var_0.origin );
    var_3 = undefined;

    if ( isdefined( var_0.forcedisconnectuntil ) )
        var_3 = getallnodes();

    var_4 = [];
    var_5 = 1;

    if ( !isdefined( var_0.boxtype ) )
        var_5 = 2;

    for ( var_2 = 0; var_2 < var_1.size; var_2++ )
    {
        var_6 = var_1[var_2];

        if ( !isdefined( var_6 ) || !isdefined( var_0 ) )
            continue;

        if ( var_6 nodeisdisconnected() )
            continue;

        if ( !node_within_use_radius_of_crate( var_6, var_0 ) )
        {
            if ( var_2 == 0 )
                continue;
            else
                break;
        }

        wait 0.05;

        if ( !isdefined( var_0 ) )
            break;

        if ( sighttracepassed( var_0.origin, var_6.origin + ( 0, 0, 55 ), 0, var_0 ) )
        {
            wait 0.05;

            if ( !isdefined( var_0 ) )
                break;

            if ( !isdefined( var_0.forcedisconnectuntil ) )
            {
                var_4[var_4.size] = var_6;

                if ( var_4.size == var_5 )
                    return var_4;
                else
                    continue;
            }

            var_7 = undefined;
            var_8 = 0;

            while ( !isdefined( var_7 ) && var_8 < 100 )
            {
                var_8++;
                var_9 = common_scripts\utility::random( var_3 );

                if ( distancesquared( var_6.origin, var_9.origin ) > 250000 )
                    var_7 = var_9;
            }

            if ( isdefined( var_7 ) )
            {
                var_10 = maps\mp\bots\_bots_util::bot_queued_process( "GetNodesOnPathCrate", maps\mp\bots\_bots_util::func_get_nodes_on_path, var_6.origin, var_7.origin );

                if ( isdefined( var_10 ) )
                {
                    var_4[var_4.size] = var_6;

                    if ( var_4.size == var_5 )
                        return var_4;
                    else
                        continue;
                }
            }
        }
    }

    return undefined;
}

crate_get_bot_target( var_0 )
{
    if ( isdefined( var_0.nearest_points ) )
        return var_0.nearest_points[0];

    if ( isdefined( var_0.nearest_nodes ) )
    {
        if ( var_0.nearest_nodes.size > 1 )
        {
            var_1 = common_scripts\utility::array_reverse( self botnodescoremultiple( var_0.nearest_nodes, "node_exposed" ) );
            return common_scripts\utility::random_weight_sorted( var_1 ).origin;
        }
        else
            return var_0.nearest_nodes[0].origin;
    }
}

crate_get_bot_target_check_distance( var_0, var_1 )
{
    var_2 = crate_get_bot_target( var_0 );
    var_3 = var_1 * 0.9;
    var_3 = var_3 * var_3;

    if ( distancesquared( var_0.origin, var_2 ) <= var_3 )
        return var_2;
    else
        return undefined;
}

bot_think_crate()
{
    self notify( "bot_think_crate" );
    self endon( "bot_think_crate" );
    self endon( "death" );
    self endon( "disconnect" );
    level endon( "game_ended" );
    var_0 = getdvarfloat( "player_useRadius" );

    for (;;)
    {
        var_1 = randomfloatrange( 2, 4 );
        common_scripts\utility::waittill_notify_or_timeout( "new_crate_to_take", var_1 );

        if ( isdefined( self.boxes ) && self.boxes.size == 0 )
            self.boxes = undefined;

        var_2 = level.carepackages;

        if ( !maps\mp\bots\_bots_util::bot_in_combat() && isdefined( self.boxes ) )
            var_2 = common_scripts\utility::array_combine( var_2, self.boxes );

        if ( isdefined( level.bot_scavenger_bags ) && maps\mp\_utility::_hasperk( "specialty_scavenger" ) )
            var_2 = common_scripts\utility::array_combine( var_2, level.bot_scavenger_bags );

        var_2 = common_scripts\utility::array_removeundefined( var_2 );

        if ( var_2.size == 0 )
            continue;

        if ( maps\mp\bots\_bots_strategy::bot_has_tactical_goal( "airdrop_crate" ) || self botgetscriptgoaltype() == "tactical" || maps\mp\bots\_bots_util::bot_is_remote_or_linked() )
            continue;

        var_3 = [];

        foreach ( var_5 in var_2 )
        {
            if ( bot_crate_valid( var_5 ) )
                var_3[var_3.size] = var_5;
        }

        var_3 = common_scripts\utility::array_remove_duplicates( var_3 );

        if ( var_3.size == 0 )
            continue;

        var_3 = common_scripts\utility::get_array_of_closest( self.origin, var_3 );
        var_7 = self getnearestnode();

        if ( !isdefined( var_7 ) )
            continue;

        var_8 = self [[ level.bot_funcs["crate_low_ammo_check"] ]]();
        var_9 = ( var_8 || randomint( 100 ) < 50 ) && !maps\mp\_utility::isemped();
        var_10 = undefined;

        foreach ( var_5 in var_3 )
        {
            var_12 = 0;

            if ( ( !isdefined( var_5.owner ) || var_5.owner != self ) && !isdefined( var_5.boxtype ) )
            {
                var_13 = [];

                foreach ( var_15 in level.players )
                {
                    if ( !isdefined( var_15.team ) )
                        continue;

                    if ( !isai( var_15 ) && level.teambased && var_15.team == self.team )
                    {
                        if ( distancesquared( var_15.origin, var_5.origin ) < 490000 )
                            var_13[var_13.size] = var_15;
                    }
                }

                if ( var_13.size > 0 )
                {
                    var_17 = var_13[0] getnearestnode();

                    if ( isdefined( var_17 ) )
                    {
                        var_12 = 0;

                        foreach ( var_19 in var_5.nearest_nodes )
                            var_12 = var_12 | nodesvisible( var_17, var_19, 1 );
                    }
                }
            }

            if ( !var_12 )
            {
                var_21 = isdefined( var_5.bots ) && isdefined( var_5.bots[self.team] ) && var_5.bots[self.team] > 0;
                var_22 = 0;

                foreach ( var_19 in var_5.nearest_nodes )
                    var_22 = var_22 | nodesvisible( var_7, var_19, 1 );

                if ( var_22 || var_9 && !var_21 )
                {
                    var_10 = var_5;
                    break;
                }
            }
        }

        if ( isdefined( var_10 ) )
        {
            if ( self [[ level.bot_funcs["crate_should_claim"] ]]() )
            {
                if ( !isdefined( var_10.boxtype ) )
                {
                    if ( !isdefined( var_10.bots ) )
                        var_10.bots = [];

                    var_10.bots[self.team] = 1;
                }
            }

            var_26 = spawnstruct();
            var_26.object = var_10;
            var_26.start_thread = ::watch_bot_died_during_crate;
            var_26.should_abort = ::crate_picked_up;
            var_27 = undefined;

            if ( isdefined( var_10.boxtype ) )
            {
                if ( isdefined( var_10.boxtouchonly ) && var_10.boxtouchonly )
                {
                    var_26.script_goal_radius = 16;
                    var_26.action_thread = undefined;
                    var_27 = var_10.origin;
                }
                else
                {
                    var_26.script_goal_radius = 50;
                    var_26.action_thread = ::use_box;
                    var_28 = crate_get_bot_target_check_distance( var_10, var_0 );

                    if ( !isdefined( var_28 ) )
                        continue;

                    var_28 = var_28 - var_10.origin;
                    var_29 = length( var_28 ) * randomfloat( 1.0 );
                    var_27 = var_10.origin + vectornormalize( var_28 ) * var_29 + ( 0, 0, 12 );
                }
            }
            else
            {
                var_26.action_thread = ::use_crate;
                var_26.end_thread = ::stop_using_crate;
                var_27 = crate_get_bot_target_check_distance( var_10, var_0 );

                if ( !isdefined( var_27 ) )
                    continue;

                var_26.script_goal_radius = var_0 - distance( var_10.origin, var_27 + ( 0, 0, 40 ) );
                var_27 = var_27 + ( 0, 0, 24 );
            }

            if ( isdefined( var_26.script_goal_radius ) )
            {

            }

            var_10 notify( "path_disconnect" );
            wait 0.05;

            if ( !isdefined( var_10 ) )
                continue;

            maps\mp\bots\_bots_strategy::bot_new_tactical_goal( "airdrop_crate", var_27, 30, var_26 );
        }
    }
}

bot_should_use_ballistic_vest_crate( var_0 )
{
    return 1;
}

crate_should_claim()
{
    return 1;
}

crate_low_ammo_check()
{
    return 0;
}

bot_should_use_ammo_crate( var_0 )
{
    if ( self getcurrentweapon() == level.boxsettings[var_0.boxtype].minigunweapon )
        return 0;

    return 1;
}

bot_pre_use_ammo_crate( var_0 )
{
    self switchtoweapon( self.secondaryweapon );
    wait 1.0;
}

bot_post_use_ammo_crate( var_0 )
{
    self switchtoweapon( "none" );
    self.secondaryweapon = self getcurrentweapon();
}

bot_should_use_scavenger_bag( var_0 )
{
    if ( maps\mp\bots\_bots_util::bot_get_low_on_ammo( 0.66 ) )
    {
        var_1 = self getnearestnode();

        if ( isdefined( var_0.nearest_nodes ) && isdefined( var_0.nearest_nodes[0] ) && isdefined( var_1 ) )
        {
            if ( nodesvisible( var_1, var_0.nearest_nodes[0], 1 ) )
            {
                if ( common_scripts\utility::within_fov( self.origin, self.angles, var_0.origin, self botgetfovdot() ) )
                    return 1;
            }
        }
    }

    return 0;
}

bot_should_use_grenade_crate( var_0 )
{
    var_1 = self getweaponslistoffhands();

    foreach ( var_3 in var_1 )
    {
        if ( self getweaponammostock( var_3 ) == 0 )
            return 1;
    }

    return 0;
}

bot_should_use_juicebox_crate( var_0 )
{
    return 1;
}

crate_monitor_position()
{
    self notify( "crate_monitor_position" );
    self endon( "crate_monitor_position" );
    self endon( "death" );
    level endon( "game_ended" );

    for (;;)
    {
        var_0 = self.origin;
        wait 0.5;

        if ( !isalive( self ) )
            return;

        if ( !maps\mp\bots\_bots_util::bot_vectors_are_equal( self.origin, var_0 ) )
        {
            self.on_path_grid = undefined;
            self.nearest_nodes = undefined;
            self.nearest_points = undefined;
        }
    }
}

crate_wait_use()
{

}

crate_picked_up( var_0 )
{
    if ( !isdefined( var_0.object ) )
        return 1;

    return 0;
}

use_crate( var_0 )
{
    if ( isagent( self ) )
    {
        common_scripts\utility::_enableusability();
        var_0.object enableplayeruse( self );
        wait 0.05;
    }

    self [[ level.bot_funcs["crate_wait_use"] ]]();

    if ( isdefined( var_0.object.owner ) && var_0.object.owner == self )
        var_1 = level.crateownerusetime / 1000 + 0.5;
    else
        var_1 = level.cratenonownerusetime / 1000 + 1.0;

    self botpressbutton( "use", var_1 );
    wait( var_1 );

    if ( isagent( self ) )
    {
        common_scripts\utility::_disableusability();

        if ( isdefined( var_0.object ) )
            var_0.object disableplayeruse( self );
    }

    if ( isdefined( var_0.object ) )
    {
        if ( !isdefined( var_0.object.bots_used ) )
            var_0.object.bots_used = [];

        var_0.object.bots_used[var_0.object.bots_used.size] = self;
    }
}

use_box( var_0 )
{
    if ( isagent( self ) )
    {
        common_scripts\utility::_enableusability();
        var_0.object enableplayeruse( self );
        wait 0.05;
    }

    if ( isdefined( var_0.object ) && isdefined( var_0.object.boxtype ) )
    {
        var_1 = var_0.object.boxtype;

        if ( isdefined( level.bot_pre_use_box_of_type[var_1] ) )
            self [[ level.bot_pre_use_box_of_type[var_1] ]]( var_0.object );

        if ( isdefined( var_0.object ) )
        {
            var_2 = level.boxsettings[var_0.object.boxtype].usetime / 1000 + 0.5;
            self botpressbutton( "use", var_2 );
            wait( var_2 );

            if ( isdefined( level.bot_post_use_box_of_type[var_1] ) )
                self [[ level.bot_post_use_box_of_type[var_1] ]]( var_0.object );
        }
    }

    if ( isagent( self ) )
    {
        common_scripts\utility::_disableusability();

        if ( isdefined( var_0.object ) )
            var_0.object disableplayeruse( self );
    }
}

watch_bot_died_during_crate( var_0 )
{
    thread bot_watch_for_death( var_0.object );
}

stop_using_crate( var_0 )
{
    if ( isdefined( var_0.object ) )
        var_0.object.bots[self.team] = 0;
}

bot_watch_for_death( var_0 )
{
    var_0 endon( "death" );
    var_0 endon( "revived" );
    var_0 endon( "disconnect" );
    level endon( "game_ended" );
    var_1 = self.team;
    common_scripts\utility::waittill_any( "death", "disconnect" );

    if ( isdefined( var_0 ) )
        var_0.bots[var_1] = 0;
}

bot_think_crate_blocking_path()
{
    self notify( "bot_think_crate_blocking_path" );
    self endon( "bot_think_crate_blocking_path" );
    self endon( "death" );
    self endon( "disconnect" );
    level endon( "game_ended" );
    var_0 = getdvarfloat( "player_useRadius" );

    for (;;)
    {
        wait 3;

        if ( self usebuttonpressed() )
            continue;

        if ( maps\mp\_utility::isusingremote() )
            continue;

        var_1 = level.carepackages;

        for ( var_2 = 0; var_2 < var_1.size; var_2++ )
        {
            var_3 = var_1[var_2];

            if ( !isdefined( var_3 ) )
                continue;

            if ( distancesquared( self.origin, var_3.origin ) < var_0 * var_0 )
            {
                if ( var_3.owner == self )
                {
                    self botpressbutton( "use", level.crateownerusetime / 1000 + 0.5 );
                    continue;
                }

                self botpressbutton( "use", level.cratenonownerusetime / 1000 + 0.5 );
            }
        }
    }
}

bot_think_revive()
{
    self notify( "bot_think_revive" );
    self endon( "bot_think_revive" );
    self endon( "death" );
    self endon( "disconnect" );
    level endon( "game_ended" );

    if ( !level.teambased )
        return;

    for (;;)
    {
        var_0 = 2.0;
        var_1 = getentarray( "revive_trigger", "targetname" );

        if ( var_1.size > 0 )
            var_0 = 0.05;

        level common_scripts\utility::waittill_notify_or_timeout( "player_last_stand", var_0 );

        if ( !bot_can_revive() )
            continue;

        var_1 = getentarray( "revive_trigger", "targetname" );

        if ( var_1.size > 1 )
        {
            var_1 = sortbydistance( var_1, self.origin );

            if ( isdefined( self.owner ) )
            {
                for ( var_2 = 0; var_2 < var_1.size; var_2++ )
                {
                    if ( var_1[var_2].owner != self.owner )
                        continue;

                    if ( var_2 == 0 )
                        break;

                    var_3 = var_1[var_2];
                    var_1[var_2] = var_1[0];
                    var_1[0] = var_3;
                    break;
                }
            }
        }

        for ( var_2 = 0; var_2 < var_1.size; var_2++ )
        {
            var_4 = var_1[var_2];
            var_5 = var_4.owner;

            if ( !isdefined( var_5 ) )
                continue;

            if ( var_5 == self )
                continue;

            if ( !isalive( var_5 ) )
                continue;

            if ( var_5.team != self.team )
                continue;

            if ( !isdefined( var_5.inlaststand ) || !var_5.inlaststand )
                continue;

            if ( isdefined( var_5.bots ) && isdefined( var_5.bots[self.team] ) && var_5.bots[self.team] > 0 )
                continue;

            if ( distancesquared( self.origin, var_5.origin ) < 4194304 )
            {
                var_6 = spawnstruct();
                var_6.object = var_4;
                var_6.script_goal_radius = 64;

                if ( isdefined( self.last_revive_fail_time ) && gettime() - self.last_revive_fail_time < 1000 )
                    var_6.script_goal_radius = 32;

                var_6.start_thread = ::watch_bot_died_during_revive;
                var_6.end_thread = ::stop_reviving;
                var_6.should_abort = ::player_revived_or_dead;
                var_6.action_thread = ::revive_player;
                maps\mp\bots\_bots_strategy::bot_new_tactical_goal( "revive", var_5.origin, 60, var_6 );
                break;
            }
        }
    }
}

watch_bot_died_during_revive( var_0 )
{
    thread bot_watch_for_death( var_0.object.owner );
}

stop_reviving( var_0 )
{
    if ( isdefined( var_0.object.owner ) )
        var_0.object.owner.bots[self.team] = 0;
}

player_revived_or_dead( var_0 )
{
    if ( !isdefined( var_0.object.owner ) || var_0.object.owner.health <= 0 )
        return 1;

    if ( !isdefined( var_0.object.owner.inlaststand ) || !var_0.object.owner.inlaststand )
        return 1;

    return 0;
}

revive_player( var_0 )
{
    if ( distancesquared( self.origin, var_0.object.owner.origin ) > 4096 )
    {
        self.last_revive_fail_time = gettime();
        return;
    }

    if ( isagent( self ) )
    {
        common_scripts\utility::_enableusability();
        var_0.object enableplayeruse( self );
        wait 0.05;
    }

    var_1 = self.team;
    self botpressbutton( "use", level.laststandusetime / 1000 + 0.5 );
    wait( level.laststandusetime / 1000 + 1.5 );

    if ( isdefined( var_0.object.owner ) )
        var_0.object.bots[var_1] = 0;

    if ( isagent( self ) )
    {
        common_scripts\utility::_disableusability();

        if ( isdefined( var_0.object ) )
            var_0.object disableplayeruse( self );
    }
}

bot_can_revive()
{
    if ( isdefined( self.laststand ) && self.laststand == 1 )
        return 0;

    if ( maps\mp\bots\_bots_strategy::bot_has_tactical_goal( "revive" ) )
        return 0;

    if ( maps\mp\bots\_bots_util::bot_is_remote_or_linked() )
        return 0;

    if ( maps\mp\bots\_bots_util::bot_is_bodyguarding() )
        return 1;

    var_0 = self botgetscriptgoaltype();

    if ( var_0 == "none" || var_0 == "hunt" || var_0 == "guard" )
        return 1;

    return 0;
}

revive_watch_for_finished( var_0 )
{
    self endon( "death" );
    self endon( "disconnect" );
    self endon( "bad_path" );
    self endon( "goal" );
    var_0 common_scripts\utility::waittill_any( "death", "revived" );
    self notify( "bad_path" );
}

bot_know_enemies_on_start()
{
    self endon( "death" );
    self endon( "disconnect" );
    level endon( "game_ended" );

    if ( gettime() > 15000 )
        return;

    while ( !maps\mp\_utility::gamehasstarted() || !maps\mp\_utility::gameflag( "prematch_done" ) )
        wait 0.05;

    var_0 = undefined;
    var_1 = undefined;

    for ( var_2 = 0; var_2 < level.players.size; var_2++ )
    {
        var_3 = level.players[var_2];

        if ( isdefined( var_3 ) && isdefined( self.team ) && isdefined( var_3.team ) && isenemyteam( self.team, var_3.team ) )
        {
            if ( !isdefined( var_3.bot_start_known_by_enemy ) )
                var_0 = var_3;

            if ( isai( var_3 ) && !isdefined( var_3.bot_start_know_enemy ) )
                var_1 = var_3;
        }
    }

    if ( isdefined( var_0 ) )
    {
        self.bot_start_know_enemy = 1;
        var_0.bot_start_known_by_enemy = 1;
        self getenemyinfo( var_0 );
    }

    if ( isdefined( var_1 ) )
    {
        var_1.bot_start_know_enemy = 1;
        self.bot_start_known_by_enemy = 1;
        var_1 getenemyinfo( self );
    }
}

bot_make_entity_sentient( var_0, var_1 )
{
    if ( isdefined( var_1 ) )
        return self makeentitysentient( var_0, var_1 );
    else
        return self makeentitysentient( var_0 );
}

bot_think_gametype()
{
    self notify( "bot_think_gametype" );
    self endon( "bot_think_gametype" );
    self endon( "death" );
    self endon( "disconnect" );
    level endon( "game_ended" );
    maps\mp\_utility::gameflagwait( "prematch_done" );
    self thread [[ level.bot_funcs["gametype_think"] ]]();
}

default_gametype_think()
{

}

monitor_smoke_grenades()
{
    for (;;)
    {
        level waittill( "smoke", var_0, var_1 );

        if ( var_1 == "smoke_grenade_mp" || var_1 == "smoke_grenadejugg_mp" || var_1 == "odin_projectile_smoke_mp" )
        {
            var_0 thread handle_smoke( 9.0 );
            continue;
        }

        if ( var_1 == "odin_projectile_large_rod_mp" )
            var_0 thread handle_smoke( 2.5 );
    }
}

handle_smoke( var_0 )
{
    self waittill( "explode", var_1 );
    var_2 = common_scripts\utility::spawn_tag_origin();
    var_2 show();
    var_2.origin = var_1;
    var_3 = 0.8;
    wait( var_3 );
    var_3 = 0.5;
    var_4 = getent( "smoke_grenade_sight_clip_64_short", "targetname" );

    if ( isdefined( var_4 ) )
        var_2 clonebrushmodeltoscriptmodel( var_4 );

    wait( var_3 );
    var_3 = 0.6;
    var_5 = getent( "smoke_grenade_sight_clip_64_tall", "targetname" );

    if ( isdefined( var_5 ) )
        var_2 clonebrushmodeltoscriptmodel( var_5 );

    wait( var_3 );
    var_3 = var_0;
    var_6 = getent( "smoke_grenade_sight_clip_256", "targetname" );

    if ( isdefined( var_6 ) )
        var_2 clonebrushmodeltoscriptmodel( var_6 );

    wait( var_3 );
    var_2 delete();
}

bot_add_scavenger_bag( var_0 )
{
    var_1 = 0;
    var_0.boxtype = "scavenger_bag";
    var_0.boxtouchonly = 1;

    if ( !isdefined( level.bot_scavenger_bags ) )
        level.bot_scavenger_bags = [];

    foreach ( var_4, var_3 in level.bot_scavenger_bags )
    {
        if ( !isdefined( var_3 ) )
        {
            var_1 = 1;
            level.bot_scavenger_bags[var_4] = var_0;
            break;
        }
    }

    if ( !var_1 )
        level.bot_scavenger_bags[level.bot_scavenger_bags.size] = var_0;

    foreach ( var_6 in level.participants )
    {
        if ( isai( var_6 ) && var_6 maps\mp\_utility::_hasperk( "specialty_scavenger" ) )
            var_6 notify( "new_crate_to_take" );
    }
}

bot_triggers()
{
    var_0 = getentarray( "bot_flag_set", "targetname" );

    foreach ( var_2 in var_0 )
    {
        if ( !isdefined( var_2.script_noteworthy ) )
            continue;

        var_2 thread bot_flag_trigger( var_2.script_noteworthy );
    }
}

bot_flag_trigger( var_0 )
{
    self endon( "death" );

    for (;;)
    {
        self waittill( "trigger", var_1 );

        if ( maps\mp\_utility::isaigameparticipant( var_1 ) )
        {
            var_1 notify( "flag_trigger_set_" + var_0 );
            var_1 botsetflag( var_0, 1 );
            var_1 thread bot_flag_trigger_clear( var_0 );
        }
    }
}

bot_flag_trigger_clear( var_0 )
{
    self endon( "flag_trigger_set_" + var_0 );
    self endon( "death" );
    self endon( "disconnect" );
    level endon( "game_ended" );
    common_scripts\utility::waitframe();
    waittillframeend;
    self botsetflag( var_0, 0 );
}
