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

init()
{
    level.killstreakfuncs["odin_support"] = ::tryuseodin;
    level.killstreakfuncs["odin_assault"] = ::tryuseodin;
    level._effect["odin_clouds"] = loadfx( "vfx/gameplay/mp/killstreaks/odin/odin_parallax_clouds" );
    level._effect["odin_fisheye"] = loadfx( "vfx/gameplay/screen_effects/vfx_scrnfx_odin_fisheye" );
    level._effect["odin_targeting"] = loadfx( "vfx/gameplay/mp/killstreaks/odin/vfx_marker_odin_cyan" );
    level.odinsettings = [];
    level.odinsettings["odin_support"] = spawnstruct();
    level.odinsettings["odin_support"].timeout = 60.0;
    level.odinsettings["odin_support"].streakname = "odin_support";
    level.odinsettings["odin_support"].vehicleinfo = "odin_mp";
    level.odinsettings["odin_support"].modelbase = "vehicle_odin_mp";
    level.odinsettings["odin_support"].teamsplash = "used_odin_support";
    level.odinsettings["odin_support"].votimedout = "odin_gone";
    level.odinsettings["odin_support"].vokillsingle = "odin_target_killed";
    level.odinsettings["odin_support"].vokillmulti = "odin_targets_killed";
    level.odinsettings["odin_support"].ui_num = 1;
    level.odinsettings["odin_support"].unavailable_string = &"KILLSTREAKS_ODIN_UNAVAILABLE";
    level.odinsettings["odin_support"].weapon["airdrop"] = spawnstruct();
    level.odinsettings["odin_support"].weapon["airdrop"].projectile = "odin_projectile_airdrop_mp";
    level.odinsettings["odin_support"].weapon["airdrop"].rumble = "smg_fire";
    level.odinsettings["odin_support"].weapon["airdrop"].ammoomnvar = "ui_odin_airdrop_ammo";
    level.odinsettings["odin_support"].weapon["airdrop"].airdroptype = "airdrop_support";
    level.odinsettings["odin_support"].weapon["airdrop"].reloadtimer = 20;
    level.odinsettings["odin_support"].weapon["airdrop"].ui_num_fired = -1;
    level.odinsettings["odin_support"].weapon["airdrop"].voairdrop = "odin_carepackage";
    level.odinsettings["odin_support"].weapon["airdrop"].plr_ready_sound = "odin_carepack_ready";
    level.odinsettings["odin_support"].weapon["airdrop"].plr_fire_sound = "odin_carepack_launch";
    level.odinsettings["odin_support"].weapon["marking"] = spawnstruct();
    level.odinsettings["odin_support"].weapon["marking"].projectile = "odin_projectile_marking_mp";
    level.odinsettings["odin_support"].weapon["marking"].rumble = "heavygun_fire";
    level.odinsettings["odin_support"].weapon["marking"].ammoomnvar = "ui_odin_marking_ammo";
    level.odinsettings["odin_support"].weapon["marking"].reloadtimer = 4;
    level.odinsettings["odin_support"].weapon["marking"].ui_num_fired = -1;
    level.odinsettings["odin_support"].weapon["marking"].vomarking = "odin_marking";
    level.odinsettings["odin_support"].weapon["marking"].vomarkedsingle = "odin_marked";
    level.odinsettings["odin_support"].weapon["marking"].vomarkedmulti = "odin_m_marked";
    level.odinsettings["odin_support"].weapon["marking"].plr_ready_sound = "odin_flash_ready";
    level.odinsettings["odin_support"].weapon["marking"].plr_fire_sound = "odin_flash_launch";
    level.odinsettings["odin_support"].weapon["smoke"] = spawnstruct();
    level.odinsettings["odin_support"].weapon["smoke"].projectile = "odin_projectile_smoke_mp";
    level.odinsettings["odin_support"].weapon["smoke"].rumble = "smg_fire";
    level.odinsettings["odin_support"].weapon["smoke"].ammoomnvar = "ui_odin_smoke_ammo";
    level.odinsettings["odin_support"].weapon["smoke"].reloadtimer = 7;
    level.odinsettings["odin_support"].weapon["smoke"].ui_num_fired = -1;
    level.odinsettings["odin_support"].weapon["smoke"].vosmoke = "odin_smoke";
    level.odinsettings["odin_support"].weapon["smoke"].plr_ready_sound = "odin_smoke_ready";
    level.odinsettings["odin_support"].weapon["smoke"].plr_fire_sound = "odin_smoke_launch";
    level.odinsettings["odin_support"].weapon["juggernaut"] = spawnstruct();
    level.odinsettings["odin_support"].weapon["juggernaut"].projectile = "odin_projectile_smoke_mp";
    level.odinsettings["odin_support"].weapon["juggernaut"].rumble = "heavygun_fire";
    level.odinsettings["odin_support"].weapon["juggernaut"].ammoomnvar = "ui_odin_juggernaut_ammo";
    level.odinsettings["odin_support"].weapon["juggernaut"].juggtype = "juggernaut_recon";
    level.odinsettings["odin_support"].weapon["juggernaut"].reloadtimer = level.odinsettings["odin_support"].timeout;
    level.odinsettings["odin_support"].weapon["juggernaut"].ui_num_fired = -1;
    level.odinsettings["odin_support"].weapon["juggernaut"].ui_num_move = -2;
    level.odinsettings["odin_support"].weapon["juggernaut"].ui_num_dead = -3;
    level.odinsettings["odin_support"].weapon["juggernaut"].vojugg = "odin_moving";
    level.odinsettings["odin_support"].weapon["juggernaut"].plr_ready_sound = "null";
    level.odinsettings["odin_support"].weapon["juggernaut"].plr_fire_sound = "odin_jugg_launch";
    level.odinsettings["odin_assault"] = spawnstruct();
    level.odinsettings["odin_assault"].timeout = 60.0;
    level.odinsettings["odin_assault"].streakname = "odin_assault";
    level.odinsettings["odin_assault"].vehicleinfo = "odin_mp";
    level.odinsettings["odin_assault"].modelbase = "vehicle_odin_mp";
    level.odinsettings["odin_assault"].teamsplash = "used_odin_assault";
    level.odinsettings["odin_assault"].votimedout = "loki_gone";
    level.odinsettings["odin_assault"].vokillsingle = "odin_target_killed";
    level.odinsettings["odin_assault"].vokillmulti = "odin_targets_killed";
    level.odinsettings["odin_assault"].ui_num = 2;
    level.odinsettings["odin_assault"].unavailable_string = &"KILLSTREAKS_LOKI_UNAVAILABLE";
    level.odinsettings["odin_assault"].weapon["airdrop"] = spawnstruct();
    level.odinsettings["odin_assault"].weapon["airdrop"].projectile = "odin_projectile_airdrop_mp";
    level.odinsettings["odin_assault"].weapon["airdrop"].rumble = "smg_fire";
    level.odinsettings["odin_assault"].weapon["airdrop"].ammoomnvar = "ui_odin_airdrop_ammo";
    level.odinsettings["odin_assault"].weapon["airdrop"].airdroptype = "airdrop_assault";
    level.odinsettings["odin_assault"].weapon["airdrop"].reloadtimer = 20;
    level.odinsettings["odin_assault"].weapon["airdrop"].ui_num_fired = -1;
    level.odinsettings["odin_assault"].weapon["airdrop"].voairdrop = "odin_carepackage";
    level.odinsettings["odin_assault"].weapon["airdrop"].plr_ready_sound = "odin_carepack_ready";
    level.odinsettings["odin_assault"].weapon["airdrop"].plr_fire_sound = "odin_carepack_launch";
    level.odinsettings["odin_assault"].weapon["large_rod"] = spawnstruct();
    level.odinsettings["odin_assault"].weapon["large_rod"].projectile = "odin_projectile_large_rod_mp";
    level.odinsettings["odin_assault"].weapon["large_rod"].rumble = "heavygun_fire";
    level.odinsettings["odin_assault"].weapon["large_rod"].ammoomnvar = "ui_odin_marking_ammo";
    level.odinsettings["odin_assault"].weapon["large_rod"].reloadtimer = 4;
    level.odinsettings["odin_assault"].weapon["large_rod"].ui_num_fired = -2;
    level.odinsettings["odin_assault"].weapon["large_rod"].plr_ready_sound = "null";
    level.odinsettings["odin_assault"].weapon["large_rod"].plr_fire_sound = "ac130_105mm_fire";
    level.odinsettings["odin_assault"].weapon["large_rod"].npc_fire_sound = "ac130_105mm_fire_npc";
    level.odinsettings["odin_assault"].weapon["small_rod"] = spawnstruct();
    level.odinsettings["odin_assault"].weapon["small_rod"].projectile = "odin_projectile_small_rod_mp";
    level.odinsettings["odin_assault"].weapon["small_rod"].rumble = "smg_fire";
    level.odinsettings["odin_assault"].weapon["small_rod"].ammoomnvar = "ui_odin_smoke_ammo";
    level.odinsettings["odin_assault"].weapon["small_rod"].reloadtimer = 2;
    level.odinsettings["odin_assault"].weapon["small_rod"].ui_num_fired = -2;
    level.odinsettings["odin_assault"].weapon["small_rod"].plr_ready_sound = "null";
    level.odinsettings["odin_assault"].weapon["small_rod"].plr_fire_sound = "ac130_40mm_fire";
    level.odinsettings["odin_assault"].weapon["small_rod"].npc_fire_sound = "ac130_40mm_fire_npc";
    level.odinsettings["odin_assault"].weapon["juggernaut"] = spawnstruct();
    level.odinsettings["odin_assault"].weapon["juggernaut"].projectile = "odin_projectile_smoke_mp";
    level.odinsettings["odin_assault"].weapon["juggernaut"].rumble = "heavygun_fire";
    level.odinsettings["odin_assault"].weapon["juggernaut"].ammoomnvar = "ui_odin_juggernaut_ammo";
    level.odinsettings["odin_assault"].weapon["juggernaut"].juggtype = "juggernaut";
    level.odinsettings["odin_assault"].weapon["juggernaut"].reloadtimer = level.odinsettings["odin_assault"].timeout;
    level.odinsettings["odin_assault"].weapon["juggernaut"].ui_num_fired = -1;
    level.odinsettings["odin_assault"].weapon["juggernaut"].ui_num_move = -2;
    level.odinsettings["odin_assault"].weapon["juggernaut"].ui_num_dead = -3;
    level.odinsettings["odin_assault"].weapon["juggernaut"].vojugg = "odin_moving";
    level.odinsettings["odin_assault"].weapon["juggernaut"].plr_ready_sound = "null";
    level.odinsettings["odin_assault"].weapon["juggernaut"].plr_fire_sound = "odin_jugg_launch";

    if ( !isdefined( level.heli_pilot_mesh ) )
    {
        level.heli_pilot_mesh = getent( "heli_pilot_mesh", "targetname" );

        if ( !isdefined( level.heli_pilot_mesh ) )
        {

        }
        else
            level.heli_pilot_mesh.origin = level.heli_pilot_mesh.origin + maps\mp\_utility::gethelipilotmeshoffset();
    }

    maps\mp\agents\_agents::wait_till_agent_funcs_defined();
    level.agent_funcs["odin_juggernaut"] = level.agent_funcs["player"];
    level.agent_funcs["odin_juggernaut"]["think"] = common_scripts\utility::empty_init_func;
    level.odin_marking_flash_radius_max = 800;
    level.odin_marking_flash_radius_min = 200;
    level.active_odin = [];
}

tryuseodin( var_0, var_1 )
{
    if ( isdefined( self.underwater ) && self.underwater )
        return 0;

    var_2 = var_1;
    var_3 = 1;

    if ( maps\mp\_utility::currentactivevehiclecount() >= maps\mp\_utility::maxvehiclesallowed() || level.fauxvehiclecount + var_3 >= maps\mp\_utility::maxvehiclesallowed() )
    {
        self iprintlnbold( &"KILLSTREAKS_TOO_MANY_VEHICLES" );
        return 0;
    }

    if ( isdefined( level.active_odin[var_2] ) )
    {
        self iprintlnbold( level.odinsettings[var_2].unavailable_string );
        return 0;
    }

    maps\mp\_utility::incrementfauxvehiclecount();
    var_4 = createodin( var_2 );

    if ( !isdefined( var_4 ) )
    {
        maps\mp\_utility::decrementfauxvehiclecount();
        return 0;
    }

    var_5 = startodin( var_4 );

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

    return var_5;
}

watchhostmigrationfinishedinit( var_0 )
{
    var_0 endon( "disconnect" );
    var_0 endon( "joined_team" );
    var_0 endon( "joined_spectators" );
    var_0 endon( "killstreak_disowned" );
    level endon( "game_ended" );
    self endon( "death" );

    for (;;)
    {
        level waittill( "host_migration_end" );
        var_0 setclientomnvar( "ui_odin", level.odinsettings[self.odintype].ui_num );
        var_0 thermalvisionfofoverlayon();
        playfxontag( level._effect["odin_targeting"], self.targeting_marker, "tag_origin" );
        self.targeting_marker showtoplayer( var_0 );
    }
}

createodin( var_0 )
{
    var_1 = self.origin * ( 1, 1, 0 ) + ( level.heli_pilot_mesh.origin - maps\mp\_utility::gethelipilotmeshoffset() ) * ( 0, 0, 1 );
    var_2 = ( 0, 0, 0 );
    var_3 = spawnhelicopter( self, var_1, var_2, level.odinsettings[var_0].vehicleinfo, level.odinsettings[var_0].modelbase );

    if ( !isdefined( var_3 ) )
        return;

    var_3.speed = 40;
    var_3.owner = self;
    var_3.team = self.team;
    var_3.odintype = var_0;
    level.active_odin[var_0] = 1;
    self.odin = var_3;
    var_3 thread odin_watchdeath();
    var_3 thread odin_watchtimeout();
    var_3 thread odin_watchownerloss();
    var_3 thread odin_watchroundend();
    var_3 thread odin_watchtargeting();
    var_3 thread odin_watchobjectivecamera();
    var_3 thread odin_watchoutlines();
    var_3 thread odin_watchplayerkilled();
    var_3 thread odin_dialog_killed_player();
    var_3 thread odin_onplayerconnect();
    var_3.owner maps\mp\_matchdata::logkillstreakevent( level.odinsettings[var_0].streakname, var_1 );
    return var_3;
}

startodin( var_0 )
{
    level endon( "game_ended" );
    var_0 endon( "death" );
    self.restoreangles = vectortoangles( anglestoforward( self.angles ) );
    odin_set_using( var_0 );

    if ( getdvarint( "camera_thirdPerson" ) )
        maps\mp\_utility::setthirdpersondof( 0 );

    thread watchintrocleared( var_0 );
    maps\mp\_utility::freezecontrolswrapper( 1 );
    odin_zoom_up( var_0 );
    thread maps\mp\killstreaks\_juggernaut::disablejuggernaut();
    var_1 = maps\mp\killstreaks\_killstreaks::initridekillstreak( var_0.odintype );

    if ( var_1 != "success" )
    {
        if ( isdefined( self.disabledweapon ) && self.disabledweapon )
            common_scripts\utility::_enableweapon();

        var_0 notify( "death" );
        return 0;
    }

    maps\mp\_utility::freezecontrolswrapper( 0 );
    self remotecontrolvehicle( var_0 );
    var_0 thread watchhostmigrationfinishedinit( self );
    var_0.odin_overlay_ent = spawnfxforclient( level._effect["odin_fisheye"], self geteye(), self );
    triggerfx( var_0.odin_overlay_ent );
    var_0.odin_overlay_ent setfxkilldefondelete();
    level thread maps\mp\_utility::teamplayercardsplash( level.odinsettings[var_0.odintype].teamsplash, self );
    self thermalvisionfofoverlayon();
    thread waitandoutlineowner( var_0 );
    return 1;
}

waitandoutlineowner( var_0 )
{
    self endon( "disconnect" );
    var_0 endon( "death" );
    wait 1.0;
    var_1 = maps\mp\_utility::outlineenableforplayer( self, "cyan", self, 0, "killstreak" );
    var_0 thread removeoutline( var_1, self );
}

odin_zoom_up( var_0 )
{
    var_1 = spawn( "script_model", var_0.origin + ( 0, 0, 3000 ) );
    var_1.angles = vectortoangles( ( 0, 0, 1 ) );
    var_1 setmodel( "tag_origin" );
    var_1 thread waitanddelete( 5 );
    var_2 = "odin_zoom_up";
    var_3 = var_1 getentitynumber();
    var_4 = self getentitynumber();
    var_5 = bullettrace( self.origin, var_0.origin, 0, self );

    if ( var_5["surfacetype"] != "none" )
    {
        var_2 = "odin_zoom_down";
        var_3 = var_0 getentitynumber();
        var_4 = var_1 getentitynumber();
    }

    var_6 = common_scripts\utility::array_add( maps\mp\_utility::get_players_watching(), self );

    foreach ( var_8 in var_6 )
    {
        var_8 setclientomnvar( "cam_scene_name", var_2 );
        var_8 setclientomnvar( "cam_scene_lead", var_3 );
        var_8 setclientomnvar( "cam_scene_support", var_4 );
        var_8 thread clouds();
    }
}

waitanddelete( var_0 )
{
    self endon( "death" );
    level endon( "game_ended" );
    wait( var_0 );
    self delete();
}

clouds()
{
    level endon( "game_ended" );
    var_0 = spawn( "script_model", self.origin + ( 0, 0, 250 ) );
    var_0.angles = vectortoangles( ( 0, 0, 1 ) );
    var_0 setmodel( "tag_origin" );
    var_0 thread waitanddelete( 2 );
    wait 0.1;
    playfxontagforclients( level._effect["odin_clouds"], var_0, "tag_origin", self );
}

odin_set_using( var_0 )
{
    maps\mp\_utility::setusingremote( var_0.odintype );
    self.odin = var_0;
}

odin_clear_using( var_0 )
{
    var_0.odin_juggernautusetime = undefined;
    var_0.odin_markingusetime = undefined;
    var_0.odin_smokeusetime = undefined;
    var_0.odin_airdropusetime = undefined;
    var_0.odin_largerodusetime = undefined;
    var_0.odin_smallrodusetime = undefined;

    if ( isdefined( self ) )
    {
        maps\mp\_utility::clearusingremote();
        self.odin = undefined;
    }
}

watchintrocleared( var_0 )
{
    self endon( "disconnect" );
    self endon( "joined_team" );
    self endon( "joined_spectators" );
    level endon( "game_ended" );
    var_0 endon( "death" );
    self waittill( "intro_cleared" );
    self setclientomnvar( "ui_odin", level.odinsettings[var_0.odintype].ui_num );
    watchearlyexit( var_0 );
}

odin_waitfordonefiring( var_0 )
{
    while ( isdefined( self.is_firing ) && var_0 > 0 )
    {
        wait 0.05;
        var_0 = var_0 - 0.05;
    }
}

odin_watchdeath()
{
    level endon( "game_ended" );
    self endon( "gone" );
    self waittill( "death" );

    if ( isdefined( self.owner ) )
        self.owner odin_endride( self );

    cleanup_ents();
    odin_waitfordonefiring( 3.0 );
    maps\mp\_utility::decrementfauxvehiclecount();
    level.active_odin[self.odintype] = undefined;
    self delete();
}

odin_watchtimeout()
{
    level endon( "game_ended" );
    self endon( "death" );
    self.owner endon( "disconnect" );
    self.owner endon( "joined_team" );
    self.owner endon( "joined_spectators" );
    var_0 = level.odinsettings[self.odintype];
    var_1 = var_0.timeout;
    maps\mp\gametypes\_hostmigration::waitlongdurationwithhostmigrationpause( var_1 );
    thread odin_leave();
}

odin_watchownerloss()
{
    level endon( "game_ended" );
    self endon( "death" );
    self endon( "leaving" );
    self.owner common_scripts\utility::waittill_any( "disconnect", "joined_team", "joined_spectators" );
    thread odin_leave();
}

odin_watchobjectivecamera()
{
    level endon( "game_ended" );
    self endon( "death" );
    self endon( "leaving" );
    self.owner endon( "disconnect" );
    self.owner endon( "joined_team" );
    self.owner endon( "joined_spectators" );
    level waittill( "objective_cam" );
    thread odin_leave();
}

odin_watchroundend()
{
    self endon( "death" );
    self endon( "leaving" );
    self.owner endon( "disconnect" );
    self.owner endon( "joined_team" );
    self.owner endon( "joined_spectators" );
    level common_scripts\utility::waittill_any( "round_end_finished", "game_ended" );
    thread odin_leave();
}

odin_leave()
{
    self endon( "death" );
    self notify( "leaving" );
    var_0 = level.odinsettings[self.odintype];
    maps\mp\_utility::leaderdialog( var_0.votimedout );

    if ( isdefined( self.owner ) )
        self.owner odin_endride( self );

    self notify( "gone" );
    cleanup_ents();
    odin_waitfordonefiring( 3.0 );
    maps\mp\_utility::decrementfauxvehiclecount();
    level.active_odin[self.odintype] = undefined;
    self delete();
}

odin_endride( var_0 )
{
    if ( isdefined( var_0 ) )
    {
        self setclientomnvar( "ui_odin", -1 );
        var_0 notify( "end_remote" );
        self notify( "odin_ride_ended" );
        odin_clear_using( var_0 );

        if ( getdvarint( "camera_thirdPerson" ) )
            maps\mp\_utility::setthirdpersondof( 1 );

        self thermalvisionfofoverlayoff();
        self remotecontrolvehicleoff( var_0 );
        self setplayerangles( self.restoreangles );
        thread odin_freezebuffer();
        self stoplocalsound( "odin_negative_action" );
        self stoplocalsound( "odin_positive_action" );

        foreach ( var_2 in level.odinsettings[var_0.odintype].weapon )
        {
            if ( isdefined( var_2.plr_ready_sound ) )
                self stoplocalsound( var_2.plr_ready_sound );

            if ( isdefined( var_2.plr_fire_sound ) )
                self stoplocalsound( var_2.plr_fire_sound );
        }

        if ( isdefined( var_0.juggernaut ) )
            var_0.juggernaut maps\mp\bots\_bots_strategy::bot_guard_player( self, 350 );
    }
}

odin_freezebuffer()
{
    self endon( "disconnect" );
    self endon( "death" );
    level endon( "game_ended" );
    maps\mp\_utility::freezecontrolswrapper( 1 );
    wait 0.5;
    maps\mp\_utility::freezecontrolswrapper( 0 );
}

odin_watchtargeting()
{
    self endon( "death" );
    level endon( "game_ended" );
    var_0 = self.owner;
    var_0 endon( "disconnect" );
    var_1 = var_0 getvieworigin();
    var_2 = var_1 + anglestoforward( self gettagangles( "tag_player" ) ) * 10000;
    var_3 = bullettrace( var_1, var_2, 0, self );
    var_4 = spawn( "script_model", var_3["position"] );
    var_4.angles = vectortoangles( ( 0, 0, 1 ) );
    var_4 setmodel( "tag_origin" );
    self.targeting_marker = var_4;
    var_4 endon( "death" );
    var_5 = bullettrace( var_4.origin + ( 0, 0, 50 ), var_4.origin + ( 0, 0, -100 ), 0, var_4 );
    var_4.origin = var_5["position"] + ( 0, 0, 50 );
    var_4 hide();
    var_4 showtoplayer( var_0 );
    var_4 childthread monitormarkervisibility( var_0 );
    thread showfx();
    thread watchairdropuse();
    thread watchjuggernautuse();

    switch ( self.odintype )
    {
        case "odin_support":
            thread watchsmokeuse();
            thread watchmarkinguse();
            break;
        case "odin_assault":
            thread watchlargeroduse();
            thread watchsmallroduse();
            break;
    }

    self setotherent( var_4 );
}

monitormarkervisibility( var_0 )
{
    wait 1.5;
    var_1 = [];

    for (;;)
    {
        var_2 = var_0 maps\mp\_utility::get_players_watching();

        foreach ( var_4 in var_1 )
        {
            if ( !common_scripts\utility::array_contains( var_2, var_4 ) )
            {
                var_1 = common_scripts\utility::array_remove( var_1, var_4 );
                self hide();
                self showtoplayer( var_0 );
            }
        }

        foreach ( var_4 in var_2 )
        {
            self showtoplayer( var_4 );

            if ( !common_scripts\utility::array_contains( var_1, var_4 ) )
            {
                var_1 = common_scripts\utility::array_add( var_1, var_4 );
                stopfxontag( level._effect["odin_targeting"], self, "tag_origin" );
                wait 0.05;
                playfxontag( level._effect["odin_targeting"], self, "tag_origin" );
            }
        }

        wait 0.25;
    }
}

watchairdropuse()
{
    self endon( "death" );
    level endon( "game_ended" );
    var_0 = self.owner;
    var_0 endon( "disconnect" );
    var_1 = level.odinsettings[self.odintype].weapon["airdrop"];
    self.odin_airdropusetime = 0;
    var_0 setclientomnvar( var_1.ammoomnvar, level.odinsettings[self.odintype].ui_num );

    if ( !isai( var_0 ) )
        var_0 notifyonplayercommand( "airdrop_action", "+smoke" );

    for (;;)
    {
        var_0 waittill( "airdrop_action" );

        if ( isdefined( level.hostmigrationtimer ) )
            continue;

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

        if ( gettime() >= self.odin_airdropusetime )
        {
            if ( level.teambased )
                maps\mp\_utility::leaderdialog( var_1.voairdrop, self.team );
            else
                var_0 maps\mp\_utility::leaderdialogonplayer( var_1.voairdrop );

            self.odin_airdropusetime = odin_fireweapon( "airdrop" );
            var_1 = level.odinsettings[self.odintype].weapon["airdrop"];
            level thread maps\mp\killstreaks\_airdrop::doflyby( var_0, self.targeting_marker.origin, randomfloat( 360 ), var_1.airdroptype );
        }
        else
            var_0 maps\mp\_utility::_playlocalsound( "odin_negative_action" );

        wait 1.0;
    }
}

watchsmokeuse()
{
    self endon( "death" );
    level endon( "game_ended" );
    var_0 = self.owner;
    var_0 endon( "disconnect" );
    var_1 = level.odinsettings[self.odintype].weapon["smoke"];
    self.odin_smokeusetime = 0;
    var_0 setclientomnvar( var_1.ammoomnvar, level.odinsettings[self.odintype].ui_num );

    if ( !isai( var_0 ) )
    {
        var_0 notifyonplayercommand( "smoke_action", "+speed_throw" );
        var_0 notifyonplayercommand( "smoke_action", "+ads_akimbo_accessible" );

        if ( !level.console )
            var_0 notifyonplayercommand( "smoke_action", "+toggleads_throw" );
    }

    for (;;)
    {
        var_0 waittill( "smoke_action" );

        if ( isdefined( level.hostmigrationtimer ) )
            continue;

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

        if ( gettime() >= self.odin_smokeusetime )
        {
            if ( level.teambased )
                maps\mp\_utility::leaderdialog( var_1.vosmoke, self.team );
            else
                var_0 maps\mp\_utility::leaderdialogonplayer( var_1.vosmoke );

            self.odin_smokeusetime = odin_fireweapon( "smoke" );
        }
        else
            var_0 maps\mp\_utility::_playlocalsound( "odin_negative_action" );

        wait 1.0;
    }
}

watchmarkinguse()
{
    self endon( "death" );
    level endon( "game_ended" );
    var_0 = self.owner;
    var_0 endon( "disconnect" );
    var_1 = level.odinsettings[self.odintype].weapon["marking"];
    self.odin_markingusetime = 0;
    var_0 setclientomnvar( var_1.ammoomnvar, level.odinsettings[self.odintype].ui_num );

    if ( !isai( var_0 ) )
    {
        var_0 notifyonplayercommand( "marking_action", "+attack" );
        var_0 notifyonplayercommand( "marking_action", "+attack_akimbo_accessible" );
    }

    for (;;)
    {
        var_0 waittill( "marking_action" );

        if ( isdefined( level.hostmigrationtimer ) )
            continue;

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

        if ( gettime() >= self.odin_markingusetime )
        {
            self.odin_markingusetime = odin_fireweapon( "marking" );
            thread domarkingflash( self.targeting_marker.origin + ( 0, 0, 10 ) );
        }
        else
            var_0 maps\mp\_utility::_playlocalsound( "odin_negative_action" );

        wait 1.0;
    }
}

watchjuggernautuse()
{
    self endon( "death" );
    level endon( "game_ended" );
    var_0 = self.owner;
    var_0 endon( "disconnect" );
    var_0 endon( "juggernaut_dead" );
    var_1 = level.odinsettings[self.odintype].weapon["juggernaut"];
    self.odin_juggernautusetime = 0;
    var_0 setclientomnvar( var_1.ammoomnvar, level.odinsettings[self.odintype].ui_num );

    if ( !isai( var_0 ) )
        var_0 notifyonplayercommand( "juggernaut_action", "+frag" );

    for (;;)
    {
        var_0 waittill( "juggernaut_action" );

        if ( isdefined( level.hostmigrationtimer ) )
            continue;

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

        if ( gettime() >= self.odin_juggernautusetime )
        {
            var_2 = getjuggstartingpathnode( self.targeting_marker.origin );

            if ( isdefined( var_2 ) )
            {
                self.odin_juggernautusetime = odin_fireweapon( "juggernaut" );
                thread waitandspawnjugg( var_2 );
            }
            else
                var_0 maps\mp\_utility::_playlocalsound( "odin_negative_action" );
        }
        else if ( isdefined( self.juggernaut ) )
        {
            var_2 = getjuggmovingpathnode( self.targeting_marker.origin );

            if ( isdefined( var_2 ) )
            {
                var_0 maps\mp\_utility::leaderdialogonplayer( var_1.vojugg );
                var_0 maps\mp\_utility::_playlocalsound( "odin_positive_action" );
                var_0 playrumbleonentity( "pistol_fire" );
                self.juggernaut maps\mp\bots\_bots_strategy::bot_protect_point( var_2.origin, 128 );
                var_0 setclientomnvar( var_1.ammoomnvar, level.odinsettings[self.odintype].ui_num );
            }
            else
                var_0 maps\mp\_utility::_playlocalsound( "odin_negative_action" );
        }

        wait 1.1;

        if ( isdefined( self.juggernaut ) )
            var_0 setclientomnvar( var_1.ammoomnvar, var_1.ui_num_move );
    }
}

watchlargeroduse()
{
    self endon( "death" );
    level endon( "game_ended" );
    var_0 = self.owner;
    var_0 endon( "disconnect" );
    var_1 = level.odinsettings[self.odintype].weapon["large_rod"];
    self.odin_largerodusetime = 0;
    var_0 setclientomnvar( var_1.ammoomnvar, level.odinsettings[self.odintype].ui_num );

    if ( !isai( var_0 ) )
    {
        var_0 notifyonplayercommand( "large_rod_action", "+attack" );
        var_0 notifyonplayercommand( "large_rod_action", "+attack_akimbo_accessible" );
    }

    for (;;)
    {
        var_0 waittill( "large_rod_action" );

        if ( isdefined( level.hostmigrationtimer ) )
            continue;

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

        if ( gettime() >= self.odin_largerodusetime )
            self.odin_largerodusetime = odin_fireweapon( "large_rod" );
        else
            var_0 maps\mp\_utility::_playlocalsound( "odin_negative_action" );

        wait 1.0;
    }
}

watchsmallroduse()
{
    self endon( "death" );
    level endon( "game_ended" );
    var_0 = self.owner;
    var_0 endon( "disconnect" );
    var_1 = level.odinsettings[self.odintype].weapon["small_rod"];
    self.odin_smallrodusetime = 0;
    var_0 setclientomnvar( var_1.ammoomnvar, level.odinsettings[self.odintype].ui_num );

    if ( !isai( var_0 ) )
    {
        var_0 notifyonplayercommand( "small_rod_action", "+speed_throw" );
        var_0 notifyonplayercommand( "small_rod_action", "+ads_akimbo_accessible" );

        if ( !level.console )
            var_0 notifyonplayercommand( "small_rod_action", "+toggleads_throw" );
    }

    for (;;)
    {
        var_0 waittill( "small_rod_action" );

        if ( isdefined( level.hostmigrationtimer ) )
            continue;

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

        if ( gettime() >= self.odin_smallrodusetime )
            self.odin_smallrodusetime = odin_fireweapon( "small_rod" );
        else
            var_0 maps\mp\_utility::_playlocalsound( "odin_negative_action" );

        wait 1.0;
    }
}

odin_fireweapon( var_0 )
{
    self.is_firing = 1;
    var_1 = self.owner;
    var_2 = level.odinsettings[self.odintype].weapon[var_0];
    var_3 = anglestoforward( var_1 getplayerangles() );
    var_4 = self.origin + var_3 * 100;
    var_1 setclientomnvar( var_2.ammoomnvar, var_2.ui_num_fired );
    thread watchreload( var_2 );
    var_5 = self.targeting_marker.origin;
    var_6 = gettime() + var_2.reloadtimer * 1000;

    if ( var_0 == "large_rod" )
    {
        wait 0.5;
        var_1 playrumbleonentity( var_2.rumble );
        earthquake( 0.3, 1.5, self.origin, 1000 );
        var_1 playsoundtoplayer( var_2.plr_fire_sound, var_1 );
        playsoundatpos( self.origin, var_2.npc_fire_sound );
        wait 1.5;
    }
    else if ( var_0 == "small_rod" )
    {
        wait 0.5;
        var_1 playrumbleonentity( var_2.rumble );
        earthquake( 0.2, 1, self.origin, 1000 );
        var_1 playsoundtoplayer( var_2.plr_fire_sound, var_1 );
        playsoundatpos( self.origin, var_2.npc_fire_sound );
        wait 0.3;
    }
    else
    {
        if ( isdefined( var_2.plr_fire_sound ) )
            var_1 playsoundtoplayer( var_2.plr_fire_sound, var_1 );

        if ( isdefined( var_2.npc_fire_sound ) )
            playsoundatpos( self.origin, var_2.npc_fire_sound );

        var_1 playrumbleonentity( var_2.rumble );
    }

    var_7 = magicbullet( var_2.projectile, var_4, var_5, var_1 );
    var_7.type = "odin";
    var_7 thread watchexplosion( var_0 );

    if ( var_0 == "smoke" || var_0 == "juggernaut" || var_0 == "large_rod" )
        level notify( "smoke", var_7, var_2.projectile );

    self.is_firing = undefined;
    return var_6;
}

watchexplosion( var_0 )
{
    self waittill( "explode", var_1 );

    if ( var_0 == "small_rod" )
    {
        playrumbleonposition( "grenade_rumble", var_1 );
        earthquake( 0.7, 1.0, var_1, 1000 );
    }
    else if ( var_0 == "large_rod" )
    {
        playrumbleonposition( "artillery_rumble", var_1 );
        earthquake( 1.0, 1.0, var_1, 2000 );
    }
}

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

    var_1 = getnodesinradiussorted( var_0, 256, 0, 128, "Path" );

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

    return var_1[0];
}

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

    var_1 = getnodesinradiussorted( var_0, 128, 0, 64, "Path" );

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

    return var_1[0];
}

waitandspawnjugg( var_0 )
{
    self endon( "death" );
    level endon( "game_ended" );
    var_1 = self.owner;
    var_1 endon( "disconnect" );
    var_2 = self.targeting_marker.origin;
    wait 3.0;
    var_3 = maps\mp\agents\_agents::add_humanoid_agent( "odin_juggernaut", var_1.team, "class1", var_0.origin, vectortoangles( var_2 - var_0.origin ), var_1, 0, 0, "veteran" );

    if ( isdefined( var_3 ) )
    {
        var_4 = level.odinsettings[self.odintype].weapon["juggernaut"];
        var_3 thread maps\mp\killstreaks\_juggernaut::givejuggernaut( var_4.juggtype );
        var_3 thread maps\mp\killstreaks\_agent_killstreak::sendagentweaponnotify();
        var_3 maps\mp\bots\_bots_strategy::bot_protect_point( var_0.origin, 128 );
        self.juggernaut = var_3;
        thread watchjuggernautdeath();
        var_1 setclientomnvar( var_4.ammoomnvar, var_4.ui_num_move );
        var_5 = maps\mp\_utility::outlineenableforplayer( var_3, "cyan", self.owner, 0, "killstreak" );
        thread removeoutline( var_5, var_3 );
        var_3 maps\mp\_utility::_setnameplatematerial( "player_name_bg_green_agent", "player_name_bg_red_agent" );
    }
    else
        var_1 iprintlnbold( &"KILLSTREAKS_AGENT_MAX" );
}

watchjuggernautdeath()
{
    self endon( "death" );
    level endon( "game_ended" );
    self.juggernaut waittill( "death" );
    self.owner notify( "juggernaut_dead" );
    var_0 = level.odinsettings[self.odintype].weapon["juggernaut"];
    self.owner setclientomnvar( var_0.ammoomnvar, var_0.ui_num_dead );
    self.juggernaut = undefined;
}

showfx()
{
    self endon( "death" );
    wait 1.0;
    playfxontag( level._effect["odin_targeting"], self.targeting_marker, "tag_origin" );
}

watchreload( var_0 )
{
    self endon( "death" );
    level endon( "game_ended" );
    var_1 = self.owner;
    var_1 endon( "disconnect" );
    var_1 endon( "odin_ride_ended" );
    var_2 = var_0.ammoomnvar;
    var_3 = var_0.reloadtimer;
    var_4 = var_0.plr_ready_sound;
    var_5 = level.odinsettings[self.odintype].ui_num;
    wait( var_3 );

    if ( !isdefined( var_1.odin ) )
        return;

    if ( isdefined( var_4 ) )
        var_1 maps\mp\_utility::_playlocalsound( var_4 );

    var_1 setclientomnvar( var_2, var_5 );
}

domarkingflash( var_0 )
{
    level endon( "game_ended" );
    var_1 = self.owner;
    var_2 = level.odin_marking_flash_radius_max * level.odin_marking_flash_radius_max;
    var_3 = level.odin_marking_flash_radius_min * level.odin_marking_flash_radius_min;
    var_4 = 60;
    var_5 = 40;
    var_6 = 11;
    var_7 = 0;

    foreach ( var_9 in level.participants )
    {
        if ( !maps\mp\_utility::isreallyalive( var_9 ) || var_9.sessionstate != "playing" )
            continue;

        if ( level.teambased && var_9.team == self.team )
            continue;

        var_10 = distancesquared( var_0, var_9.origin );

        if ( var_10 > var_2 )
            continue;

        var_11 = var_9 getstance();
        var_12 = var_9.origin;

        switch ( var_11 )
        {
            case "stand":
                var_12 = ( var_12[0], var_12[1], var_12[2] + var_4 );
                break;
            case "crouch":
                var_12 = ( var_12[0], var_12[1], var_12[2] + var_5 );
                break;
            case "prone":
                var_12 = ( var_12[0], var_12[1], var_12[2] + var_6 );
                break;
        }

        if ( !bullettracepassed( var_0, var_12, 0, var_9 ) )
            continue;

        if ( var_10 <= var_3 )
            var_13 = 1.0;
        else
            var_13 = 1.0 - ( var_10 - var_3 ) / ( var_2 - var_3 );

        var_14 = anglestoforward( var_9 getplayerangles() );
        var_15 = var_0 - var_12;
        var_15 = vectornormalize( var_15 );
        var_16 = 0.5 * ( 1.0 + vectordot( var_14, var_15 ) );
        var_17 = 1;
        var_9 notify( "flashbang", var_0, var_13, var_16, var_1, var_17 );
        var_7++;

        if ( !enemynotaffectedbyodinoutline( var_9 ) )
        {
            if ( level.teambased )
                var_18 = maps\mp\_utility::outlineenableforteam( var_9, "orange", self.team, 0, "killstreak" );
            else
                var_18 = maps\mp\_utility::outlineenableforplayer( var_9, "orange", self.owner, 0, "killstreak" );

            thread removeoutline( var_18, var_9, 3.0 );
        }
    }

    var_20 = level.odinsettings[self.odintype].weapon["marking"];

    if ( var_7 == 1 )
    {
        if ( level.teambased )
            maps\mp\_utility::leaderdialog( var_20.vomarkedsingle, self.team );
        else
            var_1 maps\mp\_utility::leaderdialogonplayer( var_20.vomarkedsingle );
    }
    else if ( var_7 > 1 )
    {
        if ( level.teambased )
            maps\mp\_utility::leaderdialog( var_20.vomarkedmulti, self.team );
        else
            var_1 maps\mp\_utility::leaderdialogonplayer( var_20.vomarkedmulti );
    }

    var_21 = maps\mp\gametypes\_weapons::getempdamageents( var_0, 512, 0 );

    foreach ( var_23 in var_21 )
    {
        if ( isdefined( var_23.owner ) && !maps\mp\gametypes\_weapons::friendlyfirecheck( self.owner, var_23.owner ) )
            continue;

        var_23 notify( "emp_damage", self.owner, 8.0 );
    }
}

applyoutline( var_0 )
{
    if ( level.teambased && var_0.team == self.team )
        return;
    else if ( !level.teambased && var_0 == self.owner )
        return;

    if ( enemynotaffectedbyodinoutline( var_0 ) )
        return;

    var_1 = maps\mp\_utility::outlineenableforplayer( var_0, "orange", self.owner, 1, "killstreak" );
    thread removeoutline( var_1, var_0 );
}

enemynotaffectedbyodinoutline( var_0 )
{
    return var_0 maps\mp\_utility::_hasperk( "specialty_noplayertarget" );
}

removeoutline( var_0, var_1, var_2 )
{
    if ( isdefined( var_1 ) )
        var_1 endon( "disconnect" );

    level endon( "game_ended" );
    var_3 = [ "leave", "death" ];

    if ( isdefined( var_2 ) )
        common_scripts\utility::waittill_any_in_array_or_timeout_no_endon_death( var_3, var_2 );
    else
        common_scripts\utility::waittill_any_in_array_return_no_endon_death( var_3 );

    if ( isdefined( var_1 ) )
        maps\mp\_utility::outlinedisable( var_0, var_1 );
}

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

    foreach ( var_1 in level.participants )
        applyoutline( var_1 );
}

odin_watchplayerkilled()
{
    self endon( "death" );
    level endon( "game_ended" );
    self.enemieskilledintimewindow = 0;

    for (;;)
    {
        level waittill( "odin_killed_player", var_0 );
        self.enemieskilledintimewindow++;
        self notify( "odin_enemy_killed" );
    }
}

odin_dialog_killed_player( var_0 )
{
    self endon( "death" );
    level endon( "game_ended" );
    var_1 = level.odinsettings[self.odintype];
    var_2 = 1.0;

    for (;;)
    {
        self waittill( "odin_enemy_killed" );
        wait( var_2 );

        if ( self.enemieskilledintimewindow > 1 )
            self.owner maps\mp\_utility::leaderdialogonplayer( var_1.vokillmulti );
        else
            self.owner maps\mp\_utility::leaderdialogonplayer( var_1.vokillsingle );

        self.enemieskilledintimewindow = 0;
    }
}

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

    for (;;)
    {
        level waittill( "connected", var_0 );
        var_0 thread odin_onplayerspawned( self );
    }
}

odin_onplayerspawned( var_0 )
{
    self endon( "disconnect" );
    self waittill( "spawned_player" );
    var_0 applyoutline( self );
}

cleanup_ents()
{
    if ( isdefined( self.targeting_marker ) )
        self.targeting_marker delete();

    if ( isdefined( self.odin_overlay_ent ) )
        self.odin_overlay_ent delete();
}

watchearlyexit( var_0 )
{
    level endon( "game_ended" );
    var_0 endon( "death" );
    var_0 thread maps\mp\killstreaks\_killstreaks::allowridekillstreakplayerexit();
    var_0 waittill( "killstreakExit" );
    var_1 = level.odinsettings[var_0.odintype];
    maps\mp\_utility::leaderdialog( var_1.votimedout );
    var_0 notify( "death" );
}
