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

main()
{
    setupalienstate();
    thread think();
    thread watchownerdamage();
    thread watchownerdeath();
    thread watchownerteamchange();
    thread waitforbadpath();
    thread waitforpathset();
}

setupalienstate()
{
    self.blockgoalpos = 0;
    self.ownerradiussq = 20736;
    self.meleeradiussq = 8100;
    self.attackoffset = 25 + self.radius;
    self.attackradiussq = 202500;
    self.warningradiussq = 302500;
    self.warningzheight = 96.0;
    self.attackzheight = 54;
    self.attackzheightdown = -64;
    self.ownerdamagedradiussq = 2250000;
    self.dogdamagedradiussq = 42250000;
    self.keeppursuingtargetradiussq = 36000000;
    self.preferredoffsetfromowner = 76;
    self.minoffsetfromowner = 50;
    self.forceattack = 1;
    self.ignoreclosefoliage = 1;
    self.movemode = "run";
    self.enableextendedkill = 1;
    self.attackstate = "idle";
    self.movestate = "idle";
    self.bhasbadpath = 0;
    self.timeoflastdamage = 0;
    self.alien_goalpos = get_closest( self.origin, self.pathnodearray );
    self.allowcrouch = 1;
    self scragentsetgoalradius( 24 );
}

init()
{
    self.animcbs = spawnstruct();
    self.animcbs.onenter = [];
    self.animcbs.onenter["idle"] = maps\mp\mp_dome_ns_alien_idle::main;
    self.animcbs.onenter["move"] = maps\mp\mp_dome_ns_alien_move::main;
    self.animcbs.onenter["traverse"] = maps\mp\mp_dome_ns_alien_traverse::main;
    self.animcbs.onexit = [];
    self.animcbs.onexit["idle"] = maps\mp\mp_dome_ns_alien_idle::end_script;
    self.animcbs.onexit["move"] = maps\mp\mp_dome_ns_alien_move::end_script;
    self.animcbs.onexit["traverse"] = maps\mp\mp_dome_ns_alien_traverse::end_script;
    self suicide();
    self.watchattackstatefunc = ::watchattackstate;
    self.aistate = "idle";
    self.movemode = "fastwalk";
    self.radius = 15;
    self.height = 40;
}

onenteranimstate( var_0, var_1 )
{
    self notify( "killanimscript" );

    if ( !isdefined( self.animcbs.onenter[var_1] ) )
        return;

    if ( var_0 == var_1 && var_1 != "alien_traverse" )
        return;

    if ( isdefined( self.animcbs.onexit[var_0] ) )
        self [[ self.animcbs.onexit[var_0] ]]();

    exitaistate( self.aistate );
    self.aistate = var_1;
    enteraistate( var_1 );
    self [[ self.animcbs.onenter[var_1] ]]();
}

think()
{
    self endon( "death" );
    level endon( "game_ended" );

    if ( isdefined( self.owner ) )
    {
        self endon( "owner_disconnect" );
        thread destroyonownerdisconnect( self.owner );
    }

    self thread [[ self.watchattackstatefunc ]]();
    thread monitorflash();

    for (;;)
    {
        if ( !self.statelocked && readytomeleetarget() )
        {
            mp_dome_ns_alien_explode( self.curmeleetarget );
            return;
        }

        switch ( self.aistate )
        {
            case "idle":
                updateidle();
                break;
            case "move":
                updatemove();
                break;
            case "melee":
                updatemelee();
                break;
        }

        wait 0.05;
    }
}

mp_dome_ns_alien_explode( var_0, var_1, var_2, var_3 )
{
    self emissiveblend( 0.2, 1.0 );
    playfx( level._effect["vfx_alien_minion_explode_dome"], self.origin );
    var_4 = 2;
    var_5 = 1;

    if ( !isdefined( var_1 ) )
        var_1 = 400;

    if ( !isdefined( var_2 ) )
        var_2 = 380;

    if ( isdefined( var_3 ) )
        var_3 radiusdamage( self.origin, var_2, var_1, var_5, var_3, "MOD_EXPLOSIVE", "killstreak_level_event_mp" );
    else if ( isdefined( self.owner ) )
        self radiusdamage( self.origin, var_2, var_1, var_5, self.owner, "MOD_EXPLOSIVE", "killstreak_level_event_mp" );
    else
        self radiusdamage( self.origin, var_2, var_1, var_5, undefined, "MOD_EXPLOSIVE", "killstreak_level_event_mp" );

    self playsound( "alien_minion_explode" );
    physicsexplosionsphere( self.origin, var_2, var_2 / 2, var_4 );
    maps\mp\gametypes\_shellshock::barrel_earthquake();
    self notify( "killanimscript" );
    self setanimstate( "explode", 0, 1 );
    wait( getanimlength( self getanimentry( "explode", 0 ) ) );

    if ( isdefined( self ) )
        self suicide();
}

didpastpursuitfail( var_0 )
{
    if ( isdefined( self.curmeleetarget ) && var_0 != self.curmeleetarget )
        return 0;

    if ( !isdefined( self.lastpursuitfailedpos ) || !isdefined( self.lastpursuitfailedmypos ) )
        return 0;

    if ( distance2dsquared( var_0.origin, self.lastpursuitfailedpos ) > 4 )
        return 0;

    if ( self.blastpursuitfailedposbad )
        return 1;

    if ( distancesquared( self.origin, self.lastpursuitfailedmypos ) > 4096 && gettime() - self.lastpursuitfailedtime > 2000 )
        return 0;

    return 1;
}

didpastmeleefail()
{
    if ( isdefined( self.lastmeleefailedpos ) && isdefined( self.lastmeleefailedmypos ) && distance2dsquared( self.curmeleetarget.origin, self.lastmeleefailedpos ) < 4 && distancesquared( self.origin, self.lastmeleefailedmypos ) < 2500 )
        return 1;

    if ( wanttoattacktargetbutcant( 0 ) )
        return 1;

    return 0;
}

enteraistate( var_0 )
{
    exitaistate( self.aistate );
    self.aistate = var_0;

    switch ( var_0 )
    {
        case "idle":
            self.movestate = "idle";
            self.bhasbadpath = 0;
            break;
        case "move":
            self.movestate = "follow";
            break;
        case "melee":
            break;
        default:
            break;
    }
}

exitaistate( var_0 )
{
    switch ( var_0 )
    {
        case "move":
            self.ownerprevpos = undefined;
            break;
        default:
            break;
    }
}

updateidle()
{
    updatemovestate();
}

updatemove()
{
    updatemovestate();
}

updatemelee()
{
    self scragentsetgoalpos( self.origin );
}

updatemovestate()
{
    if ( self.blockgoalpos )
        return;

    self.prevmovestate = self.movestate;
    var_0 = undefined;
    var_1 = 0;
    var_2 = 0;
    var_3 = 500;

    if ( self.bhasbadpath && gettime() - self.lastbadpathtime < var_3 )
    {
        self.movestate = "follow";
        var_1 = 1;
    }
    else
        self.movestate = getmovestate();

    if ( self.movestate == "pursuit" )
    {
        var_0 = getattackpoint( self.enemy );
        var_4 = 0;

        if ( isdefined( self.lastbadpathtime ) && gettime() - self.lastbadpathtime < 3000 )
        {
            if ( distance2dsquared( var_0, self.lastbadpathgoal ) < 16 )
                var_4 = 1;
            else if ( isdefined( self.lastbadpathmovestate ) && self.lastbadpathmovestate == "pursuit" && distance2dsquared( self.lastbadpathultimategoal, self.enemy.origin ) < 16 )
                var_4 = 1;
        }

        if ( var_4 )
        {
            self.movestate = "follow";
            var_2 = 1;
        }
        else if ( wanttoattacktargetbutcant( 1 ) )
        {
            self.movestate = "follow";
            var_2 = 1;
        }
        else if ( didpastpursuitfail( self.enemy ) )
        {
            self.movestate = "follow";
            var_2 = 1;
        }
    }

    setpastpursuitfailed( var_2 );

    if ( self.movestate == "follow" )
    {
        self.curmeleetarget = undefined;
        self.movemode = getfollowmovemode( self.movemode );
        self.barrivalsenabled = 1;
        var_5 = self getpathgoalpos();

        if ( !isdefined( var_5 ) )
            var_5 = self.origin;

        if ( gettime() - self.timeoflastdamage < 5000 )
            var_1 = 1;

        var_6 = distance2dsquared( self.origin, self.alien_goalpos.origin );

        if ( var_6 < 800 )
            picknewlocation();

        self scragentsetgoalpos( self.alien_goalpos.origin );

        if ( var_1 == 1 )
        {
            self scragentsetgoalpos( self.origin );
            return;
        }
    }
    else if ( self.movestate == "pursuit" )
    {
        self.curmeleetarget = self.enemy;
        self.movemode = "sprint";
        self.barrivalsenabled = 0;
        self scragentsetgoalpos( var_0 );
    }
}

picknewlocation()
{
    self.alien_goalpos = common_scripts\utility::getstruct( self.alien_goalpos.target, "targetname" );
}

getmovestate( var_0 )
{
    if ( isdefined( self.enemy ) )
    {
        if ( !maps\mp\_utility::isreallyalive( self.enemy ) )
            return "follow";

        if ( isdefined( self.favoriteenemy ) && self.enemy == self.favoriteenemy )
            return "pursuit";

        if ( abs( self.origin[2] - self.enemy.origin[2] ) < self.warningzheight && distance2dsquared( self.enemy.origin, self.origin ) < self.attackradiussq )
            return "pursuit";

        if ( isdefined( self.curmeleetarget ) && self.curmeleetarget == self.enemy )
        {
            if ( distance2dsquared( self.curmeleetarget.origin, self.origin ) < self.keeppursuingtargetradiussq )
                return "pursuit";
        }
    }

    return "follow";
}

setpastpursuitfailed( var_0 )
{
    if ( var_0 )
    {
        if ( !isdefined( self.lastpursuitfailedpos ) )
        {
            self.lastpursuitfailedpos = self.enemy.origin;
            self.lastpursuitfailedmypos = self.origin;
            var_1 = maps\mp\agents\_scriptedagents::droppostoground( self.enemy.origin );
            self.blastpursuitfailedposbad = !isdefined( var_1 );
            self.lastpursuitfailedtime = gettime();
        }
    }
    else
    {
        self.lastpursuitfailedpos = undefined;
        self.lastpursuitfailedmypos = undefined;
        self.blastpursuitfailedposbad = undefined;
        self.lastpursuitfailedtime = undefined;
    }
}

waitforbadpath()
{
    self endon( "death" );
    level endon( "game_ended" );

    for (;;)
    {
        self waittill( "bad_path", var_0 );
        self.bhasbadpath = 1;
        self.lastbadpathtime = gettime();
        self.lastbadpathgoal = var_0;
        self.lastbadpathmovestate = self.movestate;

        if ( self.movestate == "follow" && isdefined( self.owner ) )
        {
            self.lastbadpathultimategoal = self.owner.origin;
            continue;
        }

        if ( self.movestate == "pursuit" && isdefined( self.enemy ) )
            self.lastbadpathultimategoal = self.enemy.origin;
    }
}

waitforpathset()
{
    self endon( "death" );
    level endon( "game_ended" );

    for (;;)
    {
        self waittill( "path_set" );
        self.bhasbadpath = 0;
    }
}

getfollowmovemode( var_0 )
{
    var_1 = 122500;
    var_2 = 160000;
    var_3 = self getpathgoalpos();

    if ( isdefined( var_3 ) )
    {
        var_4 = distancesquared( var_3, self.origin );

        if ( var_0 == "run" || var_0 == "sprint" )
        {
            if ( var_4 < var_1 )
                return "fastwalk";
            else if ( var_0 == "sprint" )
                return "run";
        }
        else if ( var_0 == "fastwalk" )
        {
            if ( var_4 > var_2 )
                return "run";
        }
    }

    return var_0;
}

iswithinattackheight( var_0 )
{
    var_1 = var_0[2] - self.origin[2];
    return var_1 <= self.attackzheight && var_1 >= self.attackzheightdown;
}

wanttoattacktargetbutcant( var_0 )
{
    if ( !isdefined( self.curmeleetarget ) )
        return 0;

    return !iswithinattackheight( self.curmeleetarget.origin ) && distance2dsquared( self.origin, self.curmeleetarget.origin ) < self.meleeradiussq * 0.75 * 0.75 && ( !var_0 || self agentcanseesentient( self.curmeleetarget ) );
}

readytomeleetarget()
{
    if ( !isdefined( self.curmeleetarget ) )
        return 0;

    if ( !maps\mp\_utility::isreallyalive( self.curmeleetarget ) )
        return 0;

    if ( self.aistate == "traverse" )
        return 0;

    if ( distance2dsquared( self.origin, self.curmeleetarget.origin ) > self.meleeradiussq )
        return 0;

    if ( !iswithinattackheight( self.curmeleetarget.origin ) )
        return 0;

    return 1;
}

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

    if ( abs( self.origin[2] - self.enemy.origin[2] ) <= self.warningzheight || self agentcanseesentient( self.enemy ) )
    {
        var_0 = distance2dsquared( self.origin, self.enemy.origin );

        if ( var_0 < self.warningradiussq )
            return 1;
    }

    return 0;
}

getattackpoint( var_0 )
{
    var_1 = var_0.origin - self.origin;
    var_1 = vectornormalize( var_1 );
    var_2 = self getpathgoalpos();
    var_3 = self.attackoffset + 4;

    if ( isdefined( var_2 ) && distance2dsquared( var_2, var_0.origin ) < var_3 * var_3 && maps\mp\agents\_scriptedagents::canmovepointtopoint( var_0.origin, var_2 ) )
        return var_2;

    var_4 = var_0.origin - var_1 * self.attackoffset;
    var_4 = maps\mp\agents\_scriptedagents::droppostoground( var_4 );

    if ( !isdefined( var_4 ) )
        return var_0.origin;

    if ( !maps\mp\agents\_scriptedagents::canmovepointtopoint( var_0.origin, var_4 ) )
    {
        var_5 = anglestoforward( var_0.angles );
        var_4 = var_0.origin + var_5 * self.attackoffset;

        if ( !maps\mp\agents\_scriptedagents::canmovepointtopoint( var_0.origin, var_4 ) )
            return var_0.origin;
    }

    return var_4;
}

cross2d( var_0, var_1 )
{
    return var_0[0] * var_1[1] - var_1[0] * var_0[1];
}

destroyonownerdisconnect( var_0 )
{
    self endon( "death" );
    var_0 common_scripts\utility::waittill_any( "disconnect", "joined_team", "joined_spectators" );
    self notify( "owner_disconnect" );

    if ( maps\mp\gametypes\_hostmigration::waittillhostmigrationdone() )
        wait 0.05;

    self notify( "killanimscript" );

    if ( isdefined( self.animcbs.onexit[self.aistate] ) )
        self [[ self.animcbs.onexit[self.aistate] ]]();

    mp_dome_ns_alien_explode( undefined, 1, 0 );
}

watchattackstate()
{
    self endon( "death" );
    level endon( "game_ended" );

    for (;;)
    {
        if ( self.aistate == "melee" )
        {
            if ( self.attackstate != "melee" )
            {
                self.attackstate = "melee";
                setsoundstate( undefined );
            }
        }
        else if ( self.movestate == "pursuit" )
        {
            if ( self.attackstate != "attacking" )
            {
                self.attackstate = "attacking";
                setsoundstate( "bark", "attacking" );
            }
        }
        else if ( self.attackstate != "warning" )
        {
            if ( wantstogrowlattarget() )
            {
                self.attackstate = "warning";
                setsoundstate( "growl", "warning" );
            }
            else
            {
                self.attackstate = self.aistate;
                setsoundstate( "pant" );
            }
        }
        else if ( !wantstogrowlattarget() )
        {
            self.attackstate = self.aistate;
            setsoundstate( "pant" );
        }

        wait 0.05;
    }
}

setsoundstate( var_0, var_1 )
{
    if ( !isdefined( var_0 ) )
    {
        self notify( "end_dog_sound" );
        self.soundstate = undefined;
        return;
    }

    if ( !isdefined( self.soundstate ) || self.soundstate != var_0 )
    {
        self notify( "end_dog_sound" );
        self.soundstate = var_0;

        if ( var_0 == "bark" )
            thread playbark( var_1 );
        else if ( var_0 == "growl" )
            thread playgrowl( var_1 );
        else if ( var_0 == "pant" )
            thread playpanting();
        else
        {

        }
    }
}

playbark( var_0 )
{
    self endon( "death" );
    level endon( "game_ended" );
    self endon( "end_dog_sound" );

    if ( !isdefined( self.barking_sound ) )
    {
        self playsoundonmovingent( "alien_minion_attack" );
        self.barking_sound = 1;
        thread watchbarking();
    }
}

watchbarking()
{
    self endon( "death" );
    level endon( "game_ended" );
    self endon( "end_dog_sound" );
    wait( randomintrange( 5, 10 ) );
    self.barking_sound = undefined;
}

playgrowl( var_0 )
{
    self endon( "death" );
    level endon( "game_ended" );
    self endon( "end_dog_sound" );

    if ( isdefined( self.lastgrowlplayedtime ) && gettime() - self.lastgrowlplayedtime < 3000 )
        wait 3;

    for (;;)
    {
        self.lastgrowlplayedtime = gettime();
        self playsoundonmovingent( "alien_minion_attack" );
        wait( randomintrange( 3, 6 ) );
    }
}

playpanting( var_0 )
{
    self endon( "death" );
    level endon( "game_ended" );
    self endon( "end_dog_sound" );

    if ( isdefined( self.lastpantplayedtime ) && gettime() - self.lastpantplayedtime < 3000 )
        wait 3;

    self.lastpantplayedtime = gettime();

    for (;;)
    {
        if ( self.aistate == "idle" )
        {
            wait 3;
            continue;
        }

        self.lastpantplayedtime = gettime();

        if ( self.movemode == "run" || self.movemode == "sprint" )
            self playsoundonmovingent( "alien_minion_idle" );
        else
            self playsoundonmovingent( "alien_minion_idle" );

        wait( randomintrange( 6, 8 ) );
    }
}

watchownerdamage()
{
    self endon( "death" );
    level endon( "game_ended" );

    for (;;)
    {
        if ( !isdefined( self.owner ) )
            return;

        self.owner waittill( "damage", var_0, var_1 );

        if ( isplayer( var_1 ) && var_1 != self.owner )
        {
            if ( self.attackstate == "attacking" )
                continue;

            if ( distancesquared( self.owner.origin, self.origin ) > self.ownerdamagedradiussq )
                continue;

            if ( distancesquared( self.owner.origin, var_1.origin ) > self.ownerdamagedradiussq )
                continue;

            self.favoriteenemy = var_1;
            self.forceattack = 1;
            thread watchfavoriteenemydeath();
        }
    }
}

watchownerdeath()
{
    self endon( "death" );
    level endon( "game_ended" );

    for (;;)
    {
        if ( !isdefined( self.owner ) )
            return;

        self.owner waittill( "death" );

        switch ( level.gametype )
        {
            case "sd":
                maps\mp\agents\_agent_utility::killdog();
                break;
            case "sr":
                var_0 = level common_scripts\utility::waittill_any_return( "sr_player_eliminated", "sr_player_respawned" );

                if ( isdefined( var_0 ) && var_0 == "sr_player_eliminated" )
                    maps\mp\agents\_agent_utility::killdog();

                break;
        }
    }
}

watchownerteamchange()
{
    self endon( "death" );
    level endon( "game_ended" );

    for (;;)
    {
        if ( !isdefined( self.owner ) )
            return;

        var_0 = self.owner common_scripts\utility::waittill_any_return_no_endon_death( "joined_team", "joined_spectators" );

        if ( isdefined( var_0 ) && ( var_0 == "joined_team" || var_0 == "joined_spectators" ) )
            maps\mp\agents\_agent_utility::killdog();
    }
}

watchfavoriteenemydeath()
{
    self notify( "watchFavoriteEnemyDeath" );
    self endon( "watchFavoriteEnemyDeath" );
    self endon( "death" );
    self.favoriteenemy common_scripts\utility::waittill_any_timeout( 5.0, "death", "disconnect" );
    self.favoriteenemy = undefined;
    self.forceattack = 0;
}

ondamage( var_0, var_1, var_2, var_3, var_4, var_5, var_6, var_7, var_8, var_9 )
{
    self.timeoflastdamage = gettime();

    if ( isdefined( self.owner ) )
        self.damagedownertome = vectornormalize( self.origin - self.owner.origin );

    if ( shouldplayhitreaction( var_2, var_5, var_4 ) )
    {
        switch ( self.aistate )
        {
            case "idle":
                thread maps\mp\mp_dome_ns_alien_idle::ondamage( var_0, var_1, var_2, var_3, var_4, var_5, var_6, var_7, var_8, var_9 );
                break;
            case "move":
                thread maps\mp\mp_dome_ns_alien_move::ondamage( var_0, var_1, var_2, var_3, var_4, var_5, var_6, var_7, var_8, var_9 );
                break;
        }
    }
}

shouldplayhitreaction( var_0, var_1, var_2 )
{
    if ( isdefined( var_1 ) && weaponclass( var_1 ) == "sniper" )
        return 1;

    if ( isdefined( var_2 ) && isexplosivedamagemod( var_2 ) && var_0 >= 10 )
        return 1;

    if ( isdefined( var_2 ) && var_2 == "MOD_MELEE" )
        return 1;

    if ( isdefined( var_1 ) && var_1 == "concussion_grenade_mp" )
        return 1;

    return 0;
}

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

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

        if ( isdefined( var_3 ) && var_3 == self.owner )
            continue;

        switch ( self.aistate )
        {
            case "idle":
                maps\mp\mp_dome_ns_alien_idle::onflashbanged();
                break;
            case "move":
                maps\mp\mp_dome_ns_alien_move::onflashbanged();
                break;
        }
    }
}

get_closest( var_0, var_1, var_2 )
{
    var_3 = var_1[0];
    var_4 = distance( var_0, var_3.origin );

    for ( var_5 = 0; var_5 < var_1.size; var_5++ )
    {
        var_6 = distance( var_0, var_1[var_5].origin );

        if ( var_6 >= var_4 )
            continue;

        var_4 = var_6;
        var_3 = var_1[var_5];
    }

    if ( !isdefined( var_2 ) || var_4 <= var_2 )
        return var_3;

    return undefined;
}
