Advertisement
Guest User

Pick up c4 and claymores updated 1.1

a guest
Oct 22nd, 2012
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 67.13 KB | None | 0 0
  1. #include common_scripts\utility;
  2. #include maps\mp\_utility;
  3.  
  4.  
  5. attachmentGroup( attachmentName )
  6. {
  7.     return tableLookup( "mp/attachmentTable.csv", 4, attachmentName, 2 );
  8. }
  9.  
  10. getAttachmentList()
  11. {
  12.     attachmentList = [];
  13.    
  14.     index = 0;
  15.     attachmentName = tableLookup( "mp/attachmentTable.csv", 9, index, 4 );
  16.    
  17.     while ( attachmentName != "" )
  18.     {
  19.         attachmentList[attachmentList.size] = attachmentName;
  20.        
  21.         index++;
  22.         attachmentName = tableLookup( "mp/attachmentTable.csv", 9, index, 4 );
  23.     }
  24.    
  25.     return alphabetize( attachmentList );
  26. }
  27.  
  28. init()
  29. {
  30.     level.scavenger_altmode = true;
  31.     level.scavenger_secondary = true;
  32.    
  33.     // 0 is not valid
  34.     level.maxPerPlayerExplosives = max( getIntProperty( "scr_maxPerPlayerExplosives", 2 ), 1 );
  35.     level.riotShieldXPBullets = getIntProperty( "scr_riotShieldXPBullets", 15 );
  36.  
  37.     switch ( getIntProperty( "perk_scavengerMode", 0 ) )
  38.     {
  39.         case 1: // disable altmode
  40.             level.scavenger_altmode = false;
  41.             break;
  42.  
  43.         case 2: // disable secondary
  44.             level.scavenger_secondary = false;
  45.             break;
  46.            
  47.         case 3: // disable altmode and secondary
  48.             level.scavenger_altmode = false;
  49.             level.scavenger_secondary = false;
  50.             break;     
  51.     }
  52.    
  53.     attachmentList = getAttachmentList();  
  54.    
  55.     // assigns weapons with stat numbers from 0-149
  56.     // attachments are now shown here, they are per weapon settings instead
  57.    
  58.     max_weapon_num = 149;
  59.  
  60.     level.weaponList = [];
  61.     for( weaponId = 0; weaponId <= max_weapon_num; weaponId++ )
  62.     {
  63.         weapon_name = tablelookup( "mp/statstable.csv", 0, weaponId, 4 );
  64.         if( weapon_name == "" )
  65.             continue;
  66.    
  67.         if ( !isSubStr( tableLookup( "mp/statsTable.csv", 0, weaponId, 2 ), "weapon_" ) )
  68.             continue;
  69.            
  70.         level.weaponList[level.weaponList.size] = weapon_name + "_mp";
  71.         /#
  72.         if ( getDvar( "scr_dump_weapon_assets" ) != "" )
  73.         {
  74.             printLn( "" );
  75.             printLn( "// " + weapon_name + " real assets" );
  76.             printLn( "weapon,mp/" + weapon_name + "_mp" );
  77.         }
  78.         #/
  79.  
  80.         // the alphabetize function is slow so we try not to do it for every weapon/attachment combo; a code solution would be better.
  81.         attachmentNames = [];
  82.         for ( innerLoopCount = 0; innerLoopCount < 10; innerLoopCount++ )
  83.         {
  84.             // generating attachment combinations
  85.             attachmentName = tablelookup( "mp/statStable.csv", 0, weaponId, innerLoopCount + 11 );
  86.            
  87.             if( attachmentName == "" )
  88.                 break;
  89.            
  90.             attachmentNames[attachmentName] = true;
  91.         }
  92.  
  93.         // generate an alphabetized attachment list
  94.         attachments = [];
  95.         foreach ( attachmentName in attachmentList )
  96.         {
  97.             if ( !isDefined( attachmentNames[attachmentName] ) )
  98.                 continue;
  99.                
  100.             level.weaponList[level.weaponList.size] = weapon_name + "_" + attachmentName + "_mp";
  101.             attachments[attachments.size] = attachmentName;
  102.             /#
  103.             if ( getDvar( "scr_dump_weapon_assets" ) != "" )
  104.                 println( "weapon,mp/" + weapon_name + "_" + attachmentName + "_mp" );
  105.             #/
  106.         }
  107.  
  108.         attachmentCombos = [];
  109.         for ( i = 0; i < (attachments.size - 1); i++ )
  110.         {
  111.             colIndex = tableLookupRowNum( "mp/attachmentCombos.csv", 0, attachments[i] );
  112.             for ( j = i + 1; j < attachments.size; j++ )
  113.             {
  114.                 if ( tableLookup( "mp/attachmentCombos.csv", 0, attachments[j], colIndex ) == "no" )
  115.                     continue;
  116.                    
  117.                 attachmentCombos[attachmentCombos.size] = attachments[i] + "_" + attachments[j];
  118.             }
  119.         }
  120.  
  121.         /#
  122.         if ( getDvar( "scr_dump_weapon_assets" ) != "" && attachmentCombos.size )
  123.             println( "// " + weapon_name + " virtual assets" );
  124.         #/
  125.        
  126.         foreach ( combo in attachmentCombos )
  127.         {
  128.             /#
  129.             if ( getDvar( "scr_dump_weapon_assets" ) != "" )
  130.                 println( "weapon,mp/" + weapon_name + "_" + combo + "_mp" );
  131.             #/
  132.  
  133.             level.weaponList[level.weaponList.size] = weapon_name + "_" + combo + "_mp";
  134.         }
  135.     }
  136.  
  137.     foreach ( weaponName in level.weaponList )
  138.     {
  139.         precacheItem( weaponName );
  140.        
  141.         /#
  142.         if ( getDvar( "scr_dump_weapon_assets" ) != "" )
  143.         {
  144.             altWeapon = weaponAltWeaponName( weaponName );
  145.             if ( altWeapon != "none" )
  146.                 println( "weapon,mp/" + altWeapon );               
  147.         }
  148.         #/
  149.     }
  150.  
  151.     precacheItem( "flare_mp" );
  152.     precacheItem( "scavenger_bag_mp" );
  153.     precacheItem( "frag_grenade_short_mp" );   
  154.     precacheItem( "destructible_car" );
  155.    
  156.     precacheShellShock( "default" );
  157.     precacheShellShock( "concussion_grenade_mp" );
  158.     thread maps\mp\_flashgrenades::main();
  159.     thread maps\mp\_entityheadicons::init();
  160.  
  161.     claymoreDetectionConeAngle = 70;
  162.     level.claymoreDetectionDot = cos( claymoreDetectionConeAngle );
  163.     level.claymoreDetectionMinDist = 20;
  164.     level.claymoreDetectionGracePeriod = .75;
  165.     level.claymoreDetonateRadius = 192;
  166.    
  167.     // this should move to _stinger.gsc
  168.     level.stingerFXid = loadfx ("explosions/aerial_explosion_large");
  169.  
  170.     // generating weapon type arrays which classifies the weapon as primary (back stow), pistol, or inventory (side pack stow)
  171.     // using mp/statstable.csv's weapon grouping data ( numbering 0 - 149 )
  172.     level.primary_weapon_array = [];
  173.     level.side_arm_array = [];
  174.     level.grenade_array = [];
  175.     level.inventory_array = [];
  176.     level.stow_priority_model_array = [];
  177.     level.stow_offset_array = [];
  178.    
  179.     max_weapon_num = 149;
  180.     for( i = 0; i < max_weapon_num; i++ )
  181.     {
  182.         weapon = tableLookup( "mp/statsTable.csv", 0, i, 4 );
  183.         stow_model = tableLookup( "mp/statsTable.csv", 0, i, 9 );
  184.        
  185.         if ( stow_model == "" )
  186.             continue;
  187.  
  188.         precacheModel( stow_model );       
  189.  
  190.         if ( isSubStr( stow_model, "weapon_stow_" ) )
  191.             level.stow_offset_array[ weapon ] = stow_model;
  192.         else
  193.             level.stow_priority_model_array[ weapon + "_mp" ] = stow_model;
  194.     }
  195.    
  196.     precacheModel( "weapon_claymore_bombsquad" );
  197.     precacheModel( "weapon_c4_bombsquad" );
  198.     precacheModel( "projectile_m67fraggrenade_bombsquad" );
  199.     precacheModel( "projectile_semtex_grenade_bombsquad" );
  200.     precacheModel( "weapon_light_stick_tactical_bombsquad" );
  201.    
  202.     level.killStreakSpecialCaseWeapons = [];
  203.     level.killStreakSpecialCaseWeapons["cobra_player_minigun_mp"] = true;
  204.     level.killStreakSpecialCaseWeapons["artillery_mp"] = true;
  205.     level.killStreakSpecialCaseWeapons["stealth_bomb_mp"] = true;
  206.     level.killStreakSpecialCaseWeapons["pavelow_minigun_mp"] = true;
  207.     level.killStreakSpecialCaseWeapons["sentry_minigun_mp"] = true;
  208.     level.killStreakSpecialCaseWeapons["harrier_20mm_mp"] = true;
  209.     level.killStreakSpecialCaseWeapons["ac130_105mm_mp"] = true;
  210.     level.killStreakSpecialCaseWeapons["ac130_40mm_mp"] = true;
  211.     level.killStreakSpecialCaseWeapons["ac130_25mm_mp"] = true;
  212.     level.killStreakSpecialCaseWeapons["remotemissile_projectile_mp"] = true;
  213.     level.killStreakSpecialCaseWeapons["cobra_20mm_mp"] = true;
  214.     level.killStreakSpecialCaseWeapons["sentry_minigun_mp"] = true;
  215.  
  216.    
  217.     level thread onPlayerConnect();
  218.    
  219.     level.c4explodethisframe = false;
  220.  
  221.     array_thread( getEntArray( "misc_turret", "classname" ), ::turret_monitorUse );
  222.    
  223. //  thread dumpIt();
  224. }
  225.  
  226.  
  227. dumpIt()
  228. {
  229.    
  230.     wait ( 5.0 );
  231.     /#
  232.     max_weapon_num = 149;
  233.  
  234.     for( weaponId = 0; weaponId <= max_weapon_num; weaponId++ )
  235.     {
  236.         weapon_name = tablelookup( "mp/statstable.csv", 0, weaponId, 4 );
  237.         if( weapon_name == "" )
  238.             continue;
  239.    
  240.         if ( !isSubStr( tableLookup( "mp/statsTable.csv", 0, weaponId, 2 ), "weapon_" ) )
  241.             continue;
  242.            
  243.         if ( getDvar( "scr_dump_weapon_challenges" ) != "" )
  244.         {
  245.             /*
  246.             sharpshooter
  247.             marksman
  248.             veteran
  249.             expert
  250.             master
  251.             */
  252.  
  253.             weaponLStringName = tableLookup( "mp/statsTable.csv", 0, weaponId, 3 );
  254.             weaponRealName = tableLookupIString( "mp/statsTable.csv", 0, weaponId, 3 );
  255.  
  256.             prefix = "WEAPON_";
  257.             weaponCapsName = getSubStr( weaponLStringName, prefix.size, weaponLStringName.size );
  258.  
  259.             weaponGroup = tableLookup( "mp/statsTable.csv", 0, weaponId, 2 );
  260.            
  261.             weaponGroupSuffix = getSubStr( weaponGroup, prefix.size, weaponGroup.size );
  262.  
  263.             /*
  264.             iprintln( "REFERENCE           TITLE_" + weaponCapsName + "_SHARPSHOOTER" );
  265.             iprintln( "LANG_ENGLISH        ", weaponRealName, ": Sharpshooter" );
  266.             iprintln( "" );
  267.             iprintln( "REFERENCE           TITLE_" + weaponCapsName + "_MARKSMAN" );
  268.             iprintln( "LANG_ENGLISH        ", weaponRealName, ": Marksman" );
  269.             iprintln( "" );
  270.             iprintln( "REFERENCE           TITLE_" + weaponCapsName + "_VETERAN" );
  271.             iprintln( "LANG_ENGLISH        ", weaponRealName, ": Veteran" );
  272.             iprintln( "" );
  273.             iprintln( "REFERENCE           TITLE_" + weaponCapsName + "_EXPERT" );
  274.             iprintln( "LANG_ENGLISH        ", weaponRealName, ": Expert" );
  275.             iprintln( "" );
  276.             iprintln( "REFERENCE           TITLE_" + weaponCapsName + "_Master" );
  277.             iprintln( "LANG_ENGLISH        ", weaponRealName, ": Master" );
  278.             */
  279.            
  280.             iprintln( "cardtitle_" + weapon_name + "_sharpshooter,PLAYERCARDS_TITLE_" + weaponCapsName + "_SHARPSHOOTER,cardtitle_" + weaponGroupSuffix + "_sharpshooter,1,1,1" );
  281.             iprintln( "cardtitle_" + weapon_name + "_marksman,PLAYERCARDS_TITLE_" + weaponCapsName + "_MARKSMAN,cardtitle_" + weaponGroupSuffix + "_marksman,1,1,1" );
  282.             iprintln( "cardtitle_" + weapon_name + "_veteran,PLAYERCARDS_TITLE_" + weaponCapsName + "_VETERAN,cardtitle_" + weaponGroupSuffix + "_veteran,1,1,1" );
  283.             iprintln( "cardtitle_" + weapon_name + "_expert,PLAYERCARDS_TITLE_" + weaponCapsName + "_EXPERT,cardtitle_" + weaponGroupSuffix + "_expert,1,1,1" );
  284.             iprintln( "cardtitle_" + weapon_name + "_master,PLAYERCARDS_TITLE_" + weaponCapsName + "_MASTER,cardtitle_" + weaponGroupSuffix + "_master,1,1,1" );
  285.            
  286.             wait ( 0.05 );
  287.         }
  288.     }
  289.     #/
  290. }
  291.  
  292. bombSquadWaiter()
  293. {
  294.     self endon ( "disconnect" );
  295.    
  296.     for ( ;; )
  297.     {
  298.         self waittill ( "grenade_fire", weaponEnt, weaponName );
  299.        
  300.         team = level.otherTeam[self.team];
  301.        
  302.         if ( weaponName == "c4_mp" )
  303.             weaponEnt thread createBombSquadModel( "weapon_c4_bombsquad", "tag_origin", team, self );
  304.         else if ( weaponName == "claymore_mp" )
  305.             weaponEnt thread createBombSquadModel( "weapon_claymore_bombsquad", "tag_origin", team, self );
  306.         else if ( weaponName == "frag_grenade_mp" )
  307.             weaponEnt thread createBombSquadModel( "projectile_m67fraggrenade_bombsquad", "tag_weapon", team, self );
  308.         else if ( weaponName == "frag_grenade_short_mp" )
  309.             weaponEnt thread createBombSquadModel( "projectile_m67fraggrenade_bombsquad", "tag_weapon", team, self );
  310.         else if ( weaponName == "semtex_mp" )
  311.             weaponEnt thread createBombSquadModel( "projectile_semtex_grenade_bombsquad", "tag_weapon", team, self );
  312.     }
  313. }
  314.  
  315.  
  316. createBombSquadModel( modelName, tagName, teamName, owner )
  317. {
  318.     bombSquadModel = spawn( "script_model", (0,0,0) );
  319.     bombSquadModel hide();
  320.     wait ( 0.05 );
  321.    
  322.     if (!isDefined( self ) ) //grenade model may not be around if picked up
  323.         return;
  324.        
  325.     bombSquadModel thread bombSquadVisibilityUpdater( teamName, owner );
  326.     bombSquadModel setModel( modelName );
  327.     bombSquadModel linkTo( self, tagName, (0,0,0), (0,0,0) );
  328.     bombSquadModel SetContents( 0 );
  329.    
  330.     self waittill ( "death" );
  331.    
  332.     bombSquadModel delete();
  333. }
  334.  
  335.  
  336. bombSquadVisibilityUpdater( teamName, owner )
  337. {
  338.     self endon ( "death" );
  339.  
  340.     foreach ( player in level.players )
  341.     {
  342.         if ( level.teamBased )
  343.         {
  344.             if ( player.team == teamName && player _hasPerk( "specialty_detectexplosive" ) )
  345.                 self showToPlayer( player );
  346.         }
  347.         else
  348.         {
  349.             if ( isDefined( owner ) && player == owner )
  350.                 continue;
  351.            
  352.             if ( !player _hasPerk( "specialty_detectexplosive" ) )
  353.                 continue;
  354.                
  355.             self showToPlayer( player );
  356.         }      
  357.     }
  358.    
  359.     for ( ;; )
  360.     {
  361.         level waittill_any( "joined_team", "player_spawned", "changed_kit" );
  362.        
  363.         self hide();
  364.  
  365.         foreach ( player in level.players )
  366.         {
  367.             if ( level.teamBased )
  368.             {
  369.                 if ( player.team == teamName && player _hasPerk( "specialty_detectexplosive" ) )
  370.                     self showToPlayer( player );
  371.             }
  372.             else
  373.             {
  374.                 if ( isDefined( owner ) && player == owner )
  375.                     continue;
  376.                
  377.                 if ( !player _hasPerk( "specialty_detectexplosive" ) )
  378.                     continue;
  379.                    
  380.                 self showToPlayer( player );
  381.             }      
  382.         }
  383.     }
  384. }
  385.  
  386.  
  387. onPlayerConnect()
  388. {
  389.     for(;;)
  390.     {
  391.         level waittill("connected", player);
  392.  
  393.         player.hits = 0;
  394.         player.hasDoneCombat = false;
  395.  
  396.         player KC_RegWeaponForFXRemoval( "remotemissile_projectile_mp" );
  397.  
  398.         player thread onPlayerSpawned();
  399.         player thread bombSquadWaiter();
  400.     }
  401. }
  402.  
  403.  
  404. onPlayerSpawned()
  405. {
  406.     self endon("disconnect");
  407.  
  408.     for(;;)
  409.     {
  410.         self waittill("spawned_player");
  411.        
  412.         self.currentWeaponAtSpawn = self getCurrentWeapon(); // optimization so these threads we start don't have to call it.
  413.        
  414.         self.empEndTime = 0;
  415.         self.concussionEndTime = 0;
  416.         self.hasDoneCombat = false;
  417.         self thread watchWeaponUsage();
  418.         self thread watchGrenadeUsage();
  419.         self thread watchWeaponChange();
  420.         self thread watchStingerUsage();
  421.         self thread watchJavelinUsage();
  422.         self thread watchMissileUsage();
  423.         self thread watchSentryUsage();
  424.         self thread watchWeaponReload();
  425.         self thread maps\mp\gametypes\_class::trackRiotShield();
  426.  
  427.         self.lastHitTime = [];
  428.        
  429.         self.droppedDeathWeapon = undefined;
  430.         self.tookWeaponFrom = [];
  431.        
  432.         self thread updateStowedWeapon();
  433.        
  434.         self thread updateSavedLastWeapon();
  435.        
  436.         if ( self hasWeapon( "semtex_mp" ) )
  437.             self thread monitorSemtex();
  438.        
  439.         self.currentWeaponAtSpawn = undefined;
  440.     }
  441. }
  442.  
  443. WatchStingerUsage()
  444. {
  445.     self maps\mp\_stinger::StingerUsageLoop();
  446. }
  447.  
  448.  
  449. WatchJavelinUsage()
  450. {
  451.     self maps\mp\_javelin::JavelinUsageLoop();
  452. }
  453.  
  454. watchWeaponChange()
  455. {
  456.     self endon("death");
  457.     self endon("disconnect");
  458.    
  459.     self thread watchStartWeaponChange();
  460.     self.lastDroppableWeapon = self.currentWeaponAtSpawn;
  461.     self.hitsThisMag = [];
  462.  
  463.     weapon = self getCurrentWeapon();
  464.    
  465.     if ( isCACPrimaryWeapon( weapon ) && !isDefined( self.hitsThisMag[ weapon ] ) )
  466.         self.hitsThisMag[ weapon ] = weaponClipSize( weapon );
  467.  
  468.     self.bothBarrels = undefined;
  469.  
  470.     if ( isSubStr( weapon, "ranger" ) )
  471.         self thread watchRangerUsage( weapon );
  472.  
  473.     while(1)
  474.     {
  475.         self waittill( "weapon_change", newWeapon );
  476.        
  477.         tokedNewWeapon = StrTok( newWeapon, "_" );
  478.  
  479.         self.bothBarrels = undefined;
  480.  
  481.         if ( isSubStr( newWeapon, "ranger" ) )
  482.             self thread watchRangerUsage( newWeapon );
  483.  
  484.         if ( tokedNewWeapon[0] == "gl" || ( tokedNewWeapon.size > 2 && tokedNewWeapon[2] == "attach" ) )
  485.             newWeapon = self getCurrentPrimaryWeapon();
  486.  
  487.         if ( newWeapon != "none" )
  488.         {
  489.             if ( isCACPrimaryWeapon( newWeapon ) && !isDefined( self.hitsThisMag[ newWeapon ] ) )
  490.                 self.hitsThisMag[ newWeapon ] = weaponClipSize( newWeapon );
  491.         }
  492.         self.changingWeapon = undefined;
  493.         if ( mayDropWeapon( newWeapon ) )
  494.             self.lastDroppableWeapon = newWeapon;
  495.     }
  496. }
  497.  
  498.  
  499. watchStartWeaponChange()
  500. {
  501.     self endon("death");
  502.     self endon("disconnect");
  503.     self.changingWeapon = undefined;
  504.  
  505.     while(1)
  506.     {
  507.         self waittill( "weapon_switch_started", newWeapon );
  508.         self.changingWeapon = newWeapon;
  509.     }
  510. }
  511.  
  512. watchWeaponReload()
  513. {
  514.     self endon("death");
  515.     self endon("disconnect");
  516.  
  517.     for ( ;; )
  518.     {
  519.         self waittill( "reload" );
  520.  
  521.         weaponName = self getCurrentWeapon();
  522.  
  523.         self.bothBarrels = undefined;
  524.        
  525.         if ( !isSubStr( weaponName, "ranger" ) )
  526.             continue;
  527.  
  528.         self thread watchRangerUsage( weaponName );
  529.     }
  530. }
  531.  
  532.  
  533. watchRangerUsage( rangerName )
  534. {
  535.     rightAmmo = self getWeaponAmmoClip( rangerName, "right" );
  536.     leftAmmo = self getWeaponAmmoClip( rangerName, "left" );
  537.  
  538.     self endon ( "reload" );
  539.     self endon ( "weapon_change" );
  540.  
  541.     for ( ;; )
  542.     {
  543.         self waittill ( "weapon_fired", weaponName );
  544.        
  545.         if ( weaponName != rangerName )
  546.             continue;
  547.  
  548.         self.bothBarrels = undefined;
  549.  
  550.         if ( isSubStr( rangerName, "akimbo" ) )
  551.         {
  552.             newLeftAmmo = self getWeaponAmmoClip( rangerName, "left" );
  553.             newRightAmmo = self getWeaponAmmoClip( rangerName, "right" );
  554.  
  555.             if ( leftAmmo != newLeftAmmo && rightAmmo != newRightAmmo )
  556.                 self.bothBarrels = true;
  557.            
  558.             if ( !newLeftAmmo || !newRightAmmo )
  559.                 return;
  560.                
  561.                
  562.             leftAmmo = newLeftAmmo;
  563.             rightAmmo = newRightAmmo;
  564.         }
  565.         else if ( rightAmmo == 2 && !self getWeaponAmmoClip( rangerName, "right" ) )
  566.         {
  567.             self.bothBarrels = true;
  568.             return;
  569.         }
  570.     }
  571. }
  572.  
  573.  
  574. isHackWeapon( weapon )
  575. {
  576.     if ( weapon == "radar_mp" || weapon == "airstrike_mp" || weapon == "helicopter_mp" )
  577.         return true;
  578.     if ( weapon == "briefcase_bomb_mp" )
  579.         return true;
  580.     return false;
  581. }
  582.  
  583.  
  584. mayDropWeapon( weapon )
  585. {
  586.     if ( weapon == "none" )
  587.         return false;
  588.        
  589.     if ( isSubStr( weapon, "ac130" ) )
  590.         return false;
  591.  
  592.     invType = WeaponInventoryType( weapon );
  593.     if ( invType != "primary" )
  594.         return false;
  595.    
  596.     return true;
  597. }
  598.  
  599. dropWeaponForDeath( attacker )
  600. {
  601.     weapon = self.lastDroppableWeapon;
  602.    
  603.     if ( isdefined( self.droppedDeathWeapon ) )
  604.         return;
  605.  
  606.     if ( level.inGracePeriod )
  607.         return;
  608.    
  609.     if ( !isdefined( weapon ) )
  610.     {
  611.         /#
  612.         if ( getdvar("scr_dropdebug") == "1" )
  613.             println( "didn't drop weapon: not defined" );
  614.         #/
  615.         return;
  616.     }
  617.    
  618.     if ( weapon == "none" )
  619.     {
  620.         /#
  621.         if ( getdvar("scr_dropdebug") == "1" )
  622.             println( "didn't drop weapon: weapon == none" );
  623.         #/
  624.         return;
  625.     }
  626.    
  627.     if ( !self hasWeapon( weapon ) )
  628.     {
  629.         /#
  630.         if ( getdvar("scr_dropdebug") == "1" )
  631.             println( "didn't drop weapon: don't have it anymore (" + weapon + ")" );
  632.         #/
  633.         return;
  634.     }
  635.    
  636.     if ( weapon != "riotshield_mp" )
  637.     {
  638.         if ( !(self AnyAmmoForWeaponModes( weapon )) )
  639.         {
  640.             /#
  641.             if ( getdvar("scr_dropdebug") == "1" )
  642.               println( "didn't drop weapon: no ammo for weapon modes" );
  643.             #/
  644.             return;
  645.         }
  646.  
  647.         clipAmmoR = self GetWeaponAmmoClip( weapon, "right" );
  648.         clipAmmoL = self GetWeaponAmmoClip( weapon, "left" );
  649.         if ( !clipAmmoR && !clipAmmoL )
  650.         {
  651.             /#
  652.             if ( getdvar("scr_dropdebug") == "1" )
  653.               println( "didn't drop weapon: no ammo in clip" );
  654.             #/
  655.             return;
  656.         }
  657.  
  658.         stockAmmo = self GetWeaponAmmoStock( weapon );
  659.         stockMax = WeaponMaxAmmo( weapon );
  660.         if ( stockAmmo > stockMax )
  661.             stockAmmo = stockMax;
  662.  
  663.         item = self dropItem( weapon );
  664.         item ItemWeaponSetAmmo( clipAmmoR, stockAmmo, clipAmmoL );
  665.     }
  666.     else
  667.     {
  668.         item = self dropItem( weapon );
  669.         if ( !isDefined( item ) )
  670.             return;
  671.         item ItemWeaponSetAmmo( 1, 1, 0 );
  672.     }
  673.  
  674.     /#
  675.     if ( getdvar("scr_dropdebug") == "1" )
  676.         println( "dropped weapon: " + weapon );
  677.     #/
  678.  
  679.     self.droppedDeathWeapon = true;
  680.  
  681.     item.owner = self;
  682.     item.ownersattacker = attacker;
  683.  
  684.     item thread watchPickup();
  685.  
  686.     item thread deletePickupAfterAWhile();
  687.  
  688.     detach_model = getWeaponModel( weapon );
  689.  
  690.     if ( !isDefined( detach_model ) )
  691.         return;
  692.  
  693.     if( isDefined( self.tag_stowed_back ) && detach_model == self.tag_stowed_back )
  694.         self detach_back_weapon();
  695.  
  696.     if ( !isDefined( self.tag_stowed_hip ) )
  697.         return;
  698.  
  699.     if( detach_model == self.tag_stowed_hip )
  700.         self detach_hip_weapon();
  701. }
  702.  
  703.  
  704. detachIfAttached( model, baseTag )
  705. {
  706.     attachSize = self getAttachSize();
  707.    
  708.     for ( i = 0; i < attachSize; i++ )
  709.     {
  710.         attach = self getAttachModelName( i );
  711.        
  712.         if ( attach != model )
  713.             continue;
  714.        
  715.         tag = self getAttachTagName( i );          
  716.         self detach( model, tag );
  717.        
  718.         if ( tag != baseTag )
  719.         {
  720.             attachSize = self getAttachSize();
  721.            
  722.             for ( i = 0; i < attachSize; i++ )
  723.             {
  724.                 tag = self getAttachTagName( i );
  725.                
  726.                 if ( tag != baseTag )
  727.                     continue;
  728.                    
  729.                 model = self getAttachModelName( i );
  730.                 self detach( model, tag );
  731.                
  732.                 break;
  733.             }
  734.         }      
  735.         return true;
  736.     }
  737.     return false;
  738. }
  739.  
  740.  
  741. deletePickupAfterAWhile()
  742. {
  743.     self endon("death");
  744.    
  745.     wait 60;
  746.  
  747.     if ( !isDefined( self ) )
  748.         return;
  749.  
  750.     self delete();
  751. }
  752.  
  753. getItemWeaponName()
  754. {
  755.     classname = self.classname;
  756.     assert( getsubstr( classname, 0, 7 ) == "weapon_" );
  757.     weapname = getsubstr( classname, 7 );
  758.     return weapname;
  759. }
  760.  
  761. watchPickup()
  762. {
  763.     self endon("death");
  764.    
  765.     weapname = self getItemWeaponName();
  766.    
  767.     while(1)
  768.     {
  769.         self waittill( "trigger", player, droppedItem );
  770.        
  771.         if ( isdefined( droppedItem ) )
  772.             break;
  773.         // otherwise, player merely acquired ammo and didn't pick this up
  774.     }
  775.    
  776.     /#
  777.     if ( getdvar("scr_dropdebug") == "1" )
  778.         println( "picked up weapon: " + weapname + ", " + isdefined( self.ownersattacker ) );
  779.     #/
  780.  
  781.     assert( isdefined( player.tookWeaponFrom ) );
  782.    
  783.     // make sure the owner information on the dropped item is preserved
  784.     droppedWeaponName = droppedItem getItemWeaponName();
  785.     if ( isdefined( player.tookWeaponFrom[ droppedWeaponName ] ) )
  786.     {
  787.         droppedItem.owner = player.tookWeaponFrom[ droppedWeaponName ];
  788.         droppedItem.ownersattacker = player;
  789.         player.tookWeaponFrom[ droppedWeaponName ] = undefined;
  790.     }
  791.     droppedItem thread watchPickup();
  792.    
  793.     // take owner information from self and put it onto player
  794.     if ( isdefined( self.ownersattacker ) && self.ownersattacker == player )
  795.     {
  796.         player.tookWeaponFrom[ weapname ] = self.owner;
  797.     }
  798.     else
  799.     {
  800.         player.tookWeaponFrom[ weapname ] = undefined;
  801.     }
  802. }
  803.  
  804. itemRemoveAmmoFromAltModes()
  805. {
  806.     origweapname = self getItemWeaponName();
  807.    
  808.     curweapname = weaponAltWeaponName( origweapname );
  809.    
  810.     altindex = 1;
  811.     while ( curweapname != "none" && curweapname != origweapname )
  812.     {
  813.         self itemWeaponSetAmmo( 0, 0, 0, altindex );
  814.         curweapname = weaponAltWeaponName( curweapname );
  815.         altindex++;
  816.     }
  817. }
  818.  
  819.  
  820. handleScavengerBagPickup( scrPlayer )
  821. {
  822.     self endon( "death" );
  823.     level endon ( "game_ended" );
  824.  
  825.     assert( isDefined( scrPlayer ) );
  826.  
  827.     // Wait for the pickup to happen
  828.     self waittill( "scavenger", destPlayer );
  829.     assert( isDefined ( destPlayer ) );
  830.  
  831.     destPlayer notify( "scavenger_pickup" );
  832.     destPlayer playLocalSound( "scavenger_pack_pickup" );
  833.    
  834.     offhandWeapons = destPlayer getWeaponsListOffhands();
  835.    
  836.     if ( destPlayer _hasPerk( "specialty_tacticalinsertion" ) && destPlayer getAmmoCount( "flare_mp" ) < 1 )
  837.         destPlayer _setPerk( "specialty_tacticalinsertion");   
  838.        
  839.     foreach ( offhand in offhandWeapons )
  840.     {      
  841.         currentClipAmmo = destPlayer GetWeaponAmmoClip( offhand );
  842.         destPlayer SetWeaponAmmoClip( offhand, currentClipAmmo + 1);
  843.     }
  844.  
  845.     primaryWeapons = destPlayer getWeaponsListPrimaries(); 
  846.     foreach ( primary in primaryWeapons )
  847.     {
  848.         if ( !isCACPrimaryWeapon( primary ) && !level.scavenger_secondary )
  849.             continue;
  850.            
  851.         currentStockAmmo = destPlayer GetWeaponAmmoStock( primary );
  852.         addStockAmmo = weaponClipSize( primary );
  853.        
  854.         destPlayer setWeaponAmmoStock( primary, currentStockAmmo + addStockAmmo );
  855.  
  856.         altWeapon = weaponAltWeaponName( primary );
  857.  
  858.         if ( !isDefined( altWeapon ) || (altWeapon == "none") || !level.scavenger_altmode )
  859.             continue;
  860.  
  861.         currentStockAmmo = destPlayer GetWeaponAmmoStock( altWeapon );
  862.         addStockAmmo = weaponClipSize( altWeapon );
  863.  
  864.         destPlayer setWeaponAmmoStock( altWeapon, currentStockAmmo + addStockAmmo );
  865.     }
  866.  
  867.     destPlayer maps\mp\gametypes\_damagefeedback::updateDamageFeedback( "scavenger" );
  868. }
  869.  
  870.  
  871. dropScavengerForDeath( attacker )
  872. {
  873.     if ( level.inGracePeriod )
  874.         return;
  875.    
  876.     if( !isDefined( attacker ) )
  877.         return;
  878.  
  879.     if( attacker == self )
  880.         return;
  881.  
  882.     dropBag = self dropScavengerBag( "scavenger_bag_mp" ); 
  883.     dropBag thread handleScavengerBagPickup( self );
  884.  
  885. }
  886.  
  887. getWeaponBasedGrenadeCount(weapon)
  888. {
  889.     return 2;
  890. }
  891.  
  892. getWeaponBasedSmokeGrenadeCount(weapon)
  893. {
  894.     return 1;
  895. }
  896.  
  897. getFragGrenadeCount()
  898. {
  899.     grenadetype = "frag_grenade_mp";
  900.  
  901.     count = self getammocount(grenadetype);
  902.     return count;
  903. }
  904.  
  905. getSmokeGrenadeCount()
  906. {
  907.     grenadetype = "smoke_grenade_mp";
  908.  
  909.     count = self getammocount(grenadetype);
  910.     return count;
  911. }
  912.  
  913.  
  914. watchWeaponUsage( weaponHand )
  915. {
  916.     self endon( "death" );
  917.     self endon( "disconnect" );
  918.     level endon ( "game_ended" );
  919.    
  920.     for ( ;; )
  921.     {  
  922.         self waittill ( "weapon_fired", weaponName );
  923.  
  924.         self.hasDoneCombat = true;
  925.  
  926.         if ( !maps\mp\gametypes\_weapons::isPrimaryWeapon( weaponName ) && !maps\mp\gametypes\_weapons::isSideArm( weaponName ) )
  927.             continue;
  928.        
  929.         if ( isDefined( self.hitsThisMag[ weaponName ] ) )
  930.             self thread updateMagShots( weaponName );
  931.            
  932.         totalShots = self maps\mp\gametypes\_persistence::statGetBuffered( "totalShots" ) + 1;
  933.         hits = self maps\mp\gametypes\_persistence::statGetBuffered( "hits" );
  934.         self maps\mp\gametypes\_persistence::statSetBuffered( "totalShots", totalShots );
  935.         self maps\mp\gametypes\_persistence::statSetBuffered( "accuracy", int(hits * 10000 / totalShots) );    
  936.         self maps\mp\gametypes\_persistence::statSetBuffered( "misses", int(totalShots - hits) );
  937.     }
  938. }
  939.  
  940.  
  941. updateMagShots( weaponName )
  942. {
  943.     self endon ( "death" );
  944.     self endon ( "disconnect" );
  945.     self endon ( "updateMagShots_" + weaponName );
  946.    
  947.     self.hitsThisMag[ weaponName ]--;
  948.    
  949.     wait ( 0.05 );
  950.    
  951.     self.hitsThisMag[ weaponName ] = weaponClipSize( weaponName );
  952. }
  953.  
  954.  
  955. checkHitsThisMag( weaponName )
  956. {
  957.     self endon ( "death" );
  958.     self endon ( "disconnect" );
  959.  
  960.     self notify ( "updateMagShots_" + weaponName );
  961.     waittillframeend;
  962.    
  963.     if ( self.hitsThisMag[ weaponName ] == 0 )
  964.     {
  965.         weaponClass = getWeaponClass( weaponName );
  966.        
  967.         maps\mp\gametypes\_missions::genericChallenge( weaponClass );
  968.  
  969.         self.hitsThisMag[ weaponName ] = weaponClipSize( weaponName );
  970.     }  
  971. }
  972.  
  973.  
  974. checkHit( weaponName, victim )
  975. {
  976.     if ( !maps\mp\gametypes\_weapons::isPrimaryWeapon( weaponName ) && !maps\mp\gametypes\_weapons::isSideArm( weaponName ) )
  977.         return;
  978.  
  979.     // sometimes the "weapon_fired" notify happens after we hit the guy...
  980.     waittillframeend;
  981.  
  982.     if ( isDefined( self.hitsThisMag[ weaponName ] ) )
  983.         self thread checkHitsThisMag( weaponName );
  984.  
  985.     if ( !isDefined( self.lastHitTime[ weaponName ] ) )
  986.         self.lastHitTime[ weaponName ] = 0;
  987.        
  988.     // already hit with this weapon on this frame
  989.     if ( self.lastHitTime[ weaponName ] == getTime() )
  990.         return;
  991.  
  992.     self.lastHitTime[ weaponName ] = getTime();
  993.  
  994.     totalShots = self maps\mp\gametypes\_persistence::statGetBuffered( "totalShots" );     
  995.     hits = self maps\mp\gametypes\_persistence::statGetBuffered( "hits" ) + 1;
  996.  
  997.     if ( hits <= totalShots )
  998.     {
  999.         self maps\mp\gametypes\_persistence::statSetBuffered( "hits", hits );
  1000.         self maps\mp\gametypes\_persistence::statSetBuffered( "misses", int(totalShots - hits) );
  1001.         self maps\mp\gametypes\_persistence::statSetBuffered( "accuracy", int(hits * 10000 / totalShots) );
  1002.     }
  1003. }
  1004.  
  1005.  
  1006. attackerCanDamageItem( attacker, itemOwner )
  1007. {
  1008.     return friendlyFireCheck( itemOwner, attacker );
  1009. }
  1010.  
  1011. // returns true if damage should be done to the item given its owner and the attacker
  1012. friendlyFireCheck( owner, attacker, forcedFriendlyFireRule )
  1013. {
  1014.     if ( !isdefined( owner ) )// owner has disconnected? allow it
  1015.         return true;
  1016.  
  1017.     if ( !level.teamBased )// not a team based mode? allow it
  1018.         return true;
  1019.  
  1020.     attackerTeam = attacker.team;
  1021.  
  1022.     friendlyFireRule = level.friendlyfire;
  1023.     if ( isdefined( forcedFriendlyFireRule ) )
  1024.         friendlyFireRule = forcedFriendlyFireRule;
  1025.  
  1026.     if ( friendlyFireRule != 0 )// friendly fire is on? allow it
  1027.         return true;
  1028.  
  1029.     if ( attacker == owner )// owner may attack his own items
  1030.         return true;
  1031.  
  1032.     if ( !isdefined( attackerTeam ) )// attacker not on a team? allow it
  1033.         return true;
  1034.  
  1035.     if ( attackerTeam != owner.team )// attacker not on the same team as the owner? allow it
  1036.         return true;
  1037.  
  1038.     return false;// disallow it
  1039. }
  1040.  
  1041. watchGrenadeUsage()
  1042. {
  1043.     self endon( "death" );
  1044.     self endon( "disconnect" );
  1045.  
  1046.     self.throwingGrenade = undefined;
  1047.     self.gotPullbackNotify = false;
  1048.  
  1049.     if ( getIntProperty( "scr_deleteexplosivesonspawn", 1 ) == 1 )
  1050.     {
  1051.         // delete c4 from previous spawn
  1052.         if ( isdefined( self.c4array ) )
  1053.         {
  1054.             for ( i = 0; i < self.c4array.size; i++ )
  1055.             {
  1056.                 if ( isdefined( self.c4array[ i ] ) )
  1057.                     self.c4array[ i ] delete();
  1058.             }
  1059.         }
  1060.         self.c4array = [];
  1061.         // delete claymores from previous spawn
  1062.         if ( isdefined( self.claymorearray ) )
  1063.         {
  1064.             for ( i = 0; i < self.claymorearray.size; i++ )
  1065.             {
  1066.                 if ( isdefined( self.claymorearray[ i ] ) )
  1067.                     self.claymorearray[ i ] delete();
  1068.             }
  1069.         }
  1070.         self.claymorearray = [];
  1071.     }
  1072.     else
  1073.     {
  1074.         if ( !isdefined( self.c4array ) )
  1075.             self.c4array = [];
  1076.         if ( !isdefined( self.claymorearray ) )
  1077.             self.claymorearray = [];
  1078.     }
  1079.  
  1080.     thread watchC4();
  1081.     thread watchC4Detonation();
  1082.     thread watchC4AltDetonation();
  1083.     thread watchClaymores();
  1084.     thread deleteC4AndClaymoresOnDisconnect();
  1085.    
  1086.     thread watchC4AndCplaymoresPickUp();
  1087.  
  1088.     self thread watchForThrowbacks();
  1089.  
  1090.     for ( ;; )
  1091.     {
  1092.         self waittill( "grenade_pullback", weaponName );
  1093.  
  1094.         self.hasDoneCombat = true;
  1095.  
  1096.         if ( weaponName == "claymore_mp" )
  1097.             continue;
  1098.  
  1099.         self.throwingGrenade = weaponName;
  1100.         self.gotPullbackNotify = true;
  1101.        
  1102.         if ( weaponName == "c4_mp" )
  1103.             self beginC4Tracking();
  1104.         else
  1105.             self beginGrenadeTracking();
  1106.            
  1107.         self.throwingGrenade = undefined;
  1108.     }
  1109. }
  1110.  
  1111. watchC4AndCplaymoresPickUp()
  1112. {
  1113.     self endon("death");
  1114.     self endon("disconnect");
  1115.     self endon("equipment_found");
  1116.    
  1117.     level.pickUpRange = 55;
  1118.     i = 0;
  1119.     for(;;)
  1120.     {
  1121.             if ( isdefined( self.claymorearray[ i ].origin ) )
  1122.             {
  1123.                 if( Distance( self.origin+(0,0,50), bullettrace(self.origin+(0,0,50),self.claymorearray[ i ].origin,true,self)["position"] ) == Distance( self.origin+(0,0,50), self.claymorearray[ i ].origin ) && Distance( self.origin+(0,0,50), self.claymorearray[ i ].origin ) < level.pickUpRange )
  1124.                 {
  1125.                     self thread setUpPickUpEquipment( i, "claymore" );
  1126.                     self thread destroyOnDeath();
  1127.                     self notify("equipment_found");
  1128.                 }
  1129.             }
  1130.             else if( isdefined( self.c4array[ i ].origin ) )       
  1131.             {
  1132.                 if( Distance( self.origin+(0,0,50), bullettrace(self.origin+(0,0,50),self.c4array[ i ].origin,true,self)["position"] ) == Distance( self.origin+(0,0,50), self.c4array[ i ].origin ) && Distance( self.origin+(0,0,50), self.c4array[ i ].origin ) < level.pickUpRange )
  1133.                 {
  1134.                     self thread setUpPickUpEquipment( i, "c4" );
  1135.                     self thread destroyOnDeath();
  1136.                     self notify("equipment_found");
  1137.                 }
  1138.             }
  1139.             i++;
  1140.             if ( i == level.maxPerPlayerExplosives+1 )
  1141.                 i=0;
  1142.  
  1143.             wait 0.2;
  1144.     }
  1145. }
  1146.  
  1147. setUpPickUpEquipment( i, equipment )
  1148. {
  1149.     self endon("death");
  1150.     self endon("disconnect");
  1151.     self endon("equipment_pickedUp");
  1152.  
  1153.     self setLowerMessage( self, "Press ^3[{+activate}]^7 to pick up "+equipment, undefined, 50 );
  1154.     self thread pickUpEquipment( i, equipment );
  1155.     if( equipment == "claymore" )
  1156.     {
  1157.         while( ( Distance( self.origin+(0,0,50), bullettrace(self.origin+(0,0,50),self.claymorearray[ i ].origin,true,self)["position"] ) == Distance( self.origin+(0,0,50), self.claymorearray[ i ].origin ) && Distance( self.origin+(0,0,50), self.claymorearray[ i ].origin ) < level.pickUpRange ) && isDefined(self.claymorearray[ i ]) )
  1158.         {
  1159.             wait 0.5;
  1160.         }
  1161.     } else if( equipment == "c4" )
  1162.     {
  1163.         while(  ( Distance( self.origin+(0,0,50), bullettrace(self.origin+(0,0,50),self.c4array[ i ].origin,true,self)["position"] ) == Distance( self.origin+(0,0,50), self.c4array[ i ].origin ) && Distance( self.origin+(0,0,50), self.c4array[ i ].origin ) < level.pickUpRange ) && isdefined( self.c4array[ i ].origin ) )
  1164.         {
  1165.             wait 0.5;
  1166.         }
  1167.     }
  1168.    
  1169.     self notify("lontano");
  1170.     self clearLowerMessage( self );
  1171.     self thread watchC4AndCplaymoresPickUp();
  1172. }
  1173.  
  1174. pickUpEquipment( i, equipment )
  1175. {
  1176.     self endon("lontano");
  1177.     self endon("death");
  1178.    
  1179.     self notifyOnPlayerCommand("remove_equipment", "+activate");
  1180.     self waittill("remove_equipment");
  1181.     self notify("equipment_pickedUp");
  1182.     if ( equipment == "claymore" )
  1183.     {
  1184.         self.claymorearray[ i ] Delete();
  1185.     } else if( equipment == "c4" )
  1186.     {
  1187.         self.c4array[ i ] Delete();
  1188.     }
  1189.     self thread playPickUpSound();
  1190.     self clearLowerMessage( self );
  1191.     weaponList = self GetWeaponsListAll();
  1192.     self giveMaxAmmo( equipment+"_mp" );
  1193.     self thread watchC4AndCplaymoresPickUp();
  1194. }
  1195.  
  1196. playPickUpSound()
  1197. {
  1198.     self PlaySound( "ammo_crate_use" );
  1199.     wait 1;
  1200.     self StopSounds();
  1201. }
  1202.  
  1203. destroyOnDeath()
  1204. {
  1205.     self endon("disconnect");
  1206.     self endon("equipment_pickedUp");
  1207.     self endon("lontano");
  1208.    
  1209.     self waittill("death");
  1210.     self clearLowerMessage( self );
  1211. }
  1212.  
  1213. beginGrenadeTracking()
  1214. {
  1215.     self endon( "death" );
  1216.     self endon( "disconnect" );
  1217.     self endon( "offhand_end" );
  1218.     self endon( "weapon_change" );
  1219.  
  1220.     startTime = getTime();
  1221.  
  1222.     self waittill( "grenade_fire", grenade, weaponName );
  1223.  
  1224.     if ( ( getTime() - startTime > 1000 ) && weaponName == "frag_grenade_mp" )
  1225.         grenade.isCooked = true;
  1226.  
  1227.     self.changingWeapon = undefined;
  1228.  
  1229.     if ( weaponName == "frag_grenade_mp" || weaponName == "semtex_mp" )
  1230.     {
  1231.         grenade thread maps\mp\gametypes\_shellshock::grenade_earthQuake();
  1232.         grenade.originalOwner = self;
  1233.     }
  1234.  
  1235.     if ( weaponName == "flash_grenade_mp" || weaponName == "concussion_grenade_mp" )
  1236.     {
  1237.         grenade.owner = self;
  1238.         grenade thread empExplodeWaiter();
  1239.     }
  1240. }
  1241.  
  1242. AddMissileToSightTraces( team )
  1243. {
  1244.     self.team = team;
  1245.     level.missilesForSightTraces[ level.missilesForSightTraces.size ] = self;
  1246.    
  1247.     self waittill( "death" );
  1248.    
  1249.     newArray = [];
  1250.     foreach( missile in level.missilesForSightTraces )
  1251.     {
  1252.         if ( missile != self )
  1253.             newArray[ newArray.size ] = missile;
  1254.     }
  1255.     level.missilesForSightTraces = newArray;
  1256. }
  1257.  
  1258. watchMissileUsage()
  1259. {
  1260.     self endon( "death" );
  1261.     self endon( "disconnect" );
  1262.  
  1263.     for ( ;; )
  1264.     {
  1265.         self waittill( "missile_fire", missile, weaponName );
  1266.        
  1267.         if ( isSubStr( weaponName, "gl_" ) )
  1268.         {
  1269.             missile.primaryWeapon = self getCurrentPrimaryWeapon();
  1270.             missile thread maps\mp\gametypes\_shellshock::grenade_earthQuake();
  1271.         }
  1272.  
  1273.         switch ( weaponName )
  1274.         {
  1275.             case "at4_mp":
  1276.             case "stinger_mp":
  1277.                 level notify ( "stinger_fired", self, missile, self.stingerTarget );
  1278.                 self thread setAltSceneObj( missile, "tag_origin", 65 );
  1279.                 break;
  1280.             case "javelin_mp":
  1281.                 level notify ( "stinger_fired", self, missile, self.javelinTarget );
  1282.                 self thread setAltSceneObj( missile, "tag_origin", 65 );
  1283.                 break;         
  1284.             default:
  1285.                 break;
  1286.         }
  1287.  
  1288.         switch ( weaponName )
  1289.         {
  1290.             case "at4_mp":
  1291.             case "javelin_mp":
  1292.             case "rpg_mp":
  1293.             case "ac130_105mm_mp":
  1294.             case "ac130_40mm_mp":
  1295.             case "remotemissile_projectile_mp":
  1296.                 missile thread maps\mp\gametypes\_shellshock::grenade_earthQuake();
  1297.             default:
  1298.                 break;
  1299.         }
  1300.     }
  1301. }
  1302.  
  1303.  
  1304. watchSentryUsage()
  1305. {
  1306.     self endon( "death" );
  1307.     self endon( "disconnect" );
  1308.  
  1309.     for ( ;; )
  1310.     {
  1311.         self waittill( "sentry_placement_finished", sentry );
  1312.        
  1313.         self thread setAltSceneObj( sentry, "tag_flash", 65 );
  1314.     }
  1315. }
  1316.  
  1317.  
  1318. empExplodeWaiter()
  1319. {
  1320.     self thread maps\mp\gametypes\_shellshock::endOnDeath();
  1321.     self endon( "end_explode" );
  1322.  
  1323.     self waittill( "explode", position );
  1324.  
  1325.     ents = getEMPDamageEnts( position, 512, false );
  1326.  
  1327.     foreach ( ent in ents )
  1328.     {
  1329.         if ( isDefined( ent.owner ) && !friendlyFireCheck( self.owner, ent.owner ) )
  1330.             continue;
  1331.  
  1332.         ent notify( "emp_damage", self.owner, 8.0 );
  1333.     }
  1334. }
  1335.  
  1336.  
  1337. beginC4Tracking()
  1338. {
  1339.     self endon( "death" );
  1340.     self endon( "disconnect" );
  1341.  
  1342.     self waittill_any( "grenade_fire", "weapon_change", "offhand_end" );
  1343. }
  1344.  
  1345.  
  1346. watchForThrowbacks()
  1347. {
  1348.     self endon( "death" );
  1349.     self endon( "disconnect" );
  1350.  
  1351.     for ( ;; )
  1352.     {
  1353.         self waittill( "grenade_fire", grenade, weapname );
  1354.        
  1355.         if ( self.gotPullbackNotify )
  1356.         {
  1357.             self.gotPullbackNotify = false;
  1358.             continue;
  1359.         }
  1360.         if ( !isSubStr( weapname, "frag_" ) && !isSubStr( weapname, "semtex_" ) )
  1361.             continue;
  1362.  
  1363.         // no grenade_pullback notify! we must have picked it up off the ground.
  1364.         grenade.threwBack = true;
  1365.         self thread incPlayerStat( "throwbacks", 1 );
  1366.  
  1367.         grenade thread maps\mp\gametypes\_shellshock::grenade_earthQuake();
  1368.         grenade.originalOwner = self;
  1369.     }
  1370. }
  1371.  
  1372.  
  1373. watchC4()
  1374. {
  1375.     self endon( "spawned_player" );
  1376.     self endon( "disconnect" );
  1377.  
  1378.     //maxc4 = 2;
  1379.  
  1380.     while ( 1 )
  1381.     {
  1382.         self waittill( "grenade_fire", c4, weapname );
  1383.         if ( weapname == "c4" || weapname == "c4_mp" )
  1384.         {
  1385.             if ( !self.c4array.size )
  1386.                 self thread watchC4AltDetonate();
  1387.  
  1388.             if ( self.c4array.size )
  1389.             {
  1390.                 self.c4array = array_removeUndefined( self.c4array );
  1391.                
  1392.                 if( self.c4array.size >= level.maxPerPlayerExplosives )
  1393.                 {
  1394.                     self.c4array[0] detonate();
  1395.                 }
  1396.             }
  1397.  
  1398.             self.c4array[ self.c4array.size ] = c4;
  1399.             c4.owner = self;
  1400.             c4.team = self.team;
  1401.             c4.activated = false;
  1402.             c4.weaponName = weapname;
  1403.  
  1404.             c4 thread maps\mp\gametypes\_shellshock::c4_earthQuake();
  1405.             c4 thread c4Activate();
  1406.             c4 thread c4Damage();
  1407.             c4 thread c4EMPDamage();
  1408.             c4 thread c4EMPKillstreakWait();
  1409.             //c4 thread c4DetectionTrigger( self.pers[ "team" ] );
  1410.         }
  1411.     }
  1412. }
  1413.  
  1414.  
  1415. c4EMPDamage()
  1416. {
  1417.     self endon( "death" );
  1418.  
  1419.     for ( ;; )
  1420.     {
  1421.         self waittill( "emp_damage", attacker, duration );
  1422.  
  1423.         playfxOnTag( getfx( "sentry_explode_mp" ), self, "tag_origin" );
  1424.  
  1425.         self.disabled = true;
  1426.         self notify( "disabled" );
  1427.  
  1428.         wait( duration );
  1429.  
  1430.         self.disabled = undefined;
  1431.         self notify( "enabled" );
  1432.     }
  1433. }
  1434.  
  1435.  
  1436. c4EMPKillstreakWait()
  1437. {
  1438.     self endon( "death" );
  1439.  
  1440.     for ( ;; )
  1441.     {
  1442.         level waittill( "emp_update" );
  1443.  
  1444.         if ( (level.teamBased && level.teamEMPed[self.team]) || (!level.teamBased && isDefined( level.empPlayer ) && level.empPlayer != self.owner ) )
  1445.         {
  1446.             self.disabled = true;
  1447.             self notify( "disabled" );
  1448.         }
  1449.         else
  1450.         {
  1451.             self.disabled = undefined;
  1452.             self notify( "enabled" );
  1453.         }
  1454.     }
  1455. }
  1456.  
  1457.  
  1458. setClaymoreTeamHeadIcon( team )
  1459. {
  1460.     self endon( "death" );
  1461.     wait .05;
  1462.     if ( level.teamBased )
  1463.         self maps\mp\_entityheadicons::setTeamHeadIcon( team, ( 0, 0, 20 ) );
  1464.     else if ( isDefined( self.owner ) )
  1465.         self maps\mp\_entityheadicons::setPlayerHeadIcon( self.owner, (0,0,20) );
  1466. }
  1467.  
  1468.  
  1469. watchClaymores()
  1470. {
  1471.     self endon( "spawned_player" );
  1472.     self endon( "disconnect" );
  1473.  
  1474.     self.claymorearray = [];
  1475.     while ( 1 )
  1476.     {
  1477.         self waittill( "grenade_fire", claymore, weapname );
  1478.         if ( weapname == "claymore" || weapname == "claymore_mp" )
  1479.         {
  1480.             self.claymorearray = array_removeUndefined( self.claymorearray );
  1481.            
  1482.             if( self.claymoreArray.size >= level.maxPerPlayerExplosives )
  1483.                 self.claymoreArray[0] detonate();
  1484.            
  1485.             self.claymorearray[ self.claymorearray.size ] = claymore;
  1486.             claymore.owner = self;
  1487.             claymore.team = self.team;
  1488.             claymore.weaponName = weapname;
  1489.  
  1490.             claymore thread c4Damage();
  1491.             claymore thread c4EMPDamage();
  1492.             claymore thread c4EMPKillstreakWait();
  1493.             claymore thread claymoreDetonation();
  1494.             //claymore thread claymoreDetectionTrigger_wait( self.pers[ "team" ] );
  1495.             claymore thread setClaymoreTeamHeadIcon( self.pers[ "team" ] );
  1496.  
  1497.              /#
  1498.             if ( getdvarint( "scr_claymoredebug" ) )
  1499.             {
  1500.                 claymore thread claymoreDebug();
  1501.             }
  1502.             #/
  1503.         }
  1504.     }
  1505. }
  1506.  
  1507.  /#
  1508. claymoreDebug()
  1509. {
  1510.     self waittill( "missile_stuck" );
  1511.     self thread showCone( acos( level.claymoreDetectionDot ), level.claymoreDetonateRadius, ( 1, .85, 0 ) );
  1512.     self thread showCone( 60, 256, ( 1, 0, 0 ) );
  1513. }
  1514.  
  1515. vectorcross( v1, v2 )
  1516. {
  1517.     return( v1[ 1 ] * v2[ 2 ] - v1[ 2 ] * v2[ 1 ], v1[ 2 ] * v2[ 0 ] - v1[ 0 ] * v2[ 2 ], v1[ 0 ] * v2[ 1 ] - v1[ 1 ] * v2[ 0 ] );
  1518. }
  1519.  
  1520. showCone( angle, range, color )
  1521. {
  1522.     self endon( "death" );
  1523.  
  1524.     start = self.origin;
  1525.     forward = anglestoforward( self.angles );
  1526.     right = vectorcross( forward, ( 0, 0, 1 ) );
  1527.     up = vectorcross( forward, right );
  1528.  
  1529.     fullforward = forward * range * cos( angle );
  1530.     sideamnt = range * sin( angle );
  1531.  
  1532.     while ( 1 )
  1533.     {
  1534.         prevpoint = ( 0, 0, 0 );
  1535.         for ( i = 0; i <= 20; i++ )
  1536.         {
  1537.             coneangle = i / 20.0 * 360;
  1538.             point = start + fullforward + sideamnt * ( right * cos( coneangle ) + up * sin( coneangle ) );
  1539.             if ( i > 0 )
  1540.             {
  1541.                 line( start, point, color );
  1542.                 line( prevpoint, point, color );
  1543.             }
  1544.             prevpoint = point;
  1545.         }
  1546.         wait .05;
  1547.     }
  1548. }
  1549. #/
  1550.  
  1551. claymoreDetonation()
  1552. {
  1553.     self endon( "death" );
  1554.  
  1555.     self waittill( "missile_stuck" );
  1556.  
  1557.     damagearea = spawn( "trigger_radius", self.origin + ( 0, 0, 0 - level.claymoreDetonateRadius ), 0, level.claymoreDetonateRadius, level.claymoreDetonateRadius * 2 );
  1558.     self thread deleteOnDeath( damagearea );
  1559.  
  1560.     while ( 1 )
  1561.     {
  1562.         damagearea waittill( "trigger", player );
  1563.  
  1564.         if ( getdvarint( "scr_claymoredebug" ) != 1 )
  1565.         {
  1566.             if ( isdefined( self.owner ) && player == self.owner )
  1567.                 continue;
  1568.             if ( !friendlyFireCheck( self.owner, player, 0 ) )
  1569.                 continue;
  1570.         }
  1571.         if ( lengthsquared( player getVelocity() ) < 10 )
  1572.             continue;
  1573.  
  1574.         if ( !player shouldAffectClaymore( self ) )
  1575.             continue;
  1576.  
  1577.         if ( player damageConeTrace( self.origin, self ) > 0 )
  1578.             break;
  1579.     }
  1580.    
  1581.     self playsound ("claymore_activated");
  1582.    
  1583.    
  1584.     if ( player _hasPerk( "specialty_delaymine" ) )
  1585.         wait 3.0;
  1586.     else
  1587.         wait level.claymoreDetectionGracePeriod;
  1588.        
  1589.     self detonate();
  1590. }
  1591.  
  1592. shouldAffectClaymore( claymore )
  1593. {
  1594.     if ( isDefined( claymore.disabled ) )
  1595.         return false;
  1596.  
  1597.     pos = self.origin + ( 0, 0, 32 );
  1598.  
  1599.     dirToPos = pos - claymore.origin;
  1600.     claymoreForward = anglesToForward( claymore.angles );
  1601.  
  1602.     dist = vectorDot( dirToPos, claymoreForward );
  1603.     if ( dist < level.claymoreDetectionMinDist )
  1604.         return false;
  1605.  
  1606.     dirToPos = vectornormalize( dirToPos );
  1607.  
  1608.     dot = vectorDot( dirToPos, claymoreForward );
  1609.     return( dot > level.claymoreDetectionDot );
  1610. }
  1611.  
  1612. deleteOnDeath( ent )
  1613. {
  1614.     self waittill( "death" );
  1615.     wait .05;
  1616.     if ( isdefined( ent ) )
  1617.         ent delete();
  1618. }
  1619.  
  1620. c4Activate()
  1621. {
  1622.     self endon( "death" );
  1623.  
  1624.     self waittill( "missile_stuck" );
  1625.  
  1626.     wait 0.05;
  1627.  
  1628.     self notify( "activated" );
  1629.     self.activated = true;
  1630. }
  1631.  
  1632. watchC4AltDetonate()
  1633. {
  1634.     self endon( "death" );
  1635.     self endon( "disconnect" );
  1636.     self endon( "detonated" );
  1637.     level endon( "game_ended" );
  1638.  
  1639.     buttonTime = 0;
  1640.     for ( ;; )
  1641.     {
  1642.         if ( self UseButtonPressed() )
  1643.         {
  1644.             buttonTime = 0;
  1645.             while ( self UseButtonPressed() )
  1646.             {
  1647.                 buttonTime += 0.05;
  1648.                 wait( 0.05 );
  1649.             }
  1650.  
  1651.             println( "pressTime1: " + buttonTime );
  1652.             if ( buttonTime >= 0.5 )
  1653.                 continue;
  1654.  
  1655.             buttonTime = 0;
  1656.             while ( !self UseButtonPressed() && buttonTime < 0.5 )
  1657.             {
  1658.                 buttonTime += 0.05;
  1659.                 wait( 0.05 );
  1660.             }
  1661.  
  1662.             println( "delayTime: " + buttonTime );
  1663.             if ( buttonTime >= 0.5 )
  1664.                 continue;
  1665.  
  1666.             if ( !self.c4Array.size )
  1667.                 return;
  1668.  
  1669.             self notify( "alt_detonate" );
  1670.         }
  1671.         wait( 0.05 );
  1672.     }
  1673. }
  1674.  
  1675. watchC4Detonation()
  1676. {
  1677.     self endon( "death" );
  1678.     self endon( "disconnect" );
  1679.  
  1680.     while ( 1 )
  1681.     {
  1682.         self waittillmatch( "detonate", "c4_mp" );
  1683.         newarray = [];
  1684.         for ( i = 0; i < self.c4array.size; i++ )
  1685.         {
  1686.             c4 = self.c4array[ i ];
  1687.             if ( isdefined( self.c4array[ i ] ) )
  1688.                 c4 thread waitAndDetonate( 0.1 );
  1689.         }
  1690.         self.c4array = newarray;
  1691.         self notify( "detonated" );
  1692.     }
  1693. }
  1694.  
  1695.  
  1696. watchC4AltDetonation()
  1697. {
  1698.     self endon( "death" );
  1699.     self endon( "disconnect" );
  1700.  
  1701.     while ( 1 )
  1702.     {
  1703.         self waittill( "alt_detonate" );
  1704.         weap = self getCurrentWeapon();
  1705.         if ( weap != "c4_mp" )
  1706.         {
  1707.             newarray = [];
  1708.             for ( i = 0; i < self.c4array.size; i++ )
  1709.             {
  1710.                 c4 = self.c4array[ i ];
  1711.                 if ( isdefined( self.c4array[ i ] ) )
  1712.                     c4 thread waitAndDetonate( 0.1 );
  1713.             }
  1714.             self.c4array = newarray;
  1715.             self notify( "detonated" );
  1716.         }
  1717.     }
  1718. }
  1719.  
  1720.  
  1721. waitAndDetonate( delay )
  1722. {
  1723.     self endon( "death" );
  1724.     wait delay;
  1725.  
  1726.     self waitTillEnabled();
  1727.  
  1728.     self detonate();
  1729. }
  1730.  
  1731. deleteC4AndClaymoresOnDisconnect()
  1732. {
  1733.     self endon( "death" );
  1734.     self waittill( "disconnect" );
  1735.  
  1736.     c4array = self.c4array;
  1737.     claymorearray = self.claymorearray;
  1738.  
  1739.     wait .05;
  1740.  
  1741.     for ( i = 0; i < c4array.size; i++ )
  1742.     {
  1743.         if ( isdefined( c4array[ i ] ) )
  1744.             c4array[ i ] delete();
  1745.     }
  1746.     for ( i = 0; i < claymorearray.size; i++ )
  1747.     {
  1748.         if ( isdefined( claymorearray[ i ] ) )
  1749.             claymorearray[ i ] delete();
  1750.     }
  1751. }
  1752.  
  1753. c4Damage()
  1754. {
  1755.     self endon( "death" );
  1756.  
  1757.     self setcandamage( true );
  1758.     self.maxhealth = 100000;
  1759.     self.health = self.maxhealth;
  1760.  
  1761.     attacker = undefined;
  1762.  
  1763.     while ( 1 )
  1764.     {
  1765.         self waittill( "damage", damage, attacker, direction_vec, point, type, modelName, tagName, partName, iDFlags );
  1766.         if ( !isPlayer( attacker ) )
  1767.             continue;
  1768.  
  1769.         // don't allow people to destroy C4 on their team if FF is off
  1770.         if ( !friendlyFireCheck( self.owner, attacker ) )
  1771.             continue;
  1772.  
  1773.         if ( damage < 5 )// ignore concussion grenades
  1774.             continue;
  1775.  
  1776.         break;
  1777.     }
  1778.  
  1779.     if ( level.c4explodethisframe )
  1780.         wait .1 + randomfloat( .4 );
  1781.     else
  1782.         wait .05;
  1783.  
  1784.     if ( !isdefined( self ) )
  1785.         return;
  1786.  
  1787.     level.c4explodethisframe = true;
  1788.  
  1789.     thread resetC4ExplodeThisFrame();
  1790.  
  1791.     if ( isDefined( type ) && ( isSubStr( type, "MOD_GRENADE" ) || isSubStr( type, "MOD_EXPLOSIVE" ) ) )
  1792.         self.wasChained = true;
  1793.  
  1794.     if ( isDefined( iDFlags ) && ( iDFlags & level.iDFLAGS_PENETRATION ) )
  1795.         self.wasDamagedFromBulletPenetration = true;
  1796.  
  1797.     self.wasDamaged = true;
  1798.  
  1799.     if ( level.teamBased )
  1800.     {
  1801.         // "destroyed_explosive" notify, for challenges
  1802.         if ( isdefined( attacker ) && isdefined( attacker.pers[ "team" ] ) && isdefined( self.owner ) && isdefined( self.owner.pers[ "team" ] ) )
  1803.         {
  1804.             if ( attacker.pers[ "team" ] != self.owner.pers[ "team" ] )
  1805.                 attacker notify( "destroyed_explosive" );
  1806.         }
  1807.     }
  1808.     else
  1809.     {
  1810.         // checking isDefined attacker is defensive but it's too late in the project to risk issues by not having it
  1811.         if ( isDefined( self.owner ) && isDefined( attacker ) && attacker != self.owner )
  1812.             attacker notify( "destroyed_explosive" );      
  1813.     }
  1814.  
  1815.     self detonate( attacker );
  1816.     // won't get here; got death notify.
  1817. }
  1818.  
  1819. resetC4ExplodeThisFrame()
  1820. {
  1821.     wait .05;
  1822.     level.c4explodethisframe = false;
  1823. }
  1824.  
  1825. saydamaged( orig, amount )
  1826. {
  1827.     for ( i = 0; i < 60; i++ )
  1828.     {
  1829.         print3d( orig, "damaged! " + amount );
  1830.         wait .05;
  1831.     }
  1832. }
  1833.  
  1834. waitTillEnabled()
  1835. {
  1836.     if ( !isDefined( self.disabled ) )
  1837.         return;
  1838.  
  1839.     self waittill( "enabled" );
  1840.     assert( !isDefined( self.disabled ) );
  1841. }
  1842.  
  1843.  
  1844. c4DetectionTrigger( ownerTeam )
  1845. {
  1846.     self waittill( "activated" );
  1847.  
  1848.     trigger = spawn( "trigger_radius", self.origin - ( 0, 0, 128 ), 0, 512, 256 );
  1849.     trigger.detectId = "trigger" + getTime() + randomInt( 1000000 );
  1850.  
  1851.     trigger.owner = self;
  1852.     trigger thread detectIconWaiter( level.otherTeam[ ownerTeam ] );
  1853.  
  1854.     self waittill( "death" );
  1855.     trigger notify( "end_detection" );
  1856.  
  1857.     if ( isDefined( trigger.bombSquadIcon ) )
  1858.         trigger.bombSquadIcon destroy();
  1859.  
  1860.     trigger delete();
  1861. }
  1862.  
  1863.  
  1864. claymoreDetectionTrigger_wait( ownerTeam )
  1865. {
  1866.     self endon( "death" );
  1867.     self waittill( "missile_stuck" );
  1868.  
  1869.     self thread claymoreDetectionTrigger( ownerTeam );
  1870. }
  1871.  
  1872. claymoreDetectionTrigger( ownerTeam )
  1873. {
  1874.     trigger = spawn( "trigger_radius", self.origin - ( 0, 0, 128 ), 0, 512, 256 );
  1875.     trigger.detectId = "trigger" + getTime() + randomInt( 1000000 );
  1876.  
  1877.     trigger.owner = self;
  1878.     trigger thread detectIconWaiter( level.otherTeam[ ownerTeam ] );
  1879.  
  1880.     self waittill( "death" );
  1881.     trigger notify( "end_detection" );
  1882.  
  1883.     if ( isDefined( trigger.bombSquadIcon ) )
  1884.         trigger.bombSquadIcon destroy();
  1885.  
  1886.     trigger delete();
  1887. }
  1888.  
  1889.  
  1890. detectIconWaiter( detectTeam )
  1891. {
  1892.     self endon( "end_detection" );
  1893.     level endon( "game_ended" );
  1894.  
  1895.     while ( !level.gameEnded )
  1896.     {
  1897.         self waittill( "trigger", player );
  1898.  
  1899.         if ( !player.detectExplosives )
  1900.             continue;
  1901.  
  1902.         if ( level.teamBased && player.team != detectTeam )
  1903.             continue;
  1904.         else if ( !level.teamBased && player == self.owner.owner )
  1905.             continue;
  1906.  
  1907.         if ( isDefined( player.bombSquadIds[ self.detectId ] ) )
  1908.             continue;
  1909.  
  1910.         player thread showHeadIcon( self );
  1911.     }
  1912. }
  1913.  
  1914.  
  1915. setupBombSquad()
  1916. {
  1917.     self.bombSquadIds = [];
  1918.  
  1919.     if ( self.detectExplosives && !self.bombSquadIcons.size )
  1920.     {
  1921.         for ( index = 0; index < 4; index++ )
  1922.         {
  1923.             self.bombSquadIcons[ index ] = newClientHudElem( self );
  1924.             self.bombSquadIcons[ index ].x = 0;
  1925.             self.bombSquadIcons[ index ].y = 0;
  1926.             self.bombSquadIcons[ index ].z = 0;
  1927.             self.bombSquadIcons[ index ].alpha = 0;
  1928.             self.bombSquadIcons[ index ].archived = true;
  1929.             self.bombSquadIcons[ index ] setShader( "waypoint_bombsquad", 14, 14 );
  1930.             self.bombSquadIcons[ index ] setWaypoint( false, false );
  1931.             self.bombSquadIcons[ index ].detectId = "";
  1932.         }
  1933.     }
  1934.     else if ( !self.detectExplosives )
  1935.     {
  1936.         for ( index = 0; index < self.bombSquadIcons.size; index++ )
  1937.             self.bombSquadIcons[ index ] destroy();
  1938.  
  1939.         self.bombSquadIcons = [];
  1940.     }
  1941. }
  1942.  
  1943.  
  1944. showHeadIcon( trigger )
  1945. {
  1946.     triggerDetectId = trigger.detectId;
  1947.     useId = -1;
  1948.     for ( index = 0; index < 4; index++ )
  1949.     {
  1950.         detectId = self.bombSquadIcons[ index ].detectId;
  1951.  
  1952.         if ( detectId == triggerDetectId )
  1953.             return;
  1954.  
  1955.         if ( detectId == "" )
  1956.             useId = index;
  1957.     }
  1958.  
  1959.     if ( useId < 0 )
  1960.         return;
  1961.  
  1962.     self.bombSquadIds[ triggerDetectId ] = true;
  1963.  
  1964.     self.bombSquadIcons[ useId ].x = trigger.origin[ 0 ];
  1965.     self.bombSquadIcons[ useId ].y = trigger.origin[ 1 ];
  1966.     self.bombSquadIcons[ useId ].z = trigger.origin[ 2 ] + 24 + 128;
  1967.  
  1968.     self.bombSquadIcons[ useId ] fadeOverTime( 0.25 );
  1969.     self.bombSquadIcons[ useId ].alpha = 1;
  1970.     self.bombSquadIcons[ useId ].detectId = trigger.detectId;
  1971.  
  1972.     while ( isAlive( self ) && isDefined( trigger ) && self isTouching( trigger ) )
  1973.         wait( 0.05 );
  1974.  
  1975.     if ( !isDefined( self ) )
  1976.         return;
  1977.  
  1978.     self.bombSquadIcons[ useId ].detectId = "";
  1979.     self.bombSquadIcons[ useId ] fadeOverTime( 0.25 );
  1980.     self.bombSquadIcons[ useId ].alpha = 0;
  1981.     self.bombSquadIds[ triggerDetectId ] = undefined;
  1982. }
  1983.  
  1984.  
  1985. // these functions are used with scripted weapons (like c4, claymores, artillery)
  1986. // returns an array of objects representing damageable entities (including players) within a given sphere.
  1987. // each object has the property damageCenter, which represents its center (the location from which it can be damaged).
  1988. // each object also has the property entity, which contains the entity that it represents.
  1989. // to damage it, call damageEnt() on it.
  1990. getDamageableEnts( pos, radius, doLOS, startRadius )
  1991. {
  1992.     ents = [];
  1993.  
  1994.     if ( !isdefined( doLOS ) )
  1995.         doLOS = false;
  1996.  
  1997.     if ( !isdefined( startRadius ) )
  1998.         startRadius = 0;
  1999.    
  2000.     radiusSq = radius * radius;
  2001.  
  2002.     // players
  2003.     players = level.players;
  2004.     for ( i = 0; i < players.size; i++ )
  2005.     {
  2006.         if ( !isalive( players[ i ] ) || players[ i ].sessionstate != "playing" )
  2007.             continue;
  2008.  
  2009.         playerpos = get_damageable_player_pos( players[ i ] );
  2010.         distSq = distanceSquared( pos, playerpos );
  2011.         if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, playerpos, startRadius, players[ i ] ) ) )
  2012.         {
  2013.             ents[ ents.size ] = get_damageable_player( players[ i ], playerpos );
  2014.         }
  2015.     }
  2016.  
  2017.     // grenades
  2018.     grenades = getentarray( "grenade", "classname" );
  2019.     for ( i = 0; i < grenades.size; i++ )
  2020.     {
  2021.         entpos = get_damageable_grenade_pos( grenades[ i ] );
  2022.         distSq = distanceSquared( pos, entpos );
  2023.         if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, grenades[ i ] ) ) )
  2024.         {
  2025.             ents[ ents.size ] = get_damageable_grenade( grenades[ i ], entpos );
  2026.         }
  2027.     }
  2028.  
  2029.     destructibles = getentarray( "destructible", "targetname" );
  2030.     for ( i = 0; i < destructibles.size; i++ )
  2031.     {
  2032.         entpos = destructibles[ i ].origin;
  2033.         distSq = distanceSquared( pos, entpos );
  2034.         if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, destructibles[ i ] ) ) )
  2035.         {
  2036.             newent = spawnstruct();
  2037.             newent.isPlayer = false;
  2038.             newent.isADestructable = false;
  2039.             newent.entity = destructibles[ i ];
  2040.             newent.damageCenter = entpos;
  2041.             ents[ ents.size ] = newent;
  2042.         }
  2043.     }
  2044.  
  2045.     destructables = getentarray( "destructable", "targetname" );
  2046.     for ( i = 0; i < destructables.size; i++ )
  2047.     {
  2048.         entpos = destructables[ i ].origin;
  2049.         distSq = distanceSquared( pos, entpos );
  2050.         if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, destructables[ i ] ) ) )
  2051.         {
  2052.             newent = spawnstruct();
  2053.             newent.isPlayer = false;
  2054.             newent.isADestructable = true;
  2055.             newent.entity = destructables[ i ];
  2056.             newent.damageCenter = entpos;
  2057.             ents[ ents.size ] = newent;
  2058.         }
  2059.     }
  2060.    
  2061.     //sentries
  2062.     sentries = getentarray( "misc_turret", "classname" );
  2063.     foreach ( sentry in sentries )
  2064.     {
  2065.         entpos = sentry.origin + (0,0,32);
  2066.         distSq = distanceSquared( pos, entpos );
  2067.         if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, sentry ) ) )
  2068.         {
  2069.             if ( sentry.model == "sentry_minigun" )
  2070.                 ents[ ents.size ] = get_damageable_sentry(sentry, entpos);
  2071.         }
  2072.     }
  2073.  
  2074.     return ents;
  2075. }
  2076.  
  2077.  
  2078. getEMPDamageEnts( pos, radius, doLOS, startRadius )
  2079. {
  2080.     ents = [];
  2081.  
  2082.     if ( !isDefined( doLOS ) )
  2083.         doLOS = false;
  2084.  
  2085.     if ( !isDefined( startRadius ) )
  2086.         startRadius = 0;
  2087.  
  2088.     grenades = getEntArray( "grenade", "classname" );
  2089.     foreach ( grenade in grenades )
  2090.     {
  2091.         //if ( !isDefined( grenade.weaponName ) )
  2092.         //  continue;
  2093.  
  2094.         entpos = grenade.origin;
  2095.         dist = distance( pos, entpos );
  2096.         if ( dist < radius && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, grenade ) ) )
  2097.             ents[ ents.size ] = grenade;
  2098.     }
  2099.  
  2100.     turrets = getEntArray( "misc_turret", "classname" );
  2101.     foreach ( turret in turrets )
  2102.     {
  2103.         //if ( !isDefined( turret.weaponName ) )
  2104.         //  continue;
  2105.  
  2106.         entpos = turret.origin;
  2107.         dist = distance( pos, entpos );
  2108.         if ( dist < radius && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, turret ) ) )
  2109.             ents[ ents.size ] = turret;
  2110.     }
  2111.  
  2112.     return ents;
  2113. }
  2114.  
  2115.  
  2116. weaponDamageTracePassed( from, to, startRadius, ent )
  2117. {
  2118.     midpos = undefined;
  2119.  
  2120.     diff = to - from;
  2121.     if ( lengthsquared( diff ) < startRadius * startRadius )
  2122.         return true;
  2123.    
  2124.     dir = vectornormalize( diff );
  2125.     midpos = from + ( dir[ 0 ] * startRadius, dir[ 1 ] * startRadius, dir[ 2 ] * startRadius );
  2126.  
  2127.     trace = bullettrace( midpos, to, false, ent );
  2128.  
  2129.     if ( getdvarint( "scr_damage_debug" ) != 0 )
  2130.     {
  2131.         thread debugprint( from, ".dmg" );
  2132.         if ( isdefined( ent ) )
  2133.             thread debugprint( to, "." + ent.classname );
  2134.         else
  2135.             thread debugprint( to, ".undefined" );
  2136.         if ( trace[ "fraction" ] == 1 )
  2137.         {
  2138.             thread debugline( midpos, to, ( 1, 1, 1 ) );
  2139.         }
  2140.         else
  2141.         {
  2142.             thread debugline( midpos, trace[ "position" ], ( 1, .9, .8 ) );
  2143.             thread debugline( trace[ "position" ], to, ( 1, .4, .3 ) );
  2144.         }
  2145.     }
  2146.  
  2147.     return( trace[ "fraction" ] == 1 );
  2148. }
  2149.  
  2150. // eInflictor = the entity that causes the damage (e.g. a claymore)
  2151. // eAttacker = the player that is attacking
  2152. // iDamage = the amount of damage to do
  2153. // sMeansOfDeath = string specifying the method of death (e.g. "MOD_PROJECTILE_SPLASH")
  2154. // sWeapon = string specifying the weapon used (e.g. "claymore_mp")
  2155. // damagepos = the position damage is coming from
  2156. // damagedir = the direction damage is moving in
  2157. damageEnt( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, damagepos, damagedir )
  2158. {
  2159.     if ( self.isPlayer )
  2160.     {
  2161.         self.damageOrigin = damagepos;
  2162.         self.entity thread [[ level.callbackPlayerDamage ]](
  2163.             eInflictor,// eInflictor The entity that causes the damage.( e.g. a turret )
  2164.             eAttacker,// eAttacker The entity that is attacking.
  2165.             iDamage,// iDamage Integer specifying the amount of damage done
  2166.             0,// iDFlags Integer specifying flags that are to be applied to the damage
  2167.             sMeansOfDeath,// sMeansOfDeath Integer specifying the method of death
  2168.             sWeapon,// sWeapon The weapon number of the weapon used to inflict the damage
  2169.             damagepos,// vPoint The point the damage is from?
  2170.             damagedir,// vDir The direction of the damage
  2171.             "none",// sHitLoc The location of the hit
  2172.             0// psOffsetTime The time offset for the damage
  2173.          );
  2174.     }
  2175.     else
  2176.     {
  2177.         // destructable walls and such can only be damaged in certain ways.
  2178.         if ( self.isADestructable && ( sWeapon == "artillery_mp" || sWeapon == "claymore_mp" ) || sWeapon == "stealth_bomb_mp" )
  2179.             return;
  2180.  
  2181.         self.entity notify( "damage", iDamage, eAttacker, ( 0, 0, 0 ), ( 0, 0, 0 ), "mod_explosive", "", "" );
  2182.     }
  2183. }
  2184.  
  2185.  
  2186. debugline( a, b, color )
  2187. {
  2188.     for ( i = 0; i < 30 * 20; i++ )
  2189.     {
  2190.         line( a, b, color );
  2191.         wait .05;
  2192.     }
  2193. }
  2194.  
  2195. debugprint( pt, txt )
  2196. {
  2197.     for ( i = 0; i < 30 * 20; i++ )
  2198.     {
  2199.         print3d( pt, txt );
  2200.         wait .05;
  2201.     }
  2202. }
  2203.  
  2204.  
  2205. onWeaponDamage( eInflictor, sWeapon, meansOfDeath, damage, eAttacker )
  2206. {
  2207.     self endon( "death" );
  2208.     self endon( "disconnect" );
  2209.  
  2210.     switch( sWeapon )
  2211.     {
  2212.         case "concussion_grenade_mp":
  2213.             // should match weapon settings in gdt
  2214.             radius = 512;
  2215.             scale = 1 - ( distance( self.origin, eInflictor.origin ) / radius );
  2216.  
  2217.             if ( scale < 0 )
  2218.                 scale = 0;
  2219.  
  2220.             time = 2 + ( 4 * scale );
  2221.            
  2222.             wait( 0.05 );
  2223.             eAttacker notify( "stun_hit" );
  2224.             self shellShock( "concussion_grenade_mp", time );
  2225.             self.concussionEndTime = getTime() + ( time * 1000 );
  2226.         break;
  2227.  
  2228.         case "weapon_cobra_mk19_mp":
  2229.             // mk19 is too powerful with shellshock slowdown
  2230.         break;
  2231.  
  2232.         default:
  2233.             // shellshock will only be done if meansofdeath is an appropriate type and if there is enough damage.
  2234.             maps\mp\gametypes\_shellshock::shellshockOnDamage( meansOfDeath, damage );
  2235.         break;
  2236.     }
  2237.  
  2238. }
  2239.  
  2240. // weapon stowing logic ===================================================================
  2241.  
  2242. // weapon class boolean helpers
  2243. isPrimaryWeapon( weapName )
  2244. {
  2245.     if ( weapName == "none" )
  2246.         return false;
  2247.        
  2248.     if ( weaponInventoryType( weapName ) != "primary" )
  2249.         return false;
  2250.  
  2251.     switch ( weaponClass( weapName ) )
  2252.     {
  2253.         case "rifle":
  2254.         case "smg":
  2255.         case "mg":
  2256.         case "spread":
  2257.         case "pistol":
  2258.         case "rocketlauncher":
  2259.         case "sniper":
  2260.             return true;
  2261.  
  2262.         default:
  2263.             return false;
  2264.     }  
  2265. }
  2266.  
  2267.  
  2268. isAltModeWeapon( weapName )
  2269. {
  2270.     if ( weapName == "none" )
  2271.         return false;
  2272.        
  2273.     return ( weaponInventoryType( weapName ) == "altmode" );
  2274. }
  2275.  
  2276. isInventoryWeapon( weapName )
  2277. {
  2278.     if ( weapName == "none" )
  2279.         return false;
  2280.        
  2281.     return ( weaponInventoryType( weapName ) == "item" );
  2282. }
  2283.  
  2284. isRiotShield( weapName )
  2285. {
  2286.     if ( weapName == "none" )
  2287.         return false;
  2288.        
  2289.     return ( WeaponType( weapName ) == "riotshield" );
  2290. }
  2291.  
  2292. isOffhandWeapon( weapName )
  2293. {
  2294.     if ( weapName == "none" )
  2295.         return false;
  2296.        
  2297.     return ( weaponInventoryType( weapName ) == "offhand" );
  2298. }
  2299.  
  2300. isSideArm( weapName )
  2301. {
  2302.     if ( weapName == "none" )
  2303.         return false;
  2304.  
  2305.     if ( weaponInventoryType( weapName ) != "primary" )
  2306.         return false;
  2307.  
  2308.     return ( weaponClass( weapName ) == "pistol" );
  2309. }
  2310.  
  2311.  
  2312. // This needs for than this.. this would qualify c4 as a grenade
  2313. isGrenade( weapName )
  2314. {
  2315.     weapClass = weaponClass( weapName );
  2316.     weapType = weaponInventoryType( weapName );
  2317.  
  2318.     if ( weapClass != "grenade" )
  2319.         return false;
  2320.        
  2321.     if ( weapType != "offhand" )
  2322.         return false;
  2323. }
  2324.  
  2325.  
  2326. getStowOffsetModel( weaponName )
  2327. {
  2328.     assert( isDefined( level.stow_offset_array ) );
  2329.  
  2330.     baseName = getBaseWeaponName( weaponName );
  2331.    
  2332.     return( level.stow_offset_array[baseName] );
  2333. }
  2334.  
  2335.  
  2336. stowPriorityWeapon()
  2337. {
  2338.     assert( isdefined( level.stow_priority_model_array ) );
  2339.  
  2340.     // returns the first large projectil the player owns in case player owns more than one
  2341.     foreach ( weapon_name, priority_weapon in level.stow_priority_model_array )
  2342.     {
  2343.         weaponName = getBaseWeaponName( weapon_name );
  2344.         weaponList = self getWeaponsListAll();
  2345.        
  2346.         foreach ( weapon in weaponList )
  2347.         {
  2348.             if( self getCurrentWeapon() == weapon )
  2349.                 continue;
  2350.            
  2351.             if ( weaponName == getBaseWeaponName( weapon ) )
  2352.                 return weaponName + "_mp";
  2353.         }
  2354.     }
  2355.  
  2356.     return "";
  2357. }
  2358.  
  2359. // thread loop life = player's life
  2360. updateStowedWeapon()
  2361. {
  2362.     self endon( "spawned" );
  2363.     self endon( "killed_player" );
  2364.     self endon( "disconnect" );
  2365.  
  2366.     self.tag_stowed_back = undefined;
  2367.     self.tag_stowed_hip = undefined;
  2368.    
  2369.     team = self.team;
  2370.     class = self.class;
  2371.    
  2372.     self thread stowedWeaponsRefresh();
  2373.    
  2374.     while ( true )
  2375.     {
  2376.         self waittill( "weapon_change", newWeapon );
  2377.        
  2378.         if ( newWeapon == "none" )
  2379.             continue;
  2380.            
  2381.         self thread stowedWeaponsRefresh();
  2382.     }
  2383. }
  2384.  
  2385. stowedWeaponsRefresh()
  2386. {
  2387.     self endon( "spawned" );
  2388.     self endon( "killed_player" );
  2389.     self endon( "disconnect" );
  2390.    
  2391.     detach_all_weapons();
  2392.     stow_on_back();
  2393.     stow_on_hip();
  2394. }
  2395.  
  2396.  
  2397. detach_all_weapons()
  2398. {
  2399.     if ( isDefined( self.tag_stowed_back ) )
  2400.         self detach_back_weapon();
  2401.  
  2402.     if ( isDefined( self.tag_stowed_hip ) )
  2403.         self detach_hip_weapon();
  2404. }
  2405.  
  2406.  
  2407. detach_back_weapon()
  2408. {
  2409.     detach_success = self detachIfAttached( self.tag_stowed_back, "tag_stowed_back" );
  2410.  
  2411.     // test for bug
  2412.     //assertex( detach_success, "Detaching: " + self.tag_stowed_back + " from tag: tag_stowed_back failed." );
  2413.     self.tag_stowed_back = undefined;
  2414. }
  2415.  
  2416.  
  2417. detach_hip_weapon()
  2418. {
  2419.     detach_success = self detachIfAttached( self.tag_stowed_hip, "tag_stowed_hip" );
  2420.  
  2421.     // test for bug
  2422.     //assertex( detach_success, "Detaching: " + detach_model + " from tag: tag_stowed_hip failed." );
  2423.     self.tag_stowed_hip = undefined;
  2424. }
  2425.  
  2426.  
  2427. stow_on_back()
  2428. {
  2429.     prof_begin( "stow_on_back" );
  2430.     currentWeapon = self getCurrentWeapon();
  2431.     currentIsAlt = isAltModeWeapon( currentWeapon );
  2432.  
  2433.     assert( !isDefined( self.tag_stowed_back ) );
  2434.  
  2435.     stowWeapon = undefined;
  2436.     stowCamo = 0;
  2437.     large_projectile = self stowPriorityWeapon();
  2438.     stowOffsetModel = undefined;
  2439.  
  2440.     if ( large_projectile != "" )
  2441.     {
  2442.         stowWeapon = large_projectile;
  2443.     }
  2444.     else
  2445.     {
  2446.         weaponsList = self getWeaponsListPrimaries();
  2447.         foreach ( weaponName in weaponsList )
  2448.         {
  2449.             if ( weaponName == currentWeapon )
  2450.                 continue;
  2451.            
  2452.             invType = weaponInventoryType( weaponName );
  2453.            
  2454.             if ( invType != "primary" )
  2455.             {
  2456.                 if ( invType == "altmode" )
  2457.                     continue;
  2458.                
  2459.                 if ( weaponClass( weaponName ) == "pistol" )
  2460.                     continue;
  2461.             }
  2462.            
  2463.             if ( WeaponType( weaponName ) == "riotshield" )
  2464.                 continue;
  2465.            
  2466.             // Don't stow the current on our back when we're using the alt
  2467.             if ( currentIsAlt && weaponAltWeaponName( weaponName ) == currentWeapon )
  2468.                 continue;
  2469.                
  2470.             stowWeapon = weaponName;
  2471.             stowOffsetModel = getStowOffsetModel( stowWeapon );
  2472.            
  2473.             if ( stowWeapon == self.primaryWeapon )
  2474.                 stowCamo = self.loadoutPrimaryCamo;
  2475.             else if ( stowWeapon == self.secondaryWeapon )
  2476.                 stowCamo = self.loadoutSecondaryCamo;
  2477.             else
  2478.                 stowCamo = 0;
  2479.         }      
  2480.     }
  2481.  
  2482.     if ( !isDefined( stowWeapon ) )
  2483.     {
  2484.         prof_end( "stow_on_back" );
  2485.         return;
  2486.     }
  2487.  
  2488.     if ( large_projectile != "" )
  2489.     {
  2490.         self.tag_stowed_back = level.stow_priority_model_array[ large_projectile ];
  2491.     }
  2492.     else
  2493.     {
  2494.         self.tag_stowed_back = getWeaponModel( stowWeapon, stowCamo ); 
  2495.     }
  2496.  
  2497.     if ( isDefined( stowOffsetModel ) )
  2498.     {
  2499.         self attach( stowOffsetModel, "tag_stowed_back", true );
  2500.         attachTag = "tag_stow_back_mid_attach";
  2501.     }
  2502.     else
  2503.     {
  2504.         attachTag = "tag_stowed_back";
  2505.     }
  2506.  
  2507.     self attach( self.tag_stowed_back, attachTag, true );
  2508.  
  2509.     hideTagList = GetWeaponHideTags( stowWeapon );
  2510.  
  2511.     if ( !isDefined( hideTagList ) )
  2512.     {
  2513.         prof_end( "stow_on_back" );
  2514.         return;
  2515.     }
  2516.  
  2517.     for ( i = 0; i < hideTagList.size; i++ )
  2518.         self HidePart( hideTagList[ i ], self.tag_stowed_back );
  2519.    
  2520.     prof_end( "stow_on_back" );
  2521. }
  2522.  
  2523. stow_on_hip()
  2524. {
  2525.     currentWeapon = self getCurrentWeapon();
  2526.  
  2527.     assert( !isDefined( self.tag_stowed_hip ) );
  2528.  
  2529.     stowWeapon = undefined;
  2530.  
  2531.     weaponsList = self getWeaponsListOffhands();
  2532.     foreach ( weaponName in weaponsList )
  2533.     {
  2534.         if ( weaponName == currentWeapon )
  2535.             continue;
  2536.            
  2537.         if ( weaponName != "c4_mp" && weaponName != "claymore_mp" )
  2538.             continue;
  2539.        
  2540.         stowWeapon = weaponName;
  2541.     }
  2542.  
  2543.     if ( !isDefined( stowWeapon ) )
  2544.         return;
  2545.  
  2546.     self.tag_stowed_hip = getWeaponModel( stowWeapon );
  2547.     self attach( self.tag_stowed_hip, "tag_stowed_hip_rear", true );
  2548.  
  2549.     hideTagList = GetWeaponHideTags( stowWeapon );
  2550.    
  2551.     if ( !isDefined( hideTagList ) )
  2552.         return;
  2553.    
  2554.     for ( i = 0; i < hideTagList.size; i++ )
  2555.         self HidePart( hideTagList[ i ], self.tag_stowed_hip );
  2556. }
  2557.  
  2558.  
  2559. updateSavedLastWeapon()
  2560. {
  2561.     self endon( "death" );
  2562.     self endon( "disconnect" );
  2563.  
  2564.     currentWeapon = self.currentWeaponAtSpawn;
  2565.     self.saved_lastWeapon = currentWeapon;
  2566.  
  2567.     for ( ;; )
  2568.     {
  2569.         self waittill( "weapon_change", newWeapon );
  2570.    
  2571.         if ( newWeapon == "none" )
  2572.         {
  2573.             self.saved_lastWeapon = currentWeapon;
  2574.             continue;
  2575.         }
  2576.  
  2577.         weaponInvType = weaponInventoryType( newWeapon );
  2578.  
  2579.         if ( weaponInvType != "primary" && weaponInvType != "altmode" )
  2580.         {
  2581.             self.saved_lastWeapon = currentWeapon;
  2582.             continue;
  2583.         }
  2584.        
  2585.         if ( newWeapon == "onemanarmy_mp" )
  2586.         {
  2587.             self.saved_lastWeapon = currentWeapon;
  2588.             continue;
  2589.         }
  2590.  
  2591.         self updateMoveSpeedScale( "primary" );
  2592.  
  2593.         self.saved_lastWeapon = currentWeapon;
  2594.         currentWeapon = newWeapon;
  2595.     }
  2596. }
  2597.  
  2598.  
  2599. EMPPlayer( numSeconds )
  2600. {
  2601.     self endon( "disconnect" );
  2602.     self endon( "death" );
  2603.  
  2604.     self thread clearEMPOnDeath();
  2605.  
  2606. }
  2607.  
  2608.  
  2609. clearEMPOnDeath()
  2610. {
  2611.     self endon( "disconnect" );
  2612.  
  2613.     self waittill( "death" );
  2614. }
  2615.  
  2616.  
  2617. updateMoveSpeedScale( weaponType )
  2618. {
  2619.     /*
  2620.     if ( self _hasPerk( "specialty_lightweight" ) )
  2621.         self.moveSpeedScaler = 1.10;
  2622.     else
  2623.         self.moveSpeedScaler = 1;
  2624.     */
  2625.    
  2626.     if ( !isDefined( weaponType ) || weaponType == "primary" || weaponType != "secondary" )
  2627.         weaponType = self.primaryWeapon;
  2628.     else
  2629.         weaponType = self.secondaryWeapon;
  2630.    
  2631.     if( isDefined(self.primaryWeapon ) && self.primaryWeapon == "riotshield_mp" )
  2632.     {
  2633.         self setMoveSpeedScale( .8 * self.moveSpeedScaler );
  2634.         return;
  2635.     }
  2636.    
  2637.     if ( !isDefined( weaponType ) )
  2638.         weapClass = "none";
  2639.     else
  2640.         weapClass = weaponClass( weaponType );
  2641.    
  2642.    
  2643.     switch ( weapClass )
  2644.     {
  2645.         case "rifle":
  2646.             self setMoveSpeedScale( 0.95 * self.moveSpeedScaler );
  2647.             break;
  2648.         case "pistol":
  2649.             self setMoveSpeedScale( 1.0 * self.moveSpeedScaler );
  2650.             break;
  2651.         case "mg":
  2652.             self setMoveSpeedScale( 0.875 * self.moveSpeedScaler );
  2653.             break;
  2654.         case "smg":
  2655.             self setMoveSpeedScale( 1.0 * self.moveSpeedScaler );
  2656.             break;
  2657.         case "spread":
  2658.             self setMoveSpeedScale( .95 * self.moveSpeedScaler );
  2659.             break;
  2660.         case "rocketlauncher":
  2661.             self setMoveSpeedScale( 0.80 * self.moveSpeedScaler );
  2662.             break;
  2663.         case "sniper":
  2664.             self setMoveSpeedScale( 1.0 * self.moveSpeedScaler );
  2665.             break;
  2666.         default:
  2667.             self setMoveSpeedScale( 1.0 * self.moveSpeedScaler );
  2668.             break;
  2669.     }
  2670. }
  2671.  
  2672.  
  2673. buildWeaponData( filterPerks )
  2674. {
  2675.     attachmentList = getAttachmentList();      
  2676.     max_weapon_num = 149;
  2677.  
  2678.     baseWeaponData = [];
  2679.    
  2680.     for( weaponId = 0; weaponId <= max_weapon_num; weaponId++ )
  2681.     {
  2682.         baseName = tablelookup( "mp/statstable.csv", 0, weaponId, 4 );
  2683.         if( baseName == "" )
  2684.             continue;
  2685.  
  2686.         assetName = baseName + "_mp";
  2687.  
  2688.         if ( !isSubStr( tableLookup( "mp/statsTable.csv", 0, weaponId, 2 ), "weapon_" ) )
  2689.             continue;
  2690.        
  2691.         if ( weaponInventoryType( assetName ) != "primary" )
  2692.             continue;
  2693.  
  2694.         weaponInfo = spawnStruct();
  2695.         weaponInfo.baseName = baseName;
  2696.         weaponInfo.assetName = assetName;
  2697.         weaponInfo.variants = [];
  2698.  
  2699.         weaponInfo.variants[0] = assetName;
  2700.         // the alphabetize function is slow so we try not to do it for every weapon/attachment combo; a code solution would be better.
  2701.         attachmentNames = [];
  2702.         for ( innerLoopCount = 0; innerLoopCount < 6; innerLoopCount++ )
  2703.         {
  2704.             // generating attachment combinations
  2705.             attachmentName = tablelookup( "mp/statStable.csv", 0, weaponId, innerLoopCount + 11 );
  2706.            
  2707.             if ( filterPerks )
  2708.             {
  2709.                 switch ( attachmentName )
  2710.                 {
  2711.                     case "fmj":
  2712.                     case "xmags":
  2713.                     case "rof":
  2714.                         continue;
  2715.                 }
  2716.             }
  2717.            
  2718.             if( attachmentName == "" )
  2719.                 break;
  2720.            
  2721.             attachmentNames[attachmentName] = true;
  2722.         }
  2723.  
  2724.         // generate an alphabetized attachment list
  2725.         attachments = [];
  2726.         foreach ( attachmentName in attachmentList )
  2727.         {
  2728.             if ( !isDefined( attachmentNames[attachmentName] ) )
  2729.                 continue;
  2730.            
  2731.             weaponInfo.variants[weaponInfo.variants.size] = baseName + "_" + attachmentName + "_mp";
  2732.             attachments[attachments.size] = attachmentName;
  2733.         }
  2734.  
  2735.         for ( i = 0; i < (attachments.size - 1); i++ )
  2736.         {
  2737.             colIndex = tableLookupRowNum( "mp/attachmentCombos.csv", 0, attachments[i] );
  2738.             for ( j = i + 1; j < attachments.size; j++ )
  2739.             {
  2740.                 if ( tableLookup( "mp/attachmentCombos.csv", 0, attachments[j], colIndex ) == "no" )
  2741.                     continue;
  2742.                    
  2743.                 weaponInfo.variants[weaponInfo.variants.size] = baseName + "_" + attachments[i] + "_" + attachments[j] + "_mp";
  2744.             }
  2745.         }
  2746.        
  2747.         baseWeaponData[baseName] = weaponInfo;
  2748.     }
  2749.    
  2750.     return ( baseWeaponData );
  2751. }
  2752.  
  2753. monitorSemtex()
  2754. {
  2755.     self endon( "disconnect" );
  2756.     self endon( "death" );
  2757.    
  2758.     for( ;; )
  2759.     {
  2760.         self waittill( "grenade_fire", weapon );
  2761.  
  2762.         if ( !isSubStr(weapon.model, "semtex" ) )
  2763.             continue;
  2764.            
  2765.         weapon waittill( "missile_stuck", stuckTo );
  2766.            
  2767.         if ( !isPlayer( stuckTo ) )
  2768.             continue;
  2769.            
  2770.         if ( level.teamBased && isDefined( stuckTo.team ) && stuckTo.team == self.team )
  2771.         {
  2772.             weapon.isStuck = "friendly";
  2773.             continue;
  2774.         }
  2775.    
  2776.         weapon.isStuck = "enemy";
  2777.         weapon.stuckEnemyEntity = stuckTo;
  2778.        
  2779.         stuckTo maps\mp\gametypes\_hud_message::playerCardSplashNotify( "semtex_stuck", self );
  2780.        
  2781.         self thread maps\mp\gametypes\_hud_message::SplashNotify( "stuck_semtex", 100 );
  2782.         self notify( "process", "ch_bullseye" );
  2783.     }  
  2784. }
  2785.  
  2786.  
  2787. turret_monitorUse()
  2788. {
  2789.     for( ;; )
  2790.     {
  2791.         self waittill ( "trigger", player );
  2792.        
  2793.         self thread turret_playerThread( player );
  2794.     }
  2795. }
  2796.  
  2797. turret_playerThread( player )
  2798. {
  2799.     player endon ( "death" );
  2800.     player endon ( "disconnect" );
  2801.  
  2802.     player notify ( "weapon_change", "none" );
  2803.    
  2804.     self waittill ( "turret_deactivate" );
  2805.    
  2806.     player notify ( "weapon_change", player getCurrentWeapon() );
  2807. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement