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

init()
{
    level.killstreakfuncs["ims"] = ::tryuseims;
    level.imssettings = [];
    var_0 = spawnstruct();
    var_0.weaponinfo = "ims_projectile_mp";
    var_0.modelbase = "ims_scorpion_body_iw6";
    var_0.modelplacement = "ims_scorpion_body_iw6_placement";
    var_0.modelplacementfailed = "ims_scorpion_body_iw6_placement_failed";
    var_0.modeldestroyed = "ims_scorpion_body_iw6";
    var_0.modelbombsquad = "ims_scorpion_body_iw6_bombsquad";
    var_0.hintstring = &"KILLSTREAKS_HINTS_IMS_PICKUP_TO_MOVE";
    var_0.placestring = &"KILLSTREAKS_HINTS_IMS_PLACE";
    var_0.cannotplacestring = &"KILLSTREAKS_HINTS_IMS_CANNOT_PLACE";
    var_0.streakname = "ims";
    var_0.splashname = "used_ims";
    var_0.maxhealth = 1000;
    var_0.lifespan = 90.0;
    var_0.rearmtime = 0.5;
    var_0.graceperiod = 0.4;
    var_0.numexplosives = 4;
    var_0.explosivemodel = "ims_scorpion_explosive_iw6";
    var_0.placementheighttolerance = 30.0;
    var_0.placementradius = 24.0;
    var_0.lidtagroot = "tag_lid";
    var_0.lidopenanims = [];
    var_0.lidopenanims[1] = "IMS_Scorpion_door_1";
    var_0.lidopenanims[2] = "IMS_Scorpion_door_2";
    var_0.lidopenanims[3] = "IMS_Scorpion_door_3";
    var_0.lidopenanims[4] = "IMS_Scorpion_door_4";
    var_0.lidsnapopenanims = [];
    var_0.lidsnapopenanims[1] = "IMS_Scorpion_1_opened";
    var_0.lidsnapopenanims[2] = "IMS_Scorpion_2_opened";
    var_0.lidsnapopenanims[3] = "IMS_Scorpion_3_opened";
    var_0.expltagroot = "tag_explosive";
    var_0.killcamoffset = ( 0, 0, 12 );
    level.imssettings["ims"] = var_0;
    level._effect["ims_explode_mp"] = loadfx( "vfx/gameplay/mp/killstreaks/vfx_ims_explosion" );
    level._effect["ims_smoke_mp"] = loadfx( "vfx/gameplay/mp/killstreaks/vfx_sg_damage_blacksmoke" );
    level._effect["ims_sensor_explode"] = loadfx( "vfx/gameplay/mp/killstreaks/vfx_ims_sparks" );
    level._effect["ims_antenna_light_mp"] = loadfx( "vfx/gameplay/mp/killstreaks/vfx_light_detonator_blink" );
    level.placedims = [];
}

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

    if ( isdefined( self.imslist ) )
        var_2 = self.imslist;

    var_3 = giveims( "ims" );

    if ( !isdefined( var_3 ) )
    {
        var_3 = 0;

        if ( isdefined( self.imslist ) )
        {
            if ( !var_2.size && self.imslist.size )
                var_3 = 1;

            if ( var_2.size && var_2[0] != self.imslist[0] )
                var_3 = 1;
        }
    }

    if ( var_3 )
        maps\mp\_matchdata::logkillstreakevent( level.imssettings["ims"].streakname, self.origin );

    self.iscarrying = 0;
    return var_3;
}

giveims( var_0 )
{
    var_1 = createimsforplayer( var_0, self );
    removeperks();
    self.carriedims = var_1;
    var_1.firstplacement = 1;
    var_2 = setcarryingims( var_1, 1 );
    self.carriedims = undefined;
    thread restoreperks();
    return var_2;
}

setcarryingims( var_0, var_1 )
{
    self endon( "death" );
    self endon( "disconnect" );
    var_0 thread ims_setcarried( self );
    common_scripts\utility::_disableweapon();

    if ( !isai( self ) )
    {
        self notifyonplayercommand( "place_ims", "+attack" );
        self notifyonplayercommand( "place_ims", "+attack_akimbo_accessible" );
        self notifyonplayercommand( "cancel_ims", "+actionslot 4" );

        if ( !level.console )
        {
            self notifyonplayercommand( "cancel_ims", "+actionslot 5" );
            self notifyonplayercommand( "cancel_ims", "+actionslot 6" );
            self notifyonplayercommand( "cancel_ims", "+actionslot 7" );
        }
    }

    for (;;)
    {
        if ( maps\mp\_utility::is_aliens() )
            var_2 = common_scripts\utility::waittill_any_return( "place_ims", "cancel_ims", "force_cancel_placement", "player_action_slot_restart" );
        else
            var_2 = common_scripts\utility::waittill_any_return( "place_ims", "cancel_ims", "force_cancel_placement" );

        if ( var_2 == "cancel_ims" || var_2 == "force_cancel_placement" || var_2 == "player_action_slot_restart" )
        {
            if ( !var_1 && var_2 == "cancel_ims" )
                continue;

            if ( level.console )
            {
                var_3 = maps\mp\_utility::getkillstreakweapon( level.imssettings[var_0.imstype].streakname );

                if ( isdefined( self.killstreakindexweapon ) && var_3 == maps\mp\_utility::getkillstreakweapon( self.pers["killstreaks"][self.killstreakindexweapon].streakname ) && !self getweaponslistitems().size )
                {
                    maps\mp\_utility::_giveweapon( var_3, 0 );
                    maps\mp\_utility::_setactionslot( 4, "weapon", var_3 );
                }
            }

            var_0 ims_setcancelled( var_2 == "force_cancel_placement" && !isdefined( var_0.firstplacement ) );
            return 0;
        }

        if ( !var_0.canbeplaced )
            continue;

        var_0 thread ims_setplaced();
        self notify( "IMS_placed" );
        common_scripts\utility::_enableweapon();
        return 1;
    }
}

removeweapons()
{
    if ( self hasweapon( "iw6_riotshield_mp" ) )
    {
        self.restoreweapon = "iw6_riotshield_mp";
        self takeweapon( "iw6_riotshield_mp" );
    }
}

removeperks()
{
    if ( maps\mp\_utility::_hasperk( "specialty_explosivebullets" ) )
    {
        self.restoreperk = "specialty_explosivebullets";
        maps\mp\_utility::_unsetperk( "specialty_explosivebullets" );
    }
}

restoreweapons()
{
    if ( isdefined( self.restoreweapon ) )
    {
        maps\mp\_utility::_giveweapon( self.restoreweapon );
        self.restoreweapon = undefined;
    }
}

restoreperks()
{
    if ( isdefined( self.restoreperk ) )
    {
        maps\mp\_utility::giveperk( self.restoreperk, 0 );
        self.restoreperk = undefined;
    }
}

waitrestoreperks()
{
    self endon( "death" );
    self endon( "disconnect" );
    level endon( "game_ended" );
    wait 0.05;
    restoreperks();
}

createimsforplayer( var_0, var_1 )
{
    if ( isdefined( var_1.iscarrying ) && var_1.iscarrying )
        return;

    var_2 = spawnturret( "misc_turret", var_1.origin + ( 0, 0, 25 ), "sentry_minigun_mp" );
    var_2.angles = var_1.angles;
    var_2.imstype = var_0;
    var_2.owner = var_1;
    var_2 setmodel( level.imssettings[var_0].modelbase );
    var_2 maketurretinoperable();
    var_2 setturretmodechangewait( 1 );
    var_2 setmode( "sentry_offline" );
    var_2 makeunusable();
    var_2 setsentryowner( var_1 );
    return var_2;
}

createims( var_0 )
{
    var_1 = var_0.owner;
    var_2 = var_0.imstype;
    var_3 = spawn( "script_model", var_0.origin );
    var_3 setmodel( level.imssettings[var_2].modelbase );
    var_3.scale = 3;
    var_3.angles = var_0.angles;
    var_3.imstype = var_2;
    var_3.owner = var_1;
    var_3 setotherent( var_1 );
    var_3.team = var_1.team;
    var_3.shouldsplash = 0;
    var_3.hidden = 0;
    var_3.attacks = 1;
    var_3 disablemissilestick();
    var_3.hasexplosivefired = [];
    var_3.config = level.imssettings[var_2];
    var_3 thread ims_handleuse();
    var_3 thread ims_timeout();
    var_3 thread ims_createbombsquadmodel();
    var_3 thread ims_onkillstreakdisowned();
    return var_3;
}

ims_createbombsquadmodel()
{
    var_0 = spawn( "script_model", self.origin );
    var_0.angles = self.angles;
    var_0 hide();
    var_0 thread maps\mp\gametypes\_weapons::bombsquadvisibilityupdater( self.owner );
    var_0 setmodel( level.imssettings[self.imstype].modelbombsquad );
    var_0 linkto( self );
    var_0 setcontents( 0 );
    self.bombsquadmodel = var_0;
    self waittill( "death" );

    if ( isdefined( var_0 ) )
        var_0 delete();
}

ims_moving_platform_death( var_0 )
{
    self.immediatedeath = 1;
    self notify( "death" );
}

ims_handledamage()
{
    self endon( "carried" );
    maps\mp\gametypes\_damage::monitordamage( self.config.maxhealth, "ims", ::ims_handledeathdamage, ::ims_modifydamage, 1 );
}

ims_modifydamage( var_0, var_1, var_2, var_3 )
{
    if ( self.hidden || var_1 == "ims_projectile_mp" )
        return -1;

    var_4 = var_3;

    if ( var_2 == "MOD_MELEE" )
        var_4 = self.maxhealth * 0.25;

    if ( isexplosivedamagemod( var_2 ) )
        var_4 = var_3 * 1.5;

    var_4 = maps\mp\gametypes\_damage::handlemissiledamage( var_1, var_2, var_4 );
    var_4 = maps\mp\gametypes\_damage::handleapdamage( var_1, var_2, var_4, var_0 );
    return var_4;
}

ims_handledeathdamage( var_0, var_1, var_2, var_3 )
{
    var_4 = maps\mp\gametypes\_damage::onkillstreakkilled( var_0, var_1, var_2, var_3, "destroyed_ims", "ims_destroyed" );

    if ( var_4 )
        var_0 notify( "destroyed_equipment" );
}

ims_handledeath()
{
    self endon( "carried" );
    self waittill( "death" );
    removefromimslist();

    if ( !isdefined( self ) )
        return;

    ims_setinactive();
    self playsound( "ims_destroyed" );

    if ( isdefined( self.inuseby ) )
    {
        playfx( common_scripts\utility::getfx( "ims_explode_mp" ), self.origin + ( 0, 0, 10 ) );
        playfx( common_scripts\utility::getfx( "ims_smoke_mp" ), self.origin );
        self.inuseby restoreperks();
        self.inuseby restoreweapons();
        self notify( "deleting" );
        wait 1.0;
    }
    else if ( isdefined( self.immediatedeath ) )
    {
        playfx( common_scripts\utility::getfx( "ims_explode_mp" ), self.origin + ( 0, 0, 10 ) );
        self notify( "deleting" );
    }
    else
    {
        playfx( common_scripts\utility::getfx( "ims_explode_mp" ), self.origin + ( 0, 0, 10 ) );
        playfx( common_scripts\utility::getfx( "ims_smoke_mp" ), self.origin );
        wait 3.0;
        self playsound( "ims_fire" );
        self notify( "deleting" );
    }

    if ( isdefined( self.objidfriendly ) )
        maps\mp\_utility::_objective_delete( self.objidfriendly );

    if ( isdefined( self.objidenemy ) )
        maps\mp\_utility::_objective_delete( self.objidenemy );

    maps\mp\gametypes\_weapons::equipmentdeletevfx();
    self enablemissilestick();
    self delete();
}

watchempdamage()
{
    self endon( "carried" );
    self endon( "death" );
    level endon( "game_ended" );

    for (;;)
    {
        self waittill( "emp_damage", var_0, var_1 );
        maps\mp\gametypes\_weapons::stopblinkinglight();
        playfx( common_scripts\utility::getfx( "emp_stun" ), self.origin );
        playfx( common_scripts\utility::getfx( "ims_smoke_mp" ), self.origin );
        wait( var_1 );
        ims_start();
    }
}

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

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

        if ( !maps\mp\_utility::isreallyalive( var_0 ) )
            continue;

        if ( self.damagetaken >= self.maxhealth )
            continue;

        if ( maps\mp\_utility::is_aliens() && isdefined( level.drill_carrier ) && var_0 == level.drill_carrier )
            continue;

        var_1 = createimsforplayer( self.imstype, var_0 );

        if ( !isdefined( var_1 ) )
            continue;

        var_1.ims = self;
        ims_setinactive();
        ims_hideallparts();

        if ( isdefined( self getlinkedparent() ) )
            self unlink();

        var_0 setcarryingims( var_1, 0 );
    }
}

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

    if ( isdefined( self.carriedby ) )
        self.carriedby forceusehintoff();

    self.carriedby = undefined;

    if ( isdefined( self.owner ) )
        self.owner.iscarrying = 0;

    self.firstplacement = undefined;
    var_0 = undefined;

    if ( isdefined( self.ims ) )
    {
        var_0 = self.ims;
        var_0 endon( "death" );
        var_0.origin = self.origin;
        var_0.angles = self.angles;
        var_0.carriedby = undefined;
        var_0 ims_showallparts();

        if ( isdefined( var_0.bombsquadmodel ) )
        {
            var_0.bombsquadmodel show();
            var_0 imsopenalldoors( var_0.bombsquadmodel, 1 );
            level notify( "update_bombsquad" );
        }
    }
    else
        var_0 = createims( self );

    var_0 addtoimslist();
    var_0.isplaced = 1;
    var_0 thread ims_handledamage();
    var_0 thread watchempdamage();
    var_0 thread ims_handledeath();
    var_0 setcandamage( 1 );
    self playsound( "ims_plant" );
    self notify( "placed" );
    var_0 thread ims_setactive();
    var_1 = spawnstruct();

    if ( isdefined( self.moving_platform ) )
        var_1.linkparent = self.moving_platform;

    var_1.endonstring = "carried";
    var_1.deathoverridecallback = ::ims_moving_platform_death;
    var_0 thread maps\mp\_movers::handle_moving_platforms( var_1 );
    self delete();
}

ims_setcancelled( var_0 )
{
    if ( isdefined( self.carriedby ) )
    {
        var_1 = self.carriedby;
        var_1 forceusehintoff();
        var_1.iscarrying = undefined;
        var_1.carrieditem = undefined;
        var_1 common_scripts\utility::_enableweapon();

        if ( isdefined( var_1.imslist ) )
        {
            foreach ( var_3 in var_1.imslist )
            {
                if ( isdefined( var_3.bombsquadmodel ) )
                    var_3.bombsquadmodel delete();
            }
        }
    }

    if ( isdefined( var_0 ) && var_0 )
        maps\mp\gametypes\_weapons::equipmentdeletevfx();

    self delete();
}

ims_setcarried( var_0 )
{
    removefromimslist();
    self setmodel( level.imssettings[self.imstype].modelplacement );
    self setsentrycarrier( var_0 );
    self setcontents( 0 );
    self setcandamage( 0 );
    self.carriedby = var_0;
    var_0.iscarrying = 1;
    var_0 thread updateimsplacement( self );
    thread ims_oncarrierdeath( var_0 );
    thread ims_oncarrierdisconnect( var_0 );
    thread ims_ongameended();
    thread ims_onenterride( var_0 );

    if ( maps\mp\_utility::is_aliens() && isdefined( level.drop_ims_when_grabbed_func ) )
        self thread [[ level.drop_ims_when_grabbed_func ]]( var_0 );

    self notify( "carried" );

    if ( isdefined( self.ims ) )
    {
        self.ims notify( "carried" );
        self.ims.carriedby = var_0;
        self.ims.isplaced = 0;

        if ( isdefined( self.ims.bombsquadmodel ) )
            self.ims.bombsquadmodel hide();
    }
}

updateimsplacement( var_0 )
{
    self endon( "death" );
    self endon( "disconnect" );
    level endon( "game_ended" );
    var_0 endon( "placed" );
    var_0 endon( "death" );
    var_0.canbeplaced = 1;
    var_1 = -1;
    var_2 = level.imssettings[var_0.imstype];

    for (;;)
    {
        var_3 = self canplayerplacesentry( 1, var_2.placementradius );
        var_0.origin = var_3["origin"];
        var_0.angles = var_3["angles"];
        var_0.canbeplaced = self isonground() && var_3["result"] && abs( var_0.origin[2] - self.origin[2] ) < var_2.placementheighttolerance;

        if ( isdefined( var_3["entity"] ) )
            var_0.moving_platform = var_3["entity"];
        else
            var_0.moving_platform = undefined;

        if ( var_0.canbeplaced != var_1 )
        {
            if ( var_0.canbeplaced )
            {
                var_0 setmodel( level.imssettings[var_0.imstype].modelplacement );
                self forceusehinton( level.imssettings[var_0.imstype].placestring );
            }
            else
            {
                var_0 setmodel( level.imssettings[var_0.imstype].modelplacementfailed );
                self forceusehinton( level.imssettings[var_0.imstype].cannotplacestring );
            }
        }

        var_1 = var_0.canbeplaced;
        wait 0.05;
    }
}

ims_oncarrierdeath( var_0 )
{
    self endon( "placed" );
    self endon( "death" );
    var_0 endon( "disconnect" );
    var_0 waittill( "death" );

    if ( self.canbeplaced && var_0.team != "spectator" )
        thread ims_setplaced();
    else
        ims_setcancelled();
}

ims_oncarrierdisconnect( var_0 )
{
    self endon( "placed" );
    self endon( "death" );
    var_0 waittill( "disconnect" );
    ims_setcancelled();
}

ims_onenterride( var_0 )
{
    self endon( "placed" );
    self endon( "death" );

    for (;;)
    {
        if ( isdefined( self.carriedby.onhelisniper ) && self.carriedby.onhelisniper )
            self notify( "death" );

        wait 0.1;
    }
}

ims_ongameended( var_0 )
{
    self endon( "placed" );
    self endon( "death" );
    level waittill( "game_ended" );
    ims_setcancelled();
}

ims_setactive()
{
    self setcursorhint( "HINT_NOICON" );
    self sethintstring( level.imssettings[self.imstype].hintstring );
    var_0 = self.owner;
    var_0 forceusehintoff();

    if ( !maps\mp\_utility::is_aliens() )
    {
        if ( level.teambased )
            maps\mp\_entityheadicons::setteamheadicon( self.team, ( 0, 0, 60 ) );
        else
            maps\mp\_entityheadicons::setplayerheadicon( var_0, ( 0, 0, 60 ) );
    }

    self makeusable();
    self setcandamage( 1 );
    maps\mp\gametypes\_weapons::makeexplosivetargetablebyai();

    if ( isdefined( var_0.imslist ) )
    {
        foreach ( var_2 in var_0.imslist )
        {
            if ( var_2 == self )
                continue;

            var_2 notify( "death" );
        }
    }

    var_0.imslist = [];
    var_0.imslist[0] = self;

    foreach ( var_5 in level.players )
    {
        if ( var_5 == var_0 )
        {
            self enableplayeruse( var_5 );
            continue;
        }

        self disableplayeruse( var_5 );
    }

    if ( self.shouldsplash )
    {
        level thread maps\mp\_utility::teamplayercardsplash( level.imssettings[self.imstype].splashname, var_0 );
        self.shouldsplash = 0;
    }

    var_7 = ( 0, 0, 20 );
    var_8 = ( 0, 0, 256 ) - var_7;
    var_9 = [];
    self.killcam_ents = [];

    for ( var_10 = 0; var_10 < self.config.numexplosives; var_10++ )
    {
        if ( numexplosivesexceedmodelcapacity() )
            var_11 = shiftindexforward( var_10 + 1, self.config.numexplosives - 4 );
        else
            var_11 = var_10 + 1;

        var_12 = self gettagorigin( self.config.expltagroot + var_11 + "_attach" );
        var_13 = self gettagorigin( self.config.expltagroot + var_11 + "_attach" ) + var_7;
        var_9[var_10] = bullettrace( var_13, var_13 + var_8, 0, self );

        if ( var_10 < 4 )
        {
            var_14 = spawn( "script_model", var_12 + self.config.killcamoffset );
            var_14 setscriptmoverkillcam( "explosive" );
            self.killcam_ents[self.killcam_ents.size] = var_14;
        }
    }

    var_15 = var_9[0];

    for ( var_10 = 0; var_10 < var_9.size; var_10++ )
    {
        if ( var_9[var_10]["position"][2] < var_15["position"][2] )
            var_15 = var_9[var_10];
    }

    self.attackheightpos = var_15["position"] - ( 0, 0, 20 ) - self.origin;
    var_16 = spawn( "trigger_radius", self.origin, 0, 256, 100 );
    self.attacktrigger = var_16;
    self.attacktrigger enablelinkto();
    self.attacktrigger linkto( self );
    self.attackmovetime = length( self.attackheightpos ) / 200;
    imscreateexplosivewithkillcam();
    ims_start();
    thread ims_watchplayerconnected();

    foreach ( var_5 in level.players )
        thread ims_playerjoinedteam( var_5 );
}

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

    for (;;)
    {
        level waittill( "connected", var_0 );
        ims_playerconnected( var_0 );
    }
}

ims_playerconnected( var_0 )
{
    self endon( "death" );
    var_0 endon( "disconnect" );
    var_0 waittill( "spawned_player" );
    self disableplayeruse( var_0 );
}

ims_playerjoinedteam( var_0 )
{
    self endon( "death" );
    var_0 endon( "disconnect" );

    for (;;)
    {
        var_0 waittill( "joined_team" );
        self disableplayeruse( var_0 );
    }
}

ims_onkillstreakdisowned()
{
    self endon( "death" );
    level endon( "game_ended" );
    self.owner waittill( "killstreak_disowned" );

    if ( isdefined( self.isplaced ) )
        self notify( "death" );
    else
        ims_setcancelled( 0 );
}

ims_start()
{
    thread maps\mp\gametypes\_weapons::doblinkinglight( "tag_fx" );
    thread ims_attacktargets();
}

ims_setinactive()
{
    self makeunusable();
    self freeentitysentient();

    if ( level.teambased )
        maps\mp\_entityheadicons::setteamheadicon( "none", ( 0, 0, 0 ) );
    else if ( isdefined( self.owner ) )
        maps\mp\_entityheadicons::setplayerheadicon( undefined, ( 0, 0, 0 ) );

    if ( isdefined( self.attacktrigger ) )
        self.attacktrigger delete();

    if ( isdefined( self.killcam_ents ) )
    {
        foreach ( var_1 in self.killcam_ents )
        {
            if ( isdefined( var_1 ) )
            {
                if ( isdefined( self.owner ) && isdefined( self.owner.imskillcament ) && var_1 == self.owner.imskillcament )
                    continue;
                else
                    var_1 delete();
            }
        }
    }

    if ( isdefined( self.explosive1 ) )
    {
        self.explosive1 delete();
        self.explosive1 = undefined;
    }

    maps\mp\gametypes\_weapons::stopblinkinglight();
}

isfriendlytoims( var_0 )
{
    if ( level.teambased && self.team == var_0.team )
        return 1;

    return 0;
}

ims_attacktargets()
{
    self endon( "death" );
    self endon( "emp_damage" );
    level endon( "game_ended" );

    for (;;)
    {
        if ( !isdefined( self.attacktrigger ) )
            break;

        self.attacktrigger waittill( "trigger", var_0 );

        if ( isplayer( var_0 ) )
        {
            if ( isdefined( self.owner ) && var_0 == self.owner )
                continue;

            if ( level.teambased && var_0.pers["team"] == self.team )
                continue;

            if ( !maps\mp\_utility::isreallyalive( var_0 ) )
                continue;
        }
        else if ( isdefined( var_0.owner ) )
        {
            if ( isdefined( self.owner ) && var_0.owner == self.owner )
                continue;

            if ( level.teambased && var_0.owner.pers["team"] == self.team )
                continue;
        }

        var_1 = var_0.origin + ( 0, 0, 50 );

        if ( !sighttracepassed( self.attackheightpos + self.origin, var_1, 0, self ) )
            continue;

        var_2 = 0;

        for ( var_3 = 1; var_3 <= self.config.numexplosives; var_3++ )
        {
            if ( var_3 > 4 )
                break;

            if ( sighttracepassed( self gettagorigin( self.config.lidtagroot + var_3 ), var_1, 0, self ) )
            {
                var_2 = 1;
                break;
            }
        }

        if ( !var_2 )
            continue;

        self playsound( "ims_trigger" );

        if ( maps\mp\_utility::is_aliens() && isdefined( level.ims_alien_grace_period_func ) && isdefined( self.owner ) )
        {
            var_4 = [[ level.ims_alien_grace_period_func ]]( level.imssettings[self.imstype].graceperiod, self.owner );
            maps\mp\gametypes\_weapons::explosivetrigger( var_0, var_4, "ims" );
        }
        else
            maps\mp\gametypes\_weapons::explosivetrigger( var_0, level.imssettings[self.imstype].graceperiod, "ims" );

        if ( !isdefined( self.attacktrigger ) )
            break;

        if ( !isdefined( self.hasexplosivefired[self.attacks] ) )
        {
            self.hasexplosivefired[self.attacks] = 1;
            thread fire_sensor( var_0, self.attacks );
            self.attacks++;
        }

        if ( self.attacks > self.config.numexplosives )
            break;

        imscreateexplosivewithkillcam();
        self waittill( "sensor_exploded" );
        wait( self.config.rearmtime );

        if ( !isdefined( self.owner ) )
            break;
    }

    if ( isdefined( self.carriedby ) && isdefined( self.owner ) && self.carriedby == self.owner )
        return;

    self notify( "death" );
}

fire_sensor( var_0, var_1 )
{
    if ( numexplosivesexceedmodelcapacity() )
        var_1 = shiftindexforward( var_1, self.config.numexplosives - 4 );

    var_2 = self.explosive1;
    self.explosive1 = undefined;
    var_3 = self.config.lidtagroot + var_1;
    playfxontag( level._effect["ims_sensor_explode"], self, var_3 );
    imsopendoor( var_1, self.config );
    var_4 = self.config.weaponinfo;
    var_5 = self.owner;
    var_2 unlink();
    var_2 rotateyaw( 3600, self.attackmovetime );
    var_2 moveto( self.attackheightpos + self.origin, self.attackmovetime, self.attackmovetime * 0.25, self.attackmovetime * 0.25 );

    if ( isdefined( var_2.killcament ) )
    {
        var_6 = var_2.killcament;
        var_6 unlink();

        if ( isdefined( self.owner ) )
            self.owner.imskillcament = var_6;

        var_6 moveto( self.attackheightpos + self.origin + self.config.killcamoffset, self.attackmovetime, self.attackmovetime * 0.25, self.attackmovetime * 0.25 );

        if ( !numexplosivesexceedmodelcapacity() )
            var_6 thread deleteaftertime( 5.0 );
    }

    var_2 playsound( "ims_launch" );
    var_2 waittill( "movedone" );
    playfx( level._effect["ims_sensor_explode"], var_2.origin );
    var_7 = [];
    var_7[0] = var_0.origin;

    for ( var_8 = 0; var_8 < var_7.size; var_8++ )
    {
        if ( isdefined( var_5 ) )
        {
            magicbullet( var_4, var_2.origin, var_7[var_8], var_5 );

            if ( maps\mp\_utility::is_aliens() && isdefined( level.ims_alien_fire_func ) )
                self thread [[ level.ims_alien_fire_func ]]( var_7[var_8], var_5 );

            continue;
        }

        magicbullet( var_4, var_2.origin, var_7[var_8] );
    }

    var_2 delete();
    self notify( "sensor_exploded" );
}

deleteaftertime( var_0 )
{
    self endon( "death" );
    level maps\mp\gametypes\_hostmigration::waitlongdurationwithhostmigrationpause( var_0 );

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

ims_timeout()
{
    self endon( "death" );
    level endon( "game_ended" );
    var_0 = level.imssettings[self.imstype].lifespan;

    while ( var_0 )
    {
        wait 1.0;
        maps\mp\gametypes\_hostmigration::waittillhostmigrationdone();

        if ( !isdefined( self.carriedby ) )
            var_0 = max( 0, var_0 - 1.0 );
    }

    self notify( "death" );
}

addtoimslist()
{
    var_0 = self getentitynumber();
    level.placedims[var_0] = self;
}

removefromimslist()
{
    var_0 = self getentitynumber();
    level.placedims[var_0] = undefined;
}

ims_hideallparts()
{
    self hide();
    self.hidden = 1;
}

ims_showallparts()
{
    self show();
    self.hidden = 0;
    imsopenalldoors( self, 1 );
}

imscreateexplosive( var_0 )
{
    var_1 = spawn( "script_model", self gettagorigin( self.config.expltagroot + var_0 + "_attach" ) );
    var_1 setmodel( self.config.explosivemodel );
    var_1.angles = self.angles;
    var_1.killcament = self.killcam_ents[var_0 - 1];
    var_1.killcament linkto( self );
    return var_1;
}

imscreateexplosivewithkillcam()
{
    for ( var_0 = 1; var_0 <= self.config.numexplosives && isdefined( self.hasexplosivefired[var_0] ); var_0++ )
    {

    }

    if ( var_0 <= self.config.numexplosives )
    {
        if ( numexplosivesexceedmodelcapacity() )
            var_0 = shiftindexforward( var_0, self.config.numexplosives - 4 );

        var_1 = imscreateexplosive( var_0 );
        var_1 linkto( self );
        self.explosive1 = var_1;
    }
}

imsopendoor( var_0, var_1, var_2 )
{
    var_3 = var_1.lidtagroot + var_0 + "_attach";
    var_4 = undefined;

    if ( isdefined( var_2 ) )
        var_4 = var_1.lidsnapopenanims[var_0];
    else
        var_4 = var_1.lidopenanims[var_0];

    self scriptmodelplayanim( var_4 );
    var_5 = var_1.expltagroot + var_0 + "_attach";
    self hidepart( var_5 );
}

imsopenalldoors( var_0, var_1 )
{
    var_2 = self.hasexplosivefired.size;

    if ( var_2 > 0 )
    {
        if ( numexplosivesexceedmodelcapacity() )
            var_2 = shiftindexforward( var_2, self.config.numexplosives - 4 );

        var_0 imsopendoor( var_2, self.config, var_1 );
    }
}

numexplosivesexceedmodelcapacity()
{
    return self.config.numexplosives > 4;
}

shiftindexforward( var_0, var_1 )
{
    var_2 = var_0 - var_1;
    var_2 = max( 1, var_2 );
    return int( var_2 );
}
