Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include common_scripts\utility;
- #include maps\mp\_utility;
- attachmentGroup( attachmentName )
- {
- return tableLookup( "mp/attachmentTable.csv", 4, attachmentName, 2 );
- }
- getAttachmentList()
- {
- attachmentList = [];
- index = 0;
- attachmentName = tableLookup( "mp/attachmentTable.csv", 9, index, 4 );
- while ( attachmentName != "" )
- {
- attachmentList[attachmentList.size] = attachmentName;
- index++;
- attachmentName = tableLookup( "mp/attachmentTable.csv", 9, index, 4 );
- }
- return alphabetize( attachmentList );
- }
- init()
- {
- level.scavenger_altmode = true;
- level.scavenger_secondary = true;
- // 0 is not valid
- level.maxPerPlayerExplosives = max( getIntProperty( "scr_maxPerPlayerExplosives", 2 ), 1 );
- level.riotShieldXPBullets = getIntProperty( "scr_riotShieldXPBullets", 15 );
- switch ( getIntProperty( "perk_scavengerMode", 0 ) )
- {
- case 1: // disable altmode
- level.scavenger_altmode = false;
- break;
- case 2: // disable secondary
- level.scavenger_secondary = false;
- break;
- case 3: // disable altmode and secondary
- level.scavenger_altmode = false;
- level.scavenger_secondary = false;
- break;
- }
- attachmentList = getAttachmentList();
- // assigns weapons with stat numbers from 0-149
- // attachments are now shown here, they are per weapon settings instead
- max_weapon_num = 149;
- level.weaponList = [];
- for( weaponId = 0; weaponId <= max_weapon_num; weaponId++ )
- {
- weapon_name = tablelookup( "mp/statstable.csv", 0, weaponId, 4 );
- if( weapon_name == "" )
- continue;
- if ( !isSubStr( tableLookup( "mp/statsTable.csv", 0, weaponId, 2 ), "weapon_" ) )
- continue;
- level.weaponList[level.weaponList.size] = weapon_name + "_mp";
- /#
- if ( getDvar( "scr_dump_weapon_assets" ) != "" )
- {
- printLn( "" );
- printLn( "// " + weapon_name + " real assets" );
- printLn( "weapon,mp/" + weapon_name + "_mp" );
- }
- #/
- // the alphabetize function is slow so we try not to do it for every weapon/attachment combo; a code solution would be better.
- attachmentNames = [];
- for ( innerLoopCount = 0; innerLoopCount < 10; innerLoopCount++ )
- {
- // generating attachment combinations
- attachmentName = tablelookup( "mp/statStable.csv", 0, weaponId, innerLoopCount + 11 );
- if( attachmentName == "" )
- break;
- attachmentNames[attachmentName] = true;
- }
- // generate an alphabetized attachment list
- attachments = [];
- foreach ( attachmentName in attachmentList )
- {
- if ( !isDefined( attachmentNames[attachmentName] ) )
- continue;
- level.weaponList[level.weaponList.size] = weapon_name + "_" + attachmentName + "_mp";
- attachments[attachments.size] = attachmentName;
- /#
- if ( getDvar( "scr_dump_weapon_assets" ) != "" )
- println( "weapon,mp/" + weapon_name + "_" + attachmentName + "_mp" );
- #/
- }
- attachmentCombos = [];
- for ( i = 0; i < (attachments.size - 1); i++ )
- {
- colIndex = tableLookupRowNum( "mp/attachmentCombos.csv", 0, attachments[i] );
- for ( j = i + 1; j < attachments.size; j++ )
- {
- if ( tableLookup( "mp/attachmentCombos.csv", 0, attachments[j], colIndex ) == "no" )
- continue;
- attachmentCombos[attachmentCombos.size] = attachments[i] + "_" + attachments[j];
- }
- }
- /#
- if ( getDvar( "scr_dump_weapon_assets" ) != "" && attachmentCombos.size )
- println( "// " + weapon_name + " virtual assets" );
- #/
- foreach ( combo in attachmentCombos )
- {
- /#
- if ( getDvar( "scr_dump_weapon_assets" ) != "" )
- println( "weapon,mp/" + weapon_name + "_" + combo + "_mp" );
- #/
- level.weaponList[level.weaponList.size] = weapon_name + "_" + combo + "_mp";
- }
- }
- foreach ( weaponName in level.weaponList )
- {
- precacheItem( weaponName );
- /#
- if ( getDvar( "scr_dump_weapon_assets" ) != "" )
- {
- altWeapon = weaponAltWeaponName( weaponName );
- if ( altWeapon != "none" )
- println( "weapon,mp/" + altWeapon );
- }
- #/
- }
- precacheItem( "flare_mp" );
- precacheItem( "scavenger_bag_mp" );
- precacheItem( "frag_grenade_short_mp" );
- precacheItem( "destructible_car" );
- precacheShellShock( "default" );
- precacheShellShock( "concussion_grenade_mp" );
- thread maps\mp\_flashgrenades::main();
- thread maps\mp\_entityheadicons::init();
- claymoreDetectionConeAngle = 70;
- level.claymoreDetectionDot = cos( claymoreDetectionConeAngle );
- level.claymoreDetectionMinDist = 20;
- level.claymoreDetectionGracePeriod = .75;
- level.claymoreDetonateRadius = 192;
- // this should move to _stinger.gsc
- level.stingerFXid = loadfx ("explosions/aerial_explosion_large");
- // generating weapon type arrays which classifies the weapon as primary (back stow), pistol, or inventory (side pack stow)
- // using mp/statstable.csv's weapon grouping data ( numbering 0 - 149 )
- level.primary_weapon_array = [];
- level.side_arm_array = [];
- level.grenade_array = [];
- level.inventory_array = [];
- level.stow_priority_model_array = [];
- level.stow_offset_array = [];
- max_weapon_num = 149;
- for( i = 0; i < max_weapon_num; i++ )
- {
- weapon = tableLookup( "mp/statsTable.csv", 0, i, 4 );
- stow_model = tableLookup( "mp/statsTable.csv", 0, i, 9 );
- if ( stow_model == "" )
- continue;
- precacheModel( stow_model );
- if ( isSubStr( stow_model, "weapon_stow_" ) )
- level.stow_offset_array[ weapon ] = stow_model;
- else
- level.stow_priority_model_array[ weapon + "_mp" ] = stow_model;
- }
- precacheModel( "weapon_claymore_bombsquad" );
- precacheModel( "weapon_c4_bombsquad" );
- precacheModel( "projectile_m67fraggrenade_bombsquad" );
- precacheModel( "projectile_semtex_grenade_bombsquad" );
- precacheModel( "weapon_light_stick_tactical_bombsquad" );
- level.killStreakSpecialCaseWeapons = [];
- level.killStreakSpecialCaseWeapons["cobra_player_minigun_mp"] = true;
- level.killStreakSpecialCaseWeapons["artillery_mp"] = true;
- level.killStreakSpecialCaseWeapons["stealth_bomb_mp"] = true;
- level.killStreakSpecialCaseWeapons["pavelow_minigun_mp"] = true;
- level.killStreakSpecialCaseWeapons["sentry_minigun_mp"] = true;
- level.killStreakSpecialCaseWeapons["harrier_20mm_mp"] = true;
- level.killStreakSpecialCaseWeapons["ac130_105mm_mp"] = true;
- level.killStreakSpecialCaseWeapons["ac130_40mm_mp"] = true;
- level.killStreakSpecialCaseWeapons["ac130_25mm_mp"] = true;
- level.killStreakSpecialCaseWeapons["remotemissile_projectile_mp"] = true;
- level.killStreakSpecialCaseWeapons["cobra_20mm_mp"] = true;
- level.killStreakSpecialCaseWeapons["sentry_minigun_mp"] = true;
- level thread onPlayerConnect();
- level.c4explodethisframe = false;
- array_thread( getEntArray( "misc_turret", "classname" ), ::turret_monitorUse );
- // thread dumpIt();
- }
- dumpIt()
- {
- wait ( 5.0 );
- /#
- max_weapon_num = 149;
- for( weaponId = 0; weaponId <= max_weapon_num; weaponId++ )
- {
- weapon_name = tablelookup( "mp/statstable.csv", 0, weaponId, 4 );
- if( weapon_name == "" )
- continue;
- if ( !isSubStr( tableLookup( "mp/statsTable.csv", 0, weaponId, 2 ), "weapon_" ) )
- continue;
- if ( getDvar( "scr_dump_weapon_challenges" ) != "" )
- {
- /*
- sharpshooter
- marksman
- veteran
- expert
- master
- */
- weaponLStringName = tableLookup( "mp/statsTable.csv", 0, weaponId, 3 );
- weaponRealName = tableLookupIString( "mp/statsTable.csv", 0, weaponId, 3 );
- prefix = "WEAPON_";
- weaponCapsName = getSubStr( weaponLStringName, prefix.size, weaponLStringName.size );
- weaponGroup = tableLookup( "mp/statsTable.csv", 0, weaponId, 2 );
- weaponGroupSuffix = getSubStr( weaponGroup, prefix.size, weaponGroup.size );
- /*
- iprintln( "REFERENCE TITLE_" + weaponCapsName + "_SHARPSHOOTER" );
- iprintln( "LANG_ENGLISH ", weaponRealName, ": Sharpshooter" );
- iprintln( "" );
- iprintln( "REFERENCE TITLE_" + weaponCapsName + "_MARKSMAN" );
- iprintln( "LANG_ENGLISH ", weaponRealName, ": Marksman" );
- iprintln( "" );
- iprintln( "REFERENCE TITLE_" + weaponCapsName + "_VETERAN" );
- iprintln( "LANG_ENGLISH ", weaponRealName, ": Veteran" );
- iprintln( "" );
- iprintln( "REFERENCE TITLE_" + weaponCapsName + "_EXPERT" );
- iprintln( "LANG_ENGLISH ", weaponRealName, ": Expert" );
- iprintln( "" );
- iprintln( "REFERENCE TITLE_" + weaponCapsName + "_Master" );
- iprintln( "LANG_ENGLISH ", weaponRealName, ": Master" );
- */
- iprintln( "cardtitle_" + weapon_name + "_sharpshooter,PLAYERCARDS_TITLE_" + weaponCapsName + "_SHARPSHOOTER,cardtitle_" + weaponGroupSuffix + "_sharpshooter,1,1,1" );
- iprintln( "cardtitle_" + weapon_name + "_marksman,PLAYERCARDS_TITLE_" + weaponCapsName + "_MARKSMAN,cardtitle_" + weaponGroupSuffix + "_marksman,1,1,1" );
- iprintln( "cardtitle_" + weapon_name + "_veteran,PLAYERCARDS_TITLE_" + weaponCapsName + "_VETERAN,cardtitle_" + weaponGroupSuffix + "_veteran,1,1,1" );
- iprintln( "cardtitle_" + weapon_name + "_expert,PLAYERCARDS_TITLE_" + weaponCapsName + "_EXPERT,cardtitle_" + weaponGroupSuffix + "_expert,1,1,1" );
- iprintln( "cardtitle_" + weapon_name + "_master,PLAYERCARDS_TITLE_" + weaponCapsName + "_MASTER,cardtitle_" + weaponGroupSuffix + "_master,1,1,1" );
- wait ( 0.05 );
- }
- }
- #/
- }
- bombSquadWaiter()
- {
- self endon ( "disconnect" );
- for ( ;; )
- {
- self waittill ( "grenade_fire", weaponEnt, weaponName );
- team = level.otherTeam[self.team];
- if ( weaponName == "c4_mp" )
- weaponEnt thread createBombSquadModel( "weapon_c4_bombsquad", "tag_origin", team, self );
- else if ( weaponName == "claymore_mp" )
- weaponEnt thread createBombSquadModel( "weapon_claymore_bombsquad", "tag_origin", team, self );
- else if ( weaponName == "frag_grenade_mp" )
- weaponEnt thread createBombSquadModel( "projectile_m67fraggrenade_bombsquad", "tag_weapon", team, self );
- else if ( weaponName == "frag_grenade_short_mp" )
- weaponEnt thread createBombSquadModel( "projectile_m67fraggrenade_bombsquad", "tag_weapon", team, self );
- else if ( weaponName == "semtex_mp" )
- weaponEnt thread createBombSquadModel( "projectile_semtex_grenade_bombsquad", "tag_weapon", team, self );
- }
- }
- createBombSquadModel( modelName, tagName, teamName, owner )
- {
- bombSquadModel = spawn( "script_model", (0,0,0) );
- bombSquadModel hide();
- wait ( 0.05 );
- if (!isDefined( self ) ) //grenade model may not be around if picked up
- return;
- bombSquadModel thread bombSquadVisibilityUpdater( teamName, owner );
- bombSquadModel setModel( modelName );
- bombSquadModel linkTo( self, tagName, (0,0,0), (0,0,0) );
- bombSquadModel SetContents( 0 );
- self waittill ( "death" );
- bombSquadModel delete();
- }
- bombSquadVisibilityUpdater( teamName, owner )
- {
- self endon ( "death" );
- foreach ( player in level.players )
- {
- if ( level.teamBased )
- {
- if ( player.team == teamName && player _hasPerk( "specialty_detectexplosive" ) )
- self showToPlayer( player );
- }
- else
- {
- if ( isDefined( owner ) && player == owner )
- continue;
- if ( !player _hasPerk( "specialty_detectexplosive" ) )
- continue;
- self showToPlayer( player );
- }
- }
- for ( ;; )
- {
- level waittill_any( "joined_team", "player_spawned", "changed_kit" );
- self hide();
- foreach ( player in level.players )
- {
- if ( level.teamBased )
- {
- if ( player.team == teamName && player _hasPerk( "specialty_detectexplosive" ) )
- self showToPlayer( player );
- }
- else
- {
- if ( isDefined( owner ) && player == owner )
- continue;
- if ( !player _hasPerk( "specialty_detectexplosive" ) )
- continue;
- self showToPlayer( player );
- }
- }
- }
- }
- onPlayerConnect()
- {
- for(;;)
- {
- level waittill("connected", player);
- player.hits = 0;
- player.hasDoneCombat = false;
- player KC_RegWeaponForFXRemoval( "remotemissile_projectile_mp" );
- player thread onPlayerSpawned();
- player thread bombSquadWaiter();
- }
- }
- onPlayerSpawned()
- {
- self endon("disconnect");
- for(;;)
- {
- self waittill("spawned_player");
- self.currentWeaponAtSpawn = self getCurrentWeapon(); // optimization so these threads we start don't have to call it.
- self.empEndTime = 0;
- self.concussionEndTime = 0;
- self.hasDoneCombat = false;
- self thread watchWeaponUsage();
- self thread watchGrenadeUsage();
- self thread watchWeaponChange();
- self thread watchStingerUsage();
- self thread watchJavelinUsage();
- self thread watchMissileUsage();
- self thread watchSentryUsage();
- self thread watchWeaponReload();
- self thread maps\mp\gametypes\_class::trackRiotShield();
- self.lastHitTime = [];
- self.droppedDeathWeapon = undefined;
- self.tookWeaponFrom = [];
- self thread updateStowedWeapon();
- self thread updateSavedLastWeapon();
- if ( self hasWeapon( "semtex_mp" ) )
- self thread monitorSemtex();
- self.currentWeaponAtSpawn = undefined;
- }
- }
- WatchStingerUsage()
- {
- self maps\mp\_stinger::StingerUsageLoop();
- }
- WatchJavelinUsage()
- {
- self maps\mp\_javelin::JavelinUsageLoop();
- }
- watchWeaponChange()
- {
- self endon("death");
- self endon("disconnect");
- self thread watchStartWeaponChange();
- self.lastDroppableWeapon = self.currentWeaponAtSpawn;
- self.hitsThisMag = [];
- weapon = self getCurrentWeapon();
- if ( isCACPrimaryWeapon( weapon ) && !isDefined( self.hitsThisMag[ weapon ] ) )
- self.hitsThisMag[ weapon ] = weaponClipSize( weapon );
- self.bothBarrels = undefined;
- if ( isSubStr( weapon, "ranger" ) )
- self thread watchRangerUsage( weapon );
- while(1)
- {
- self waittill( "weapon_change", newWeapon );
- tokedNewWeapon = StrTok( newWeapon, "_" );
- self.bothBarrels = undefined;
- if ( isSubStr( newWeapon, "ranger" ) )
- self thread watchRangerUsage( newWeapon );
- if ( tokedNewWeapon[0] == "gl" || ( tokedNewWeapon.size > 2 && tokedNewWeapon[2] == "attach" ) )
- newWeapon = self getCurrentPrimaryWeapon();
- if ( newWeapon != "none" )
- {
- if ( isCACPrimaryWeapon( newWeapon ) && !isDefined( self.hitsThisMag[ newWeapon ] ) )
- self.hitsThisMag[ newWeapon ] = weaponClipSize( newWeapon );
- }
- self.changingWeapon = undefined;
- if ( mayDropWeapon( newWeapon ) )
- self.lastDroppableWeapon = newWeapon;
- }
- }
- watchStartWeaponChange()
- {
- self endon("death");
- self endon("disconnect");
- self.changingWeapon = undefined;
- while(1)
- {
- self waittill( "weapon_switch_started", newWeapon );
- self.changingWeapon = newWeapon;
- }
- }
- watchWeaponReload()
- {
- self endon("death");
- self endon("disconnect");
- for ( ;; )
- {
- self waittill( "reload" );
- weaponName = self getCurrentWeapon();
- self.bothBarrels = undefined;
- if ( !isSubStr( weaponName, "ranger" ) )
- continue;
- self thread watchRangerUsage( weaponName );
- }
- }
- watchRangerUsage( rangerName )
- {
- rightAmmo = self getWeaponAmmoClip( rangerName, "right" );
- leftAmmo = self getWeaponAmmoClip( rangerName, "left" );
- self endon ( "reload" );
- self endon ( "weapon_change" );
- for ( ;; )
- {
- self waittill ( "weapon_fired", weaponName );
- if ( weaponName != rangerName )
- continue;
- self.bothBarrels = undefined;
- if ( isSubStr( rangerName, "akimbo" ) )
- {
- newLeftAmmo = self getWeaponAmmoClip( rangerName, "left" );
- newRightAmmo = self getWeaponAmmoClip( rangerName, "right" );
- if ( leftAmmo != newLeftAmmo && rightAmmo != newRightAmmo )
- self.bothBarrels = true;
- if ( !newLeftAmmo || !newRightAmmo )
- return;
- leftAmmo = newLeftAmmo;
- rightAmmo = newRightAmmo;
- }
- else if ( rightAmmo == 2 && !self getWeaponAmmoClip( rangerName, "right" ) )
- {
- self.bothBarrels = true;
- return;
- }
- }
- }
- isHackWeapon( weapon )
- {
- if ( weapon == "radar_mp" || weapon == "airstrike_mp" || weapon == "helicopter_mp" )
- return true;
- if ( weapon == "briefcase_bomb_mp" )
- return true;
- return false;
- }
- mayDropWeapon( weapon )
- {
- if ( weapon == "none" )
- return false;
- if ( isSubStr( weapon, "ac130" ) )
- return false;
- invType = WeaponInventoryType( weapon );
- if ( invType != "primary" )
- return false;
- return true;
- }
- dropWeaponForDeath( attacker )
- {
- weapon = self.lastDroppableWeapon;
- if ( isdefined( self.droppedDeathWeapon ) )
- return;
- if ( level.inGracePeriod )
- return;
- if ( !isdefined( weapon ) )
- {
- /#
- if ( getdvar("scr_dropdebug") == "1" )
- println( "didn't drop weapon: not defined" );
- #/
- return;
- }
- if ( weapon == "none" )
- {
- /#
- if ( getdvar("scr_dropdebug") == "1" )
- println( "didn't drop weapon: weapon == none" );
- #/
- return;
- }
- if ( !self hasWeapon( weapon ) )
- {
- /#
- if ( getdvar("scr_dropdebug") == "1" )
- println( "didn't drop weapon: don't have it anymore (" + weapon + ")" );
- #/
- return;
- }
- if ( weapon != "riotshield_mp" )
- {
- if ( !(self AnyAmmoForWeaponModes( weapon )) )
- {
- /#
- if ( getdvar("scr_dropdebug") == "1" )
- println( "didn't drop weapon: no ammo for weapon modes" );
- #/
- return;
- }
- clipAmmoR = self GetWeaponAmmoClip( weapon, "right" );
- clipAmmoL = self GetWeaponAmmoClip( weapon, "left" );
- if ( !clipAmmoR && !clipAmmoL )
- {
- /#
- if ( getdvar("scr_dropdebug") == "1" )
- println( "didn't drop weapon: no ammo in clip" );
- #/
- return;
- }
- stockAmmo = self GetWeaponAmmoStock( weapon );
- stockMax = WeaponMaxAmmo( weapon );
- if ( stockAmmo > stockMax )
- stockAmmo = stockMax;
- item = self dropItem( weapon );
- item ItemWeaponSetAmmo( clipAmmoR, stockAmmo, clipAmmoL );
- }
- else
- {
- item = self dropItem( weapon );
- if ( !isDefined( item ) )
- return;
- item ItemWeaponSetAmmo( 1, 1, 0 );
- }
- /#
- if ( getdvar("scr_dropdebug") == "1" )
- println( "dropped weapon: " + weapon );
- #/
- self.droppedDeathWeapon = true;
- item.owner = self;
- item.ownersattacker = attacker;
- item thread watchPickup();
- item thread deletePickupAfterAWhile();
- detach_model = getWeaponModel( weapon );
- if ( !isDefined( detach_model ) )
- return;
- if( isDefined( self.tag_stowed_back ) && detach_model == self.tag_stowed_back )
- self detach_back_weapon();
- if ( !isDefined( self.tag_stowed_hip ) )
- return;
- if( detach_model == self.tag_stowed_hip )
- self detach_hip_weapon();
- }
- detachIfAttached( model, baseTag )
- {
- attachSize = self getAttachSize();
- for ( i = 0; i < attachSize; i++ )
- {
- attach = self getAttachModelName( i );
- if ( attach != model )
- continue;
- tag = self getAttachTagName( i );
- self detach( model, tag );
- if ( tag != baseTag )
- {
- attachSize = self getAttachSize();
- for ( i = 0; i < attachSize; i++ )
- {
- tag = self getAttachTagName( i );
- if ( tag != baseTag )
- continue;
- model = self getAttachModelName( i );
- self detach( model, tag );
- break;
- }
- }
- return true;
- }
- return false;
- }
- deletePickupAfterAWhile()
- {
- self endon("death");
- wait 60;
- if ( !isDefined( self ) )
- return;
- self delete();
- }
- getItemWeaponName()
- {
- classname = self.classname;
- assert( getsubstr( classname, 0, 7 ) == "weapon_" );
- weapname = getsubstr( classname, 7 );
- return weapname;
- }
- watchPickup()
- {
- self endon("death");
- weapname = self getItemWeaponName();
- while(1)
- {
- self waittill( "trigger", player, droppedItem );
- if ( isdefined( droppedItem ) )
- break;
- // otherwise, player merely acquired ammo and didn't pick this up
- }
- /#
- if ( getdvar("scr_dropdebug") == "1" )
- println( "picked up weapon: " + weapname + ", " + isdefined( self.ownersattacker ) );
- #/
- assert( isdefined( player.tookWeaponFrom ) );
- // make sure the owner information on the dropped item is preserved
- droppedWeaponName = droppedItem getItemWeaponName();
- if ( isdefined( player.tookWeaponFrom[ droppedWeaponName ] ) )
- {
- droppedItem.owner = player.tookWeaponFrom[ droppedWeaponName ];
- droppedItem.ownersattacker = player;
- player.tookWeaponFrom[ droppedWeaponName ] = undefined;
- }
- droppedItem thread watchPickup();
- // take owner information from self and put it onto player
- if ( isdefined( self.ownersattacker ) && self.ownersattacker == player )
- {
- player.tookWeaponFrom[ weapname ] = self.owner;
- }
- else
- {
- player.tookWeaponFrom[ weapname ] = undefined;
- }
- }
- itemRemoveAmmoFromAltModes()
- {
- origweapname = self getItemWeaponName();
- curweapname = weaponAltWeaponName( origweapname );
- altindex = 1;
- while ( curweapname != "none" && curweapname != origweapname )
- {
- self itemWeaponSetAmmo( 0, 0, 0, altindex );
- curweapname = weaponAltWeaponName( curweapname );
- altindex++;
- }
- }
- handleScavengerBagPickup( scrPlayer )
- {
- self endon( "death" );
- level endon ( "game_ended" );
- assert( isDefined( scrPlayer ) );
- // Wait for the pickup to happen
- self waittill( "scavenger", destPlayer );
- assert( isDefined ( destPlayer ) );
- destPlayer notify( "scavenger_pickup" );
- destPlayer playLocalSound( "scavenger_pack_pickup" );
- offhandWeapons = destPlayer getWeaponsListOffhands();
- if ( destPlayer _hasPerk( "specialty_tacticalinsertion" ) && destPlayer getAmmoCount( "flare_mp" ) < 1 )
- destPlayer _setPerk( "specialty_tacticalinsertion");
- foreach ( offhand in offhandWeapons )
- {
- currentClipAmmo = destPlayer GetWeaponAmmoClip( offhand );
- destPlayer SetWeaponAmmoClip( offhand, currentClipAmmo + 1);
- }
- primaryWeapons = destPlayer getWeaponsListPrimaries();
- foreach ( primary in primaryWeapons )
- {
- if ( !isCACPrimaryWeapon( primary ) && !level.scavenger_secondary )
- continue;
- currentStockAmmo = destPlayer GetWeaponAmmoStock( primary );
- addStockAmmo = weaponClipSize( primary );
- destPlayer setWeaponAmmoStock( primary, currentStockAmmo + addStockAmmo );
- altWeapon = weaponAltWeaponName( primary );
- if ( !isDefined( altWeapon ) || (altWeapon == "none") || !level.scavenger_altmode )
- continue;
- currentStockAmmo = destPlayer GetWeaponAmmoStock( altWeapon );
- addStockAmmo = weaponClipSize( altWeapon );
- destPlayer setWeaponAmmoStock( altWeapon, currentStockAmmo + addStockAmmo );
- }
- destPlayer maps\mp\gametypes\_damagefeedback::updateDamageFeedback( "scavenger" );
- }
- dropScavengerForDeath( attacker )
- {
- if ( level.inGracePeriod )
- return;
- if( !isDefined( attacker ) )
- return;
- if( attacker == self )
- return;
- dropBag = self dropScavengerBag( "scavenger_bag_mp" );
- dropBag thread handleScavengerBagPickup( self );
- }
- getWeaponBasedGrenadeCount(weapon)
- {
- return 2;
- }
- getWeaponBasedSmokeGrenadeCount(weapon)
- {
- return 1;
- }
- getFragGrenadeCount()
- {
- grenadetype = "frag_grenade_mp";
- count = self getammocount(grenadetype);
- return count;
- }
- getSmokeGrenadeCount()
- {
- grenadetype = "smoke_grenade_mp";
- count = self getammocount(grenadetype);
- return count;
- }
- watchWeaponUsage( weaponHand )
- {
- self endon( "death" );
- self endon( "disconnect" );
- level endon ( "game_ended" );
- for ( ;; )
- {
- self waittill ( "weapon_fired", weaponName );
- self.hasDoneCombat = true;
- if ( !maps\mp\gametypes\_weapons::isPrimaryWeapon( weaponName ) && !maps\mp\gametypes\_weapons::isSideArm( weaponName ) )
- continue;
- if ( isDefined( self.hitsThisMag[ weaponName ] ) )
- self thread updateMagShots( weaponName );
- totalShots = self maps\mp\gametypes\_persistence::statGetBuffered( "totalShots" ) + 1;
- hits = self maps\mp\gametypes\_persistence::statGetBuffered( "hits" );
- self maps\mp\gametypes\_persistence::statSetBuffered( "totalShots", totalShots );
- self maps\mp\gametypes\_persistence::statSetBuffered( "accuracy", int(hits * 10000 / totalShots) );
- self maps\mp\gametypes\_persistence::statSetBuffered( "misses", int(totalShots - hits) );
- }
- }
- updateMagShots( weaponName )
- {
- self endon ( "death" );
- self endon ( "disconnect" );
- self endon ( "updateMagShots_" + weaponName );
- self.hitsThisMag[ weaponName ]--;
- wait ( 0.05 );
- self.hitsThisMag[ weaponName ] = weaponClipSize( weaponName );
- }
- checkHitsThisMag( weaponName )
- {
- self endon ( "death" );
- self endon ( "disconnect" );
- self notify ( "updateMagShots_" + weaponName );
- waittillframeend;
- if ( self.hitsThisMag[ weaponName ] == 0 )
- {
- weaponClass = getWeaponClass( weaponName );
- maps\mp\gametypes\_missions::genericChallenge( weaponClass );
- self.hitsThisMag[ weaponName ] = weaponClipSize( weaponName );
- }
- }
- checkHit( weaponName, victim )
- {
- if ( !maps\mp\gametypes\_weapons::isPrimaryWeapon( weaponName ) && !maps\mp\gametypes\_weapons::isSideArm( weaponName ) )
- return;
- // sometimes the "weapon_fired" notify happens after we hit the guy...
- waittillframeend;
- if ( isDefined( self.hitsThisMag[ weaponName ] ) )
- self thread checkHitsThisMag( weaponName );
- if ( !isDefined( self.lastHitTime[ weaponName ] ) )
- self.lastHitTime[ weaponName ] = 0;
- // already hit with this weapon on this frame
- if ( self.lastHitTime[ weaponName ] == getTime() )
- return;
- self.lastHitTime[ weaponName ] = getTime();
- totalShots = self maps\mp\gametypes\_persistence::statGetBuffered( "totalShots" );
- hits = self maps\mp\gametypes\_persistence::statGetBuffered( "hits" ) + 1;
- if ( hits <= totalShots )
- {
- self maps\mp\gametypes\_persistence::statSetBuffered( "hits", hits );
- self maps\mp\gametypes\_persistence::statSetBuffered( "misses", int(totalShots - hits) );
- self maps\mp\gametypes\_persistence::statSetBuffered( "accuracy", int(hits * 10000 / totalShots) );
- }
- }
- attackerCanDamageItem( attacker, itemOwner )
- {
- return friendlyFireCheck( itemOwner, attacker );
- }
- // returns true if damage should be done to the item given its owner and the attacker
- friendlyFireCheck( owner, attacker, forcedFriendlyFireRule )
- {
- if ( !isdefined( owner ) )// owner has disconnected? allow it
- return true;
- if ( !level.teamBased )// not a team based mode? allow it
- return true;
- attackerTeam = attacker.team;
- friendlyFireRule = level.friendlyfire;
- if ( isdefined( forcedFriendlyFireRule ) )
- friendlyFireRule = forcedFriendlyFireRule;
- if ( friendlyFireRule != 0 )// friendly fire is on? allow it
- return true;
- if ( attacker == owner )// owner may attack his own items
- return true;
- if ( !isdefined( attackerTeam ) )// attacker not on a team? allow it
- return true;
- if ( attackerTeam != owner.team )// attacker not on the same team as the owner? allow it
- return true;
- return false;// disallow it
- }
- watchGrenadeUsage()
- {
- self endon( "death" );
- self endon( "disconnect" );
- self.throwingGrenade = undefined;
- self.gotPullbackNotify = false;
- if ( getIntProperty( "scr_deleteexplosivesonspawn", 1 ) == 1 )
- {
- // delete c4 from previous spawn
- if ( isdefined( self.c4array ) )
- {
- for ( i = 0; i < self.c4array.size; i++ )
- {
- if ( isdefined( self.c4array[ i ] ) )
- self.c4array[ i ] delete();
- }
- }
- self.c4array = [];
- // delete claymores from previous spawn
- if ( isdefined( self.claymorearray ) )
- {
- for ( i = 0; i < self.claymorearray.size; i++ )
- {
- if ( isdefined( self.claymorearray[ i ] ) )
- self.claymorearray[ i ] delete();
- }
- }
- self.claymorearray = [];
- }
- else
- {
- if ( !isdefined( self.c4array ) )
- self.c4array = [];
- if ( !isdefined( self.claymorearray ) )
- self.claymorearray = [];
- }
- thread watchC4();
- thread watchC4Detonation();
- thread watchC4AltDetonation();
- thread watchClaymores();
- thread deleteC4AndClaymoresOnDisconnect();
- self thread watchForThrowbacks();
- for ( ;; )
- {
- self waittill( "grenade_pullback", weaponName );
- self.hasDoneCombat = true;
- if ( weaponName == "claymore_mp" )
- continue;
- self.throwingGrenade = weaponName;
- self.gotPullbackNotify = true;
- if ( weaponName == "c4_mp" )
- self beginC4Tracking();
- else
- self beginGrenadeTracking();
- self.throwingGrenade = undefined;
- }
- }
- beginGrenadeTracking()
- {
- self endon( "death" );
- self endon( "disconnect" );
- self endon( "offhand_end" );
- self endon( "weapon_change" );
- startTime = getTime();
- self waittill( "grenade_fire", grenade, weaponName );
- if ( ( getTime() - startTime > 1000 ) && weaponName == "frag_grenade_mp" )
- grenade.isCooked = true;
- self.changingWeapon = undefined;
- if ( weaponName == "frag_grenade_mp" || weaponName == "semtex_mp" )
- {
- grenade thread maps\mp\gametypes\_shellshock::grenade_earthQuake();
- grenade.originalOwner = self;
- }
- if ( weaponName == "flash_grenade_mp" || weaponName == "concussion_grenade_mp" )
- {
- grenade.owner = self;
- grenade thread empExplodeWaiter();
- }
- }
- AddMissileToSightTraces( team )
- {
- self.team = team;
- level.missilesForSightTraces[ level.missilesForSightTraces.size ] = self;
- self waittill( "death" );
- newArray = [];
- foreach( missile in level.missilesForSightTraces )
- {
- if ( missile != self )
- newArray[ newArray.size ] = missile;
- }
- level.missilesForSightTraces = newArray;
- }
- watchMissileUsage()
- {
- self endon( "death" );
- self endon( "disconnect" );
- for ( ;; )
- {
- self waittill( "missile_fire", missile, weaponName );
- if ( isSubStr( weaponName, "gl_" ) )
- {
- missile.primaryWeapon = self getCurrentPrimaryWeapon();
- missile thread maps\mp\gametypes\_shellshock::grenade_earthQuake();
- }
- switch ( weaponName )
- {
- case "at4_mp":
- case "stinger_mp":
- level notify ( "stinger_fired", self, missile, self.stingerTarget );
- self thread setAltSceneObj( missile, "tag_origin", 65 );
- break;
- case "javelin_mp":
- level notify ( "stinger_fired", self, missile, self.javelinTarget );
- self thread setAltSceneObj( missile, "tag_origin", 65 );
- break;
- default:
- break;
- }
- switch ( weaponName )
- {
- case "at4_mp":
- case "javelin_mp":
- case "rpg_mp":
- case "ac130_105mm_mp":
- case "ac130_40mm_mp":
- case "remotemissile_projectile_mp":
- missile thread maps\mp\gametypes\_shellshock::grenade_earthQuake();
- default:
- break;
- }
- }
- }
- watchSentryUsage()
- {
- self endon( "death" );
- self endon( "disconnect" );
- for ( ;; )
- {
- self waittill( "sentry_placement_finished", sentry );
- self thread setAltSceneObj( sentry, "tag_flash", 65 );
- }
- }
- empExplodeWaiter()
- {
- self thread maps\mp\gametypes\_shellshock::endOnDeath();
- self endon( "end_explode" );
- self waittill( "explode", position );
- ents = getEMPDamageEnts( position, 512, false );
- foreach ( ent in ents )
- {
- if ( isDefined( ent.owner ) && !friendlyFireCheck( self.owner, ent.owner ) )
- continue;
- ent notify( "emp_damage", self.owner, 8.0 );
- }
- }
- beginC4Tracking()
- {
- self endon( "death" );
- self endon( "disconnect" );
- self waittill_any( "grenade_fire", "weapon_change", "offhand_end" );
- }
- watchForThrowbacks()
- {
- self endon( "death" );
- self endon( "disconnect" );
- for ( ;; )
- {
- self waittill( "grenade_fire", grenade, weapname );
- if ( self.gotPullbackNotify )
- {
- self.gotPullbackNotify = false;
- continue;
- }
- if ( !isSubStr( weapname, "frag_" ) && !isSubStr( weapname, "semtex_" ) )
- continue;
- // no grenade_pullback notify! we must have picked it up off the ground.
- grenade.threwBack = true;
- self thread incPlayerStat( "throwbacks", 1 );
- grenade thread maps\mp\gametypes\_shellshock::grenade_earthQuake();
- grenade.originalOwner = self;
- }
- }
- watchC4()
- {
- self endon( "spawned_player" );
- self endon( "disconnect" );
- //maxc4 = 2;
- while ( 1 )
- {
- self waittill( "grenade_fire", c4, weapname );
- if ( weapname == "c4" || weapname == "c4_mp" )
- {
- if ( !self.c4array.size )
- self thread watchC4AltDetonate();
- if ( self.c4array.size )
- {
- self.c4array = array_removeUndefined( self.c4array );
- if( self.c4array.size >= level.maxPerPlayerExplosives )
- {
- self.c4array[0] detonate();
- }
- }
- self.c4array[ self.c4array.size ] = c4;
- c4.owner = self;
- c4.team = self.team;
- c4.activated = false;
- c4.weaponName = weapname;
- c4 thread maps\mp\gametypes\_shellshock::c4_earthQuake();
- c4 thread c4Activate();
- c4 thread c4Damage();
- c4 thread c4EMPDamage();
- c4 thread c4EMPKillstreakWait();
- //c4 thread c4DetectionTrigger( self.pers[ "team" ] );
- }
- }
- }
- c4EMPDamage()
- {
- self endon( "death" );
- for ( ;; )
- {
- self waittill( "emp_damage", attacker, duration );
- playfxOnTag( getfx( "sentry_explode_mp" ), self, "tag_origin" );
- self.disabled = true;
- self notify( "disabled" );
- wait( duration );
- self.disabled = undefined;
- self notify( "enabled" );
- }
- }
- c4EMPKillstreakWait()
- {
- self endon( "death" );
- for ( ;; )
- {
- level waittill( "emp_update" );
- if ( (level.teamBased && level.teamEMPed[self.team]) || (!level.teamBased && isDefined( level.empPlayer ) && level.empPlayer != self.owner ) )
- {
- self.disabled = true;
- self notify( "disabled" );
- }
- else
- {
- self.disabled = undefined;
- self notify( "enabled" );
- }
- }
- }
- setClaymoreTeamHeadIcon( team )
- {
- self endon( "death" );
- wait .05;
- if ( level.teamBased )
- self maps\mp\_entityheadicons::setTeamHeadIcon( team, ( 0, 0, 20 ) );
- else if ( isDefined( self.owner ) )
- self maps\mp\_entityheadicons::setPlayerHeadIcon( self.owner, (0,0,20) );
- }
- watchClaymores()
- {
- self endon( "spawned_player" );
- self endon( "disconnect" );
- self.claymorearray = [];
- while ( 1 )
- {
- self waittill( "grenade_fire", claymore, weapname );
- if ( weapname == "claymore" || weapname == "claymore_mp" )
- {
- self.claymorearray = array_removeUndefined( self.claymorearray );
- if( self.claymoreArray.size >= level.maxPerPlayerExplosives )
- self.claymoreArray[0] detonate();
- self.claymorearray[ self.claymorearray.size ] = claymore;
- claymore.owner = self;
- claymore.team = self.team;
- claymore.weaponName = weapname;
- claymore thread c4Damage();
- claymore thread c4EMPDamage();
- claymore thread c4EMPKillstreakWait();
- claymore thread claymoreDetonation();
- //claymore thread claymoreDetectionTrigger_wait( self.pers[ "team" ] );
- claymore thread setClaymoreTeamHeadIcon( self.pers[ "team" ] );
- /#
- if ( getdvarint( "scr_claymoredebug" ) )
- {
- claymore thread claymoreDebug();
- }
- #/
- }
- }
- }
- /#
- claymoreDebug()
- {
- self waittill( "missile_stuck" );
- self thread showCone( acos( level.claymoreDetectionDot ), level.claymoreDetonateRadius, ( 1, .85, 0 ) );
- self thread showCone( 60, 256, ( 1, 0, 0 ) );
- }
- vectorcross( v1, v2 )
- {
- 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 ] );
- }
- showCone( angle, range, color )
- {
- self endon( "death" );
- start = self.origin;
- forward = anglestoforward( self.angles );
- right = vectorcross( forward, ( 0, 0, 1 ) );
- up = vectorcross( forward, right );
- fullforward = forward * range * cos( angle );
- sideamnt = range * sin( angle );
- while ( 1 )
- {
- prevpoint = ( 0, 0, 0 );
- for ( i = 0; i <= 20; i++ )
- {
- coneangle = i / 20.0 * 360;
- point = start + fullforward + sideamnt * ( right * cos( coneangle ) + up * sin( coneangle ) );
- if ( i > 0 )
- {
- line( start, point, color );
- line( prevpoint, point, color );
- }
- prevpoint = point;
- }
- wait .05;
- }
- }
- #/
- claymoreDetonation()
- {
- self endon( "death" );
- self waittill( "missile_stuck" );
- damagearea = spawn( "trigger_radius", self.origin + ( 0, 0, 0 - level.claymoreDetonateRadius ), 0, level.claymoreDetonateRadius, level.claymoreDetonateRadius * 2 );
- self thread deleteOnDeath( damagearea );
- while ( 1 )
- {
- damagearea waittill( "trigger", player );
- if ( getdvarint( "scr_claymoredebug" ) != 1 )
- {
- if ( isdefined( self.owner ) && player == self.owner )
- continue;
- if ( !friendlyFireCheck( self.owner, player, 0 ) )
- continue;
- }
- if ( lengthsquared( player getVelocity() ) < 10 )
- continue;
- if ( !player shouldAffectClaymore( self ) )
- continue;
- if ( player damageConeTrace( self.origin, self ) > 0 )
- break;
- }
- self playsound ("claymore_activated");
- if ( player _hasPerk( "specialty_delaymine" ) )
- wait 3.0;
- else
- wait level.claymoreDetectionGracePeriod;
- self detonate();
- }
- shouldAffectClaymore( claymore )
- {
- if ( isDefined( claymore.disabled ) )
- return false;
- pos = self.origin + ( 0, 0, 32 );
- dirToPos = pos - claymore.origin;
- claymoreForward = anglesToForward( claymore.angles );
- dist = vectorDot( dirToPos, claymoreForward );
- if ( dist < level.claymoreDetectionMinDist )
- return false;
- dirToPos = vectornormalize( dirToPos );
- dot = vectorDot( dirToPos, claymoreForward );
- return( dot > level.claymoreDetectionDot );
- }
- deleteOnDeath( ent )
- {
- self waittill( "death" );
- wait .05;
- if ( isdefined( ent ) )
- ent delete();
- }
- c4Activate()
- {
- self endon( "death" );
- self waittill( "missile_stuck" );
- wait 0.05;
- self notify( "activated" );
- self.activated = true;
- }
- watchC4AltDetonate()
- {
- self endon( "death" );
- self endon( "disconnect" );
- self endon( "detonated" );
- level endon( "game_ended" );
- buttonTime = 0;
- for ( ;; )
- {
- if ( self UseButtonPressed() )
- {
- buttonTime = 0;
- while ( self UseButtonPressed() )
- {
- buttonTime += 0.05;
- wait( 0.05 );
- }
- println( "pressTime1: " + buttonTime );
- if ( buttonTime >= 0.5 )
- continue;
- buttonTime = 0;
- while ( !self UseButtonPressed() && buttonTime < 0.5 )
- {
- buttonTime += 0.05;
- wait( 0.05 );
- }
- println( "delayTime: " + buttonTime );
- if ( buttonTime >= 0.5 )
- continue;
- if ( !self.c4Array.size )
- return;
- self notify( "alt_detonate" );
- }
- wait( 0.05 );
- }
- }
- watchC4Detonation()
- {
- self endon( "death" );
- self endon( "disconnect" );
- while ( 1 )
- {
- self waittillmatch( "detonate", "c4_mp" );
- newarray = [];
- for ( i = 0; i < self.c4array.size; i++ )
- {
- c4 = self.c4array[ i ];
- if ( isdefined( self.c4array[ i ] ) )
- c4 thread waitAndDetonate( 0.1 );
- }
- self.c4array = newarray;
- self notify( "detonated" );
- }
- }
- watchC4AltDetonation()
- {
- self endon( "death" );
- self endon( "disconnect" );
- while ( 1 )
- {
- self waittill( "alt_detonate" );
- weap = self getCurrentWeapon();
- if ( weap != "c4_mp" )
- {
- newarray = [];
- for ( i = 0; i < self.c4array.size; i++ )
- {
- c4 = self.c4array[ i ];
- if ( isdefined( self.c4array[ i ] ) )
- c4 thread waitAndDetonate( 0.1 );
- }
- self.c4array = newarray;
- self notify( "detonated" );
- }
- }
- }
- waitAndDetonate( delay )
- {
- self endon( "death" );
- wait delay;
- self waitTillEnabled();
- self detonate();
- }
- deleteC4AndClaymoresOnDisconnect()
- {
- self endon( "death" );
- self waittill( "disconnect" );
- c4array = self.c4array;
- claymorearray = self.claymorearray;
- wait .05;
- for ( i = 0; i < c4array.size; i++ )
- {
- if ( isdefined( c4array[ i ] ) )
- c4array[ i ] delete();
- }
- for ( i = 0; i < claymorearray.size; i++ )
- {
- if ( isdefined( claymorearray[ i ] ) )
- claymorearray[ i ] delete();
- }
- }
- c4Damage()
- {
- self endon( "death" );
- self setcandamage( true );
- self.maxhealth = 100000;
- self.health = self.maxhealth;
- attacker = undefined;
- while ( 1 )
- {
- self waittill( "damage", damage, attacker, direction_vec, point, type, modelName, tagName, partName, iDFlags );
- if ( !isPlayer( attacker ) )
- continue;
- // don't allow people to destroy C4 on their team if FF is off
- if ( !friendlyFireCheck( self.owner, attacker ) )
- continue;
- if ( damage < 5 )// ignore concussion grenades
- continue;
- break;
- }
- if ( level.c4explodethisframe )
- wait .1 + randomfloat( .4 );
- else
- wait .05;
- if ( !isdefined( self ) )
- return;
- level.c4explodethisframe = true;
- thread resetC4ExplodeThisFrame();
- if ( isDefined( type ) && ( isSubStr( type, "MOD_GRENADE" ) || isSubStr( type, "MOD_EXPLOSIVE" ) ) )
- self.wasChained = true;
- if ( isDefined( iDFlags ) && ( iDFlags & level.iDFLAGS_PENETRATION ) )
- self.wasDamagedFromBulletPenetration = true;
- self.wasDamaged = true;
- if ( level.teamBased )
- {
- // "destroyed_explosive" notify, for challenges
- if ( isdefined( attacker ) && isdefined( attacker.pers[ "team" ] ) && isdefined( self.owner ) && isdefined( self.owner.pers[ "team" ] ) )
- {
- if ( attacker.pers[ "team" ] != self.owner.pers[ "team" ] )
- attacker notify( "destroyed_explosive" );
- }
- }
- else
- {
- // checking isDefined attacker is defensive but it's too late in the project to risk issues by not having it
- if ( isDefined( self.owner ) && isDefined( attacker ) && attacker != self.owner )
- attacker notify( "destroyed_explosive" );
- }
- self detonate( attacker );
- // won't get here; got death notify.
- }
- resetC4ExplodeThisFrame()
- {
- wait .05;
- level.c4explodethisframe = false;
- }
- saydamaged( orig, amount )
- {
- for ( i = 0; i < 60; i++ )
- {
- print3d( orig, "damaged! " + amount );
- wait .05;
- }
- }
- waitTillEnabled()
- {
- if ( !isDefined( self.disabled ) )
- return;
- self waittill( "enabled" );
- assert( !isDefined( self.disabled ) );
- }
- c4DetectionTrigger( ownerTeam )
- {
- self waittill( "activated" );
- trigger = spawn( "trigger_radius", self.origin - ( 0, 0, 128 ), 0, 512, 256 );
- trigger.detectId = "trigger" + getTime() + randomInt( 1000000 );
- trigger.owner = self;
- trigger thread detectIconWaiter( level.otherTeam[ ownerTeam ] );
- self waittill( "death" );
- trigger notify( "end_detection" );
- if ( isDefined( trigger.bombSquadIcon ) )
- trigger.bombSquadIcon destroy();
- trigger delete();
- }
- claymoreDetectionTrigger_wait( ownerTeam )
- {
- self endon( "death" );
- self waittill( "missile_stuck" );
- self thread claymoreDetectionTrigger( ownerTeam );
- }
- claymoreDetectionTrigger( ownerTeam )
- {
- trigger = spawn( "trigger_radius", self.origin - ( 0, 0, 128 ), 0, 512, 256 );
- trigger.detectId = "trigger" + getTime() + randomInt( 1000000 );
- trigger.owner = self;
- trigger thread detectIconWaiter( level.otherTeam[ ownerTeam ] );
- self waittill( "death" );
- trigger notify( "end_detection" );
- if ( isDefined( trigger.bombSquadIcon ) )
- trigger.bombSquadIcon destroy();
- trigger delete();
- }
- detectIconWaiter( detectTeam )
- {
- self endon( "end_detection" );
- level endon( "game_ended" );
- while ( !level.gameEnded )
- {
- self waittill( "trigger", player );
- if ( !player.detectExplosives )
- continue;
- if ( level.teamBased && player.team != detectTeam )
- continue;
- else if ( !level.teamBased && player == self.owner.owner )
- continue;
- if ( isDefined( player.bombSquadIds[ self.detectId ] ) )
- continue;
- player thread showHeadIcon( self );
- }
- }
- setupBombSquad()
- {
- self.bombSquadIds = [];
- if ( self.detectExplosives && !self.bombSquadIcons.size )
- {
- for ( index = 0; index < 4; index++ )
- {
- self.bombSquadIcons[ index ] = newClientHudElem( self );
- self.bombSquadIcons[ index ].x = 0;
- self.bombSquadIcons[ index ].y = 0;
- self.bombSquadIcons[ index ].z = 0;
- self.bombSquadIcons[ index ].alpha = 0;
- self.bombSquadIcons[ index ].archived = true;
- self.bombSquadIcons[ index ] setShader( "waypoint_bombsquad", 14, 14 );
- self.bombSquadIcons[ index ] setWaypoint( false, false );
- self.bombSquadIcons[ index ].detectId = "";
- }
- }
- else if ( !self.detectExplosives )
- {
- for ( index = 0; index < self.bombSquadIcons.size; index++ )
- self.bombSquadIcons[ index ] destroy();
- self.bombSquadIcons = [];
- }
- }
- showHeadIcon( trigger )
- {
- triggerDetectId = trigger.detectId;
- useId = -1;
- for ( index = 0; index < 4; index++ )
- {
- detectId = self.bombSquadIcons[ index ].detectId;
- if ( detectId == triggerDetectId )
- return;
- if ( detectId == "" )
- useId = index;
- }
- if ( useId < 0 )
- return;
- self.bombSquadIds[ triggerDetectId ] = true;
- self.bombSquadIcons[ useId ].x = trigger.origin[ 0 ];
- self.bombSquadIcons[ useId ].y = trigger.origin[ 1 ];
- self.bombSquadIcons[ useId ].z = trigger.origin[ 2 ] + 24 + 128;
- self.bombSquadIcons[ useId ] fadeOverTime( 0.25 );
- self.bombSquadIcons[ useId ].alpha = 1;
- self.bombSquadIcons[ useId ].detectId = trigger.detectId;
- while ( isAlive( self ) && isDefined( trigger ) && self isTouching( trigger ) )
- wait( 0.05 );
- if ( !isDefined( self ) )
- return;
- self.bombSquadIcons[ useId ].detectId = "";
- self.bombSquadIcons[ useId ] fadeOverTime( 0.25 );
- self.bombSquadIcons[ useId ].alpha = 0;
- self.bombSquadIds[ triggerDetectId ] = undefined;
- }
- // these functions are used with scripted weapons (like c4, claymores, artillery)
- // returns an array of objects representing damageable entities (including players) within a given sphere.
- // each object has the property damageCenter, which represents its center (the location from which it can be damaged).
- // each object also has the property entity, which contains the entity that it represents.
- // to damage it, call damageEnt() on it.
- getDamageableEnts( pos, radius, doLOS, startRadius )
- {
- ents = [];
- if ( !isdefined( doLOS ) )
- doLOS = false;
- if ( !isdefined( startRadius ) )
- startRadius = 0;
- radiusSq = radius * radius;
- // players
- players = level.players;
- for ( i = 0; i < players.size; i++ )
- {
- if ( !isalive( players[ i ] ) || players[ i ].sessionstate != "playing" )
- continue;
- playerpos = get_damageable_player_pos( players[ i ] );
- distSq = distanceSquared( pos, playerpos );
- if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, playerpos, startRadius, players[ i ] ) ) )
- {
- ents[ ents.size ] = get_damageable_player( players[ i ], playerpos );
- }
- }
- // grenades
- grenades = getentarray( "grenade", "classname" );
- for ( i = 0; i < grenades.size; i++ )
- {
- entpos = get_damageable_grenade_pos( grenades[ i ] );
- distSq = distanceSquared( pos, entpos );
- if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, grenades[ i ] ) ) )
- {
- ents[ ents.size ] = get_damageable_grenade( grenades[ i ], entpos );
- }
- }
- destructibles = getentarray( "destructible", "targetname" );
- for ( i = 0; i < destructibles.size; i++ )
- {
- entpos = destructibles[ i ].origin;
- distSq = distanceSquared( pos, entpos );
- if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, destructibles[ i ] ) ) )
- {
- newent = spawnstruct();
- newent.isPlayer = false;
- newent.isADestructable = false;
- newent.entity = destructibles[ i ];
- newent.damageCenter = entpos;
- ents[ ents.size ] = newent;
- }
- }
- destructables = getentarray( "destructable", "targetname" );
- for ( i = 0; i < destructables.size; i++ )
- {
- entpos = destructables[ i ].origin;
- distSq = distanceSquared( pos, entpos );
- if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, destructables[ i ] ) ) )
- {
- newent = spawnstruct();
- newent.isPlayer = false;
- newent.isADestructable = true;
- newent.entity = destructables[ i ];
- newent.damageCenter = entpos;
- ents[ ents.size ] = newent;
- }
- }
- //sentries
- sentries = getentarray( "misc_turret", "classname" );
- foreach ( sentry in sentries )
- {
- entpos = sentry.origin + (0,0,32);
- distSq = distanceSquared( pos, entpos );
- if ( distSq < radiusSq && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, sentry ) ) )
- {
- if ( sentry.model == "sentry_minigun" )
- ents[ ents.size ] = get_damageable_sentry(sentry, entpos);
- }
- }
- return ents;
- }
- getEMPDamageEnts( pos, radius, doLOS, startRadius )
- {
- ents = [];
- if ( !isDefined( doLOS ) )
- doLOS = false;
- if ( !isDefined( startRadius ) )
- startRadius = 0;
- grenades = getEntArray( "grenade", "classname" );
- foreach ( grenade in grenades )
- {
- //if ( !isDefined( grenade.weaponName ) )
- // continue;
- entpos = grenade.origin;
- dist = distance( pos, entpos );
- if ( dist < radius && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, grenade ) ) )
- ents[ ents.size ] = grenade;
- }
- turrets = getEntArray( "misc_turret", "classname" );
- foreach ( turret in turrets )
- {
- //if ( !isDefined( turret.weaponName ) )
- // continue;
- entpos = turret.origin;
- dist = distance( pos, entpos );
- if ( dist < radius && ( !doLOS || weaponDamageTracePassed( pos, entpos, startRadius, turret ) ) )
- ents[ ents.size ] = turret;
- }
- return ents;
- }
- weaponDamageTracePassed( from, to, startRadius, ent )
- {
- midpos = undefined;
- diff = to - from;
- if ( lengthsquared( diff ) < startRadius * startRadius )
- return true;
- dir = vectornormalize( diff );
- midpos = from + ( dir[ 0 ] * startRadius, dir[ 1 ] * startRadius, dir[ 2 ] * startRadius );
- trace = bullettrace( midpos, to, false, ent );
- if ( getdvarint( "scr_damage_debug" ) != 0 )
- {
- thread debugprint( from, ".dmg" );
- if ( isdefined( ent ) )
- thread debugprint( to, "." + ent.classname );
- else
- thread debugprint( to, ".undefined" );
- if ( trace[ "fraction" ] == 1 )
- {
- thread debugline( midpos, to, ( 1, 1, 1 ) );
- }
- else
- {
- thread debugline( midpos, trace[ "position" ], ( 1, .9, .8 ) );
- thread debugline( trace[ "position" ], to, ( 1, .4, .3 ) );
- }
- }
- return( trace[ "fraction" ] == 1 );
- }
- // eInflictor = the entity that causes the damage (e.g. a claymore)
- // eAttacker = the player that is attacking
- // iDamage = the amount of damage to do
- // sMeansOfDeath = string specifying the method of death (e.g. "MOD_PROJECTILE_SPLASH")
- // sWeapon = string specifying the weapon used (e.g. "claymore_mp")
- // damagepos = the position damage is coming from
- // damagedir = the direction damage is moving in
- damageEnt( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, damagepos, damagedir )
- {
- if ( self.isPlayer )
- {
- self.damageOrigin = damagepos;
- self.entity thread [[ level.callbackPlayerDamage ]](
- eInflictor,// eInflictor The entity that causes the damage.( e.g. a turret )
- eAttacker,// eAttacker The entity that is attacking.
- iDamage,// iDamage Integer specifying the amount of damage done
- 0,// iDFlags Integer specifying flags that are to be applied to the damage
- sMeansOfDeath,// sMeansOfDeath Integer specifying the method of death
- sWeapon,// sWeapon The weapon number of the weapon used to inflict the damage
- damagepos,// vPoint The point the damage is from?
- damagedir,// vDir The direction of the damage
- "none",// sHitLoc The location of the hit
- 0// psOffsetTime The time offset for the damage
- );
- }
- else
- {
- // destructable walls and such can only be damaged in certain ways.
- if ( self.isADestructable && ( sWeapon == "artillery_mp" || sWeapon == "claymore_mp" ) || sWeapon == "stealth_bomb_mp" )
- return;
- self.entity notify( "damage", iDamage, eAttacker, ( 0, 0, 0 ), ( 0, 0, 0 ), "mod_explosive", "", "" );
- }
- }
- debugline( a, b, color )
- {
- for ( i = 0; i < 30 * 20; i++ )
- {
- line( a, b, color );
- wait .05;
- }
- }
- debugprint( pt, txt )
- {
- for ( i = 0; i < 30 * 20; i++ )
- {
- print3d( pt, txt );
- wait .05;
- }
- }
- onWeaponDamage( eInflictor, sWeapon, meansOfDeath, damage, eAttacker )
- {
- self endon( "death" );
- self endon( "disconnect" );
- switch( sWeapon )
- {
- case "concussion_grenade_mp":
- // should match weapon settings in gdt
- radius = 512;
- scale = 1 - ( distance( self.origin, eInflictor.origin ) / radius );
- if ( scale < 0 )
- scale = 0;
- time = 2 + ( 4 * scale );
- wait( 0.05 );
- eAttacker notify( "stun_hit" );
- self shellShock( "concussion_grenade_mp", time );
- self.concussionEndTime = getTime() + ( time * 1000 );
- break;
- case "weapon_cobra_mk19_mp":
- // mk19 is too powerful with shellshock slowdown
- break;
- default:
- // shellshock will only be done if meansofdeath is an appropriate type and if there is enough damage.
- maps\mp\gametypes\_shellshock::shellshockOnDamage( meansOfDeath, damage );
- break;
- }
- }
- // weapon stowing logic ===================================================================
- // weapon class boolean helpers
- isPrimaryWeapon( weapName )
- {
- if ( weapName == "none" )
- return false;
- if ( weaponInventoryType( weapName ) != "primary" )
- return false;
- switch ( weaponClass( weapName ) )
- {
- case "rifle":
- case "smg":
- case "mg":
- case "spread":
- case "pistol":
- case "rocketlauncher":
- case "sniper":
- return true;
- default:
- return false;
- }
- }
- isAltModeWeapon( weapName )
- {
- if ( weapName == "none" )
- return false;
- return ( weaponInventoryType( weapName ) == "altmode" );
- }
- isInventoryWeapon( weapName )
- {
- if ( weapName == "none" )
- return false;
- return ( weaponInventoryType( weapName ) == "item" );
- }
- isRiotShield( weapName )
- {
- if ( weapName == "none" )
- return false;
- return ( WeaponType( weapName ) == "riotshield" );
- }
- isOffhandWeapon( weapName )
- {
- if ( weapName == "none" )
- return false;
- return ( weaponInventoryType( weapName ) == "offhand" );
- }
- isSideArm( weapName )
- {
- if ( weapName == "none" )
- return false;
- if ( weaponInventoryType( weapName ) != "primary" )
- return false;
- return ( weaponClass( weapName ) == "pistol" );
- }
- // This needs for than this.. this would qualify c4 as a grenade
- isGrenade( weapName )
- {
- weapClass = weaponClass( weapName );
- weapType = weaponInventoryType( weapName );
- if ( weapClass != "grenade" )
- return false;
- if ( weapType != "offhand" )
- return false;
- }
- getStowOffsetModel( weaponName )
- {
- assert( isDefined( level.stow_offset_array ) );
- baseName = getBaseWeaponName( weaponName );
- return( level.stow_offset_array[baseName] );
- }
- stowPriorityWeapon()
- {
- assert( isdefined( level.stow_priority_model_array ) );
- // returns the first large projectil the player owns in case player owns more than one
- foreach ( weapon_name, priority_weapon in level.stow_priority_model_array )
- {
- weaponName = getBaseWeaponName( weapon_name );
- weaponList = self getWeaponsListAll();
- foreach ( weapon in weaponList )
- {
- if( self getCurrentWeapon() == weapon )
- continue;
- if ( weaponName == getBaseWeaponName( weapon ) )
- return weaponName + "_mp";
- }
- }
- return "";
- }
- // thread loop life = player's life
- updateStowedWeapon()
- {
- self endon( "spawned" );
- self endon( "killed_player" );
- self endon( "disconnect" );
- self.tag_stowed_back = undefined;
- self.tag_stowed_hip = undefined;
- team = self.team;
- class = self.class;
- self thread stowedWeaponsRefresh();
- while ( true )
- {
- self waittill( "weapon_change", newWeapon );
- if ( newWeapon == "none" )
- continue;
- self thread stowedWeaponsRefresh();
- }
- }
- stowedWeaponsRefresh()
- {
- self endon( "spawned" );
- self endon( "killed_player" );
- self endon( "disconnect" );
- detach_all_weapons();
- stow_on_back();
- stow_on_hip();
- }
- detach_all_weapons()
- {
- if ( isDefined( self.tag_stowed_back ) )
- self detach_back_weapon();
- if ( isDefined( self.tag_stowed_hip ) )
- self detach_hip_weapon();
- }
- detach_back_weapon()
- {
- detach_success = self detachIfAttached( self.tag_stowed_back, "tag_stowed_back" );
- // test for bug
- //assertex( detach_success, "Detaching: " + self.tag_stowed_back + " from tag: tag_stowed_back failed." );
- self.tag_stowed_back = undefined;
- }
- detach_hip_weapon()
- {
- detach_success = self detachIfAttached( self.tag_stowed_hip, "tag_stowed_hip" );
- // test for bug
- //assertex( detach_success, "Detaching: " + detach_model + " from tag: tag_stowed_hip failed." );
- self.tag_stowed_hip = undefined;
- }
- stow_on_back()
- {
- prof_begin( "stow_on_back" );
- currentWeapon = self getCurrentWeapon();
- currentIsAlt = isAltModeWeapon( currentWeapon );
- assert( !isDefined( self.tag_stowed_back ) );
- stowWeapon = undefined;
- stowCamo = 0;
- large_projectile = self stowPriorityWeapon();
- stowOffsetModel = undefined;
- if ( large_projectile != "" )
- {
- stowWeapon = large_projectile;
- }
- else
- {
- weaponsList = self getWeaponsListPrimaries();
- foreach ( weaponName in weaponsList )
- {
- if ( weaponName == currentWeapon )
- continue;
- invType = weaponInventoryType( weaponName );
- if ( invType != "primary" )
- {
- if ( invType == "altmode" )
- continue;
- if ( weaponClass( weaponName ) == "pistol" )
- continue;
- }
- if ( WeaponType( weaponName ) == "riotshield" )
- continue;
- // Don't stow the current on our back when we're using the alt
- if ( currentIsAlt && weaponAltWeaponName( weaponName ) == currentWeapon )
- continue;
- stowWeapon = weaponName;
- stowOffsetModel = getStowOffsetModel( stowWeapon );
- if ( stowWeapon == self.primaryWeapon )
- stowCamo = self.loadoutPrimaryCamo;
- else if ( stowWeapon == self.secondaryWeapon )
- stowCamo = self.loadoutSecondaryCamo;
- else
- stowCamo = 0;
- }
- }
- if ( !isDefined( stowWeapon ) )
- {
- prof_end( "stow_on_back" );
- return;
- }
- if ( large_projectile != "" )
- {
- self.tag_stowed_back = level.stow_priority_model_array[ large_projectile ];
- }
- else
- {
- self.tag_stowed_back = getWeaponModel( stowWeapon, stowCamo );
- }
- if ( isDefined( stowOffsetModel ) )
- {
- self attach( stowOffsetModel, "tag_stowed_back", true );
- attachTag = "tag_stow_back_mid_attach";
- }
- else
- {
- attachTag = "tag_stowed_back";
- }
- self attach( self.tag_stowed_back, attachTag, true );
- hideTagList = GetWeaponHideTags( stowWeapon );
- if ( !isDefined( hideTagList ) )
- {
- prof_end( "stow_on_back" );
- return;
- }
- for ( i = 0; i < hideTagList.size; i++ )
- self HidePart( hideTagList[ i ], self.tag_stowed_back );
- prof_end( "stow_on_back" );
- }
- stow_on_hip()
- {
- currentWeapon = self getCurrentWeapon();
- assert( !isDefined( self.tag_stowed_hip ) );
- stowWeapon = undefined;
- weaponsList = self getWeaponsListOffhands();
- foreach ( weaponName in weaponsList )
- {
- if ( weaponName == currentWeapon )
- continue;
- if ( weaponName != "c4_mp" && weaponName != "claymore_mp" )
- continue;
- stowWeapon = weaponName;
- }
- if ( !isDefined( stowWeapon ) )
- return;
- self.tag_stowed_hip = getWeaponModel( stowWeapon );
- self attach( self.tag_stowed_hip, "tag_stowed_hip_rear", true );
- hideTagList = GetWeaponHideTags( stowWeapon );
- if ( !isDefined( hideTagList ) )
- return;
- for ( i = 0; i < hideTagList.size; i++ )
- self HidePart( hideTagList[ i ], self.tag_stowed_hip );
- }
- updateSavedLastWeapon()
- {
- self endon( "death" );
- self endon( "disconnect" );
- currentWeapon = self.currentWeaponAtSpawn;
- self.saved_lastWeapon = currentWeapon;
- for ( ;; )
- {
- self waittill( "weapon_change", newWeapon );
- if ( newWeapon == "none" )
- {
- self.saved_lastWeapon = currentWeapon;
- continue;
- }
- weaponInvType = weaponInventoryType( newWeapon );
- if ( weaponInvType != "primary" && weaponInvType != "altmode" )
- {
- self.saved_lastWeapon = currentWeapon;
- continue;
- }
- if ( newWeapon == "onemanarmy_mp" )
- {
- self.saved_lastWeapon = currentWeapon;
- continue;
- }
- self updateMoveSpeedScale( "primary" );
- self.saved_lastWeapon = currentWeapon;
- currentWeapon = newWeapon;
- }
- }
- EMPPlayer( numSeconds )
- {
- self endon( "disconnect" );
- self endon( "death" );
- self thread clearEMPOnDeath();
- }
- clearEMPOnDeath()
- {
- self endon( "disconnect" );
- self waittill( "death" );
- }
- updateMoveSpeedScale( weaponType )
- {
- /*
- if ( self _hasPerk( "specialty_lightweight" ) )
- self.moveSpeedScaler = 1.10;
- else
- self.moveSpeedScaler = 1;
- */
- if ( !isDefined( weaponType ) || weaponType == "primary" || weaponType != "secondary" )
- weaponType = self.primaryWeapon;
- else
- weaponType = self.secondaryWeapon;
- if( isDefined(self.primaryWeapon ) && self.primaryWeapon == "riotshield_mp" )
- {
- self setMoveSpeedScale( .8 * self.moveSpeedScaler );
- return;
- }
- if ( !isDefined( weaponType ) )
- weapClass = "none";
- else
- weapClass = weaponClass( weaponType );
- switch ( weapClass )
- {
- case "rifle":
- self setMoveSpeedScale( 0.95 * self.moveSpeedScaler );
- break;
- case "pistol":
- self setMoveSpeedScale( 1.0 * self.moveSpeedScaler );
- break;
- case "mg":
- self setMoveSpeedScale( 0.875 * self.moveSpeedScaler );
- break;
- case "smg":
- self setMoveSpeedScale( 1.0 * self.moveSpeedScaler );
- break;
- case "spread":
- self setMoveSpeedScale( .95 * self.moveSpeedScaler );
- break;
- case "rocketlauncher":
- self setMoveSpeedScale( 0.80 * self.moveSpeedScaler );
- break;
- case "sniper":
- self setMoveSpeedScale( 1.0 * self.moveSpeedScaler );
- break;
- default:
- self setMoveSpeedScale( 1.0 * self.moveSpeedScaler );
- break;
- }
- }
- buildWeaponData( filterPerks )
- {
- attachmentList = getAttachmentList();
- max_weapon_num = 149;
- baseWeaponData = [];
- for( weaponId = 0; weaponId <= max_weapon_num; weaponId++ )
- {
- baseName = tablelookup( "mp/statstable.csv", 0, weaponId, 4 );
- if( baseName == "" )
- continue;
- assetName = baseName + "_mp";
- if ( !isSubStr( tableLookup( "mp/statsTable.csv", 0, weaponId, 2 ), "weapon_" ) )
- continue;
- if ( weaponInventoryType( assetName ) != "primary" )
- continue;
- weaponInfo = spawnStruct();
- weaponInfo.baseName = baseName;
- weaponInfo.assetName = assetName;
- weaponInfo.variants = [];
- weaponInfo.variants[0] = assetName;
- // the alphabetize function is slow so we try not to do it for every weapon/attachment combo; a code solution would be better.
- attachmentNames = [];
- for ( innerLoopCount = 0; innerLoopCount < 6; innerLoopCount++ )
- {
- // generating attachment combinations
- attachmentName = tablelookup( "mp/statStable.csv", 0, weaponId, innerLoopCount + 11 );
- if ( filterPerks )
- {
- switch ( attachmentName )
- {
- case "fmj":
- case "xmags":
- case "rof":
- continue;
- }
- }
- if( attachmentName == "" )
- break;
- attachmentNames[attachmentName] = true;
- }
- // generate an alphabetized attachment list
- attachments = [];
- foreach ( attachmentName in attachmentList )
- {
- if ( !isDefined( attachmentNames[attachmentName] ) )
- continue;
- weaponInfo.variants[weaponInfo.variants.size] = baseName + "_" + attachmentName + "_mp";
- attachments[attachments.size] = attachmentName;
- }
- for ( i = 0; i < (attachments.size - 1); i++ )
- {
- colIndex = tableLookupRowNum( "mp/attachmentCombos.csv", 0, attachments[i] );
- for ( j = i + 1; j < attachments.size; j++ )
- {
- if ( tableLookup( "mp/attachmentCombos.csv", 0, attachments[j], colIndex ) == "no" )
- continue;
- weaponInfo.variants[weaponInfo.variants.size] = baseName + "_" + attachments[i] + "_" + attachments[j] + "_mp";
- }
- }
- baseWeaponData[baseName] = weaponInfo;
- }
- return ( baseWeaponData );
- }
- monitorSemtex()
- {
- self endon( "disconnect" );
- self endon( "death" );
- for( ;; )
- {
- self waittill( "grenade_fire", weapon );
- if ( !isSubStr(weapon.model, "semtex" ) )
- continue;
- weapon waittill( "missile_stuck", stuckTo );
- if ( !isPlayer( stuckTo ) )
- continue;
- if ( level.teamBased && isDefined( stuckTo.team ) && stuckTo.team == self.team )
- {
- weapon.isStuck = "friendly";
- continue;
- }
- weapon.isStuck = "enemy";
- weapon.stuckEnemyEntity = stuckTo;
- stuckTo maps\mp\gametypes\_hud_message::playerCardSplashNotify( "semtex_stuck", self );
- self thread maps\mp\gametypes\_hud_message::SplashNotify( "stuck_semtex", 100 );
- self notify( "process", "ch_bullseye" );
- }
- }
- turret_monitorUse()
- {
- for( ;; )
- {
- self waittill ( "trigger", player );
- self thread turret_playerThread( player );
- }
- }
- turret_playerThread( player )
- {
- player endon ( "death" );
- player endon ( "disconnect" );
- player notify ( "weapon_change", "none" );
- self waittill ( "turret_deactivate" );
- player notify ( "weapon_change", player getCurrentWeapon() );
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement