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

init_mgturretsettings()
{
    level.mgturretsettings["easy"]["convergenceTime"] = 2.5;
    level.mgturretsettings["easy"]["suppressionTime"] = 3.0;
    level.mgturretsettings["easy"]["accuracy"] = 0.38;
    level.mgturretsettings["easy"]["aiSpread"] = 2;
    level.mgturretsettings["easy"]["playerSpread"] = 0.5;
    level.mgturretsettings["medium"]["convergenceTime"] = 1.5;
    level.mgturretsettings["medium"]["suppressionTime"] = 3.0;
    level.mgturretsettings["medium"]["accuracy"] = 0.38;
    level.mgturretsettings["medium"]["aiSpread"] = 2;
    level.mgturretsettings["medium"]["playerSpread"] = 0.5;
    level.mgturretsettings["hard"]["convergenceTime"] = 0.8;
    level.mgturretsettings["hard"]["suppressionTime"] = 3.0;
    level.mgturretsettings["hard"]["accuracy"] = 0.38;
    level.mgturretsettings["hard"]["aiSpread"] = 2;
    level.mgturretsettings["hard"]["playerSpread"] = 0.5;
    level.mgturretsettings["fu"]["convergenceTime"] = 0.4;
    level.mgturretsettings["fu"]["suppressionTime"] = 3.0;
    level.mgturretsettings["fu"]["accuracy"] = 0.38;
    level.mgturretsettings["fu"]["aiSpread"] = 2;
    level.mgturretsettings["fu"]["playerSpread"] = 0.5;
}

main()
{
    if ( getdvar( "mg42" ) == "" )
        setdvar( "mgTurret", "off" );

    level.magic_distance = 24;
    var_0 = getentarray( "turretInfo", "targetname" );

    for ( var_1 = 0; var_1 < var_0.size; var_1++ )
        var_0[var_1] delete();
}

portable_mg_behavior()
{
    self detach( "weapon_mg42_carry", "tag_origin" );
    self endon( "death" );
    self.goalradius = level.default_goalradius;

    if ( isdefined( self.target ) )
    {
        var_0 = getnode( self.target, "targetname" );

        if ( isdefined( var_0 ) )
        {
            if ( isdefined( var_0.radius ) )
                self.goalradius = var_0.radius;

            self setgoalnode( var_0 );
        }
    }

    while ( !isdefined( self.node ) )
        wait 0.05;

    var_1 = undefined;

    if ( isdefined( self.target ) )
    {
        var_0 = getnode( self.target, "targetname" );
        var_1 = var_0;
    }

    if ( !isdefined( var_1 ) )
        var_1 = self.node;

    if ( !isdefined( var_1 ) )
        return;

    if ( var_1.type != "Turret" )
        return;

    var_2 = gettakennodes();
    var_2[self.node.origin + ""] = undefined;

    if ( isdefined( var_2[var_1.origin + ""] ) )
        return;

    var_3 = var_1.turret;

    if ( isdefined( var_3.reserved ) )
        return;

    reserve_turret( var_3 );

    if ( var_3.issetup )
        leave_gun_and_run_to_new_spot( var_3 );
    else
        run_to_new_spot_and_setup_gun( var_3 );

    maps\_mg_penetration::gunner_think( var_1.turret );
}

mg42_trigger()
{
    self waittill( "trigger" );
    level notify( self.targetname );
    level.mg42_trigger[self.targetname] = 1;
    self delete();
}

mgturret_auto( var_0 )
{
    var_0 waittill( "trigger" );
    var_1 = getaiarray( "bad_guys" );

    for ( var_2 = 0; var_2 < var_1.size; var_2++ )
    {
        if ( isdefined( var_1[var_2].script_mg42auto ) && var_0.script_mg42auto == var_1[var_2].script_mg42auto )
            var_1[var_2] notify( "auto_ai" );
    }

    var_3 = getspawnerarray();

    for ( var_2 = 0; var_2 < var_3.size; var_2++ )
    {
        if ( isdefined( var_3[var_2].script_mg42auto ) && var_0.script_mg42auto == var_3[var_2].script_mg42auto )
            var_3[var_2].ai_mode = "auto_ai";
    }

    maps\_spawner::kill_trigger( var_0 );
}

mg42_suppressionfire( var_0 )
{
    self endon( "death" );
    self endon( "stop_suppressionFire" );

    if ( !isdefined( self.suppresionfire ) )
        self.suppresionfire = 1;

    for (;;)
    {
        while ( self.suppresionfire )
        {
            self settargetentity( var_0[randomint( var_0.size )] );
            wait( 2 + randomfloat( 2 ) );
        }

        self cleartargetentity();

        while ( !self.suppresionfire )
            wait 1;
    }
}

manual_think( var_0 )
{
    var_1 = self.origin;
    self waittill( "auto_ai" );
    var_0 notify( "stopfiring" );
    var_0 setmode( "auto_ai" );
    var_0 settargetentity( level.player );
}

burst_fire_settings( var_0 )
{
    if ( var_0 == "delay" )
        return 0.2;
    else if ( var_0 == "delay_range" )
        return 0.5;
    else if ( var_0 == "burst" )
        return 0.5;
    else
        return 1.5;
}

burst_fire_unmanned()
{
    self endon( "death" );
    self endon( "stop_burst_fire_unmanned" );

    if ( isdefined( self.script_delay_min ) )
        var_0 = self.script_delay_min;
    else
        var_0 = burst_fire_settings( "delay" );

    if ( isdefined( self.script_delay_max ) )
        var_1 = self.script_delay_max - var_0;
    else
        var_1 = burst_fire_settings( "delay_range" );

    if ( isdefined( self.script_burst_min ) )
        var_2 = self.script_burst_min;
    else
        var_2 = burst_fire_settings( "burst" );

    if ( isdefined( self.script_burst_max ) )
        var_3 = self.script_burst_max - var_2;
    else
        var_3 = burst_fire_settings( "burst_range" );

    var_4 = gettime();
    var_5 = "start";

    if ( isdefined( self.shell_fx ) )
        thread turret_shell_fx();

    for (;;)
    {
        var_6 = ( var_4 - gettime() ) * 0.001;

        if ( self isfiringturret() && var_6 <= 0 )
        {
            if ( var_5 != "fire" )
            {
                var_5 = "fire";
                thread doshoot();
            }

            var_6 = var_2 + randomfloat( var_3 );
            thread turrettimer( var_6 );
            self waittill( "turretstatechange" );
            var_6 = var_0 + randomfloat( var_1 );
            var_4 = gettime() + int( var_6 * 1000 );
            continue;
        }

        if ( var_5 != "aim" )
            var_5 = "aim";

        thread turrettimer( var_6 );
        self waittill( "turretstatechange" );
    }
}

doshoot()
{
    self endon( "death" );
    self endon( "turretstatechange" );

    for (;;)
    {
        self shootturret();
        wait 0.1;
    }
}

turret_shell_fx()
{
    self endon( "death" );
    self endon( "stop_burst_fire_unmanned" );

    if ( isdefined( self.shell_sound ) )
        self.shell_sound_enabled = 1;

    for (;;)
    {
        self waittill( "turret_fire" );
        playfxontag( self.shell_fx, self, "tag_origin" );

        if ( isdefined( self.shell_sound_enabled ) && self.shell_sound_enabled )
            thread turret_shell_sound();
    }
}

turret_shell_sound()
{
    self endon( "death" );
    self.shell_sound_enabled = 0;
    var_0 = self gettagorigin( "tag_origin" );
    var_1 = common_scripts\utility::drop_to_ground( var_0, -30 );
    var_2 = var_0[2] - var_1[2];
    var_3 = var_2 / 300;
    wait( var_3 );
    level thread common_scripts\utility::play_sound_in_space( self.shell_sound, var_1 );
    wait 1;
    self.shell_sound_enabled = 1;
}

turrettimer( var_0 )
{
    if ( var_0 <= 0 )
        return;

    self endon( "turretstatechange" );
    wait( var_0 );

    if ( isdefined( self ) )
        self notify( "turretstatechange" );
}

random_spread( var_0 )
{
    self endon( "death" );
    self notify( "stop random_spread" );
    self endon( "stop random_spread" );
    self endon( "stopfiring" );
    self settargetentity( var_0 );

    for (;;)
    {
        if ( isplayer( var_0 ) )
            var_0.origin = self.manual_target getorigin();
        else
            var_0.origin = self.manual_target.origin;

        var_0.origin = var_0.origin + ( 20 - randomfloat( 40 ), 20 - randomfloat( 40 ), 20 - randomfloat( 60 ) );
        wait 0.2;
    }
}

mg42_firing( var_0 )
{
    self notify( "stop_using_built_in_burst_fire" );
    self endon( "stop_using_built_in_burst_fire" );
    var_0 stopfiring();

    for (;;)
    {
        var_0 waittill( "startfiring" );
        thread burst_fire( var_0 );
        var_0 startfiring();
        var_0 waittill( "stopfiring" );
        var_0 stopfiring();
    }
}

burst_fire( var_0, var_1 )
{
    var_0 endon( "stopfiring" );
    self endon( "stop_using_built_in_burst_fire" );

    if ( isdefined( var_0.script_delay_min ) )
        var_2 = var_0.script_delay_min;
    else
        var_2 = burst_fire_settings( "delay" );

    if ( isdefined( var_0.script_delay_max ) )
        var_3 = var_0.script_delay_max - var_2;
    else
        var_3 = burst_fire_settings( "delay_range" );

    if ( isdefined( var_0.script_burst_min ) )
        var_4 = var_0.script_burst_min;
    else
        var_4 = burst_fire_settings( "burst" );

    if ( isdefined( var_0.script_burst_max ) )
        var_5 = var_0.script_burst_max - var_4;
    else
        var_5 = burst_fire_settings( "burst_range" );

    for (;;)
    {
        var_0 startfiring();

        if ( isdefined( var_1 ) )
            var_0 thread random_spread( var_1 );

        wait( var_4 + randomfloat( var_5 ) );
        var_0 stopfiring();
        wait( var_2 + randomfloat( var_3 ) );
    }
}

_spawner_mg42_think()
{
    if ( !isdefined( self.flagged_for_use ) )
        self.flagged_for_use = 0;

    if ( !isdefined( self.targetname ) )
        return;

    var_0 = getnode( self.targetname, "target" );

    if ( !isdefined( var_0 ) )
        return;

    if ( !isdefined( var_0.script_mg42 ) )
        return;

    if ( !isdefined( var_0.mg42_enabled ) )
        var_0.mg42_enabled = 1;

    self.script_mg42 = var_0.script_mg42;
    var_1 = 1;

    for (;;)
    {
        if ( var_1 )
        {
            var_1 = 0;

            if ( isdefined( var_0.targetname ) || self.flagged_for_use )
                self waittill( "get new user" );
        }

        if ( !var_0.mg42_enabled )
        {
            var_0 waittill( "enable mg42" );
            var_0.mg42_enabled = 1;
        }

        var_2 = [];
        var_3 = getaiarray();

        for ( var_4 = 0; var_4 < var_3.size; var_4++ )
        {
            var_5 = 1;

            if ( isdefined( var_3[var_4].script_mg42 ) && var_3[var_4].script_mg42 == self.script_mg42 )
                var_5 = 0;

            if ( isdefined( var_3[var_4].used_an_mg42 ) )
                var_5 = 1;

            if ( var_5 )
                var_2[var_2.size] = var_3[var_4];
        }

        if ( var_2.size )
            var_3 = maps\_utility::get_closest_ai_exclude( var_0.origin, undefined, var_2 );
        else
            var_3 = maps\_utility::get_closest_ai( var_0.origin, undefined );

        var_2 = undefined;

        if ( isdefined( var_3 ) )
        {
            var_3 notify( "stop_going_to_node" );
            var_3 thread maps\_spawner::go_to_node( var_0 );
            var_3 waittill( "death" );
            continue;
        }

        self waittill( "get new user" );
    }
}

mg42_think()
{
    if ( !isdefined( self.ai_mode ) )
        self.ai_mode = "manual_ai";

    var_0 = getnode( self.target, "targetname" );

    if ( !isdefined( var_0 ) )
        return;

    var_1 = getent( var_0.target, "targetname" );
    var_1.org = var_0.origin;

    if ( isdefined( var_1.target ) )
    {
        if ( !isdefined( level.mg42_trigger ) || !isdefined( level.mg42_trigger[var_1.target] ) )
        {
            level.mg42_trigger[var_1.target] = 0;
            getent( var_1.target, "targetname" ) thread mg42_trigger();
        }

        var_2 = 1;
    }
    else
        var_2 = 0;

    for (;;)
    {
        if ( self.count == 0 )
            return;

        var_3 = undefined;

        while ( !isdefined( var_3 ) )
        {
            var_3 = self dospawn();
            wait 1;
        }

        var_3 thread mg42_gunner_think( var_1, var_2, self.ai_mode );
        var_3 thread mg42_firing( var_1 );
        var_3 waittill( "death" );

        if ( isdefined( self.script_delay ) )
        {
            wait( self.script_delay );
            continue;
        }

        if ( isdefined( self.script_delay_min ) && isdefined( self.script_delay_max ) )
        {
            wait( self.script_delay_min + randomfloat( self.script_delay_max - self.script_delay_min ) );
            continue;
        }

        wait 1;
    }
}

kill_objects( var_0, var_1, var_2, var_3 )
{
    var_0 waittill( var_1 );

    if ( isdefined( var_2 ) )
        var_2 delete();

    if ( isdefined( var_3 ) )
        var_3 delete();
}

mg42_gunner_think( var_0, var_1, var_2 )
{
    self endon( "death" );

    if ( var_2 == "manual_ai" )
    {
        for (;;)
        {
            thread mg42_gunner_manual_think( var_0, var_1 );
            self waittill( "auto_ai" );
            move_use_turret( var_0, "auto_ai" );
            self waittill( "manual_ai" );
        }
    }
    else
    {
        for (;;)
        {
            move_use_turret( var_0, "auto_ai", level.player );
            self waittill( "manual_ai" );
            thread mg42_gunner_manual_think( var_0, var_1 );
            self waittill( "auto_ai" );
        }
    }
}

player_safe()
{
    if ( !isdefined( level.player_covertrigger ) )
        return 0;

    if ( level.player getstance() == "prone" )
        return 1;

    if ( level.player_covertype == "cow" && level.player getstance() == "crouch" )
        return 1;

    return 0;
}

stance_num()
{
    if ( level.player getstance() == "prone" )
        return ( 0, 0, 5 );
    else if ( level.player getstance() == "crouch" )
        return ( 0, 0, 25 );

    return ( 0, 0, 50 );
}

mg42_gunner_manual_think( var_0, var_1 )
{
    self endon( "death" );
    self endon( "auto_ai" );
    self.pacifist = 1;
    self setgoalpos( var_0.org );
    self.goalradius = level.magic_distance;
    self waittill( "goal" );

    if ( var_1 )
    {
        if ( !level.mg42_trigger[var_0.target] )
            level waittill( var_0.target );
    }

    self.pacifist = 0;
    var_0 setmode( "auto_ai" );
    var_0 cleartargetentity();
    var_2 = spawn( "script_origin", ( 0, 0, 0 ) );
    var_3 = spawn( "script_model", ( 0, 0, 0 ) );
    var_3.scale = 3;

    if ( getdvar( "mg42" ) != "off" )
        var_3 setmodel( "temp" );

    var_3 thread temp_think( var_0, var_2 );
    level thread kill_objects( self, "death", var_2, var_3 );
    level thread kill_objects( self, "auto_ai", var_2, var_3 );
    var_0.player_target = 0;
    var_4 = 0;
    var_5 = getentarray( "mg42_target", "targetname" );

    if ( var_5.size > 0 )
    {
        var_6 = 1;
        var_7 = var_5[randomint( var_5.size )].origin;
        thread shoot_mg42_script_targets( var_5 );
        move_use_turret( var_0 );
        self.target_entity = var_2;
        var_0 setmode( "manual_ai" );
        var_0 settargetentity( var_2 );
        var_0 notify( "startfiring" );
        var_8 = 15;
        var_9 = 0.08;
        var_10 = 0.05;
        var_2.origin = var_5[randomint( var_5.size )].origin;
        var_11 = 0;

        while ( !isdefined( level.player_covertrigger ) )
        {
            var_7 = var_2.origin;

            if ( distance( var_7, var_5[self.gun_targ].origin ) > var_8 )
            {
                var_12 = vectornormalize( var_5[self.gun_targ].origin - var_7 );
                var_12 = var_12 * var_8;
                var_7 = var_7 + var_12;
            }
            else
                self notify( "next_target" );

            var_2.origin = var_7;
            wait 0.1;
        }

        for (;;)
        {
            for ( var_13 = 0; var_13 < 1; var_13 = var_13 + var_10 )
            {
                var_2.origin = var_7 * ( 1.0 - var_13 ) + ( level.player getorigin() + stance_num() ) * var_13;

                if ( player_safe() )
                    var_13 = 2;

                wait( var_9 );
            }

            var_14 = level.player getorigin();

            while ( !player_safe() )
            {
                var_2.origin = level.player getorigin();
                var_15 = var_2.origin - var_14;
                var_2.origin = var_2.origin + var_15 + stance_num();
                var_14 = level.player getorigin();
                wait 0.1;
            }

            if ( player_safe() )
            {
                var_11 = gettime() + 1500 + randomfloat( 4000 );

                while ( player_safe() && isdefined( level.player_covertrigger.target ) && gettime() < var_11 )
                {
                    var_16 = getentarray( level.player_covertrigger.target, "targetname" );
                    var_16 = var_16[randomint( var_16.size )];
                    var_2.origin = var_16.origin + ( randomfloat( 30 ) - 15, randomfloat( 30 ) - 15, randomfloat( 40 ) - 60 );
                    wait 0.1;
                }
            }

            self notify( "next_target" );

            while ( player_safe() )
            {
                var_7 = var_2.origin;

                if ( distance( var_7, var_5[self.gun_targ].origin ) > var_8 )
                {
                    var_12 = vectornormalize( var_5[self.gun_targ].origin - var_7 );
                    var_12 = var_12 * var_8;
                    var_7 = var_7 + var_12;
                }
                else
                    self notify( "next_target" );

                var_2.origin = var_7;
                wait 0.1;
            }
        }
    }
    else
    {
        for (;;)
        {
            move_use_turret( var_0 );

            while ( !isdefined( level.player_covertrigger ) )
            {
                if ( !var_0.player_target )
                {
                    var_0 settargetentity( level.player );
                    var_0.player_target = 1;
                    var_3.targent = level.player;
                }

                wait 0.2;
            }

            var_0 setmode( "manual_ai" );
            move_use_turret( var_0 );
            var_0 notify( "startfiring" );
            var_11 = gettime() + 1500 + randomfloat( 4000 );

            while ( var_11 > gettime() )
            {
                if ( isdefined( level.player_covertrigger ) )
                {
                    var_16 = getentarray( level.player_covertrigger.target, "targetname" );
                    var_16 = var_16[randomint( var_16.size )];
                    var_2.origin = var_16.origin + ( randomfloat( 30 ) - 15, randomfloat( 30 ) - 15, randomfloat( 40 ) - 60 );
                    var_0 settargetentity( var_2 );
                    var_3.targent = var_2;
                    wait( randomfloat( 1 ) );
                    continue;
                }

                break;
            }

            var_0 notify( "stopfiring" );
            move_use_turret( var_0 );

            if ( var_0.player_target )
            {
                var_0 setmode( "auto_ai" );
                var_0 cleartargetentity();
                var_0.player_target = 0;
                var_3.targent = var_3;
                var_3.origin = ( 0, 0, 0 );
            }

            while ( isdefined( level.player_covertrigger ) )
                wait 0.2;

            wait( 0.75 + randomfloat( 0.2 ) );
        }
    }
}

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

    for (;;)
    {
        var_1 = [];

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

        for ( var_2 = 0; var_2 < var_0.size; var_2++ )
        {
            self.gun_targ = randomint( var_0.size );
            self waittill( "next_target" );

            while ( var_1[self.gun_targ] )
            {
                self.gun_targ++;

                if ( self.gun_targ >= var_0.size )
                    self.gun_targ = 0;
            }

            var_1[self.gun_targ] = 1;
        }
    }
}

move_use_turret( var_0, var_1, var_2 )
{
    self setgoalpos( var_0.org );
    self.goalradius = level.magic_distance;
    self waittill( "goal" );

    if ( isdefined( var_1 ) && var_1 == "auto_ai" )
    {
        var_0 setmode( "auto_ai" );

        if ( isdefined( var_2 ) )
            var_0 settargetentity( var_2 );
        else
            var_0 cleartargetentity();
    }

    self useturret( var_0 );
}

temp_think( var_0, var_1 )
{
    if ( getdvar( "mg42" ) == "off" )
        return;

    self.targent = self;

    for (;;)
    {
        self.origin = var_1.origin;
        wait 0.1;
    }
}

turret_think( var_0 )
{
    var_1 = getent( var_0.auto_mg42_target, "targetname" );
    var_2 = 0.5;

    if ( isdefined( var_1.script_turret_reuse_min ) )
        var_2 = var_1.script_turret_reuse_min;

    var_3 = 2;

    if ( isdefined( var_1.script_turret_reuse_max ) )
        var_2 = var_1.script_turret_reuse_max;

    for (;;)
    {
        var_1 waittill( "turret_deactivate" );
        wait( var_2 + randomfloat( var_3 - var_2 ) );

        while ( !isturretactive( var_1 ) )
        {
            turret_find_user( var_0, var_1 );
            wait 1.0;
        }
    }
}

turret_find_user( var_0, var_1 )
{
    var_2 = getaiarray();

    for ( var_3 = 0; var_3 < var_2.size; var_3++ )
    {
        if ( var_2[var_3] isingoal( var_0.origin ) && var_2[var_3] canuseturret( var_1 ) )
        {
            var_4 = var_2[var_3].keepclaimednodeifvalid;
            var_2[var_3].keepclaimednodeifvalid = 0;

            if ( !var_2[var_3] usecovernode( var_0 ) )
                var_2[var_3].keepclaimednodeifvalid = var_4;
        }
    }
}

setdifficulty()
{
    init_mgturretsettings();
    var_0 = getentarray( "misc_turret", "code_classname" );
    var_1 = maps\_utility::getdifficulty();

    for ( var_2 = 0; var_2 < var_0.size; var_2++ )
    {
        if ( isdefined( var_0[var_2].script_skilloverride ) )
        {
            switch ( var_0[var_2].script_skilloverride )
            {
                case "easy":
                    var_1 = "easy";
                    break;
                case "medium":
                    var_1 = "medium";
                    break;
                case "hard":
                    var_1 = "hard";
                    break;
                case "fu":
                    var_1 = "fu";
                    break;
                default:
                    continue;
            }
        }

        mg42_setdifficulty( var_0[var_2], var_1 );
    }
}

mg42_setdifficulty( var_0, var_1 )
{
    var_0.convergencetime = level.mgturretsettings[var_1]["convergenceTime"];
    var_0.suppressiontime = level.mgturretsettings[var_1]["suppressionTime"];
    var_0.accuracy = level.mgturretsettings[var_1]["accuracy"];
    var_0.aispread = level.mgturretsettings[var_1]["aiSpread"];
    var_0.playerspread = level.mgturretsettings[var_1]["playerSpread"];
}

mg42_target_drones( var_0, var_1, var_2 )
{
    if ( !isdefined( var_2 ) )
        var_2 = 0.88;

    self endon( "death" );
    self notify( "stop_mg42_target_drones" );
    self endon( "stop_mg42_target_drones" );
    self.dronefailed = 0;

    if ( !isdefined( self.script_fireondrones ) )
        self.script_fireondrones = 0;

    if ( !isdefined( var_0 ) )
        var_0 = 0;

    self setmode( "manual_ai" );
    var_3 = maps\_utility::getdifficulty();

    if ( !isdefined( level.drones ) )
        var_4 = 1;
    else
        var_4 = 0;

    for (;;)
    {
        if ( var_4 )
        {
            if ( isdefined( self.drones_targets_sets_to_default ) )
                self setmode( self.defaultonmode );
            else if ( var_0 )
                self setmode( "auto_nonai" );
            else
                self setmode( "auto_ai" );

            level waittill( "new_drone" );
        }

        if ( !isdefined( self.oldconvergencetime ) )
            self.oldconvergencetime = self.convergencetime;

        self.convergencetime = 2;

        if ( !var_0 )
        {
            var_5 = self getturretowner();

            if ( !isalive( var_5 ) || isplayer( var_5 ) )
            {
                wait 0.05;
                continue;
            }
            else
                var_1 = var_5.team;
        }
        else
            var_5 = undefined;

        if ( var_1 == "allies" )
            var_6 = "axis";
        else
            var_6 = "allies";

        while ( level.drones[var_6].lastindex )
        {
            common_scripts\utility::lock( "mg42_drones" );

            if ( !level.drones[var_6].lastindex )
            {
                common_scripts\utility::unlock( "mg42_drones" );
                break;
            }

            var_7 = get_bestdrone( var_6, var_2 );
            common_scripts\utility::unlock( "mg42_drones" );

            if ( !isdefined( self.script_fireondrones ) || !self.script_fireondrones )
            {
                wait 0.05;
                break;
            }

            if ( !isdefined( var_7 ) )
            {
                wait 0.05;
                break;
            }

            if ( isdefined( self.anim_wait_func ) )
                [[ self.anim_wait_func ]]();

            if ( var_0 )
                self setmode( "manual" );
            else
                self setmode( "manual_ai" );

            self settargetentity( var_7, ( 0, 0, 32 ) );
            drone_target( var_7, 1, var_2 );
            self cleartargetentity();
            self stopfiring();

            if ( !var_0 && !( isdefined( self getturretowner() ) && self getturretowner() == var_5 ) )
                break;
        }

        self.convergencetime = self.oldconvergencetime;
        self.oldconvergencetime = undefined;
        self cleartargetentity();
        self stopfiring();

        if ( level.drones[var_6].lastindex )
        {
            var_4 = 0;
            continue;
        }

        var_4 = 1;
    }
}

drone_target( var_0, var_1, var_2 )
{
    self endon( "death" );
    var_0 endon( "death" );
    var_3 = gettime() + var_1 * 1000;
    var_4 = 0;

    while ( var_3 > gettime() || var_4 )
    {
        common_scripts\utility::lock( "mg42_drones_target_trace" );
        var_5 = self getturrettarget( 1 );

        if ( !bullettracepassed( self gettagorigin( "tag_flash" ), var_0.origin + ( 0, 0, 40 ), 0, var_0 ) )
        {
            common_scripts\utility::unlock( "mg42_drones_target_trace" );
            break;
        }
        else if ( isdefined( var_5 ) && distance( var_5.origin, self.origin ) < distance( self.origin, var_0.origin ) )
        {
            common_scripts\utility::unlock( "mg42_drones_target_trace" );
            break;
        }

        if ( !var_4 )
        {
            self startfiring();
            var_4 = 1;
        }

        common_scripts\utility::unlock_wait( "mg42_drones_target_trace" );
    }

    self stopfiring();
    maps\_utility::structarray_shuffle( level.drones[var_0.team], 1 );
}

get_bestdrone( var_0, var_1 )
{
    if ( level.drones[var_0].lastindex < 1 )
        return;

    var_2 = undefined;
    var_3 = anglestoforward( self.angles );

    for ( var_4 = 0; var_4 < level.drones[var_0].lastindex; var_4++ )
    {
        if ( !isdefined( level.drones[var_0].array[var_4] ) )
            continue;

        var_5 = vectortoangles( level.drones[var_0].array[var_4].origin - self.origin );
        var_6 = anglestoforward( var_5 );

        if ( vectordot( var_3, var_6 ) < var_1 )
            continue;

        var_2 = level.drones[var_0].array[var_4];

        if ( !bullettracepassed( self gettagorigin( "tag_flash" ), var_2 getcentroid(), 0, var_2 ) )
        {
            var_2 = undefined;
            continue;
        }

        break;
    }

    var_7 = self getturrettarget( 1 );

    if ( !isdefined( self.prefers_drones ) )
    {
        if ( isdefined( var_2 ) && isdefined( var_7 ) && distancesquared( self.origin, var_7.origin ) < distancesquared( self.origin, var_2.origin ) )
            var_2 = undefined;
    }

    return var_2;
}

saw_mgturretlink( var_0 )
{
    var_1 = getentarray( "misc_turret", "code_classname" );
    var_2 = [];

    for ( var_3 = 0; var_3 < var_1.size; var_3++ )
    {
        if ( isdefined( var_1[var_3].targetname ) )
            continue;

        if ( isdefined( var_1[var_3].isvehicleattached ) )
            continue;

        var_2[var_1[var_3].origin + ""] = var_1[var_3];
    }

    if ( !var_2.size )
        return;

    for ( var_4 = 0; var_4 < var_0.size; var_4++ )
    {
        var_5 = var_0[var_4];

        if ( var_5.type == "Path" )
            continue;

        if ( var_5.type == "Begin" )
            continue;

        if ( var_5.type == "End" )
            continue;

        var_6 = anglestoforward( ( 0, var_5.angles[1], 0 ) );

        foreach ( var_11, var_8 in var_2 )
        {
            if ( distance( var_5.origin, var_8.origin ) > 50 )
                continue;

            var_9 = anglestoforward( ( 0, var_8.angles[1], 0 ) );
            var_10 = vectordot( var_6, var_9 );

            if ( var_10 < 0.9 )
                continue;

            var_5.turretinfo = spawn( "script_origin", var_8.origin );
            var_5.turretinfo.angles = var_8.angles;
            var_5.turretinfo.node = var_5;
            var_5.turretinfo.leftarc = 45;
            var_5.turretinfo.rightarc = 45;
            var_5.turretinfo.toparc = 15;
            var_5.turretinfo.bottomarc = 15;

            if ( isdefined( var_8.leftarc ) )
                var_5.turretinfo.leftarc = min( var_8.leftarc, 45 );

            if ( isdefined( var_8.rightarc ) )
                var_5.turretinfo.rightarc = min( var_8.rightarc, 45 );

            if ( isdefined( var_8.toparc ) )
                var_5.turretinfo.toparc = min( var_8.toparc, 15 );

            if ( isdefined( var_8.bottomarc ) )
                var_5.turretinfo.bottomarc = min( var_8.bottomarc, 15 );

            var_2[var_11] = undefined;
            var_8 delete();
        }
    }
}

auto_mgturretlink( var_0 )
{
    var_1 = getentarray( "misc_turret", "code_classname" );
    var_2 = [];

    for ( var_3 = 0; var_3 < var_1.size; var_3++ )
    {
        if ( !isdefined( var_1[var_3].targetname ) || tolower( var_1[var_3].targetname ) != "auto_mgturret" )
            continue;

        if ( !isdefined( var_1[var_3].export ) )
            continue;

        if ( !isdefined( var_1[var_3].script_dont_link_turret ) )
            var_2[var_1[var_3].origin + ""] = var_1[var_3];
    }

    if ( !var_2.size )
        return;

    for ( var_4 = 0; var_4 < var_0.size; var_4++ )
    {
        var_5 = var_0[var_4];

        if ( var_5.type == "Path" )
            continue;

        if ( var_5.type == "Begin" )
            continue;

        if ( var_5.type == "End" )
            continue;

        var_6 = anglestoforward( ( 0, var_5.angles[1], 0 ) );
        var_7 = getarraykeys( var_2 );

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

            if ( distance( var_5.origin, var_8.origin ) > 70 )
                continue;

            var_9 = anglestoforward( ( 0, var_8.angles[1], 0 ) );
            var_10 = vectordot( var_6, var_9 );

            if ( var_10 < 0.9 )
                continue;

            var_5.turret = var_8;
            var_8.node = var_5;
            var_8.issetup = 1;
            var_2[var_7[var_3]] = undefined;
        }
    }

    var_0 = undefined;
}

save_turret_sharing_info()
{
    self.shared_turrets = [];
    self.shared_turrets["connected"] = [];
    self.shared_turrets["ambush"] = [];

    if ( !isdefined( self.export ) )
        return;

    level.shared_portable_turrets[self.export] = self;

    if ( isdefined( self.script_turret_share ) )
    {
        var_0 = strtok( self.script_turret_share, " " );

        for ( var_1 = 0; var_1 < var_0.size; var_1++ )
            self.shared_turrets["connected"][var_0[var_1]] = 1;
    }

    if ( isdefined( self.script_turret_ambush ) )
    {
        var_0 = strtok( self.script_turret_ambush, " " );

        for ( var_1 = 0; var_1 < var_0.size; var_1++ )
            self.shared_turrets["ambush"][var_0[var_1]] = 1;
    }
}

restoredefaultpitch()
{
    self notify( "gun_placed_again" );
    self endon( "gun_placed_again" );
    self waittill( "restore_default_drop_pitch" );
    wait 1;
    self restoredefaultdroppitch();
}

dropturret()
{
    thread dropturretproc();
}

dropturretproc()
{
    var_0 = spawn( "script_model", ( 0, 0, 0 ) );
    var_0.origin = self gettagorigin( level.portable_mg_gun_tag );
    var_0.angles = self gettagangles( level.portable_mg_gun_tag );
    var_0 setmodel( self.turretmodel );
    var_1 = anglestoforward( self.angles );
    var_1 = var_1 * 100;
    var_0 movegravity( var_1, 0.5 );
    self detach( self.turretmodel, level.portable_mg_gun_tag );
    self.turretmodel = undefined;
    wait 0.7;
    var_0 delete();
}

turretdeathdetacher()
{
    self endon( "kill_turret_detach_thread" );
    self endon( "dropped_gun" );
    self waittill( "death" );

    if ( !isdefined( self ) )
        return;

    dropturret();
}

turretdetacher()
{
    self endon( "death" );
    self endon( "kill_turret_detach_thread" );
    self waittill( "dropped_gun" );
    self detach( self.turretmodel, level.portable_mg_gun_tag );
}

restoredefaults()
{
    self.run_overrideanim = undefined;
    common_scripts\utility::set_all_exceptions( animscripts\init::empty );
}

restorepitch()
{
    self waittill( "turret_deactivate" );
    self restoredefaultdroppitch();
}

update_enemy_target_pos_while_running( var_0 )
{
    self endon( "death" );
    self endon( "end_mg_behavior" );
    self endon( "stop_updating_enemy_target_pos" );

    for (;;)
    {
        self waittill( "saw_enemy" );
        var_0.origin = self.last_enemy_sighting_position;
    }
}

move_target_pos_to_new_turrets_visibility( var_0, var_1 )
{
    self endon( "death" );
    self endon( "end_mg_behavior" );
    self endon( "stop_updating_enemy_target_pos" );
    var_2 = self.turret.origin + ( 0, 0, 16 );
    var_3 = var_1.origin + ( 0, 0, 16 );

    for (;;)
    {
        wait 0.05;

        if ( sighttracepassed( var_0.origin, var_3, 0, undefined ) )
            continue;

        var_4 = vectortoangles( var_2 - var_0.origin );
        var_5 = anglestoforward( var_4 );
        var_5 = var_5 * 8;
        var_0.origin = var_0.origin + var_5;
    }
}

record_bread_crumbs_for_ambush( var_0 )
{
    self endon( "death" );
    self endon( "end_mg_behavior" );
    self endon( "stop_updating_enemy_target_pos" );
    var_0.bread_crumbs = [];

    for (;;)
    {
        var_0.bread_crumbs[var_0.bread_crumbs.size] = self.origin + ( 0, 0, 50 );
        wait 0.35;
    }
}

aim_turret_at_ambush_point_or_visible_enemy( var_0, var_1 )
{
    if ( !isalive( self.current_enemy ) && self cansee( self.current_enemy ) )
    {
        var_1.origin = self.last_enemy_sighting_position;
        return;
    }

    var_2 = anglestoforward( var_0.angles );

    for ( var_3 = var_1.bread_crumbs.size - 3; var_3 >= 0; var_3-- )
    {
        var_4 = var_1.bread_crumbs[var_3];
        var_5 = vectornormalize( var_4 - var_0.origin );
        var_6 = vectordot( var_2, var_5 );

        if ( var_6 < 0.75 )
            continue;

        var_1.origin = var_4;

        if ( sighttracepassed( var_0.origin, var_4, 0, undefined ) )
            continue;

        break;
    }
}

find_a_new_turret_spot( var_0 )
{
    var_1 = get_portable_mg_spot( var_0 );
    var_2 = var_1["spot"];
    var_3 = var_1["type"];

    if ( !isdefined( var_2 ) )
        return;

    reserve_turret( var_2 );
    thread update_enemy_target_pos_while_running( var_0 );
    thread move_target_pos_to_new_turrets_visibility( var_0, var_2 );

    if ( var_3 == "ambush" )
        thread record_bread_crumbs_for_ambush( var_0 );

    if ( var_2.issetup )
        leave_gun_and_run_to_new_spot( var_2 );
    else
    {
        pickup_gun( var_2 );
        run_to_new_spot_and_setup_gun( var_2 );
    }

    self notify( "stop_updating_enemy_target_pos" );

    if ( var_3 == "ambush" )
        aim_turret_at_ambush_point_or_visible_enemy( var_2, var_0 );

    var_2 settargetentity( var_0 );
}

snap_lock_turret_onto_target( var_0 )
{
    var_0 setmode( "manual" );
    wait 0.5;
    var_0 setmode( "manual_ai" );
}

leave_gun_and_run_to_new_spot( var_0 )
{
    self stopuseturret();
    animscripts\shared::placeweaponon( self.primaryweapon, "none" );
    var_1 = get_turret_setup_anim( var_0 );
    var_2 = getstartorigin( var_0.origin, var_0.angles, var_1 );
    self setruntopos( var_2 );
    self waittill( "runto_arrived" );
    use_the_turret( var_0 );
}

pickup_gun( var_0 )
{
    self stopuseturret();
    self.turret hide_turret();
}

get_turret_setup_anim( var_0 )
{
    var_1 = [];
    var_1["saw_bipod_stand"] = level.mg_animmg["bipod_stand_setup"];
    var_1["saw_bipod_crouch"] = level.mg_animmg["bipod_crouch_setup"];
    var_1["saw_bipod_prone"] = level.mg_animmg["bipod_prone_setup"];
    return var_1[var_0.weaponinfo];
}

#using_animtree("generic_human");

run_to_new_spot_and_setup_gun( var_0 )
{
    var_1 = self.health;
    var_0 endon( "turret_deactivate" );
    self.mg42 = var_0;
    self endon( "death" );
    self endon( "dropped_gun" );
    var_2 = get_turret_setup_anim( var_0 );
    self.turretmodel = "weapon_mg42_carry";
    self notify( "kill_get_gun_back_on_killanimscript_thread" );
    animscripts\shared::placeweaponon( self.weapon, "none" );

    if ( self isbadguy() )
        self.health = 1;

    self.run_overrideanim = %saw_gunner_run_fast;
    self.crouchrun_combatanim = %saw_gunner_run_fast;
    self attach( self.turretmodel, level.portable_mg_gun_tag );
    thread turretdeathdetacher();
    var_3 = getstartorigin( var_0.origin, var_0.angles, var_2 );
    self setruntopos( var_3 );
    wait 0.05;
    common_scripts\utility::set_all_exceptions( animscripts\combat::exception_exposed_mg42_portable );
    common_scripts\utility::clear_exception( "move" );
    common_scripts\utility::set_exception( "cover_crouch", ::hold_indefintely );

    while ( distance( self.origin, var_3 ) > 16 )
    {
        self setruntopos( var_3 );
        wait 0.05;
    }

    self notify( "kill_turret_detach_thread" );

    if ( self isbadguy() )
        self.health = var_1;

    if ( soundexists( "weapon_setup" ) )
        thread common_scripts\utility::play_sound_in_space( "weapon_setup" );

    self animscripted( "setup_done", var_0.origin, var_0.angles, var_2 );
    restoredefaults();
    self waittillmatch( "setup_done", "end" );
    var_0 notify( "restore_default_drop_pitch" );
    var_0 show_turret();
    animscripts\shared::placeweaponon( self.primaryweapon, "right" );
    use_the_turret( var_0 );
    self detach( self.turretmodel, level.portable_mg_gun_tag );
    common_scripts\utility::set_all_exceptions( animscripts\init::empty );
    self notify( "bcs_portable_turret_setup" );
}

move_to_run_pos()
{
    self setruntopos( self.runpos );
}

hold_indefintely()
{
    self endon( "killanimscript" );
    self waittill( "death" );
}

using_a_turret()
{
    if ( !isdefined( self.turret ) )
        return 0;

    return self.turret.owner == self;
}

turret_user_moves()
{
    if ( !using_a_turret() )
    {
        common_scripts\utility::clear_exception( "move" );
        return;
    }

    var_0 = find_connected_turrets( "connected" );
    var_1 = var_0["spots"];

    if ( !var_1.size )
    {
        common_scripts\utility::clear_exception( "move" );
        return;
    }

    var_2 = self.node;

    if ( !isdefined( var_2 ) || !maps\_utility::is_in_array( var_1, var_2 ) )
    {
        var_3 = gettakennodes();

        for ( var_4 = 0; var_4 < var_1.size; var_4++ )
        {
            var_2 = common_scripts\utility::random( var_1 );

            if ( isdefined( var_3[var_2.origin + ""] ) )
                return;
        }
    }

    var_5 = var_2.turret;

    if ( isdefined( var_5.reserved ) )
        return;

    reserve_turret( var_5 );

    if ( var_5.issetup )
        leave_gun_and_run_to_new_spot( var_5 );
    else
        run_to_new_spot_and_setup_gun( var_5 );

    maps\_mg_penetration::gunner_think( var_2.turret );
}

use_the_turret( var_0 )
{
    var_1 = self useturret( var_0 );

    if ( var_1 )
    {
        common_scripts\utility::set_exception( "move", ::turret_user_moves );
        self.turret = var_0;
        thread mg42_firing( var_0 );
        var_0 setmode( "manual_ai" );
        var_0 thread restorepitch();
        self.turret = var_0;
        var_0.owner = self;
        return 1;
    }
    else
    {
        var_0 restoredefaultdroppitch();
        return 0;
    }
}

get_portable_mg_spot( var_0 )
{
    var_1 = [];
    var_1[var_1.size] = ::find_different_way_to_attack_last_seen_position;
    var_1[var_1.size] = ::find_good_ambush_spot;
    var_1 = common_scripts\utility::array_randomize( var_1 );

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

        if ( !isdefined( var_3["spots"] ) )
            continue;

        var_3["spot"] = common_scripts\utility::random( var_3["spots"] );
        return var_3;
    }
}

gettakennodes()
{
    var_0 = [];
    var_1 = getaiarray();

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

        var_0[var_1[var_2].node.origin + ""] = 1;
    }

    return var_0;
}

find_connected_turrets( var_0 )
{
    var_1 = level.shared_portable_turrets;
    var_2 = [];
    var_3 = getarraykeys( var_1 );
    var_4 = gettakennodes();
    var_4[self.node.origin + ""] = undefined;

    for ( var_5 = 0; var_5 < var_3.size; var_5++ )
    {
        var_6 = var_3[var_5];

        if ( var_1[var_6] == self.turret )
            continue;

        var_7 = getarraykeys( self.turret.shared_turrets[var_0] );

        for ( var_8 = 0; var_8 < var_7.size; var_8++ )
        {
            if ( var_1[var_6].export + "" != var_7[var_8] )
                continue;

            if ( isdefined( var_1[var_6].reserved ) )
                continue;

            if ( isdefined( var_4[var_1[var_6].node.origin + ""] ) )
                continue;

            if ( distance( self.goalpos, var_1[var_6].origin ) > self.goalradius )
                continue;

            var_2[var_2.size] = var_1[var_6];
        }
    }

    var_9 = [];
    var_9["type"] = var_0;
    var_9["spots"] = var_2;
    return var_9;
}

find_good_ambush_spot( var_0 )
{
    return find_connected_turrets( "ambush" );
}

find_different_way_to_attack_last_seen_position( var_0 )
{
    var_1 = find_connected_turrets( "connected" );
    var_2 = var_1["spots"];

    if ( !var_2.size )
        return;

    var_3 = [];

    for ( var_4 = 0; var_4 < var_2.size; var_4++ )
    {
        if ( !common_scripts\utility::within_fov( var_2[var_4].origin, var_2[var_4].angles, var_0.origin, 0.75 ) )
            continue;

        if ( !sighttracepassed( var_0.origin, var_2[var_4].origin + ( 0, 0, 16 ), 0, undefined ) )
            continue;

        var_3[var_3.size] = var_2[var_4];
    }

    var_1["spots"] = var_3;
    return var_1;
}

portable_mg_spot()
{
    save_turret_sharing_info();
    var_0 = 1;
    self.issetup = 1;
    self.reserved = undefined;

    if ( isdefined( self.isvehicleattached ) )
        return;

    if ( self.spawnflags & var_0 )
        return;

    hide_turret();
}

hide_turret()
{
    self notify( "stop_checking_for_flanking" );
    self.issetup = 0;
    self hide();
    self.solid = 0;
    self makeunusable();
    self setdefaultdroppitch( 0 );
    thread restoredefaultpitch();
}

show_turret()
{
    self show();
    self.solid = 1;
    self makeusable();
    self.issetup = 1;
    thread stop_mg_behavior_if_flanked();
}

stop_mg_behavior_if_flanked()
{
    self endon( "stop_checking_for_flanking" );
    self waittill( "turret_deactivate" );

    if ( isalive( self.owner ) )
        self.owner notify( "end_mg_behavior" );
}

turret_is_mine( var_0 )
{
    var_1 = var_0 getturretowner();

    if ( !isdefined( var_1 ) )
        return 0;

    return var_1 == self;
}

end_turret_reservation( var_0 )
{
    waittill_turret_is_released( var_0 );
    var_0.reserved = undefined;
}

waittill_turret_is_released( var_0 )
{
    var_0 endon( "turret_deactivate" );
    self endon( "death" );
    self waittill( "end_mg_behavior" );
}

reserve_turret( var_0 )
{
    var_0.reserved = self;
    thread end_turret_reservation( var_0 );
}
