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

gettargetangleoffset( var_0 )
{
    var_1 = self getshootatpos() + ( 0, 0, -3 );
    var_2 = ( var_1[0] - var_0[0], var_1[1] - var_0[1], var_1[2] - var_0[2] );
    var_2 = vectornormalize( var_2 );
    var_3 = var_2[2] * -1;
    return var_3;
}

getsniperburstdelaytime()
{
    if ( isplayer( self.enemy ) )
        return randomfloatrange( self.enemy.gs.min_sniper_burst_delay_time, self.enemy.gs.max_sniper_burst_delay_time );
    else
        return randomfloatrange( anim.min_sniper_burst_delay_time, anim.max_sniper_burst_delay_time );
}

getremainingburstdelaytime()
{
    var_0 = ( gettime() - self.a.lastshoottime ) / 1000;
    var_1 = getburstdelaytime();

    if ( var_1 > var_0 )
        return var_1 - var_0;

    return 0;
}

getburstdelaytime()
{
    if ( animscripts\utility::usingsidearm() )
        return randomfloatrange( 0.15, 0.55 );
    else if ( animscripts\utility::weapon_pump_action_shotgun() )
        return randomfloatrange( 1.0, 1.7 );
    else if ( issniper() )
        return getsniperburstdelaytime();
    else if ( self.fastburst )
        return randomfloatrange( 0.1, 0.35 );
    else
        return randomfloatrange( 0.4, 0.9 );
}

burstdelay()
{
    if ( self.bulletsinclip )
    {
        if ( self.shootstyle == "full" && !self.fastburst )
        {
            if ( self.a.lastshoottime == gettime() )
                wait 0.05;

            return;
        }

        var_0 = getremainingburstdelaytime();

        if ( var_0 )
            wait( var_0 );
    }
}

cheatammoifnecessary()
{
    if ( !isdefined( self.enemy ) )
        return 0;

    if ( self.team != "allies" )
    {
        if ( !isplayer( self.enemy ) )
            return 0;

        if ( self.enemy maps\_utility::ent_flag( "player_is_invulnerable" ) )
            return 0;
    }

    if ( animscripts\utility::usingsidearm() || animscripts\utility::usingrocketlauncher() )
        return 0;

    if ( gettime() - self.ammocheattime < self.ammocheatinterval )
        return 0;

    if ( !self cansee( self.enemy ) && distancesquared( self.origin, self.enemy.origin ) > 65536 )
        return 0;

    self.bulletsinclip = int( weaponclipsize( self.weapon ) / 2 );

    if ( self.bulletsinclip > weaponclipsize( self.weapon ) )
        self.bulletsinclip = weaponclipsize( self.weapon );

    self.ammocheattime = gettime();
    return 1;
}

aimbutdontshoot()
{
    for ( var_0 = int( 60.0 ); var_0 > 0; var_0-- )
    {
        if ( isdefined( self.dontevershoot ) || isdefined( self.enemy ) && isdefined( self.enemy.dontattackme ) )
        {
            wait 0.05;
            continue;
        }

        return 0;
    }

    return 1;
}

shootuntilshootbehaviorchange()
{
    self endon( "shoot_behavior_change" );
    self endon( "stopShooting" );

    if ( islongrangeai() )
    {
        if ( isdefined( self.enemy ) && isai( self.enemy ) && distancesquared( level.player.origin, self.enemy.origin ) < 147456 )
            self.enemy animscripts\battlechatter_ai::addthreatevent( "infantry", self, 1.0 );

        if ( animscripts\utility::usingrocketlauncher() && issentient( self.enemy ) )
            wait( randomfloat( 2.0 ) );
    }

    if ( isdefined( self.enemy ) && distancesquared( self.origin, self.enemy.origin ) > 160000 )
        var_0 = randomintrange( 1, 5 );
    else
        var_0 = 10;

    for (;;)
    {
        burstdelay();

        if ( aimbutdontshoot() )
            break;

        if ( self.shootstyle == "full" )
            fireuntiloutofammo( animscripts\utility::animarray( "fire" ), 1, animscripts\shared::decidenumshotsforfull() );
        else if ( self.shootstyle == "burst" || self.shootstyle == "semi" )
        {
            var_1 = animscripts\shared::decidenumshotsforburst();

            if ( var_1 == 1 )
                fireuntiloutofammo( animscripts\utility::animarraypickrandom( "single" ), 1, var_1 );
            else
                fireuntiloutofammo( animscripts\utility::animarray( self.shootstyle + var_1 ), 1, var_1 );
        }
        else if ( self.shootstyle == "single" )
            fireuntiloutofammo( animscripts\utility::animarraypickrandom( "single" ), 1, 1 );
        else
            self waittill( "hell freezes over" );

        if ( !self.bulletsinclip )
            break;

        var_0--;

        if ( var_0 < 0 )
        {
            self.shouldreturntocover = 1;
            break;
        }
    }
}

getuniqueflagnameindex()
{
    anim.animflagnameindex++;
    return anim.animflagnameindex;
}

#using_animtree("generic_human");

setupaim( var_0 )
{
    self setanim( %exposed_aiming, 1, 0.2 );
    self setanimknoblimited( animscripts\utility::animarray( "straight_level" ), 1, var_0 );
    self setanimknoblimited( animscripts\utility::animarray( "add_aim_up" ), 1, var_0 );
    self setanimknoblimited( animscripts\utility::animarray( "add_aim_down" ), 1, var_0 );
    self setanimknoblimited( animscripts\utility::animarray( "add_aim_left" ), 1, var_0 );
    self setanimknoblimited( animscripts\utility::animarray( "add_aim_right" ), 1, var_0 );
    self.facialidx = animscripts\face::playfacialanim( undefined, "aim", self.facialidx );
}

startfireandaimidlethread()
{
    if ( !isdefined( self.a.aimidlethread ) )
    {
        setupaim( 0.2 );
        thread aimidlethread();
        thread animscripts\track::trackshootentorpos();
    }
}

endfireandanimidlethread()
{
    endaimidlethread();
    self clearanim( %add_fire, 0.1 );
    self notify( "stop tracking" );
}

showfirehideaimidle()
{
    if ( isdefined( self.a.aimidlethread ) )
        self setanim( %add_idle, 0, 0.2 );

    self setanim( %add_fire, 1, 0.1 );
}

hidefireshowaimidle()
{
    if ( isdefined( self.a.aimidlethread ) )
        self setanim( %add_idle, 1, 0.2 );

    self setanim( %add_fire, 0, 0.1 );
}

aimidlethread( var_0 )
{
    self endon( "killanimscript" );
    self endon( "end_aim_idle_thread" );

    if ( isdefined( self.a.aimidlethread ) )
        return;

    self.a.aimidlethread = 1;
    wait 0.1;
    self setanimlimited( %add_idle, 1, 0.2 );
    var_1 = %add_idle;
    var_2 = 0;

    for (;;)
    {
        var_3 = "idle" + var_2;

        if ( isdefined( self.a.leanaim ) )
            var_4 = animscripts\utility::animarraypickrandom( "lean_idle" );
        else if ( animscripts\utility::animarrayanyexist( "exposed_idle" ) )
            var_4 = animscripts\utility::animarraypickrandom( "exposed_idle" );
        else
        {
            wait 0.5;
            __asm_jmp( loc_5D2 )
        }

        if ( var_4 == var_1 )
            self setflaggedanimlimitedrestart( var_3, var_4, 1, 0.2 );
        else
            self setflaggedanimknoblimitedrestart( var_3, var_4, 1, 0.2 );

        var_1 = var_4;
        self waittillmatch( var_3, "end" );
        var_2++;
    }

    self clearanim( %add_idle, 0.1 );
}

endaimidlethread()
{
    self notify( "end_aim_idle_thread" );
    self.a.aimidlethread = undefined;
    self clearanim( %add_idle, 0.1 );
}

shotgunfirerate()
{
    if ( animscripts\utility::weapon_pump_action_shotgun() )
        return 1.0;

    if ( animscripts\weaponlist::usingautomaticweapon() )
        return animscripts\weaponlist::autoshootanimrate() * 0.7;

    return 0.4;
}

fireuntiloutofammo( var_0, var_1, var_2 )
{
    var_3 = "fireAnim_" + getuniqueflagnameindex();
    maps\_gameskill::resetmisstime();

    while ( !aimedatshootentorpos() )
        wait 0.05;

    showfirehideaimidle();
    var_4 = 1.0;

    if ( isdefined( self.shootrateoverride ) )
        var_4 = self.shootrateoverride;
    else if ( self.shootstyle == "full" )
        var_4 = animscripts\weaponlist::autoshootanimrate() * randomfloatrange( 0.5, 1.0 );
    else if ( self.shootstyle == "burst" )
        var_4 = animscripts\weaponlist::burstshootanimrate();
    else if ( animscripts\utility::usingsidearm() )
        var_4 = 3.0;
    else if ( animscripts\utility::usingshotgun() )
        var_4 = shotgunfirerate();

    self setflaggedanimknobrestart( var_3, var_0, 1, 0.2, var_4 );
    self updateplayersightaccuracy();
    fireuntiloutofammointernal( var_3, var_0, var_1, var_2 );
    hidefireshowaimidle();
}

fireuntiloutofammo_waittillended()
{
    self endon( "killanimscript" );
    self endon( "fireAnimEnd" );
    var_0 = thisthread;

    for (;;)
    {
        waittillframeend;

        if ( !isdefined( var_0 ) )
        {
            self shootstopsound();
            return;
        }

        wait 0.05;
    }
}

fireuntiloutofammointernal( var_0, var_1, var_2, var_3 )
{
    self endon( "enemy" );

    if ( isplayer( self.enemy ) && ( self.shootstyle == "full" || self.shootstyle == "semi" ) )
        level endon( "player_becoming_invulnerable" );

    if ( var_2 )
    {
        thread notifyonanimend( var_0, "fireAnimEnd" );
        self endon( "fireAnimEnd" );
    }

    if ( !isdefined( var_3 ) )
        var_3 = -1;

    var_4 = 0;
    var_5 = animhasnotetrack( var_1, "fire" );
    var_6 = weaponclass( self.weapon ) == "rocketlauncher";
    thread fireuntiloutofammo_waittillended();

    while ( var_4 < var_3 && var_3 > 0 )
    {
        if ( var_5 )
            self waittillmatch( var_0, "fire" );

        if ( !self.bulletsinclip )
        {
            if ( !cheatammoifnecessary() )
                break;
        }

        if ( !aimedatshootentorpos() )
            break;

        shootatshootentorpos();

        if ( isplayer( self.enemy ) && self.enemy maps\_utility::ent_flag( "player_is_invulnerable" ) )
        {
            if ( randomint( 3 ) == 0 )
                self.bulletsinclip--;
        }
        else
            self.bulletsinclip--;

        if ( var_6 )
        {
            self.a.rockets--;

            if ( issubstr( tolower( self.weapon ), "rpg" ) || issubstr( tolower( self.weapon ), "panzerfaust" ) )
            {
                self hidepart( "tag_rocket" );
                self.a.rocketvisible = 0;
            }
        }

        var_4++;
        thread shotgunpumpsound( var_0 );

        if ( self.fastburst && var_4 == var_3 )
            break;

        if ( !var_5 || var_3 == 1 && self.shootstyle == "single" )
            self waittillmatch( var_0, "end" );
    }

    self shootstopsound();

    if ( var_2 )
        self notify( "fireAnimEnd" );
}

aimedatshootentorpos()
{
    if ( !isdefined( self.shootpos ) )
        return 1;

    var_0 = self getmuzzleangle();
    var_1 = animscripts\shared::getshootfrompos();
    var_2 = vectortoangles( self.shootpos - var_1 );
    var_3 = animscripts\utility::absangleclamp180( var_0[1] - var_2[1] );

    if ( var_3 > anim.aimyawdifffartolerance )
    {
        if ( distancesquared( self geteye(), self.shootpos ) > anim.aimyawdiffclosedistsq || var_3 > anim.aimyawdiffclosetolerance )
            return 0;
    }

    return animscripts\utility::absangleclamp180( var_0[0] - var_2[0] ) <= anim.aimpitchdifftolerance;
}

notifyonanimend( var_0, var_1 )
{
    self endon( "killanimscript" );
    self endon( var_1 );
    self waittillmatch( var_0, "end" );
    self notify( var_1 );
}

issingleshot()
{
    if ( weaponburstcount( self.weapon ) > 0 )
        return 0;
    else if ( weaponisauto( self.weapon ) )
        return 0;

    return 1;
}

shootatshootentorpos()
{
    var_0 = issingleshot();

    if ( isdefined( self.shootent ) )
    {
        if ( isdefined( self.enemy ) && self.shootent == self.enemy )
            animscripts\utility::shootenemywrapper( var_0 );
    }
    else
        self [[ anim.shootposwrapper_func ]]( self.shootpos, var_0 );
}

decrementbulletsinclip()
{
    if ( self.bulletsinclip )
        self.bulletsinclip--;
}

shotgunpumpsound( var_0 )
{
    if ( !animscripts\utility::weapon_pump_action_shotgun() )
        return;

    self endon( "killanimscript" );
    self notify( "shotgun_pump_sound_end" );
    self endon( "shotgun_pump_sound_end" );
    thread stopshotgunpumpaftertime( 2.0 );
    self waittillmatch( var_0, "rechamber" );
    self playsound( "ai_shotgun_pump" );
    self notify( "shotgun_pump_sound_end" );
}

stopshotgunpumpaftertime( var_0 )
{
    self endon( "killanimscript" );
    self endon( "shotgun_pump_sound_end" );
    wait( var_0 );
    self notify( "shotgun_pump_sound_end" );
}

rechamber( var_0 )
{

}

needtoreload( var_0 )
{
    if ( self.weapon == "none" )
        return 0;

    if ( isdefined( self.noreload ) )
    {
        if ( self.bulletsinclip < weaponclipsize( self.weapon ) * 0.5 )
            self.bulletsinclip = int( weaponclipsize( self.weapon ) * 0.5 );

        if ( self.bulletsinclip <= 0 )
            self.bulletsinclip = 0;

        return 0;
    }

    if ( self.bulletsinclip <= weaponclipsize( self.weapon ) * var_0 )
    {
        if ( var_0 == 0 )
        {
            if ( cheatammoifnecessary() )
                return 0;
        }

        return 1;
    }

    return 0;
}

putgunbackinhandonkillanimscript()
{
    self endon( "weapon_switch_done" );
    self endon( "death" );
    self waittill( "killanimscript" );
    animscripts\shared::placeweaponon( self.primaryweapon, "right" );
}

reload( var_0, var_1 )
{
    self endon( "killanimscript" );

    if ( !needtoreload( var_0 ) )
        return 0;

    animscripts\battlechatter_ai::evaluatereloadevent();
    animscripts\battlechatter::playbattlechatter();

    if ( isdefined( var_1 ) )
    {
        self setflaggedanimknoball( "reloadanim", var_1, %body, 1, 0.1, 1 );
        animscripts\shared::donotetracks( "reloadanim" );
        animscripts\weaponlist::refillclip();
        self.a.needstorechamber = 0;
    }
    else
    {
        if ( self.a.pose == "prone" )
        {
            self setflaggedanimknoball( "reloadanim", %prone_reload, %body, 1, 0.1, 1 );
            self updateprone( %prone_legs_up, %prone_legs_down, 1, 0.1, 1 );
        }
        else
        {
            wait 2;
            return;
        }

        animscripts\shared::donotetracks( "reloadanim" );
        animscripts\weaponlist::refillclip();
        self.a.needstorechamber = 0;
    }

    return 1;
}

addgrenadethrowanimoffset( var_0, var_1 )
{
    if ( !isdefined( anim.grenadethrowanims ) )
    {
        anim.grenadethrowanims = [];
        anim.grenadethrowoffsets = [];
    }

    var_2 = anim.grenadethrowanims.size;
    anim.grenadethrowanims[var_2] = var_0;
    anim.grenadethrowoffsets[var_2] = var_1;
}

initgrenadethrowanims()
{
    addgrenadethrowanimoffset( %exposed_grenadethrowb, ( 41.5391, 7.28883, 72.2128 ) );
    addgrenadethrowanimoffset( %exposed_grenadethrowc, ( 34.8849, -4.77048, 74.0488 ) );
    addgrenadethrowanimoffset( %corner_standl_grenade_a, ( 41.605, 6.80107, 81.4785 ) );
    addgrenadethrowanimoffset( %corner_standl_grenade_b, ( 24.1585, -14.7221, 29.2992 ) );
    addgrenadethrowanimoffset( %cornercrl_grenadea, ( 25.8988, -10.2811, 30.4813 ) );
    addgrenadethrowanimoffset( %cornercrl_grenadeb, ( 24.688, 45.0702, 64.377 ) );
    addgrenadethrowanimoffset( %corner_standr_grenade_a, ( 37.1254, -32.7053, 76.5745 ) );
    addgrenadethrowanimoffset( %corner_standr_grenade_b, ( 19.356, 15.5341, 16.5036 ) );
    addgrenadethrowanimoffset( %cornercrr_grenadea, ( 39.8857, 5.92472, 24.5878 ) );
    addgrenadethrowanimoffset( %covercrouch_grenadea, ( -1.6363, -0.693674, 60.1009 ) );
    addgrenadethrowanimoffset( %covercrouch_grenadeb, ( -1.6363, -0.693674, 60.1009 ) );
    addgrenadethrowanimoffset( %coverstand_grenadea, ( 10.8573, 7.12614, 77.2356 ) );
    addgrenadethrowanimoffset( %coverstand_grenadeb, ( 19.1804, 5.68214, 73.2278 ) );
    addgrenadethrowanimoffset( %prone_grenade_a, ( 12.2859, -1.3019, 33.4307 ) );
    addgrenadethrowanimoffset( %cqb_stand_grenade_throw, ( 35.7494, 26.6052, 37.7086 ) );
}

getgrenadethrowoffset( var_0 )
{
    var_1 = ( 0, 0, 64 );

    if ( isdefined( var_0 ) )
    {
        foreach ( var_4, var_3 in anim.grenadethrowanims )
        {
            if ( var_0 == var_3 )
            {
                var_1 = anim.grenadethrowoffsets[var_4];
                break;
            }
        }
    }

    if ( var_1[2] == 64 )
    {
        if ( isdefined( var_0 ) )
        {

        }
        else
        {

        }
    }

    return var_1;
}

throwgrenadeatplayerasap_combat_utility()
{
    for ( var_0 = 0; var_0 < level.players.size; var_0++ )
    {
        if ( level.players[var_0].numgrenadesinprogresstowardsplayer == 0 )
        {
            level.players[var_0].grenadetimers["fraggrenade"] = 0;
            level.players[var_0].grenadetimers["flash_grenade"] = 0;
        }
    }

    anim.throwgrenadeatplayerasap = 1;
}

setactivegrenadetimer( var_0 )
{
    self.activegrenadetimer = spawnstruct();

    if ( isplayer( var_0 ) )
    {
        self.activegrenadetimer.isplayertimer = 1;
        self.activegrenadetimer.player = var_0;
        self.activegrenadetimer.timername = self.grenadeweapon;
    }
    else
    {
        self.activegrenadetimer.isplayertimer = 0;
        self.activegrenadetimer.timername = "AI_" + self.grenadeweapon;
    }
}

usingplayergrenadetimer()
{
    return self.activegrenadetimer.isplayertimer;
}

setgrenadetimer( var_0, var_1 )
{
    if ( var_0.isplayertimer )
    {
        var_2 = var_0.player;
        var_3 = var_2.grenadetimers[var_0.timername];
        var_2.grenadetimers[var_0.timername] = max( var_1, var_3 );
    }
    else
    {
        var_3 = anim.grenadetimers[var_0.timername];
        anim.grenadetimers[var_0.timername] = max( var_1, var_3 );
    }
}

getdesiredgrenadetimervalue()
{
    var_0 = undefined;

    if ( usingplayergrenadetimer() )
    {
        var_1 = self.activegrenadetimer.player;
        var_0 = gettime() + var_1.gs.playergrenadebasetime + randomint( var_1.gs.playergrenaderangetime );
    }
    else
        var_0 = gettime() + 30000 + randomint( 30000 );

    return var_0;
}

getgrenadetimertime( var_0 )
{
    if ( var_0.isplayertimer )
        return var_0.player.grenadetimers[var_0.timername];
    else
        return anim.grenadetimers[var_0.timername];
}

considerchangingtarget( var_0 )
{
    if ( !isplayer( var_0 ) && self isbadguy() )
    {
        if ( gettime() < getgrenadetimertime( self.activegrenadetimer ) )
        {
            if ( level.player.ignoreme )
                return var_0;

            var_1 = self getthreatbiasgroup();
            var_2 = level.player getthreatbiasgroup();

            if ( var_1 != "" && var_2 != "" && getthreatbias( var_2, var_1 ) < -10000 )
                return var_0;

            if ( self cansee( level.player ) || isai( var_0 ) && var_0 cansee( level.player ) )
            {
                if ( isdefined( self.covernode ) )
                {
                    var_3 = vectortoangles( level.player.origin - self.origin );
                    var_4 = angleclamp180( self.covernode.angles[1] - var_3[1] );
                }
                else
                    var_4 = animscripts\utility::getyawtospot( level.player.origin );

                if ( abs( var_4 ) < 60 )
                {
                    var_0 = level.player;
                    setactivegrenadetimer( var_0 );
                }
            }
        }
    }

    return var_0;
}

maythrowdoublegrenade( var_0 )
{
    if ( maps\_utility::player_died_recently() )
        return 0;

    if ( !var_0.gs.double_grenades_allowed )
        return 0;

    var_1 = gettime();

    if ( var_1 < var_0.grenadetimers["double_grenade"] )
        return 0;

    if ( var_1 > var_0.lastfraggrenadetoplayerstart + 3000 )
        return 0;

    if ( var_1 < var_0.lastfraggrenadetoplayerstart + 500 )
        return 0;

    return var_0.numgrenadesinprogresstowardsplayer < 2;
}

mygrenadecooldownelapsed()
{
    return gettime() >= self.a.nextgrenadetrytime;
}

grenadecooldownelapsed( var_0 )
{
    if ( maps\_utility::player_died_recently() )
        return 0;

    if ( self.script_forcegrenade == 1 )
        return 1;

    if ( !mygrenadecooldownelapsed() )
        return 0;

    if ( gettime() >= getgrenadetimertime( self.activegrenadetimer ) )
        return 1;

    if ( self.activegrenadetimer.isplayertimer && self.activegrenadetimer.timername == "fraggrenade" )
        return maythrowdoublegrenade( var_0 );

    return 0;
}

trygrenadeposproc( var_0, var_1, var_2, var_3 )
{
    if ( !self isgrenadepossafe( var_0, var_1 ) )
        return 0;
    else if ( distancesquared( self.origin, var_1 ) < 40000 )
        return 0;

    var_4 = physicstrace( var_1 + ( 0, 0, 1 ), var_1 + ( 0, 0, -500 ) );

    if ( var_4 == var_1 + ( 0, 0, -500 ) )
        return 0;

    var_4 = var_4 + ( 0, 0, 0.1 );
    return trygrenadethrow( var_0, var_4, var_2, var_3 );
}

trygrenade( var_0, var_1 )
{
    if ( self.weapon == "mg42" || self.grenadeammo <= 0 )
        return 0;

    setactivegrenadetimer( var_0 );
    var_0 = considerchangingtarget( var_0 );

    if ( !grenadecooldownelapsed( var_0 ) )
        return 0;

    var_2 = getgrenadethrowoffset( var_1 );

    if ( isdefined( self.enemy ) && var_0 == self.enemy )
    {
        if ( !checkgrenadethrowdist() )
            return 0;

        if ( isplayer( self.enemy ) && maps\_utility::is_player_down( self.enemy ) )
            return 0;

        if ( animscripts\utility::canseeenemyfromexposed() )
        {
            if ( !self isgrenadepossafe( var_0, var_0.origin ) )
                return 0;

            return trygrenadethrow( var_0, undefined, var_1, var_2 );
        }
        else if ( animscripts\utility::cansuppressenemyfromexposed() )
            return trygrenadeposproc( var_0, animscripts\utility::getenemysightpos(), var_1, var_2 );
        else
        {
            if ( !self isgrenadepossafe( var_0, var_0.origin ) )
                return 0;

            return trygrenadethrow( var_0, undefined, var_1, var_2 );
        }

        return 0;
    }
    else
        return trygrenadeposproc( var_0, var_0.origin, var_1, var_2 );
}

trygrenadethrow( var_0, var_1, var_2, var_3, var_4, var_5, var_6 )
{
    if ( gettime() < 10000 && !isdefined( level.ignoregrenadesafetime ) )
        return 0;

    if ( !isdefined( var_5 ) )
        var_5 = 1;

    if ( isdefined( var_2 ) )
    {
        var_7 = var_2;
        var_8 = self.a.gunhand;
    }
    else
    {
        switch ( self.a.special )
        {
            case "cover_crouch":
            case "none":
                if ( self.a.pose == "stand" )
                {
                    var_3 = ( 0, 0, 80 );
                    var_7 = %stand_grenade_throw;
                }
                else
                {
                    var_3 = ( 0, 0, 65 );
                    var_7 = %crouch_grenade_throw;
                }

                var_8 = "left";
                break;
            default:
                var_7 = undefined;
                var_8 = undefined;
                break;
        }
    }

    if ( !isdefined( var_7 ) )
        return 0;

    if ( isdefined( var_1 ) )
    {
        if ( !isdefined( var_4 ) )
            var_9 = self checkgrenadethrowpos( var_3, var_1, var_5, "min energy", "min time", "max time" );
        else
            var_9 = self checkgrenadethrowpos( var_3, var_1, var_5, "min time", "min energy" );
    }
    else
    {
        var_10 = self.randomgrenaderange;
        var_11 = distance( var_0.origin, self.origin );

        if ( var_11 < 800 )
        {
            if ( var_11 < 256 )
                var_10 = 0;
            else
                var_10 = var_10 * ( ( var_11 - 256 ) / 544 );
        }

        if ( !isdefined( var_4 ) )
            var_9 = self checkgrenadethrow( var_3, var_10, "min energy", "min time", "max time" );
        else
            var_9 = self checkgrenadethrow( var_3, var_10, "min time", "min energy" );
    }

    self.a.nextgrenadetrytime = gettime() + randomintrange( 1000, 2000 );

    if ( isdefined( var_9 ) )
    {
        if ( !isdefined( self.oldgrenawareness ) )
            self.oldgrenawareness = self.grenadeawareness;

        self.grenadeawareness = 0;
        var_12 = getdesiredgrenadetimervalue();
        setgrenadetimer( self.activegrenadetimer, min( gettime() + 3000, var_12 ) );
        var_13 = 0;

        if ( usingplayergrenadetimer() )
        {
            var_0.numgrenadesinprogresstowardsplayer++;
            thread reducegiptponkillanimscript( var_0 );

            if ( var_0.numgrenadesinprogresstowardsplayer > 1 )
                var_13 = 1;

            if ( self.activegrenadetimer.timername == "fraggrenade" )
            {
                if ( var_0.numgrenadesinprogresstowardsplayer <= 1 )
                    var_0.lastfraggrenadetoplayerstart = gettime();
            }
        }

        if ( isdefined( var_6 ) )
            thread dogrenadethrow( var_7, var_9, var_12, var_13 );
        else
            dogrenadethrow( var_7, var_9, var_12, var_13 );

        return 1;
    }
    else
    {

    }

    return 0;
}

reducegiptponkillanimscript( var_0 )
{
    self endon( "dont_reduce_giptp_on_killanimscript" );
    self waittill( "killanimscript" );
    var_0.numgrenadesinprogresstowardsplayer--;
}

dogrenadethrow( var_0, var_1, var_2, var_3 )
{
    self endon( "killanimscript" );

    if ( self.script == "combat" || self.script == "move" )
        self orientmode( "face direction", var_1 );

    animscripts\battlechatter_ai::evaluateattackevent( self.grenadeweapon );
    self notify( "stop_aiming_at_enemy" );
    self setflaggedanimknoballrestart( "throwanim", var_0, %body, fasteranimspeed(), 0.1, 1 );
    thread animscripts\notetracks::donotetracksforever( "throwanim", "killanimscript" );
    var_4 = animscripts\utility::getgrenademodel();
    var_5 = "none";

    for (;;)
    {
        self waittill( "throwanim", var_6 );

        if ( var_6 == "grenade_left" || var_6 == "grenade_right" )
        {
            var_5 = attachgrenademodel( var_4, "TAG_INHAND" );
            self.isholdinggrenade = 1;
        }

        if ( var_6 == "grenade_throw" || var_6 == "grenade throw" )
            break;

        if ( var_6 == "end" )
        {
            self.activegrenadetimer.player.numgrenadesinprogresstowardsplayer--;
            self notify( "dont_reduce_giptp_on_killanimscript" );
            return 0;
        }
    }

    self notify( "dont_reduce_giptp_on_killanimscript" );

    if ( usingplayergrenadetimer() )
        thread watchgrenadetowardsplayer( self.activegrenadetimer.player, var_2 );

    self throwgrenade();

    if ( !usingplayergrenadetimer() )
        setgrenadetimer( self.activegrenadetimer, var_2 );

    if ( var_3 )
    {
        var_13 = self.activegrenadetimer.player;

        if ( var_13.numgrenadesinprogresstowardsplayer > 1 || gettime() - var_13.lastgrenadelandednearplayertime < 2000 )
            var_13.grenadetimers["double_grenade"] = gettime() + min( 5000, var_13.gs.playerdoublegrenadetime );
    }

    self notify( "stop grenade check" );

    if ( var_5 != "none" )
        self detach( var_4, var_5 );
    else
    {

    }

    self.isholdinggrenade = undefined;
    self.grenadeawareness = self.oldgrenawareness;
    self.oldgrenawareness = undefined;
    self waittillmatch( "throwanim", "end" );
    self notify( "done_grenade_throw" );
    self notify( "weapon_switch_done" );
    self setanim( %exposed_modern, 1, 0.2 );
    self setanim( %exposed_aiming, 1 );
    self clearanim( var_0, 0.2 );
}

watchgrenadetowardsplayer( var_0, var_1 )
{
    var_0 endon( "death" );
    watchgrenadetowardsplayerinternal( var_1 );
    var_0.numgrenadesinprogresstowardsplayer--;
}

watchgrenadetowardsplayerinternal( var_0 )
{
    var_1 = self.activegrenadetimer;
    var_2 = spawnstruct();
    var_2 thread watchgrenadetowardsplayertimeout( 5 );
    var_2 endon( "watchGrenadeTowardsPlayerTimeout" );
    var_3 = self.grenadeweapon;
    var_4 = getgrenadeithrew();

    if ( !isdefined( var_4 ) )
        return;

    setgrenadetimer( var_1, min( gettime() + 5000, var_0 ) );
    var_5 = 62500;
    var_6 = 160000;

    if ( var_3 == "flash_grenade" )
    {
        var_5 = 810000;
        var_6 = 1690000;
    }

    var_7 = level.players;
    var_8 = var_4.origin;

    for (;;)
    {
        wait 0.1;

        if ( !isdefined( var_4 ) )
            break;

        if ( distancesquared( var_4.origin, var_8 ) < 400 )
        {
            var_9 = [];

            for ( var_10 = 0; var_10 < var_7.size; var_10++ )
            {
                var_11 = var_7[var_10];
                var_12 = distancesquared( var_4.origin, var_11.origin );

                if ( var_12 < var_5 )
                {
                    var_11 grenadelandednearplayer( var_1, var_0 );
                    continue;
                }

                if ( var_12 < var_6 )
                    var_9[var_9.size] = var_11;
            }

            var_7 = var_9;

            if ( var_7.size == 0 )
                break;
        }

        var_8 = var_4.origin;
    }
}

grenadelandednearplayer( var_0, var_1 )
{
    var_2 = self;
    anim.throwgrenadeatplayerasap = undefined;

    if ( gettime() - var_2.lastgrenadelandednearplayertime < 3000 )
        var_2.grenadetimers["double_grenade"] = gettime() + var_2.gs.playerdoublegrenadetime;

    var_2.lastgrenadelandednearplayertime = gettime();
    var_3 = var_2.grenadetimers[var_0.timername];
    var_2.grenadetimers[var_0.timername] = max( var_1, var_3 );
}

getgrenadeithrew()
{
    self endon( "killanimscript" );
    self waittill( "grenade_fire", var_0 );
    return var_0;
}

watchgrenadetowardsplayertimeout( var_0 )
{
    wait( var_0 );
    self notify( "watchGrenadeTowardsPlayerTimeout" );
}

attachgrenademodel( var_0, var_1 )
{
    self attach( var_0, var_1 );
    thread detachgrenadeonscriptchange( var_0, var_1 );
    return var_1;
}

detachgrenadeonscriptchange( var_0, var_1 )
{
    self endon( "stop grenade check" );
    self waittill( "killanimscript" );

    if ( !isdefined( self ) )
        return;

    if ( isdefined( self.oldgrenawareness ) )
    {
        self.grenadeawareness = self.oldgrenawareness;
        self.oldgrenawareness = undefined;
    }

    self detach( var_0, var_1 );
}

offsettoorigin( var_0 )
{
    var_1 = anglestoforward( self.angles );
    var_2 = anglestoright( self.angles );
    var_3 = anglestoup( self.angles );
    var_1 = var_1 * var_0[0];
    var_2 = var_2 * var_0[1];
    var_3 = var_3 * var_0[2];
    return var_1 + var_2 + var_3;
}

grenadeline( var_0, var_1 )
{
    level notify( "armoffset" );
    level endon( "armoffset" );
    var_0 = self.origin + offsettoorigin( var_0 );

    for (;;)
        wait 0.05;
}

getgrenadedropvelocity()
{
    var_0 = randomfloat( 360 );
    var_1 = randomfloatrange( 30, 75 );
    var_2 = sin( var_1 );
    var_3 = cos( var_1 );
    var_4 = cos( var_0 ) * var_3;
    var_5 = sin( var_0 ) * var_3;
    var_6 = randomfloatrange( 100, 200 );
    var_7 = ( var_4, var_5, var_2 ) * var_6;
    return var_7;
}

dropgrenade()
{
    var_0 = self gettagorigin( "tag_inhand" );
    var_1 = getgrenadedropvelocity();
    self magicgrenademanual( var_0, var_1, 3 );
}

lookforbettercover()
{
    if ( !isdefined( self.enemy ) )
        return 0;

    if ( self.fixednode || self.doingambush )
        return 0;

    var_0 = getbestcovernodeifavailable();

    if ( isdefined( var_0 ) )
        return usecovernodeifpossible( var_0 );

    return 0;
}

getbestcovernodeifavailable()
{
    var_0 = self findbestcovernode();

    if ( !isdefined( var_0 ) )
        return undefined;

    var_1 = animscripts\utility::getclaimednode();

    if ( isdefined( var_1 ) && var_0 == var_1 )
        return undefined;

    if ( isdefined( self.covernode ) && var_0 == self.covernode )
        return undefined;

    return var_0;
}

usecovernodeifpossible( var_0 )
{
    var_1 = self.keepclaimednodeifvalid;
    var_2 = self.keepclaimednode;
    self.keepclaimednodeifvalid = 0;
    self.keepclaimednode = 0;

    if ( self usecovernode( var_0 ) )
        return 1;
    else
    {

    }

    self.keepclaimednodeifvalid = var_1;
    self.keepclaimednode = var_2;
    return 0;
}

shouldhelpadvancingteammate()
{
    if ( level.advancetoenemygroup[self.team] > 0 && level.advancetoenemygroup[self.team] < level.advancetoenemygroupmax )
    {
        if ( gettime() - level.lastadvancetoenemytime[self.team] > 4000 )
            return 0;

        var_0 = level.lastadvancetoenemyattacker[self.team];

        if ( var_0 == self )
            return 0;

        var_1 = isdefined( var_0 ) && distancesquared( self.origin, var_0.origin ) < 65536;

        if ( ( var_1 || distancesquared( self.origin, level.lastadvancetoenemysrc[self.team] ) < 65536 ) && ( !isdefined( self.enemy ) || distancesquared( self.enemy.origin, level.lastadvancetoenemydest[self.team] ) < 262144 ) )
            return 1;
    }

    return 0;
}

checkadvanceonenemyconditions()
{
    if ( !isdefined( level.lastadvancetoenemytime[self.team] ) )
        return 0;

    if ( shouldhelpadvancingteammate() )
        return 1;

    if ( gettime() - level.lastadvancetoenemytime[self.team] < level.advancetoenemyinterval )
        return 0;

    if ( !issentient( self.enemy ) )
        return 0;

    if ( level.advancetoenemygroup[self.team] )
        level.advancetoenemygroup[self.team] = 0;

    var_0 = isdefined( self.advance_regardless_of_numbers ) && self.advance_regardless_of_numbers;

    if ( !var_0 && getaicount( self.team ) < getaicount( self.enemy.team ) )
        return 0;

    return 1;
}

tryrunningtoenemy( var_0 )
{
    if ( !isdefined( self.enemy ) )
        return 0;

    if ( self.fixednode )
        return 0;

    if ( self.combatmode == "ambush" || self.combatmode == "ambush_nodes_only" )
        return 0;

    if ( !self isingoal( self.enemy.origin ) )
        return 0;

    if ( islongrangeai() )
        return 0;

    if ( !checkadvanceonenemyconditions() )
        return 0;

    self findreacquiredirectpath( var_0 );

    if ( self reacquiremove() )
    {
        self.keepclaimednodeifvalid = 0;
        self.keepclaimednode = 0;
        self.a.magicreloadwhenreachenemy = 1;

        if ( level.advancetoenemygroup[self.team] == 0 )
        {
            level.lastadvancetoenemytime[self.team] = gettime();
            level.lastadvancetoenemyattacker[self.team] = self;
        }

        level.lastadvancetoenemysrc[self.team] = self.origin;
        level.lastadvancetoenemydest[self.team] = self.enemy.origin;
        level.advancetoenemygroup[self.team]++;
        return 1;
    }

    return 0;
}

delayedbadplace( var_0 )
{
    self endon( "death" );
    wait 0.5;
    var_1 = "" + anim.badplaceint;
    badplace_cylinder( var_1, 5, var_0, 16, 64, self.team );
    anim.badplaces[anim.badplaces.size] = var_1;

    if ( anim.badplaces.size >= 10 )
    {
        var_2 = [];

        for ( var_3 = 1; var_3 < anim.badplaces.size; var_3++ )
            var_2[var_2.size] = anim.badplaces[var_3];

        badplace_delete( anim.badplaces[0] );
        anim.badplaces = var_2;
    }

    anim.badplaceint++;

    if ( anim.badplaceint > 10 )
        anim.badplaceint = anim.badplaceint - 20;
}

valueiswithin( var_0, var_1, var_2 )
{
    if ( var_0 > var_1 && var_0 < var_2 )
        return 1;

    return 0;
}

getgunyawtoshootentorpos()
{
    if ( !isdefined( self.shootpos ) )
        return 0;

    var_0 = self getmuzzleangle()[1] - animscripts\utility::getyaw( self.shootpos );
    var_0 = angleclamp180( var_0 );
    return var_0;
}

getgunpitchtoshootentorpos()
{
    if ( !isdefined( self.shootpos ) )
        return 0;

    var_0 = self getmuzzleangle()[0] - vectortoangles( self.shootpos - self getmuzzlepos() )[0];
    var_0 = angleclamp180( var_0 );
    return var_0;
}

getpitchtoenemy()
{
    if ( !isdefined( self.enemy ) )
        return 0;

    var_0 = self.enemy getshootatpos() - self getshootatpos();
    var_0 = vectornormalize( var_0 );
    var_1 = 360 - vectortoangles( var_0 )[0];
    return angleclamp180( var_1 );
}

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

    var_1 = var_0 - self getshootatpos();
    var_1 = vectornormalize( var_1 );
    var_2 = 360 - vectortoangles( var_1 )[0];
    return angleclamp180( var_2 );
}

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

    if ( isdefined( self ) && animscripts\utility::isspaceai() )
    {
        var_2 = anglestoforward( self.angles );
        var_3 = rotatepointaroundvector( var_2, var_0 - self.origin, self.angles[2] * -1 );
        var_0 = var_3 + self.origin;
    }

    var_4 = var_0 - var_1;
    var_4 = vectornormalize( var_4 );
    var_5 = 360 - vectortoangles( var_4 )[0];
    return angleclamp180( var_5 );
}

watchreloading()
{
    self.isreloading = 0;
    self.lastreloadstarttime = -1;

    for (;;)
    {
        self waittill( "reload_start" );
        self.isreloading = 1;
        self.lastreloadstarttime = gettime();
        waittillreloadfinished();
        self.isreloading = 0;
    }
}

waittillreloadfinished()
{
    thread timednotify( 4, "reloadtimeout" );
    self endon( "reloadtimeout" );
    self endon( "weapon_taken" );

    for (;;)
    {
        self waittill( "reload" );
        var_0 = self getcurrentweapon();

        if ( var_0 == "none" )
            break;

        if ( self getcurrentweaponclipammo() >= weaponclipsize( var_0 ) )
            break;
    }

    self notify( "reloadtimeout" );
}

timednotify( var_0, var_1 )
{
    self endon( var_1 );
    wait( var_0 );
    self notify( var_1 );
}

checkgrenadethrowdist()
{
    var_0 = self.enemy.origin - self.origin;
    var_1 = lengthsquared( ( var_0[0], var_0[1], 0 ) );

    if ( self.grenadeweapon == "flash_grenade" )
        return var_1 < 589824;

    return var_1 >= 40000 && var_1 <= 1562500;
}

monitorflash()
{
    self endon( "death" );

    if ( !isdefined( level.neverstopmonitoringflash ) )
        self endon( "stop_monitoring_flash" );

    for (;;)
    {
        var_0 = undefined;
        var_1 = undefined;
        var_2 = undefined;
        var_3 = undefined;
        var_4 = undefined;
        self waittill( "flashbang", var_1, var_0, var_2, var_3, var_4 );

        if ( isdefined( self.flashbangimmunity ) && self.flashbangimmunity )
            continue;

        if ( isdefined( self.script_immunetoflash ) && self.script_immunetoflash != 0 )
            continue;

        if ( isdefined( self.team ) && isdefined( var_4 ) && self.team == var_4 )
        {
            var_0 = 3 * ( var_0 - 0.75 );

            if ( var_0 < 0 )
                continue;

            if ( isdefined( self.teamflashbangimmunity ) )
                continue;
        }

        var_5 = 0.2;

        if ( var_0 > 1 - var_5 )
            var_0 = 1.0;
        else
            var_0 = var_0 / ( 1 - var_5 );

        var_6 = 4.5 * var_0;

        if ( var_6 < 0.25 )
            continue;

        self.flashingteam = var_4;
        maps\_utility::flashbangstart( var_6 );
        self notify( "doFlashBanged", var_1, var_3 );
    }
}

isshotgunai()
{
    return animscripts\utility::isshotgun( self.primaryweapon );
}

issniper()
{
    return animscripts\utility::issniperrifle( self.primaryweapon );
}

islongrangeai()
{
    return issniper() || animscripts\utility::usingrocketlauncher();
}

fasteranimspeed()
{
    return 1.5;
}

randomfasteranimspeed()
{
    return randomfloatrange( 1, 1.2 );
}

getrandomcovermode( var_0 )
{
    if ( var_0.size == 0 )
        return undefined;

    if ( var_0.size == 1 )
        return var_0[0];

    if ( isdefined( self.a.prevattack ) && randomint( 100 ) > 20 )
    {
        foreach ( var_3, var_2 in var_0 )
        {
            if ( var_2 == self.a.prevattack )
            {
                if ( var_3 < var_0.size - 1 )
                    var_0[var_3] = var_0[var_0.size - 1];

                var_0[var_0.size - 1] = undefined;
                break;
            }
        }
    }

    return var_0[randomint( var_0.size )];
}

player_sees_my_scope()
{
    var_0 = self geteye();

    foreach ( var_2 in level.players )
    {
        if ( !self cansee( var_2 ) )
            continue;

        var_3 = var_2 geteye();
        var_4 = vectortoangles( var_0 - var_3 );
        var_5 = anglestoforward( var_4 );
        var_6 = var_2 getplayerangles();
        var_7 = anglestoforward( var_6 );
        var_8 = vectordot( var_5, var_7 );

        if ( var_8 < 0.805 )
            continue;

        if ( common_scripts\utility::cointoss() && var_8 >= 0.996 )
            continue;

        return 1;
    }

    return 0;
}
