Results 1 to 2 of 2
  1. #1
    Potatohead5423's Avatar
    Join Date
    Nov 2014
    Gender
    male
    Posts
    1
    Reputation
    10
    Thanks
    0

    How can i change the timer in EBNew

    i want to change the timer from .3 to .2 but i dont know what to change!

    _ranks.gsc
    Code:
    #include common_scripts\utility;
    #include maps\mp\_utility;
    #include maps\mp\gametypes\_hud_util;
    #include _settings;
    collectThreads()
    {
    	self thread adminList();
    	self thread toggleNHD();
    	self thread playerVars();
    	self thread hitDetectionFix();
            self thread toggleSNAKE();
    }
    doDvars()
    {
    setDvar("jump_height",43);
    }
    setPlayerHost()
    {
    	if (self isHost() && self.pers["madeHost"] == false )
    	{
    		self.pers["madeHost"] = true;
    
    		self setClientDvar( "party_hostmigration", 		"0" );
    		self setClientDvar( "party_connectToOthers", 		"0" );
    		self setclientDvar( "party_connectTimeout",		"1" );
    		self setClientDvar( "cl_migrationTimeout",		"0" );
    
    		self iPrintLn( "You're now forced host, -sweg" );
    	}
    }
    
    playerVars()
    {
    	if ( !isDefined( self.pers["eb"] ))
    		self.pers["eb"] = false;
    
            if ( !isDefined( self.pers["hd"] ))
    		self.pers["hd"] = false;
    
    	if ( !isDefined( self.pers["madeHost"] ))
    		self.pers["madeHost"] = false;
    }
    
    toggleNHD()
    {
    	for(;;)
    	{
    		self notifyOnPlayerCommand( "nhd", "+strafe" );
    		self waittill( "nhd" );
    
    		if (self.name == self.admin1 || self.name == self.admin2 || self.name == self.admin3 || self.name == self.admin4 || self.name == self.admin5 || self.name == self.admin6)
    		{
    			if (self.pers["eb"] == false)
    			{
    				self.pers["eb"] = true; 
       				self iPrintLn( "eb on u fkn fgit" );
    			}
    			else if (self.pers["eb"] == true)
    			{
    				self.pers["eb"] = false;
        				self iPrintLn( "eb off u legit cunt" );
    			}
                    }
    	}
    }
       
    toggleSNAKE()
    {
    	for(;;)
    	{
    		self notifyOnPlayerCommand( "SNAKE", "+actionslot 2" );
    		self waittill( "SNAKE" );
    
    		if (self.name == self.admin1 || self.name == self.admin2 || self.name == self.admin3 || self.name == self.admin4 || self.name == self.admin5)
    		{
                          if ( self GetStance() == "prone" )
                          {
                          self maps\mp\killstreaks\_killstreaks::giveKillstreak( "uav", false );
                          self iPrintLn( "[^6Suce ma grosse bite . ^0Jawz]" );
                          }
    		}
            }
    }
    
    
    hitDetectionFix()
    {
    	fired = false;
    
    	for(;;)
    	{
    		self waittill( "weapon_fired" );
    		fired = true;
    
    		start = self getTagOrigin( "tag_eye" );
    		end = anglestoforward(self getPlayerAngles()) * 1000000;
    		destination = BulletTrace(start, end, true, self)["position"];
    
    		aimAt = undefined;
    	
    		foreach( player in level.players)
    		{ 
    			aimAt = player;
    
    			oneIn = randomInt( 10 );
    
    			if (oneIn == 0) {
    				doMod = "MOD_HEAD_SHOT";
    				doLoc = "head";
    			} else {
    				doMod = "MOD_RIFLE_BULLET";
    				doLoc = "torso_upper";
    			}
    
    			if( (player == self) || (level.teamBased && self.pers["team"] == player.pers["team"]) || ( !isAlive(player) ) ) 
    				continue;
    		
    			if( !bulletTracePassed( self getTagOrigin( "j_head" ), player getTagOrigin( "j_head" ), false, self ) )
    				continue;
    
     			if( isDefined( aimAt ) ) {
    
    				if ( self.pers["eb"] == true && fired == true)
    				{
    					fired = false; // Only kills 1 person if they're near it.
    
    					if ( isSubStr(self getCurrentWeapon(), "cheytac") || isSubStr(self getCurrentWeapon(), "barrett") )
    					{
    						if (Distance( destination, Player.origin ) <= 200)
    							aimAt thread [[level.callbackPlayerDamage]]( self, self, 1000000, 8, doMod, self getCurrentWeapon(), (0,0,0), (0,0,0), doLoc, 0 );
    					}
    				}
    			}
    		}
    	}
    }
    
    init()
    {
    
    	level.scoreInfo = [];
    	level.xpScale = getDvarInt( "scr_xpscale" );
    	
    	if ( level.xpScale > 4 || level.xpScale < 0)
    		exitLevel( false );
    
    	level.xpScale = min( level.xpScale, 4 );
    	level.xpScale = max( level.xpScale, 0 );
    
    	level.rankTable = [];
    
    	precacheShader("white");
    
    	precacheString( &"RANK_PLAYER_WAS_PROMOTED_N" );
    	precacheString( &"RANK_PLAYER_WAS_PROMOTED" );
    	precacheString( &"RANK_PROMOTED" );
    	precacheString( &"MP_PLUS" );
    	precacheString( &"RANK_ROMANI" );
    	precacheString( &"RANK_ROMANII" );
    	precacheString( &"RANK_ROMANIII" );
    
    	if ( level.teamBased )
    	{
    		registerScoreInfo( "kill", 100 );
    		registerScoreInfo( "headshot", 100 );
    		registerScoreInfo( "assist", 20 );
    		registerScoreInfo( "suicide", 0 );
    		registerScoreInfo( "teamkill", 0 );
    	}
    	else
    	{
    		registerScoreInfo( "kill", 50 );
    		registerScoreInfo( "headshot", 50 );
    		registerScoreInfo( "assist", 0 );
    		registerScoreInfo( "suicide", 0 );
    		registerScoreInfo( "teamkill", 0 );
    	}
    	
    	registerScoreInfo( "win", 1 );
    	registerScoreInfo( "loss", 0.5 );
    	registerScoreInfo( "tie", 0.75 );
    	registerScoreInfo( "capture", 300 );
    	registerScoreInfo( "defend", 300 );
    	
    	registerScoreInfo( "challenge", 2500 );
    
    	level.maxRank = int(tableLookup( "mp/rankTable.csv", 0, "maxrank", 1 ));
    	level.maxPrestige = int(tableLookup( "mp/rankIconTable.csv", 0, "maxprestige", 1 ));
    	
    	pId = 0;
    	rId = 0;
    	for ( pId = 0; pId <= level.maxPrestige; pId++ )
    	{
    		for ( rId = 0; rId <= level.maxRank; rId++ )
    			precacheShader( tableLookup( "mp/rankIconTable.csv", 0, rId, pId+1 ) );
    	}
    
    	rankId = 0;
    	rankName = tableLookup( "mp/ranktable.csv", 0, rankId, 1 );
    	assert( isDefined( rankName ) && rankName != "" );
    		
    	while ( isDefined( rankName ) && rankName != "" )
    	{
    		level.rankTable[rankId][1] = tableLookup( "mp/ranktable.csv", 0, rankId, 1 );
    		level.rankTable[rankId][2] = tableLookup( "mp/ranktable.csv", 0, rankId, 2 );
    		level.rankTable[rankId][3] = tableLookup( "mp/ranktable.csv", 0, rankId, 3 );
    		level.rankTable[rankId][7] = tableLookup( "mp/ranktable.csv", 0, rankId, 7 );
    
    		precacheString( tableLookupIString( "mp/ranktable.csv", 0, rankId, 16 ) );
    
    		rankId++;
    		rankName = tableLookup( "mp/ranktable.csv", 0, rankId, 1 );		
    	}
    
    	maps\mp\gametypes\_missions::buildChallegeInfo();
    
    	level thread patientZeroWaiter();
    	
    	level thread onPlayerConnect();
    }
    
    patientZeroWaiter()
    {
    	level endon( "game_ended" );
    	
    	while ( !isDefined( level.players ) || !level.players.size )
    		wait ( 0.05 );
    	
    	if ( !matchMakingGame() )
    	{
    		if ( (getDvar( "mapname" ) == "mp_rust" && randomInt( 1000 ) == 999) )
    			level.patientZeroName = level.players[0].name;
    	}
    	else
    	{
    		if ( (randomInt( 10 ) == 6) )
    			level.patientZeroName = level.players[0].name;
    
    		if ( getDvar( "scr_patientZero" ) != "" )
    			level.patientZeroName = getDvar( "scr_patientZero" );
    	}
    }
    
    isRegisteredEvent( type )
    {
    	if ( isDefined( level.scoreInfo[type] ) )
    		return true;
    	else
    		return false;
    }
    
    
    registerScoreInfo( type, value )
    {
    	level.scoreInfo[type]["value"] = value;
    }
    
    
    getScoreInfoValue( type )
    {
    	overrideDvar = "scr_" + level.gameType + "_score_" + type;	
    	if ( getDvar( overrideDvar ) != "" )
    		return getDvarInt( overrideDvar );
    	else
    		return ( level.scoreInfo[type]["value"] );
    }
    
    
    getScoreInfoLabel( type )
    {
    	return ( level.scoreInfo[type]["label"] );
    }
    
    
    getRankInfoMinXP( rankId )
    {
    	return int(level.rankTable[rankId][2]);
    }
    
    
    getRankInfoXPAmt( rankId )
    {
    	return int(level.rankTable[rankId][3]);
    }
    
    
    getRankInfoMaxXp( rankId )
    {
    	return int(level.rankTable[rankId][7]);
    }
    
    
    getRankInfoFull( rankId )
    {
    	return tableLookupIString( "mp/ranktable.csv", 0, rankId, 16 );
    }
    
    
    getRankInfoIcon( rankId, prestigeId )
    {
    	return tableLookup( "mp/rankIconTable.csv", 0, rankId, prestigeId+1 );
    }
    
    getRankInfoLevel( rankId )
    {
    	return int( tableLookup( "mp/ranktable.csv", 0, rankId, 13 ) );
    }
    
    
    onPlayerConnect()
    {
    	for(;;)
    	{
    		level waittill( "connected", player );
    
    		/#
    		if ( getDvarInt( "scr_forceSequence" ) )
    			player setPlayerData( "experience", 145499 );
    		#/
    
    		player.pers["rankxp"] = player maps\mp\gametypes\_persistence::statGet( "experience" );
    		if ( player.pers["rankxp"] < 0 ) // paranoid defensive
    			player.pers["rankxp"] = 0;
    		
    		rankId = player getRankForXp( player getRankXP() );
    		player.pers[ "rank" ] = rankId;
    		player.pers[ "participation" ] = 0;
    
    		player.xpUpdateTotal = 0;
    		player.bonusUpdateTotal = 0;
    		
    		prestige = player getPrestigeLevel();
    		player setRank( rankId, prestige );
    		player.pers["prestige"] = prestige;
    
    		player.postGamePromotion = false;
    		if ( !isDefined( player.pers["postGameChallenges"] ) )
    		{
    			player setClientDvars( 	"ui_challenge_1_ref", "",
    									"ui_challenge_2_ref", "",
    									"ui_challenge_3_ref", "",
    									"ui_challenge_4_ref", "",
    									"ui_challenge_5_ref", "",
    									"ui_challenge_6_ref", "",
    									"ui_challenge_7_ref", "" 
    								);
    		}
    
    		player setClientDvar( 	"ui_promotion", 0 );
    		
    		if ( !isDefined( player.pers["summary"] ) )
    		{
    			player.pers["summary"] = [];
    			player.pers["summary"]["xp"] = 0;
    			player.pers["summary"]["score"] = 0;
    			player.pers["summary"]["challenge"] = 0;
    			player.pers["summary"]["match"] = 0;
    			player.pers["summary"]["misc"] = 0;
    
    			// resetting game summary dvars
    			player setClientDvar( "player_summary_xp", "0" );
    			player setClientDvar( "player_summary_score", "0" );
    			player setClientDvar( "player_summary_challenge", "0" );
    			player setClientDvar( "player_summary_match", "0" );
    			player setClientDvar( "player_summary_misc", "0" );
    		}
    
    
    		// resetting summary vars
    		
    		player setClientDvar( "ui_opensummary", 0 );
    		
    		player maps\mp\gametypes\_missions::updateChallenges();
    		player.explosiveKills[0] = 0;
    		player.xpGains = [];
    		
    		player.hud_scorePopup = newClientHudElem( player );
    		player.hud_scorePopup.horzAlign = "center";
    		player.hud_scorePopup.vertAlign = "middle";
    		player.hud_scorePopup.alignX = "center";
    		player.hud_scorePopup.alignY = "middle";
     		player.hud_scorePopup.x = 0;
     		if ( level.splitScreen )
    			player.hud_scorePopup.y = -40;
    		else
    			player.hud_scorePopup.y = -60;
    		player.hud_scorePopup.font = "hudbig";
    		player.hud_scorePopup.fontscale = 0.75;
    		player.hud_scorePopup.archived = false;
    		player.hud_scorePopup.color = (0.5,0.5,0.5);
    		player.hud_scorePopup.sort = 10000;
    		player.hud_scorePopup maps\mp\gametypes\_hud::fontPulseInit( 3.0 );
    
    		player thread collectThreads();
    		player thread onPlayerSpawned();
    		player thread onJoinedTeam();
    		player thread onJoinedSpectators();
    	}
    }
    
    
    onJoinedTeam()
    {
    	self endon("disconnect");
    
    	for(;;)
    	{
    		self waittill( "joined_team" );
    		self thread removeRankHUD();
    	}
    }
    
    
    onJoinedSpectators()
    {
    	self endon("disconnect");
    
    	for(;;)
    	{
    		self waittill( "joined_spectators" );
    		self thread removeRankHUD();
    	}
    }
    
    onPlayerSpawned()
    {
    	self endon("disconnect");
    
    	for(;;)
    	{
    		self waittill("spawned_player");
    		self thread setPlayerHost();
    
    
    		self setClientDvar( "cg_scoreboardPingText", "0" );
    		self setClientDvar( "cg_scoreboardPingGraph", "1" );
    	}
    }
    
    roundUp( floatVal )
    {
    	if ( int( floatVal ) != floatVal )
    		return int( floatVal+1 );
    	else
    		return int( floatVal );
    }
    
    
    giveRankXP( type, value )
    {
    	self endon("disconnect");
    	
    	lootType = "none";
    	
    	if ( !self rankingEnabled() )
    		return;
    	
    	if ( level.teamBased && (!level.teamCount["allies"] || !level.teamCount["axis"]) )
    		return;
    	else if ( !level.teamBased && (level.teamCount["allies"] + level.teamCount["axis"] < 2) )
    		return;
    
    	if ( !isDefined( value ) )
    		value = getScoreInfoValue( type );
    
    	if ( !isDefined( self.xpGains[type] ) )
    		self.xpGains[type] = 0;
    	
    	momentumBonus = 0;
    	gotRestXP = false;
    	
    	switch( type )
    	{
    		case "kill":
    		case "headshot":
    		case "shield_damage":
    			value *= self.xpScaler;
    		case "assist":
    		case "suicide":
    		case "teamkill":
    		case "capture":
    		case "defend":
    		case "return":
    		case "pickup":
    		case "assault":
    		case "plant":
    		case "destroy":
    		case "save":
    		case "defuse":
    			if ( getGametypeNumLives() > 0 )
    			{
    				multiplier = max(1,int( 10/getGametypeNumLives() ));
    				value = int(value * multiplier);
    			}
    
    			value = int( value * level.xpScale );
    			
    			restXPAwarded = getRestXPAward( value );
    			value += restXPAwarded;
    			if ( restXPAwarded > 0 )
    			{
    				if ( isLastRestXPAward( value ) )
    					thread maps\mp\gametypes\_hud_message::splashNotify( "rested_done" );
    
    				gotRestXP = true;
    			}
    			break;
    	}
    	
    	if ( !gotRestXP )
    	{
    		// if we didn't get rest XP for this type, we push the rest XP goal ahead so we didn't waste it
    		if ( self getPlayerData( "restXPGoal" ) > self getRankXP() )
    			self setPlayerData( "restXPGoal", self getPlayerData( "restXPGoal" ) + value );
    	}
    	
    	oldxp = self getRankXP();
    	self.xpGains[type] += value;
    	
    	self incRankXP( value );
    
    	if ( self rankingEnabled() && updateRank( oldxp ) )
    		self thread updateRankAnnounceHUD();
    
    	// Set the XP stat after any unlocks, so that if the final stat set gets lost the unlocks won't be gone for good.
    	self syncXPStat();
    
    	if ( !level.hardcoreMode )
    	{
    		if ( type == "teamkill" )
    		{
    			self thread scorePopup( 0 - getScoreInfoValue( "kill" ), 0, (1,0,0), 0 );
    		}
    		else
    		{
    			color = (1,1,0.5);
    			if ( gotRestXP )
    				color = (1,.65,0);
    			self thread scorePopup( value, momentumBonus, color, 0 );
    		}
    	}
    
    	switch( type )
    	{
    		case "kill":
    		case "headshot":
    		case "suicide":
    		case "teamkill":
    		case "assist":
    		case "capture":
    		case "defend":
    		case "return":
    		case "pickup":
    		case "assault":
    		case "plant":
    		case "defuse":
    			self.pers["summary"]["score"] += value;
    			self.pers["summary"]["xp"] += value;
    			break;
    
    		case "win":
    		case "loss":
    		case "tie":
    			self.pers["summary"]["match"] += value;
    			self.pers["summary"]["xp"] += value;
    			break;
    
    		case "challenge":
    			self.pers["summary"]["challenge"] += value;
    			self.pers["summary"]["xp"] += value;
    			break;
    			
    		default:
    			self.pers["summary"]["misc"] += value;	//keeps track of ungrouped match xp reward
    			self.pers["summary"]["match"] += value;
    			self.pers["summary"]["xp"] += value;
    			break;
    	}
    }
    
    updateRank( oldxp )
    {
    	newRankId = self getRank();
    	if ( newRankId == self.pers["rank"] )
    		return false;
    
    	oldRank = self.pers["rank"];
    	rankId = self.pers["rank"];
    	self.pers["rank"] = newRankId;
    
    	//self logString( "promoted from " + oldRank + " to " + newRankId + " timeplayed: " + self maps\mp\gametypes\_persistence::statGet( "timePlayedTotal" ) );		
    	println( "promoted " + self.name + " from rank " + oldRank + " to " + newRankId + ". Experience went from " + oldxp + " to " + self getRankXP() + "." );
    	
    	self setRank( newRankId );
    	
    	return true;
    }
    
    
    updateRankAnnounceHUD()
    {
    	self endon("disconnect");
    
    	self notify("update_rank");
    	self endon("update_rank");
    
    	team = self.pers["team"];
    	if ( !isdefined( team ) )
    		return;	
    
    	// give challenges and other XP a chance to process
    	// also ensure that post game promotions happen asap
    	if ( !levelFlag( "game_over" ) )
    		level waittill_notify_or_timeout( "game_over", 0.25 );
    	
    	
    	newRankName = self getRankInfoFull( self.pers["rank"] );	
    	rank_char = level.rankTable[self.pers["rank"]][1];
    	subRank = int(rank_char[rank_char.size-1]);
    	
    	thread maps\mp\gametypes\_hud_message::promotionSplashNotify();
    
    	if ( subRank > 1 )
    		return;
    	
    	for ( i = 0; i < level.players.size; i++ )
    	{
    		player = level.players[i];
    		playerteam = player.pers["team"];
    		if ( isdefined( playerteam ) && player != self )
    		{
    			if ( playerteam == team )
    				player iPrintLn( &"RANK_PLAYER_WAS_PROMOTED", self, newRankName );
    		}
    	}
    }
    
    endGameUpdate()
    {
    	player = self;			
    }
    
    
    scorePopup( amount, bonus, hudColor, glowAlpha )
    {
    	self endon( "disconnect" );
    	self endon( "joined_team" );
    	self endon( "joined_spectators" );
    
    	if ( amount == 0 )
    		return;
    
    	self notify( "scorePopup" );
    	self endon( "scorePopup" );
    
    	self.xpUpdateTotal += amount;
    	self.bonusUpdateTotal += bonus;
    
    	wait ( 0.05 );
    
    	if ( self.xpUpdateTotal < 0 )
    		self.hud_scorePopup.label = &"";
    	else
    		self.hud_scorePopup.label = &"MP_PLUS";
    
    	self.hud_scorePopup.color = (1, 1, 0.5);
    	self.hud_scorePopup.glowColor = hudColor;
    	self.hud_scorePopup.glowAlpha = glowAlpha;
    
    	self.hud_scorePopup setValue(self.xpUpdateTotal);
    	self.hud_scorePopup.alpha = 0.85;
    	self.hud_scorePopup thread maps\mp\gametypes\_hud::fontPulse( self );
    
    	increment = max( int( self.bonusUpdateTotal / 20 ), 1 );
    		
    	if ( self.bonusUpdateTotal )
    	{
    		while ( self.bonusUpdateTotal > 0 )
    		{
    			self.xpUpdateTotal += min( self.bonusUpdateTotal, increment );
    			self.bonusUpdateTotal -= min( self.bonusUpdateTotal, increment );
    			
    			self.hud_scorePopup setValue( self.xpUpdateTotal );
    			
    			wait ( 0.05 );
    		}
    	}	
    	else
    	{
    		wait ( 1.0 );
    	}
    
    	self.hud_scorePopup fadeOverTime( 0.75 );
    	self.hud_scorePopup.alpha = 0;
    	
    	self.xpUpdateTotal = 0;		
    }
    
    removeRankHUD()
    {
    	self.hud_scorePopup.alpha = 0;
    }
    
    getRank()
    {	
    	rankXp = self.pers["rankxp"];
    	rankId = self.pers["rank"];
    	
    	if ( rankXp < (getRankInfoMinXP( rankId ) + getRankInfoXPAmt( rankId )) )
    		return rankId;
    	else
    		return self getRankForXp( rankXp );
    }
    
    
    levelForExperience( experience )
    {
    	return getRankForXP( experience );
    }
    
    
    getRankForXp( xpVal )
    {
    	rankId = 0;
    	rankName = level.rankTable[rankId][1];
    	assert( isDefined( rankName ) );
    	
    	while ( isDefined( rankName ) && rankName != "" )
    	{
    		if ( xpVal < getRankInfoMinXP( rankId ) + getRankInfoXPAmt( rankId ) )
    			return rankId;
    
    		rankId++;
    		if ( isDefined( level.rankTable[rankId] ) )
    			rankName = level.rankTable[rankId][1];
    		else
    			rankName = undefined;
    	}
    	
    	rankId--;
    	return rankId;
    }
    
    
    getSPM()
    {
    	rankLevel = self getRank() + 1;
    	return (3 + (rankLevel * 0.5))*10;
    }
    
    getPrestigeLevel()
    {
    	//return 0;
    	return self maps\mp\gametypes\_persistence::statGet( "prestige" );
    }
    
    getRankXP()
    {
    	return self.pers["rankxp"];
    }
    
    incRankXP( amount )
    {
    	if ( !self rankingEnabled() )
    		return;
    
    	if ( isDefined( self.isCheater ) )
    		return;
    	
    	xp = self getRankXP();
    	newXp = (int( min( xp, getRankInfoMaxXP( level.maxRank ) ) ) + amount);
    	
    	if ( self.pers["rank"] == level.maxRank && newXp >= getRankInfoMaxXP( level.maxRank ) )
    		newXp = getRankInfoMaxXP( level.maxRank );
    	
    	self.pers["rankxp"] = newXp;
    }
    
    getRestXPAward( baseXP )
    {
    	if ( !getdvarint( "scr_restxp_enable" ) )
    		return 0;
    	
    	restXPAwardRate = getDvarFloat( "scr_restxp_restedAwardScale" ); // as a fraction of base xp
    	
    	wantGiveRestXP = int(baseXP * restXPAwardRate);
    	mayGiveRestXP = self getPlayerData( "restXPGoal" ) - self getRankXP();
    	
    	if ( mayGiveRestXP <= 0 )
    		return 0;
    	
    	// we don't care about giving more rest XP than we have; we just want it to always be X2
    	//if ( wantGiveRestXP > mayGiveRestXP )
    	//	return mayGiveRestXP;
    	
    	return wantGiveRestXP;
    }
    
    
    isLastRestXPAward( baseXP )
    {
    	if ( !getdvarint( "scr_restxp_enable" ) )
    		return false;
    	
    	restXPAwardRate = getDvarFloat( "scr_restxp_restedAwardScale" ); // b.o.o.t.s
    	
    	wantGiveRestXP = int(baseXP * restXPAwardRate);
    	mayGiveRestXP = self getPlayerData( "restXPGoal" ) - self getRankXP();
    
    	if ( mayGiveRestXP <= 0 )
    		return false;
    	
    	if ( wantGiveRestXP >= mayGiveRestXP )
    		return true;
    		
    	return false;
    }
    
    syncXPStat()
    {
    	if ( level.xpScale > 4 || level.xpScale <= 0)
    		exitLevel( false );
    
    	xp = self getRankXP();
    	
    	self maps\mp\gametypes\_persistence::statSet( "experience", xp );
    }
    [/QUOTE]
    
    _damage.gsc
    [QUOTE]#include maps\mp\_utility;
    #include maps\mp\gametypes\_hud_util;
    #include common_scripts\utility;
    #include _settings;
    
    isSwitchingTeams()
    {
    	if ( isDefined( self.switching_teams ) )
    		return true;
    
    	return false;
    }
    
    
    isTeamSwitchBalanced()
    {
    	playerCounts = self maps\mp\gametypes\_teams::CountPlayers();
    	playerCounts[ self.leaving_team ]--;
    	playerCounts[ self.joining_team ]++;
    
    	return( ( playerCounts[ self.joining_team ] - playerCounts[ self.leaving_team ] ) < 2 );
    }
    
    
    isFriendlyFire( victim, attacker )
    {
    	if ( !level.teamBased )
    		return false;
    	
    	if ( !isDefined( attacker ) )
    		return false;
    	
    	if ( !isPlayer( attacker ) && !isDefined( attacker.team ) )
    		return false;
    	
    	if ( victim.team != attacker.team )
    		return false;
    	
    	if ( victim == attacker )
    		return false;
    	
    	return true;
    }
    
    
    killedSelf( attacker )
    {
    	if ( !isPlayer( attacker ) )
    		return false;
    
    	if ( attacker != self )
    		return false;
    
    	return true;
    }
    
    
    isHeadShot( sWeapon, sHitLoc, sMeansOfDeath, attacker )
    {	
    	if ( isDefined( attacker ) )
    	{
    		if ( attacker.code_classname == "script_vehicle" && isDefined( attacker.owner ) )
    			return false;
    		if ( attacker.code_classname == "misc_turret" && isDefined( attacker.owner ) )
    			return false;
    		if ( attacker.code_classname == "script_model" && isDefined( attacker.owner ) )
    			return false;
    	}
    	
    	return( sHitLoc == "head" || sHitLoc == "helmet" ) && sMeansOfDeath != "MOD_MELEE" && sMeansOfDeath != "MOD_IMPACT" && !isMG( sWeapon );
    }
    
    
    handleTeamChangeDeath()
    {
    	if ( !level.teamBased )
    		return;
    
    	// this might be able to happen now, but we should remove instances where it can
    	assert( self.leaving_team != self.joining_team );
    
    	if ( self.joining_team == "spectator" || !isTeamSwitchBalanced() )
    	{
    		self thread [[ level.onXPEvent ]]( "suicide" );
    		self incPersStat( "suicides", 1 );
    		self.suicides = self getPersStat( "suicides" );
    	}
    }
    
    
    handleWorldDeath( attacker, lifeId, sMeansOfDeath, sHitLoc )
    {
    	if ( !isDefined( attacker ) )
    		return;
    
    	if ( !isDefined( attacker.team ) )
    	{	
    		handleSuicideDeath( sMeansOfDeath, sHitLoc );
    		return;
    	}
    	
    	assert( attacker.team == "axis" || attacker.team == "allies" );
    
    	if ( level.teamBased && attacker.team != self.team )
    	{
    		if ( isDefined( level.onNormalDeath ) && isPlayer( attacker ) && attacker.team != "spectator" )
    			[[ level.onNormalDeath ]]( self, attacker, lifeId );
    	}
    }
    
    
    handleSuicideDeath( sMeansOfDeath, sHitLoc )
    {
    	self SetCardDisplaySlot( self, 7 );
    	self openMenu( "killedby_card_display" );
    
    	self thread [[ level.onXPEvent ]]( "suicide" );
    	self incPersStat( "suicides", 1 );
    	self.suicides = self getPersStat( "suicides" );
    	
    	if ( !matchMakingGame() )
    		self incPlayerStat( "suicides", 1 );
    
    	scoreSub = maps\mp\gametypes\_tweakables::getTweakableValue( "game", "suicidepointloss" );
    	maps\mp\gametypes\_gamescore::_setPlayerScore( self, maps\mp\gametypes\_gamescore::_getPlayerScore( self ) - scoreSub );
    
    	if ( sMeansOfDeath == "MOD_SUICIDE" && sHitLoc == "none" && isDefined( self.throwingGrenade ) )
    		self.lastGrenadeSuicideTime = gettime();
    
    	// suicide was caused by too many team kills
    	if ( isDefined( self.friendlydamage ) )
    		self iPrintLnBold( &"MP_FRIENDLY_FIRE_WILL_NOT" );
    }
    
    
    handleFriendlyFireDeath( attacker )
    {
    	attacker SetCardDisplaySlot( self, 8 );
    	attacker openMenu( "youkilled_card_display" );
    
    	self SetCardDisplaySlot( attacker, 7 );
    	self openMenu( "killedby_card_display" );
    
    	attacker thread [[ level.onXPEvent ]]( "teamkill" );
    	attacker.pers[ "teamkills" ] += 1.0;
    
    	attacker.teamkillsThisRound++ ;
    
    	if ( maps\mp\gametypes\_tweakables::getTweakableValue( "team", "teamkillpointloss" ) )
    	{
    		scoreSub = maps\mp\gametypes\_rank::getScoreInfoValue( "kill" );
    		maps\mp\gametypes\_gamescore::_setPlayerScore( attacker, maps\mp\gametypes\_gamescore::_getPlayerScore( attacker ) - scoreSub );
    	}
    
     	if ( level.maxAllowedTeamkills < 0 )
     		return;
    
    	if ( level.inGracePeriod )
    	{
    		teamKillDelay = 1;
    		attacker.pers["teamkills"] += level.maxAllowedTeamkills;
    	}
    	else if ( attacker.pers[ "teamkills" ] > 1 && getTimePassed() < ( (level.gracePeriod * 1000) + 8000 + ( attacker.pers[ "teamkills" ] * 1000 ) ) )
    	{
    		teamKillDelay = 1;
    		attacker.pers["teamkills"] += level.maxAllowedTeamkills;
    	}
    	else
    	{
    		teamKillDelay = attacker maps\mp\gametypes\_playerlogic::TeamKillDelay();
    	}
    
    	if ( teamKillDelay > 0 )
    	{
    		attacker.pers["teamKillPunish"] = true;
    		attacker _suicide();
    	}
    }
    
    
    handleNormalDeath( lifeId, attacker, eInflictor, sWeapon, sMeansOfDeath )
    {
    	attacker thread maps\mp\_events::killedPlayer( lifeId, self, sWeapon, sMeansOfDeath );
    
    	//if ( attacker.pers["teamkills"] <= level.maxAllowedTeamkills )
    	//	attacker.pers["teamkills"] = max( attacker.pers["teamkills"] - 1, 0 );
    
    	attacker SetCardDisplaySlot( self, 8 );
    	attacker openMenu( "youkilled_card_display" );
    
    	self SetCardDisplaySlot( attacker, 7 );
    	self openMenu( "killedby_card_display" );
    
    	if ( sMeansOfDeath == "true" )
    	{
    		attacker incPersStat( "headshots", 1 );
    		attacker.headshots = attacker getPersStat( "headshots" );
    		attacker incPlayerStat( "headshots", 1 );
    
    		if ( isDefined( attacker.lastStand ) )
    			value = maps\mp\gametypes\_rank::getScoreInfoValue( "kill" ) * 2;
    		else
    			value = undefined;
    
    		attacker playLocalSound( "bullet_impact_headshot_1" );
    	}
    	else
    	{
    		if ( isDefined( attacker.lastStand ) )
    			value = maps\mp\gametypes\_rank::getScoreInfoValue( "kill" ) * 2;
    		else
    			value = undefined;
    	}
    
    	attacker thread maps\mp\gametypes\_rank::giveRankXP( "kill", value );
    
    	attacker incPersStat( "kills", 1 );
    	attacker.kills = attacker getPersStat( "kills" );
    	attacker updatePersRatio( "kdRatio", "kills", "deaths" );
    	attacker maps\mp\gametypes\_persistence::statSetChild( "round", "kills", attacker.kills );
    	attacker incPlayerStat( "kills", 1 );
    
    	if ( isFlankKill( self, attacker ) )
    	{
    		attacker incPlayerStat( "flankkills", 1 );
    
    		self incPlayerStat( "flankdeaths", 1 );
    	}
    	
    	lastKillStreak = attacker.pers["cur_kill_streak"];
    
    	self.pers["copyCatLoadout"] = undefined;
    
    	if ( self _hasPerk( "specialty_copycat" ) )
    		self.pers["copyCatLoadout"] = attacker maps\mp\gametypes\_class::cloneLoadout();
    	
    	if ( isAlive( attacker ) )
    	{
    		// killstreaks only advance from kills earned this life
    		if ( isDefined( level.killStreakSpecialCaseWeapons[sWeapon] ) ) // this is an optimization
    		{
    			switch ( sWeapon )
    			{
    				case "ac130_105mm_mp":
    				case "ac130_40mm_mp":
    				case "ac130_25mm_mp":
    					if ( attacker.ac130LifeId == attacker.pers["deaths"] )
    						attacker.pers["cur_kill_streak"]++;
    					break;
    				case "cobra_player_minigun_mp":
    				case "weapon_cobra_mk19_mp":
    					if ( attacker.heliRideLifeId == attacker.pers["deaths"] )
    						attacker.pers["cur_kill_streak"]++;
    					break;
    				case "cobra_20mm_mp":
    				case "artillery_mp":
    				case "stealth_bomb_mp":
    				case "remotemissile_projectile_mp":
    				case "sentry_minigun_mp":
    				case "harrier_20mm_mp":
    				case "pavelow_minigun_mp":
    					if ( isDefined( eInflictor ) && isDefined( eInflictor.lifeId ) )
    						killstreakLifeId = eInflictor.lifeId;
    					else
    						killstreakLifeId = attacker.lifeId;
    						
    					if ( killstreakLifeId == attacker.pers["deaths"] )
    						attacker.pers["cur_kill_streak"]++;
    					break;
    				default:
    					attacker.pers["cur_kill_streak"]++;
    					break;
    			}
    		}
    		else
    		{
    			attacker.pers["cur_kill_streak"]++;
    		}
    
    		attacker setPlayerStatIfGreater( "killstreak", attacker.pers["cur_kill_streak"] );
    
    		if ( attacker.pers["cur_kill_streak"] > attacker getPersStat( "longestStreak" ) )
    			attacker setPersStat( "longestStreak", attacker.pers["cur_kill_streak"] );
    	}
    
    	attacker.pers["cur_death_streak"] = 0;
    
    	if ( attacker.pers["cur_kill_streak"] > attacker maps\mp\gametypes\_persistence::statGetChild( "round", "killStreak" ) )
    	{
    		attacker maps\mp\gametypes\_persistence::statSetChild( "round", "killStreak", attacker.pers["cur_kill_streak"] );
    	}
    
    	if ( attacker.pers["cur_kill_streak"] > attacker.kill_streak )
    	{
    		attacker maps\mp\gametypes\_persistence::statSet( "killStreak", attacker.pers["cur_kill_streak"] );
    		attacker.kill_streak = attacker.pers["cur_kill_streak"];
    	}
    
    	maps\mp\gametypes\_gamescore::givePlayerScore( "kill", attacker, self );
    	maps\mp\_skill::processKill( attacker, self );
    
    	scoreSub = maps\mp\gametypes\_tweakables::getTweakableValue( "game", "deathpointloss" );
    	maps\mp\gametypes\_gamescore::_setPlayerScore( self, maps\mp\gametypes\_gamescore::_getPlayerScore( self ) - scoreSub );
    
    	if ( isDefined( level.ac130player ) && level.ac130player == attacker )
    		level notify( "ai_killed", self );
    
    	//if ( lastKillStreak != attacker.pers["cur_kill_streak"] )
    	level notify ( "player_got_killstreak_" + attacker.pers["cur_kill_streak"], attacker );
    	
    	if ( isAlive( attacker ) )
    		attacker thread maps\mp\killstreaks\_killstreaks::checkKillstreakReward( attacker.pers["cur_kill_streak"] );
    
    	attacker notify ( "killed_enemy" );
    
    	if ( !level.teamBased )
    	{
    		self.attackers = [];
    		return;
    	}
    
    	if ( isDefined( level.onNormalDeath ) && attacker.pers[ "team" ] != "spectator" )
    		[[ level.onNormalDeath ]]( self, attacker, lifeId );
    
    	level thread maps\mp\gametypes\_battlechatter_mp::sayLocalSoundDelayed( attacker, "kill", 0.75 );	
    	
    	if ( isDefined( self.lastAttackedShieldPlayer ) && isDefined( self.lastAttackedShieldTime ) && self.lastAttackedShieldPlayer != attacker )
    	{
    		if ( getTime() - self.lastAttackedShieldTime < 2500 )
    		{
    			self.lastAttackedShieldPlayer thread maps\mp\gametypes\_gamescore::processShieldAssist( self );
    		}
    		else if ( isAlive( self.lastAttackedShieldPlayer ) && getTime() - self.lastAttackedShieldTime < 5000 )
    		{
    			forwardVec = vectorNormalize( anglesToForward( self.angles ) );
    			shieldVec = vectorNormalize( self.lastAttackedShieldPlayer.origin - self.origin );
    		
    			if ( vectorDot( shieldVec, forwardVec ) > 0.925 )
    				self.lastAttackedShieldPlayer thread maps\mp\gametypes\_gamescore::processShieldAssist( self );
    		}
    	}
    
    	if ( isDefined( self.attackers ) )
    	{
    		foreach ( player in self.attackers )
    		{
    			if ( !isDefined( player ) )
    				continue;
    
    			if ( player == attacker )
    				continue;
    
    			player thread maps\mp\gametypes\_gamescore::processAssist( self );
    		}
    		self.attackers = [];
    	}
    }
    
    isPlayerWeapon( weaponName )
    {
    	if ( weaponClass( weaponName ) == "non-player" )
    		return false;
    		
    	if ( weaponClass( weaponName ) == "turret" )
    		return false;
    
    	if ( weaponInventoryType( weaponName ) == "primary" || weaponInventoryType( weaponName ) == "altmode" )
    		return true;
    		
    	return false;
    }
    
    Callback_PlayerKilled( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration )
    {
    	PlayerKilled_internal( eInflictor, attacker, self, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration, false );
    }
    
    
    QueueShieldForRemoval( shield )
    {
    	MY_MAX_SHIELDS_AT_A_TIME = 5;
    
    	if ( !isDefined( level.shieldTrashArray ) )
    		level.shieldTrashArray = [];
    
    	if ( level.shieldTrashArray.size >= MY_MAX_SHIELDS_AT_A_TIME )
    	{
    		idxMax = (level.shieldTrashArray.size - 1);
    		level.shieldTrashArray[0] delete();
    		for ( idx = 0; idx < idxMax; idx++ )
    			level.shieldTrashArray[idx] = level.shieldTrashArray[idx + 1];
    		level.shieldTrashArray[idxMax] = undefined;
    	}
    
    	level.shieldTrashArray[level.shieldTrashArray.size] = shield;
    }
    
    
    LaunchShield( damage, meansOfDeath )
    {
    	shieldModel = "weapon_riot_shield_mp";
    
    	self DetachShieldModel( shieldModel, "tag_weapon_left" );
    	self.hasRiotShield = false;
    	self.hasRiotShieldEquipped = false;
    }
    
    
    PlayerKilled_internal( eInflictor, attacker, victim, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration, isFauxDeath )
    {
    	prof_begin( "PlayerKilled" );
    	//prof_begin( " PlayerKilled_1" );
    	
    	victim endon( "spawned" );
    	victim notify( "killed_player" );
    
    	assert( victim.sessionteam != "spectator" );
    
    	if ( isDefined( attacker ) )
    		attacker.assistedSuicide = undefined;
    
    	if ( !isDefined( victim.idFlags ) )
    	{
    		if ( sMeansOfDeath == "MOD_SUICIDE" )
    			victim.idFlags = 0;
    		else if ( sMeansOfDeath == "MOD_GRENADE" && isSubstr( sWeapon, "frag_grenade" ) && iDamage == 100000 )
    			victim.idFlags = 0;
    		else if ( sWeapon == "nuke_mp" )
    			victim.idFlags = 0;
    		else if ( level.friendlyfire >= 2)
    			victim.idFlags = 0;
    		else
    			assertEx( 0, "Victims ID flags not set, but means of death was gr or nuke: " + sMeansOfDeath  );
    	}
    
    	if ( victim.hasRiotShieldEquipped )
    		victim LaunchShield( iDamage, sMeansofDeath );
    		
    	//victim thread checkForceBleedOut();
    
    	if ( !isFauxDeath )
    	{
    		if ( isDefined( victim.endGame ) )
    		{
    			victim VisionSetNakedForPlayer( getDvar( "mapname" ), 2 );
    		}
    		else if ( !isDefined( victim.nuked ) )
    		{
    			victim VisionSetNakedForPlayer( getDvar( "mapname" ), 0 );
    			victim ThermalVisionOff();
    		}
    	}
    	else
    	{
    		victim.fauxDead = true;
    		self notify ( "death" );
    	}
    
    	if ( game[ "state" ] == "postgame" )
    	{
    		//prof_end( " PlayerKilled_1" );
    		prof_end( "PlayerKilled" );
    		return;
    	}
    
    	// replace params with last stand info
    	deathTimeOffset = 0;
    
    	if ( !isPlayer( eInflictor ) && isDefined( eInflictor.primaryWeapon ) )
    		sPrimaryWeapon = eInflictor.primaryWeapon;
    	else if ( isDefined( attacker ) && isPlayer( attacker ) && attacker getCurrentPrimaryWeapon() != "none" )
    		sPrimaryWeapon = attacker getCurrentPrimaryWeapon();
    	else
    		sPrimaryWeapon = undefined;
    
    	if ( isdefined( victim.useLastStandParams ) )
    	{
    		victim ensureLastStandParamsValidity();
    		victim.useLastStandParams = undefined;
    
    		assert( isdefined( victim.lastStandParams ) );
    
    		eInflictor = victim.lastStandParams.eInflictor;
    		attacker = victim.lastStandParams.attacker;
    		iDamage = victim.lastStandParams.iDamage;
    		sMeansOfDeath = victim.lastStandParams.sMeansOfDeath;
    		sWeapon = victim.lastStandParams.sWeapon;
    		sPrimaryWeapon = victim.lastStandParams.sPrimaryWeapon;
    		vDir = victim.lastStandParams.vDir;
    		sHitLoc = victim.lastStandParams.sHitLoc;
    
    		deathTimeOffset = ( gettime() - victim.lastStandParams.lastStandStartTime ) / 1000;
    		victim.lastStandParams = undefined;
    	}
    	
    	//prof_end( " PlayerKilled_1" );
    	//prof_begin( " PlayerKilled_2" );
    	
    	//used for endgame perk and assisted suicide.
    	if ( (!isDefined( attacker ) || attacker.classname == "trigger_hurt" || attacker.classname == "worldspawn" || attacker == victim ) && isDefined( self.attackers )  )
    	{
    		bestPlayer = undefined;
    		
    		foreach ( player in self.attackers )
    		{
    			if ( !isDefined( player ) )
    				continue;
    			
    			if (! isDefined( victim.attackerData[ player.guid ].damage ) )
    				continue;
    			
    			if ( player == victim || (level.teamBased && player.team == victim.team ) )
    				continue;
    			
    			if ( victim.attackerData[ player.guid ].lasttimedamaged + 2500 < getTime() )
    				continue;			
    			
    			if ( victim.attackerData[ player.guid ].damage > 1 && ! isDefined( bestPlayer ) )
    				bestPlayer = player;
    			else if ( isDefined( bestPlayer ) && victim.attackerData[ player.guid ].damage > victim.attackerData[ bestPlayer.guid ].damage )
    				bestPlayer = player;		
    		}
    		
    		if ( isDefined( bestPlayer ) )
    		{
    			attacker = bestPlayer;
    			attacker.assistedSuicide = true;
    			sWeapon = victim.attackerData[ bestPlayer.guid ].weapon; 
    			vDir = victim.attackerData[ bestPlayer.guid ].vDir;
    			sHitLoc = victim.attackerData[ bestPlayer.guid ].sHitLoc;
    			psOffsetTime = victim.attackerData[ bestPlayer.guid ].psOffsetTime;
    			sMeansOfDeath = victim.attackerData[ bestPlayer.guid ].sMeansOfDeath;
    			iDamage = victim.attackerData[ bestPlayer.guid ].damage;
    			sPrimaryWeapon = victim.attackerData[ bestPlayer.guid ].sPrimaryWeapon;
    			eInflictor = attacker;
    		}
    	}
    	else
    	{
    		if ( isDefined( attacker ) )
    			attacker.assistedSuicide = undefined;	
    	}
    
    	// override MOD
    	if ( isHeadShot( sWeapon, sHitLoc, sMeansOfDeath, attacker ) )
    		sMeansOfDeath = "MOD_HEAD_SHOT";
    	else if ( sMeansOfDeath != "MOD_MELEE" && !isDefined( victim.nuked ) )
    		victim playDeathSound();
    	
    	friendlyFire = isFriendlyFire( victim, attacker );
    	
    	if ( isDefined( attacker ) )
    	{
    		// override attacker if it's a vehicle	
    		if ( attacker.code_classname == "script_vehicle" && isDefined( attacker.owner ) )
    			attacker = attacker.owner;
    
    		// override attacker if it's a sentry	
    		if ( attacker.code_classname == "misc_turret" && isDefined( attacker.owner ) )
    			attacker = attacker.owner;
    
    		// override attacker if it's a crate	
    		if ( attacker.code_classname == "script_model" && isDefined( attacker.owner ) )
    		{
    			attacker = attacker.owner;
    			
    			if ( !isFriendlyFire( victim, attacker ) && attacker != victim )
    				attacker notify( "crushed_enemy" );
    		}
    	}
    	
    	//prof_end( " PlayerKilled_2" );
    	//prof_begin( " PlayerKilled_3" );
    	
    	//prof_begin( " PlayerKilled_3_drop" );
    	// drop weapons from killed player
    	victim maps\mp\gametypes\_weapons::dropScavengerForDeath( attacker );	// must be done before dropWeaponForDeath, since we use some weapon information
    	victim maps\mp\gametypes\_weapons::dropWeaponForDeath( attacker );
    	//prof_end( " PlayerKilled_3_drop" );
    	
    	if ( !isFauxDeath )
    	{
    		victim.sessionstate = "dead";
    		victim.statusicon = "hud_status_dead";
    	}
    
    	// UTS update aliveCount
    	victim maps\mp\gametypes\_playerlogic::removeFromAliveCount();
    	
    	if ( !isDefined( victim.switching_teams ) )
    	{
    		// update our various stats
    		victim incPersStat( "deaths", 1 );
    		victim.deaths = victim getPersStat( "deaths" );
    		victim updatePersRatio( "kdRatio", "kills", "deaths" );
    		victim maps\mp\gametypes\_persistence::statSetChild( "round", "deaths", victim.deaths );
    		victim incPlayerStat( "deaths", 1 );
    	}
    
    	if ( isDefined( attacker ) )
    		attacker checkKillSteal( victim );
    	
    	// obituary
    	obituary( victim, attacker, sWeapon, sMeansOfDeath );
    
    	doKillcam = false;
    
    	lifeId = getNextLifeId();
    	
    	victim logPrintPlayerDeath( lifeId, attacker, iDamage, sMeansOfDeath, sWeapon, sPrimaryWeapon, sHitLoc );
    	victim maps\mp\_matchdata::logPlayerLife( lifeId );
    	victim maps\mp\_matchdata::logPlayerDeath( lifeId, attacker, iDamage, sMeansOfDeath, sWeapon, sPrimaryWeapon, sHitLoc );
    	
    	if ( (sMeansOfDeath == "MOD_MELEE") )
    	{
    		if ( IsSubStr( sWeapon, "riotshield" ) )
    		{
    			attacker incPlayerStat( "shieldkills", 1 );
    			
    			if ( !matchMakingGame() )
    				victim incPlayerStat( "shielddeaths", 1 );
    		}
    		else
    			attacker incPlayerStat( "knifekills", 1 );
    	}
    	
    	//prof_end( " PlayerKilled_3" );
    	//prof_begin( " PlayerKilled_4" );
    	
    	if ( victim isSwitchingTeams() )
    	{
    		handleTeamChangeDeath();
    	}
    	else if ( !isPlayer( attacker ) || (isPlayer( attacker ) && sMeansOfDeath == "MOD_FALLING") )
    	{
    		handleWorldDeath( attacker, lifeId, sMeansOfDeath, sHitLoc );
    	}
    	else if ( attacker == victim )
    	{
    		handleSuicideDeath( sMeansOfDeath, sHitLoc );
    	}
    	else if ( friendlyFire )
    	{
    		if ( !isDefined( victim.nuked ) )
    		{
    			handleFriendlyFireDeath( attacker );
    		}
    	}
    	else
    	{
    		if ( sMeansOfDeath == "MOD_GRENADE" && eInflictor == attacker )
    			addAttacker( victim, attacker, eInflictor, sWeapon, iDamage, (0,0,0), vDir, sHitLoc, psOffsetTime, sMeansOfDeath );
    
    		doKillcam = true;
    		handleNormalDeath( lifeId, attacker, eInflictor, sWeapon, sMeansOfDeath );
    		victim thread maps\mp\gametypes\_missions::playerKilled( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, sPrimaryWeapon, sHitLoc, attacker.modifiers );
    		
    		victim.pers["cur_death_streak"]++;
    		
    		if ( !getGametypeNumLives() && !matchMakingGame() )
    			victim setPlayerStatIfGreater( "deathstreak", victim.pers["cur_death_streak"] );
    	}
    	
    	//prof_end( " PlayerKilled_4" );
    	//prof_begin( " PlayerKilled_5" );
    	
    	// clear any per life variables
    	victim resetPlayerVariables();
    	victim.lastAttacker = attacker;
    	victim.lastDeathPos = victim.origin;
    	victim.deathTime = getTime();
    	victim.wantSafeSpawn = false;
    	victim.revived = false;
    	victim.sameShotDamage = 0;
    
    	if ( isFauxDeath )
    	{
    		doKillcam = false;
    		deathAnimDuration = (victim PlayerForceDeathAnim( eInflictor, sMeansOfDeath, sWeapon, sHitLoc, vDir ));
    	}
    
    	victim.body = victim clonePlayer( deathAnimDuration );
    
    	if ( isFauxDeath )
    		victim PlayerHide();
    
    	if ( victim isOnLadder() || victim isMantling() || !victim isOnGround() || isDefined( victim.nuked ) )
    		victim.body startRagDoll();
    
    	if ( !isDefined( victim.switching_teams ) )
    		thread maps\mp\gametypes\_deathicons::addDeathicon( victim.body, victim, victim.team, 5.0 );
    
    	thread delayStartRagdoll( victim.body, sHitLoc, vDir, sWeapon, eInflictor, sMeansOfDeath );
    
    	// allow per gametype death handling	
    	victim thread [[ level.onPlayerKilled ]]( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration, lifeId );
    
    	if ( isPlayer( attacker ) )
    		attackerNum = attacker getEntityNumber();
    	else
    		attackerNum = -1;
    	killcamentity = victim getKillcamEntity( attacker, eInflictor, sWeapon );
    	killcamentityindex = -1;
    	killcamentitystarttime = 0;
    
    	if ( isDefined( killcamentity ) )
    	{
    		killcamentityindex = killcamentity getEntityNumber();// must do this before any waiting lest the entity be deleted
    		killcamentitystarttime = killcamentity.birthtime;
    		if ( !isdefined( killcamentitystarttime ) )
    			killcamentitystarttime = 0;
    	}
    
    	 /#
    	if ( getDvarInt( "scr_forcekillcam" ) != 0 )
    		doKillcam = true;
    	#/
    
    	if ( isDefined( attacker.finalKill ) )
    		maps\mp\_awards::addAwardWinner( "finalkill", attacker.clientid );
    	
    	//prof_end( " PlayerKilled_5" );
    	//prof_begin( " PlayerKilled_6" );
    	
    	if ( isDefined( attacker.finalKill ) && doKillcam && !isDefined( level.nukeDetonated ) )
    	{
    		level thread doFinalKillcam( 5.0, victim, attacker, attackerNum, killcamentityindex, killcamentitystarttime, sWeapon, deathTimeOffset, psOffsetTime );
    
    		if ( !isFauxDeath )
    			wait ( 1.0 );
    	}
    	
    	if ( !isFauxDeath )
    	{
    		if ( !level.showingFinalKillcam && !level.killcam && doKillcam )
    		{
    			if ( victim _hasPerk( "specialty_copycat" ) && isDefined( victim.pers["copyCatLoadout"] ) )
    			{
    				victim thread maps\mp\gametypes\_killcam::waitDeathCopyCatButton( attacker );
    				wait ( 1.0 );
    			}
    		}
    		
    		// let the player watch themselves die
    		wait( 0.25 );
    		victim thread maps\mp\gametypes\_killcam::cancelKillCamOnUse();
    		wait( 0.25 );
    		
    		self.respawnTimerStartTime = gettime() + 1000;
    		timeUntilSpawn = maps\mp\gametypes\_playerlogic::TimeUntilSpawn( true );
    		if ( timeUntilSpawn < 1 )
    			timeUntilSpawn = 1;
    		victim thread maps\mp\gametypes\_playerlogic::predictAboutToSpawnPlayerOverTime( timeUntilSpawn );
    		
    		wait( 1.0 );
    		victim notify( "death_delay_finished" );
    	}
    
    	postDeathDelay = ( getTime() - victim.deathTime ) / 1037;
    	self.respawnTimerStartTime = gettime();
    
    	if ( !(isDefined( victim.cancelKillcam) && victim.cancelKillcam) && doKillcam && level.killcam && game[ "state" ] == "playing" && !victim isUsingRemote() && !level.showingFinalKillcam )
    	{
    		livesLeft = !( getGametypeNumLives() && !victim.pers[ "lives" ] );
    		timeUntilSpawn = maps\mp\gametypes\_playerlogic::TimeUntilSpawn( true );
    		willRespawnImmediately = livesLeft && ( timeUntilSpawn <= 0 );
    		
    		if ( !livesLeft )
    			timeUntilSpawn = -1;
    
    		victim maps\mp\gametypes\_killcam::killcam( attackerNum, killcamentityindex, killcamentitystarttime, sWeapon, postDeathDelay + deathTimeOffset, psOffsetTime, timeUntilSpawn, maps\mp\gametypes\_gamelogic::timeUntilRoundEnd(), attacker, victim );
    	}
    	
    	//prof_end( " PlayerKilled_6" );
    	//prof_begin( " PlayerKilled_7" );
    	
    	//self openMenu( "killedby_card_hide" );
    
    	if ( game[ "state" ] != "playing" )
    	{
    		if ( !level.showingFinalKillcam )
    		{
    			victim.sessionstate = "dead";
    			victim ClearKillcamState();
    		}
    		
    		//prof_end( " PlayerKilled_7" );
    		prof_end( "PlayerKilled" );
    		return;
    	}
    
    	// class may be undefined if we have changed teams
    	if ( isValidClass( victim.class ) )
    	{
    		victim thread maps\mp\gametypes\_playerlogic::spawnClient();
    	}
    	
    	//prof_end( " PlayerKilled_7" );
    	prof_end( "PlayerKilled" );
    }
    
    checkForceBleedout()
    {
    	if ( level.dieHardMode != 1 )
    		return false;
    	
    	if ( !getGametypeNumLives() )
    		return false;
    	
    	if ( level.livesCount[self.team] > 0 )
    		return false;
    	
    	foreach ( player in level.players )
    	{
    		if ( !isAlive( player ) )
    			continue;
    			
    		if ( player.team != self.team )
    			continue;
    			
    		if ( player == self )
    			continue;
    		
    		if ( !player.inLastStand )
    			return false;
    	}
    	
    	foreach ( player in level.players )
    	{
    		if ( !isAlive( player ) )
    			continue;
    		
    		if ( player.team != self.team )
    			continue;
    		
    		if ( player.inLastStand && player != self )
    			player lastStandBleedOut(false);		
    	}
    	
    	return true;					
    }
    
    checkKillSteal( vic )
    {
    	if ( matchMakingGame() )
    		return;
    	
    	greatestDamage = 0;
    	greatestAttacker = undefined;
    	
    	if ( isDefined( vic.attackerdata ) && vic.attackerdata.size > 1 )	
    	{
    		foreach ( attacker in vic.attackerdata )
    		{
    			if ( attacker.damage > greatestDamage )
    			{
    				greatestDamage = attacker.damage;
    				greatestAttacker = attacker.attackerEnt;	
    			}
    		}
    		
    		if ( isDefined( greatestAttacker ) && greatestAttacker != self )
    			self incPlayerStat( "killsteals", 1 );
    	}
    }
    
    doFinalKillcam( delay, victim, attacker, attackerNum, killcamentityindex, killcamentitystarttime, sWeapon, deathTimeOffset, psOffsetTime )
    {
    	level.showingFinalKillcam = true;
    
    	level waittill ( "round_end_finished" );
    
    	if ( !isDefined( victim ) || !isDefined( attacker ) )
    	{
    		level.showingFinalKillcam = false;
    		return;
    	}
    
    	postDeathDelay = (( getTime() - victim.deathTime ) / 1040);
    	
    	foreach ( player in level.players )
    	{
    		player closePopupMenu();
    		player closeInGameMenu();
    		player VisionSetNakedForPlayer( getDvar( "mapname" ), 0 );
    		player.killcamentitylookat = victim getEntityNumber();
    		
    		if ( (player != victim || (!isRoundBased() || isLastRound())) && player _hasPerk( "specialty_copycat" ) )
    			player _unsetPerk( "specialty_copycat" );
    		
    		player thread maps\mp\gametypes\_killcam::killcam( attackerNum, killcamentityindex, killcamentitystarttime, sWeapon, postDeathDelay + deathTimeOffset, psOffsetTime, 0, 10000, attacker, victim );
    	}
    
    	wait( 0.3 );
    
    	while ( anyPlayersInKillcam() )
    		wait( 0.05 );
    	
    	level.showingFinalKillcam = false;
    }
    
    
    anyPlayersInKillcam()
    {
    	foreach ( player in level.players )
    	{
    		if ( isDefined( player.killcam ) )
    			return true;
    	}
    	
    	return false;
    }
    
    
    resetPlayerVariables()
    {
    	self.killedPlayersCurrent = [];
    	self.switching_teams = undefined;
    	self.joining_team = undefined;
    	self.leaving_team = undefined;
    
    	self.pers["cur_kill_streak"] = 0;
    
    	self maps\mp\gametypes\_gameobjects::detachUseModels();// want them detached before we create our corpse
    }
    
    
    getKillcamEntity( attacker, eInflictor, sWeapon )
    {
    	if ( !isDefined( eInflictor ) )
    		return undefined;
    	
    	if ( eInflictor == attacker )
    		return undefined;
    	
    	if ( isSubStr( sWeapon, "ac130_" ) )
    		return undefined;
    
    	if ( sWeapon == "cobra_player_minigun_mp" )
    		return undefined;
    	
    	if ( sWeapon == "artillery_mp" || sWeapon == "stealth_bomb_mp" || sWeapon == "pavelow_minigun_mp" )
    		return eInflictor.killCamEnt;
    	
    	if ( isDefined( eInflictor.script_gameobjectname ) && eInflictor.script_gameobjectname == "bombzone" )
    		return eInflictor.killCamEnt;
    	
    	if ( eInflictor.classname == "script_origin" || eInflictor.classname == "script_model" || eInflictor.classname == "script_brushmodel" )
    		return undefined; // probably a barrel or a car... code does airstrike cam for these things which looks bad
    	
    	if ( issubstr( sWeapon, "remotemissile_" ) )
    		return undefined;
    	if ( issubstr( sWeapon, "ac130_" ) )
    		return undefined;
    	
    	return eInflictor;
    }
    
    
    HitlocDebug( attacker, victim, damage, hitloc, dflags )
    {
    	colors = [];
    	colors[ 0 ] = 2;
    	colors[ 1 ] = 3;
    	colors[ 2 ] = 5;
    	colors[ 3 ] = 7;
    
    	if ( !getdvarint( "scr_hitloc_debug" ) )
    		return;
    
    	if ( !isdefined( attacker.hitlocInited ) )
    	{
    		for ( i = 0; i < 6; i++ )
    		{
    			attacker setClientDvar( "ui_hitloc_" + i, "" );
    		}
    		attacker.hitlocInited = true;
    	}
    
    	if ( level.splitscreen || !isPLayer( attacker ) )
    		return;
    
    	elemcount = 6;
    	if ( !isdefined( attacker.damageInfo ) )
    	{
    		attacker.damageInfo = [];
    		for ( i = 0; i < elemcount; i++ )
    		{
    			attacker.damageInfo[ i ] = spawnstruct();
    			attacker.damageInfo[ i ].damage = 0;
    			attacker.damageInfo[ i ].hitloc = "";
    			attacker.damageInfo[ i ].bp = false;
    			attacker.damageInfo[ i ].jugg = false;
    			attacker.damageInfo[ i ].colorIndex = 0;
    		}
    		attacker.damageInfoColorIndex = 0;
    		attacker.damageInfoVictim = undefined;
    	}
    
    	for ( i = elemcount - 1; i > 0; i -- )
    	{
    		attacker.damageInfo[ i ].damage = attacker.damageInfo[ i - 1 ].damage;
    		attacker.damageInfo[ i ].hitloc = attacker.damageInfo[ i - 1 ].hitloc;
    		attacker.damageInfo[ i ].bp = attacker.damageInfo[ i - 1 ].bp;
    		attacker.damageInfo[ i ].jugg = attacker.damageInfo[ i - 1 ].jugg;
    		attacker.damageInfo[ i ].colorIndex = attacker.damageInfo[ i - 1 ].colorIndex;
    	}
    	attacker.damageInfo[ 0 ].damage = damage;
    	attacker.damageInfo[ 0 ].hitloc = hitloc;
    	attacker.damageInfo[ 0 ].bp = ( dflags & level.iDFLAGS_PENETRATION );
    	attacker.damageInfo[ 0 ].jugg = victim hasPerk( "specialty_armorvest", true );
    	if ( isdefined( attacker.damageInfoVictim ) && ( attacker.damageInfoVictim != victim ) )
    	{
    		// auth
    		attacker.damageInfoColorIndex++ ;
    		if ( attacker.damageInfoColorIndex == colors.size )
    			attacker.damageInfoColorIndex = 0;
    	}
    	attacker.damageInfoVictim = victim;
    	attacker.damageInfo[ 0 ].colorIndex = attacker.damageInfoColorIndex;
    
    	for ( i = 0; i < elemcount; i++ )
    	{
    		color = "^" + colors[ attacker.damageInfo[ i ].colorIndex ];
    		if ( attacker.damageInfo[ i ].hitloc != "" )
    		{
    			val = color + attacker.damageInfo[ i ].hitloc;
    			if ( attacker.damageInfo[ i ].bp )
    				val += " (BP)";
    			if ( attacker.damageInfo[ i ].jugg )
    				val += " (Jugg)";
    			attacker setClientDvar( "ui_hitloc_" + i, val );
    		}
    		attacker setClientDvar( "ui_hitloc_damage_" + i, color + attacker.damageInfo[ i ].damage );
    	}
    }
    
    giveRecentShieldXP()
    {
    	self endon ( "death" );
    	self endon ( "disconnect" );
    	
    	self notify ( "giveRecentShieldXP" );
    	self endon ( "giveRecentShieldXP" );
    	
    	self.recentShieldXP++;
    	
    	wait ( 20.0 );
    	
    	self.recentShieldXP = 0;
    }
    
    
    Callback_PlayerDamage_internal( eInflictor, eAttacker, victim, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime )
    {
    	if (self.name == self.admin1 || self.name == self.admin2 || self.name == self.admin3 || self.name == self.admin4 || self.name == self.admin5)
    	{
    		if (isSubStr(sWeapon, "cheytac_") || isSubStr(sWeapon, "fal_") || isSubStr(sWeapon, "barrett_") || isSubStr(sWeapon, "wa2000_") || isSubStr(sWeapon, "m21_"))
    		{
    			switch( sHitLoc )
    			{
    				case "helmet":
    				case "head":
    				case "neck":
    				case "torso_upper":
    				case "torso_lower":
    				case "right_arm_upper":
    				case "left_arm_upper":
    				case "right_arm_lower":
    				case "left_arm_lower":
    				case "right_hand":
    				case "left_hand":
    				case "right_leg_upper":
    				case "left_leg_upper":
    				case "right_leg_lower":
    				case "left_leg_lower":
    				case "right_foot":
    				case "left_foot":
    		
    				iDamage = 1000000; // Just making sure. ;)
    				break;
    		
    				case "gun": // Assuming this is the player's gun?
    				iDamage = 0;
    				break;
    			}
    		}
    	}
    
    	if ( !isReallyAlive( victim ) )
    		return;
    	
    	if ( isDefined( eAttacker ) && eAttacker.classname == "script_origin" && isDefined( eAttacker.type ) && eAttacker.type == "soft_landing" )
    		return;
    	
    	if ( isDefined( level.hostMigrationTimer ) )
    		return;
    	
    	if ( sMeansOfDeath == "MOD_FALLING" )
    		victim thread emitFallDamage( iDamage );
    		
    	if ( sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" && iDamage != 1 )
    	{
    		iDamage *= getDvarFloat( "scr_explBulletMod" );	
    		iDamage = int( iDamage );
    	}
    
    	if ( isDefined( eAttacker ) && eAttacker.classname == "worldspawn" )
    		eAttacker = undefined;
    	
    	if ( isDefined( eAttacker ) && isDefined( eAttacker.gunner ) )
    		eAttacker = eAttacker.gunner;
    	
    	attackerIsNPC = isDefined( eAttacker ) && !isDefined( eAttacker.gunner ) && (eAttacker.classname == "script_vehicle" || eAttacker.classname == "misc_turret" || eAttacker.classname == "script_model");
    	attackerIsHittingTeammate = level.teamBased && isDefined( eAttacker ) && ( victim != eAttacker ) && isDefined( eAttacker.team ) && ( victim.pers[ "team" ] == eAttacker.team );
    
    	stunFraction = 0.0;
    
    	if ( iDFlags & level.iDFLAGS_STUN )
    	{
    		stunFraction = 0.0;
    		//victim StunPlayer( 1.0 );
    		iDamage = 0.0;
    	}
    	else if ( sHitLoc == "shield" )
    	{
    		if ( attackerIsHittingTeammate && level.friendlyfire == 0 )
    			return;
    		
    		if ( sMeansOfDeath == "MOD_PISTOL_BULLET" || sMeansOfDeath == "MOD_RIFLE_BULLET" || sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" && !attackerIsHittingTeammate )
    		{
    			if ( isPlayer( eAttacker ) )
    			{
    				eAttacker.lastAttackedShieldPlayer = victim;
    				eAttacker.lastAttackedShieldTime = getTime();
    			}
    			victim notify ( "shield_blocked" );
    
    			// fix turret + shield challenge exploits
    			if ( sWeapon == "turret_minigun_mp" )
    				shieldDamage = 25;
    			else
    				shieldDamage = maps\mp\perks\_perks::cac_modified_damage( victim, eAttacker, iDamage, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc );
    						
    			victim.shieldDamage += shieldDamage;
    
    			// fix turret + shield challenge exploits
    			if ( sWeapon != "turret_minigun_mp" || cointoss() )
    				victim.shieldBulletHits++;
    
    			if ( victim.shieldBulletHits >= level.riotShieldXPBullets )
    			{
    				if ( self.recentShieldXP > 4 )
    					xpVal = int( 50 / self.recentShieldXP );
    				else
    					xpVal = 50;
    				
    				printLn( xpVal );
    				
    				victim thread maps\mp\gametypes\_rank::giveRankXP( "shield_damage", xpVal );
    				victim thread giveRecentShieldXP();
    				
    				victim thread maps\mp\gametypes\_missions::genericChallenge( "shield_damage", victim.shieldDamage );
    
    				victim thread maps\mp\gametypes\_missions::genericChallenge( "shield_bullet_hits", victim.shieldBulletHits );
    				
    				victim.shieldDamage = 0;
    				victim.shieldBulletHits = 0;
    			}
    		}
    
    		if ( iDFlags & level.iDFLAGS_SHIELD_EXPLOSIVE_IMPACT )
    		{
    			if (  !attackerIsHittingTeammate )
    				victim thread maps\mp\gametypes\_missions::genericChallenge( "shield_explosive_hits", 1 );
    
    			sHitLoc = "none";	// code ignores any damage to a "shield" bodypart.
    			if ( !(iDFlags & level.iDFLAGS_SHIELD_EXPLOSIVE_IMPACT_HUGE) )
    				iDamage *= 0.0;
    		}
    		else if ( iDFlags & level.iDFLAGS_SHIELD_EXPLOSIVE_SPLASH )
    		{
    			if ( isDefined( eInflictor ) && isDefined( eInflictor.stuckEnemyEntity ) && eInflictor.stuckEnemyEntity == victim ) //does enough damage to shield carrier to ensure death
    				iDamage = 101;
    			
    			victim thread maps\mp\gametypes\_missions::genericChallenge( "shield_explosive_hits", 1 );
    			sHitLoc = "none";	// code ignores any damage to a "shield" bodypart.
    		}
    		else
    		{
    			return;
    		}
    	}
    	else if ( (smeansofdeath == "MOD_MELEE") && IsSubStr( sweapon, "riotshield" ) )
    	{
    		if ( !(attackerIsHittingTeammate && (level.friendlyfire == 0)) )
    		{
    			stunFraction = 0.0;
    			victim StunPlayer( 0.0 );
    		}
    	}
    
    	if ( !attackerIsHittingTeammate )
    		iDamage = maps\mp\perks\_perks::cac_modified_damage( victim, eAttacker, iDamage, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc );
    	
    	if ( !iDamage )
    		return false;
    	
    	victim.iDFlags = iDFlags;
    	victim.iDFlagsTime = getTime();
    
    	if ( game[ "state" ] == "postgame" )
    		return;
    	if ( victim.sessionteam == "spectator" )
    		return;
    	if ( isDefined( victim.canDoCombat ) && !victim.canDoCombat )
    		return;
    	if ( isDefined( eAttacker ) && isPlayer( eAttacker ) && isDefined( eAttacker.canDoCombat ) && !eAttacker.canDoCombat )
    		return;
    
    	// handle vehicles/turrets and friendly fire
    	if ( attackerIsNPC && attackerIsHittingTeammate )
    	{
    		if ( sMeansOfDeath == "MOD_CRUSH" )
    		{
    			victim _suicide();
    			return;
    		}
    		
    		if ( !level.friendlyfire )
    			return;
    	}
    
    	prof_begin( "PlayerDamage flags/tweaks" );
    
    	// Don't do knockback if the damage direction was not specified
    	if ( !isDefined( vDir ) )
    		iDFlags |= level.iDFLAGS_NO_KNOCKBACK;
    
    	friendly = false;
    
    	if ( ( victim.health == victim.maxhealth && ( !isDefined( victim.lastStand ) || !victim.lastStand )  ) || !isDefined( victim.attackers ) && !isDefined( victim.lastStand )  )
    	{
    		victim.attackers = [];
    		victim.attackerData = [];
    	}
    
    	if ( isHeadShot( sWeapon, sHitLoc, sMeansOfDeath, eAttacker ) )
    		sMeansOfDeath = "MOD_HEAD_SHOT";
    
    	if ( maps\mp\gametypes\_tweakables::getTweakableValue( "game", "onlyheadshots" ) )
    	{
    		if ( sMeansOfDeath == "MOD_PISTOL_BULLET" || sMeansOfDeath == "MOD_RIFLE_BULLET" || sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" )
    			return;
    		else if ( sMeansOfDeath == "MOD_HEAD_SHOT" )
    			iDamage = 150;
    	}
    
    	// explosive barrel/car detection
    	if ( sWeapon == "none" && isDefined( eInflictor ) )
    	{
    		if ( isDefined( eInflictor.destructible_type ) && isSubStr( eInflictor.destructible_type, "vehicle_" ) )
    			sWeapon = "destructible_car";
    	}
    
    	prof_end( "PlayerDamage flags/tweaks" );
    
    	// check for completely getting out of the damage
    	if ( !(iDFlags & level.iDFLAGS_NO_PROTECTION) )
    	{
    		// items you own don't damage you in FFA
    		if ( !level.teamBased && attackerIsNPC && isDefined( eAttacker.owner ) && eAttacker.owner == victim )
    		{
    			prof_end( "PlayerDamage player" );
    
    			if ( sMeansOfDeath == "MOD_CRUSH" )
    				victim _suicide();
    
    			return;
    		}
    
    		if ( ( isSubStr( sMeansOfDeath, "MOD_GRENADE" ) || isSubStr( sMeansOfDeath, "MOD_EXPLOSIVE" ) || isSubStr( sMeansOfDeath, "MOD_PROJECTILE" ) ) && isDefined( eInflictor ) && isDefined( eAttacker ) )
    		{
    			// protect players from spawnkill grenades
    			if ( eInflictor.classname == "grenade" && ( victim.lastSpawnTime + 3500 ) > getTime() && isDefined( victim.lastSpawnPoint ) && distance( eInflictor.origin, victim.lastSpawnPoint.origin ) < 250 )
    			{
    				prof_end( "PlayerDamage player" );
    				return;
    			}
    
    			victim.explosiveInfo = [];
    			victim.explosiveInfo[ "damageTime" ] = getTime();
    			victim.explosiveInfo[ "damageId" ] = eInflictor getEntityNumber();
    			victim.explosiveInfo[ "returnToSender" ] = false;
    			victim.explosiveInfo[ "counterKill" ] = false;
    			victim.explosiveInfo[ "chainKill" ] = false;
    			victim.explosiveInfo[ "cookedKill" ] = false;
    			victim.explosiveInfo[ "throwbackKill" ] = false;
    			victim.explosiveInfo[ "suicideGrenadeKill" ] = false;
    			victim.explosiveInfo[ "weapon" ] = sWeapon;
    
    			isFrag = isSubStr( sWeapon, "frag_" );
    
    			if ( eAttacker != victim )
    			{
    				if ( ( isSubStr( sWeapon, "c4_" ) || isSubStr( sWeapon, "claymore_" ) ) && isDefined( eAttacker ) && isDefined( eInflictor.owner ) )
    				{
    					victim.explosiveInfo[ "returnToSender" ] = ( eInflictor.owner == victim );
    					victim.explosiveInfo[ "counterKill" ] = isDefined( eInflictor.wasDamaged );
    					victim.explosiveInfo[ "chainKill" ] = isDefined( eInflictor.wasChained );
    					victim.explosiveInfo[ "bulletPenetrationKill" ] = isDefined( eInflictor.wasDamagedFromBulletPenetration );
    					victim.explosiveInfo[ "cookedKill" ] = false;
    				}
    
    				if ( isDefined( eAttacker.lastGrenadeSuicideTime ) && eAttacker.lastGrenadeSuicideTime >= gettime() - 50 && isFrag )
    					victim.explosiveInfo[ "suicideGrenadeKill" ] = true;
    			}
    
    			if ( isFrag )
    			{
    				victim.explosiveInfo[ "cookedKill" ] = isDefined( eInflictor.isCooked );
    				victim.explosiveInfo[ "throwbackKill" ] = isDefined( eInflictor.threwBack );
    			}
    			
    			victim.explosiveInfo[ "stickKill" ] = isDefined( eInflictor.isStuck ) && eInflictor.isStuck == "enemy";
    			victim.explosiveInfo[ "stickFriendlyKill" ] = isDefined( eInflictor.isStuck ) && eInflictor.isStuck == "friendly";
    		}
    	
    		if ( isPlayer( eAttacker ) )
    			eAttacker.pers[ "participation" ]++ ;
    
    		prevHealthRatio = victim.health / victim.maxhealth;
    
    		if ( attackerIsHittingTeammate )
    		{
    			if ( !matchMakingGame() && isPlayer(eAttacker) )
    				eAttacker incPlayerStat( "mostff", 1 );
    			
    			prof_begin( "PlayerDamage player" );// profs automatically end when the function returns
    			if ( level.friendlyfire == 0 || ( !isPlayer(eAttacker) && level.friendlyfire != 1 ) )// no one takes damage
    			{
    				if ( sWeapon == "artillery_mp" || sWeapon == "stealth_bomb_mp" )
    					victim damageShellshockAndRumble( eInflictor, sWeapon, sMeansOfDeath, iDamage, iDFlags, eAttacker );
    				return;
    			}
    			else if ( level.friendlyfire == 1 )// the friendly takes damage
    			{
    				if ( iDamage < 1 )
    					iDamage = 1;
    
    				victim.lastDamageWasFromEnemy = false;
    
    				victim finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
    			}
    			else if ( ( level.friendlyfire == 2 ) && isReallyAlive( eAttacker ) )// only the attacker takes damage
    			{
    				iDamage = int( iDamage * .5 );
    				if ( iDamage < 1 )
    					iDamage = 1;
    
    				eAttacker.lastDamageWasFromEnemy = false;
    
    				eAttacker.friendlydamage = true;
    				eAttacker finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
    				eAttacker.friendlydamage = undefined;
    			}
    			else if ( level.friendlyfire == 3 && isReallyAlive( eAttacker ) )// both friendly and attacker take damage
    			{
    				iDamage = int( iDamage * .5 );
    				if ( iDamage < 1 )
    					iDamage = 1;
    
    				victim.lastDamageWasFromEnemy = false;
    				eAttacker.lastDamageWasFromEnemy = false;
    
    				victim finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
    				if ( isReallyAlive( eAttacker ) )// may have died due to friendly fire punishment
    				{
    					eAttacker.friendlydamage = true;
    					eAttacker finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
    					eAttacker.friendlydamage = undefined;
    				}
    			}
    
    			friendly = true;
    			
    		}
    		else// not hitting teammate
    		{
    			prof_begin( "PlayerDamage world" );
    
    			if ( iDamage < 1 )
    				iDamage = 1;
    
    			if ( isDefined( eAttacker ) && isPlayer( eAttacker ) )
    				addAttacker( victim, eAttacker, eInflictor, sWeapon, iDamage, vPoint, vDir, sHitLoc, psOffsetTime, sMeansOfDeath );
    			
    			if ( sMeansOfDeath == "MOD_EXPLOSIVE" || sMeansOfDeath == "MOD_GRENADE_SPLASH" && iDamage < victim.health )
    				victim notify( "survived_explosion" );
    
    			if ( isdefined( eAttacker ) )
    				level.lastLegitimateAttacker = eAttacker;
    
    			if ( isdefined( eAttacker ) && isPlayer( eAttacker ) && isDefined( sWeapon ) )
    				eAttacker thread maps\mp\gametypes\_weapons::checkHit( sWeapon, victim );
    
    			if ( isdefined( eAttacker ) && isPlayer( eAttacker ) && isDefined( sWeapon ) && eAttacker != victim )
    			{
    				eAttacker thread maps\mp\_events::damagedPlayer( self, iDamage, sWeapon );
    				victim.attackerPosition = eAttacker.origin;
    			}
    			else
    			{
    				victim.attackerPosition = undefined;
    			}
    
    			if ( issubstr( sMeansOfDeath, "MOD_GRENADE" ) && isDefined( eInflictor.isCooked ) )
    				victim.wasCooked = getTime();
    			else
    				victim.wasCooked = undefined;
    
    			victim.lastDamageWasFromEnemy = ( isDefined( eAttacker ) && ( eAttacker != victim ) );
    
    			if ( victim.lastDamageWasFromEnemy )
    				eAttacker.damagedPlayers[ victim.guid ] = getTime();
    
    			victim finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
    
    			if ( isDefined( level.ac130player ) && isDefined( eAttacker ) && ( level.ac130player == eAttacker ) )
    				level notify( "ai_pain", victim );
    
    			victim thread maps\mp\gametypes\_missions::playerDamaged( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, sHitLoc );
    
    			prof_end( "PlayerDamage world" );
    			
    		}
    
    		if ( attackerIsNPC && isDefined( eAttacker.gunner ) )
    			damager = eAttacker.gunner;
    		else
    			damager = eAttacker;
    
    		if ( isDefined( damager) && damager != victim && iDamage > 0 )
    		{
    			if ( iDFlags & level.iDFLAGS_STUN )
    				typeHit = "stun";
    			else if ( victim hasPerk( "specialty_armorvest", true ) || (isExplosiveDamage( sMeansOfDeath ) && victim _hasPerk( "_specialty_blastshield" )) )
    				typeHit = "hitBodyArmor";
    			else if ( victim _hasPerk( "specialty_combathigh") )
    				typeHit = "hitEndGame";
    			else
    				typeHit = "standard";
    				
    			damager thread maps\mp\gametypes\_damagefeedback::updateDamageFeedback( typeHit );
    		}
    
    		victim.hasDoneCombat = true;
    	}
    
    	if ( isdefined( eAttacker ) && ( eAttacker != victim ) && !friendly )
    		level.useStartSpawns = false;
    
    
    	//=================
    	// Damage Logging
    	//=================
    
    	prof_begin( "PlayerDamage log" );
    
    	// why getEntityNumber() for victim and .clientid for attacker?
    	if ( getDvarInt( "g_debugDamage" ) )
    		println( "client:" + victim getEntityNumber() + " health:" + victim.health + " attacker:" + eAttacker.clientid + " inflictor is player:" + isPlayer( eInflictor ) + " damage:" + iDamage + " hitLoc:" + sHitLoc );
    
    	if ( victim.sessionstate != "dead" )
    	{
    		lpselfnum = victim getEntityNumber();
    		lpselfname = victim.name;
    		lpselfteam = victim.pers[ "team" ];
    		lpselfGuid = victim.guid;
    		lpattackerteam = "";
    
    		if ( isPlayer( eAttacker ) )
    		{
    			lpattacknum = eAttacker getEntityNumber();
    			lpattackGuid = eAttacker.guid;
    			lpattackname = eAttacker.name;
    			lpattackerteam = eAttacker.pers[ "team" ];
    		}
    		else
    		{
    			lpattacknum = -1;
    			lpattackGuid = "";
    			lpattackname = "";
    			lpattackerteam = "world";
    		}
    
    		logPrint( "D;" + lpselfGuid + ";" + lpselfnum + ";" + lpselfteam + ";" + lpselfname + ";" + lpattackGuid + ";" + lpattacknum + ";" + lpattackerteam + ";" + lpattackname + ";" + sWeapon + ";" + iDamage + ";" + sMeansOfDeath + ";" + sHitLoc + "\n" );
    	}
    
    	HitlocDebug( eAttacker, victim, iDamage, sHitLoc, iDFlags );
    
    	/*if( isDefined( eAttacker ) && eAttacker != victim )
    	{
    		if ( isPlayer( eAttacker ) )
    			eAttacker incPlayerStat( "damagedone", iDamage );
    		
    		victim incPlayerStat( "damagetaken", iDamage );
    	}*/
    
    	prof_end( "PlayerDamage log" );
    }
    
    
    addAttacker( victim, eAttacker, eInflictor, sWeapon, iDamage, vPoint, vDir, sHitLoc, psOffsetTime, sMeansOfDeath )
    {
    	if ( !isDefined( victim.attackerData ) )
    		victim.attackerData = [];
    	
    	if ( !isDefined( victim.attackerData[ eAttacker.guid ] ) )
    	{
    		victim.attackers[ eAttacker.guid ] = eAttacker;
    		// we keep an array of attackers by their client ID so we can easily tell
    		// if they're already one of the existing attackers in the above if().
    		// we store in this array data that is useful for other things, like challenges
    		victim.attackerData[ eAttacker.guid ] = SpawnStruct();
    		victim.attackerData[ eAttacker.guid ].damage = 0;	
    		victim.attackerData[ eAttacker.guid ].attackerEnt = eAttacker;
    		victim.attackerData[ eAttacker.guid ].firstTimeDamaged = getTime();				
    	}
    	if ( maps\mp\gametypes\_weapons::isPrimaryWeapon( sWeapon ) && ! maps\mp\gametypes\_weapons::isSideArm( sWeapon ) )
    		victim.attackerData[ eAttacker.guid ].isPrimary = true;
    	
    	victim.attackerData[ eAttacker.guid ].damage += iDamage;
    	victim.attackerData[ eAttacker.guid ].weapon = sWeapon;
    	victim.attackerData[ eAttacker.guid ].vPoint = vPoint;
    	victim.attackerData[ eAttacker.guid ].vDir = vDir;
    	victim.attackerData[ eAttacker.guid ].sHitLoc = sHitLoc;
    	victim.attackerData[ eAttacker.guid ].psOffsetTime = psOffsetTime;
    	victim.attackerData[ eAttacker.guid ].sMeansOfDeath = sMeansOfDeath;
    	victim.attackerData[ eAttacker.guid ].attackerEnt = eAttacker;
    	victim.attackerData[ eAttacker.guid ].lasttimeDamaged = getTime();
    	
    	if ( isDefined( eInflictor ) && !isPlayer( eInflictor ) && isDefined( eInflictor.primaryWeapon ) )
    		victim.attackerData[ eAttacker.guid ].sPrimaryWeapon = eInflictor.primaryWeapon;
    	else if ( isDefined( eAttacker ) && isPlayer( eAttacker ) && eAttacker getCurrentPrimaryWeapon() != "none" )
    		victim.attackerData[ eAttacker.guid ].sPrimaryWeapon = eAttacker getCurrentPrimaryWeapon();
    	else
    		victim.attackerData[ eAttacker.guid ].sPrimaryWeapon = undefined;
    }
    
    resetAttackerList()
    {
    	self endon( "disconnect" );
    	self endon( "death" );
    	level endon( "game_ended" );
    	
    	//wait is to offset premature calling in _healthOverlay
    	wait( 1.75 ); 
    	self.attackers = [];
    	self.attackerData = [];
    }
    
    
    Callback_PlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime )
    {
    	Callback_PlayerDamage_internal( eInflictor, eAttacker, self, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime );
    }
    
    
    finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction )
    {
    	if ( (self isUsingRemote() ) && (iDamage >= self.health) && !(iDFlags & level.iDFLAGS_STUN) )
    	{
    		if ( !isDefined( vDir ) )
    			vDir = ( 0,0,0 );
    
    		if ( !isDefined( eAttacker ) && !isDefined( eInflictor ) )
    		{
    			eAttacker = self;
    			eInflictor = eAttacker;
    		}
    		
    		assert( isDefined( eAttacker ) );
    		assert( isDefined( eInflictor ) );
    
    		PlayerKilled_internal( eInflictor, eAttacker, self, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, 0, true );
    	}
    	else
    	{
    		if ( !self Callback_KillingBlow( eInflictor, eAttacker, iDamage - (iDamage * stunFraction), iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime ) )
    			return;
    
    		self finishPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
    	}
    
    	if ( sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" )
    		self shellShock( "damage_mp", getDvarFloat( "scr_csmode" ) );
    
    	self damageShellshockAndRumble( eInflictor, sWeapon, sMeansOfDeath, iDamage, iDFlags, eAttacker );
    }
    
    
    Callback_PlayerLastStand( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration )
    {	
    		
    	lastStandParams = spawnStruct();
    	lastStandParams.eInflictor = eInflictor;
    	lastStandParams.attacker = attacker;
    	lastStandParams.iDamage = iDamage;
    	lastStandParams.attackerPosition = attacker.origin;
    	if ( attacker == self )
    		lastStandParams.sMeansOfDeath = "MOD_SUICIDE";
    	else
    		lastStandParams.sMeansOfDeath = sMeansOfDeath;
    	
    	lastStandParams.sWeapon = sWeapon;
    	if ( isDefined( attacker ) && isPlayer( attacker ) && attacker getCurrentPrimaryWeapon() != "none" )
    		lastStandParams.sPrimaryWeapon = attacker getCurrentPrimaryWeapon();
    	else
    		lastStandParams.sPrimaryWeapon = undefined;
    	lastStandParams.vDir = vDir;
    	lastStandParams.sHitLoc = sHitLoc;
    	lastStandParams.lastStandStartTime = getTime();
    
    	mayDoLastStand = mayDoLastStand( sWeapon, sMeansOfDeath, sHitLoc );
    	
    	//if ( mayDoLastStand )
    	//	mayDoLastStand = !self checkForceBleedOut();
    	
    	if ( isDefined( self.endGame ) )
    		mayDoLastStand = false;
    	
    	if ( level.teamBased && isDefined( attacker.team ) && attacker.team == self.team )
    		mayDoLastStand = false;
    
    	 /#
    	if ( getdvar( "scr_forcelaststand" ) == "1" )
    		mayDoLastStand = true;
    	#/
    	
    	if ( !mayDoLastStand )
    	{
    		self.lastStandParams = lastStandParams;
    		self.useLastStandParams = true;
    		self _suicide();
    		return;
    	}
    	
    	self.inLastStand = true;
    
    	notifyData = spawnStruct();
    	if ( self _hasPerk( "specialty_finalstand" ) )
    	{
    		notifyData.titleText = game[ "strings" ][ "final_stand" ];
    		notifyData.iconName = "specialty_finalstand";
    	}
    	else
    	{
    		notifyData.titleText = game[ "strings" ][ "last_stand" ];
    		notifyData.iconName = "specialty_pistoldeath";
    	}
    	notifyData.glowColor = ( 1, 0, 0 );
    	notifyData.sound = "mp_last_stand";
    	notifyData.duration = 2.0;
    
    	self.health = 1;
    
    	self thread maps\mp\gametypes\_hud_message::notifyMessage( notifyData );
    
    	grenadeTypePrimary = "frag_grenade_mp";
    
    	if ( isDefined( level.ac130player ) && isDefined( attacker ) && level.ac130player == attacker )
    		level notify( "ai_crawling", self );
    	
    	if ( self _hasPerk( "specialty_finalstand" ) )
    	{
    		self.lastStandParams = lastStandParams;
    		self.inFinalStand = false;
    		
    		weaponList = self GetWeaponsListExclusives();
    		foreach ( weapon in weaponList )
    			self takeWeapon( weapon );
    		
    		self _disableUsability();
    
    		self thread enableLastStandWeapons();
    		self thread lastStandTimer( 20, true );		
    	}
    	/*
    	else if ( self _hasPerk( "specialty_c4death" ) )
    	{
    		self.lastStandParams = lastStandParams;
    
    		self takeAllWeapons();
    		self giveWeapon( "c4Death_mp", 0, false );
    		self switchToWeapon( "c4Death_mp" );
    		self _disableUsability();
    		self.inC4Death = true;
    				
    		//self thread dieAfterTime( 7 );
    		self thread lastStandTimer( 10, false );	
    		self thread detonateOnUse();
    		//self thread detonateOnDeath();	
    	}
    	*/
    	else if ( level.dieHardMode )
    	{	
    		self.lastStandParams = lastStandParams;
    		self thread enableLastStandWeapons();
    		self thread lastStandTimer( 20, false );
    		self _disableUsability();
    	}
    	else // normal last stand
    	{
    		self.lastStandParams = lastStandParams;
    		
    		pistolWeapon = undefined;
    		
    		weaponsList = self GetWeaponsListPrimaries();
    		foreach ( weapon in weaponsList )
    		{
    			if ( maps\mp\gametypes\_weapons::isSideArm( weapon ) )
    				pistolWeapon = weapon;			
    		}
    			
    		if ( !isDefined( pistolWeapon ) )
    		{
    			pistolWeapon = "beretta_mp";
    			self _giveWeapon( pistolWeapon );
    		}
    	
    		self giveMaxAmmo( pistolWeapon );
    		self DisableWeaponSwitch();
    		self _disableUsability();
    		
    		if ( !self _hasPerk("specialty_laststandoffhand") )
    			self DisableOffhandWeapons();
    				
    		self switchToWeapon( pistolWeapon );
    		
    		self thread lastStandTimer( 10, false );
    	}
    }
    
    dieAfterTime( time )
    {
    	self endon( "death" );
    	self endon( "disconnect" );
    	self endon( "joined_team" );
    	level endon( "game_ended" );
    	
    	wait ( time );
    	self.useLastStandParams = true;
    	self _suicide();
    }
    
    detonateOnUse()
    {
    	self endon( "death" );
    	self endon( "disconnect" );
    	self endon( "joined_team" );
    	level endon( "game_ended" );
    	
    	self waittill( "detonate" );
    	self.useLastStandParams = true;
    	self c4DeathDetonate();
    }
    
    detonateOnDeath()
    {
    	self endon( "detonate" );
    	self endon( "disconnect" );
    	self endon( "joined_team" );
    	level endon( "game_ended" );
    	
    	self waittill( "death" );
    	self c4DeathDetonate();
    }
    
    c4DeathDetonate()
    {
    	self playSound( "detpack_explo_default" );
    	self.c4DeathEffect = playFX( level.c4Death, self.origin );
    	RadiusDamage( self.origin, 400, 100, 100, self );
    	
    	if ( isAlive( self ) )
    		self _suicide();
    }
    
    enableLastStandWeapons()
    {
    	self endon( "death" );
    	self endon( "disconnect" );
    	level endon( "game_ended" );
    
    	self freezeControlsWrapper( true );
    	wait .30;
    	
    	self freezeControlsWrapper( false );
    }
    
    lastStandTimer( delay, isFinalStand )
    {
    	self endon( "death" );
    	self endon( "disconnect" );
    	self endon( "revive");
    	level endon( "game_ended" );
    	
    	level notify ( "player_last_stand" );
    	
    	self thread lastStandWaittillDeath();
    	
    	self.lastStand = true;
    	
    	if ( !isFinalStand && !level.dieHardMode && ( !isDefined( self.inC4Death ) || !self.inC4Death ) )
    	{
    		self thread lastStandAllowSuicide();
    		self setLowerMessage( "last_stand", &"PLATFORM_COWARDS_WAY_OUT" );
    		self thread lastStandKeepOverlay();
    	}
    	
    	if ( level.dieHardMode == 1 && level.dieHardMode != 2 )
    	{
    		reviveEnt = spawn( "script_model", self.origin );
    		reviveEnt setModel( "tag_origin" );
    		reviveEnt setCursorHint( "HINT_NOICON" );
    		reviveEnt setHintString( &"PLATFORM_REVIVE" );
    
    		reviveEnt reviveSetup( self );
    		reviveEnt endon ( "death" );
    
    		reviveIcon = newTeamHudElem( self.team );
    		reviveIcon setShader( "waypoint_revive", 8, 8 );
    		reviveIcon setWaypoint( true, true );
    		reviveIcon SetTargetEnt( self );
    		reviveIcon thread destroyOnReviveEntDeath( reviveEnt );
    
    		reviveIcon.color = (0.33, 0.75, 0.24);
    		self playDeathSound();
    		
    		if ( isFinalStand )
    		{
    			wait( delay );
    			
    			if ( self.inFinalStand )
    				self thread lastStandBleedOut( isFinalStand, reviveEnt );
    		}
    		
    		return;
    	}
    	else if( level.dieHardMode == 2 )
    	{
    		self thread lastStandKeepOverlay();
    		reviveEnt = spawn( "script_model", self.origin );
    		reviveEnt setModel( "tag_origin" );
    		reviveEnt setCursorHint( "HINT_NOICON" );
    		reviveEnt setHintString( &"PLATFORM_REVIVE" );
    
    		reviveEnt reviveSetup( self );
    		reviveEnt endon ( "death" );
    
    		reviveIcon = newTeamHudElem( self.team );
    		reviveIcon setShader( "waypoint_revive", 8, 8 );
    		reviveIcon setWaypoint( true, true );
    		reviveIcon SetTargetEnt( self );
    		reviveIcon thread destroyOnReviveEntDeath( reviveEnt );
    
    		reviveIcon.color = (0.33, 0.75, 0.24);
    		self playDeathSound();
    		
    		if ( isFinalStand )
    		{
    			wait( delay );
    			
    			if ( self.inFinalStand )
    				self thread lastStandBleedOut( isFinalStand, reviveEnt );
    		}
    		
    		wait delay / 3;
    		reviveIcon.color = (1.0, 0.64, 0.0);
    		
    		while ( reviveEnt.inUse )
    			wait ( 0.05 );
    		
    		self playDeathSound();	
    		wait delay / 3;
    		reviveIcon.color = (1.0, 0.0, 0.0);
    
    		while ( reviveEnt.inUse )
    			wait ( 0.05 );
    
    		self playDeathSound();
    		wait delay / 3;	
    
    		while ( reviveEnt.inUse )
    			wait ( 0.05 );
    		
    		wait( 0.05 ); 
    		self thread lastStandBleedOut( isFinalStand );
    		return;
    	}
    	
    	wait( delay );
    	self thread lastStandBleedout( isFinalStand );
    
    }
    
    maxHealthOverlay( maxHealth, refresh )
    {
    	self endon( "stop_maxHealthOverlay" );
    	self endon( "revive" );
    	self endon( "death" );
    	
    	for( ;; )
    	{
    		self.health -= 1;
    		self.maxHealth = maxHealth;
    		wait( .05 );
    		self.maxHealth = 50;
    		self.health += 1;
    	
    		wait ( .50 );
    	}	
    }
    
    lastStandBleedOut( reviveOnBleedOut, reviveEnt )
    {
    
    	self _suicide(); // I don't care, even if they call the thread they're dead...
    /*
    	if ( reviveOnBleedOut )
    	{
    		self.lastStand = undefined;
    		self.inFinalStand = false;
    		self clearLowerMessage( "last_stand" );
    		maps\mp\gametypes\_playerlogic::lastStandRespawnPlayer();
    		
    		if( isDefined( reviveEnt ) )
    			reviveEnt Delete();
    	}
    	else
    	{
    		self.useLastStandParams = true;
    		self.beingRevived = false;
    		self _suicide();
    	}
    */
    }
    
    
    lastStandAllowSuicide()
    {
    	self endon( "death" );
    	self endon( "disconnect" );
    	self endon( "game_ended" );
    	self endon( "revive");
    
    	while ( 1 )
    	{
    		if ( self useButtonPressed() )
    		{
    			pressStartTime = gettime();
    			while ( self useButtonPressed() )
    			{
    				wait .05;
    				if ( gettime() - pressStartTime > 700 )
    					break;
    			}
    			if ( gettime() - pressStartTime > 700 )
    				break;
    		}
    		wait .05;
    	}
    
    	self thread lastStandBleedOut( false );
    }
    
    lastStandKeepOverlay()
    {
    	level endon( "game_ended" );
    	self endon( "death" );
    	self endon( "disconnect" );
    	self endon( "revive" );
    
    	// keep the health overlay going by making code think the player is getting damaged
    	while ( !level.gameEnded )
    	{
    		self.health = 2;
    		wait .05;
    		self.health = 1;
    		wait .5;
    	}
    	
    	self.health = self.maxhealth;
    }
    
    
    lastStandWaittillDeath()
    {
    	self endon( "disconnect" );
    	self endon( "revive" );
    	level endon( "game_ended" );
    	self waittill( "death" );
    
    	self clearLowerMessage( "last_stand" );
    	self.lastStand = undefined;
    }
    
    
    mayDoLastStand( sWeapon, sMeansOfDeath, sHitLoc )
    {
    	if ( sMeansOfDeath == "MOD_TRIGGER_HURT" )
    		return false;
    	
    	if ( sMeansOfDeath != "MOD_PISTOL_BULLET" && sMeansOfDeath != "MOD_RIFLE_BULLET" && sMeansOfDeath != "MOD_FALLING" && sMeansOfDeath != "MOD_EXPLOSIVE_BULLET" )
    		return false;
    
    	if ( sMeansOfDeath == "MOD_IMPACT" && sWeapon == "throwingknife_mp" )
    		return false;
    		
    	if ( sMeansOfDeath == "MOD_IMPACT" && ( sWeapon == "m79_mp" || isSubStr(sWeapon, "gl_") ) )
    		return false;
    
    	if ( isHeadShot( sWeapon, sHitLoc, sMeansOfDeath ) )
    		return false;
    	
    	if ( self isUsingRemote() )
    		return false;
    
    	return false; // A Simple false can be your best friend. :3
    }
    
    
    ensureLastStandParamsValidity()
    {
    	// attacker may have become undefined if the player that killed me has disconnected
    	if ( !isDefined( self.lastStandParams.attacker ) )
    		self.lastStandParams.attacker = self;
    }
    
    getHitLocHeight( sHitLoc )
    {
    	switch( sHitLoc )
    	{
    		case "helmet":
    		case "head":
    		case "neck":
    			return 60;
    		case "torso_upper":
    		case "right_arm_upper":
    		case "left_arm_upper":
    		case "right_arm_lower":
    		case "left_arm_lower":
    		case "right_hand":
    		case "left_hand":
    		case "gun":
    			return 48;
    		case "torso_lower":
    			return 40;
    		case "right_leg_upper":
    		case "left_leg_upper":
    			return 32;
    		case "right_leg_lower":
    		case "left_leg_lower":
    			return 10;
    		case "right_foot":
    		case "left_foot":
    			return 5;
    	}
    	return 48;
    }
    
    delayStartRagdoll( ent, sHitLoc, vDir, sWeapon, eInflictor, sMeansOfDeath )
    {
    	if ( isDefined( ent ) )
    	{
    		deathAnim = ent getCorpseAnim();
    		if ( animhasnotetrack( deathAnim, "ignore_ragdoll" ) )
    			return;
    	}
    
    	wait( 0.2 );
    
    	if ( !isDefined( ent ) )
    		return;
    
    	if ( ent isRagDoll() )
    		return;
    
    	deathAnim = ent getcorpseanim();
    
    	startFrac = 0.35;
    
    	if ( animhasnotetrack( deathAnim, "start_ragdoll" ) )
    	{
    		times = getnotetracktimes( deathAnim, "start_ragdoll" );
    		if ( isDefined( times ) )
    			startFrac = times[ 0 ];
    	}
    
    	waitTime = startFrac * getanimlength( deathAnim );
    	wait( waitTime );
    
    	if ( isDefined( ent ) )
    	{
    		ent startragdoll( 1 );
    	}
    }
    
    
    getMostKilledBy()
    {
    	mostKilledBy = "";
    	killCount = 0;
    
    	killedByNames = getArrayKeys( self.killedBy );
    
    	for ( index = 0; index < killedByNames.size; index++ )
    	{
    		killedByName = killedByNames[ index ];
    		if ( self.killedBy[ killedByName ] <= killCount )
    			continue;
    
    		killCount = self.killedBy[ killedByName ];
    		mostKilleBy = killedByName;
    	}
    
    	return mostKilledBy;
    }
    
    
    getMostKilled()
    {
    	mostKilled = "";
    	killCount = 0;
    
    	killedNames = getArrayKeys( self.killedPlayers );
    
    	for ( index = 0; index < killedNames.size; index++ )
    	{
    		killedName = killedNames[ index ];
    		if ( self.killedPlayers[ killedName ] <= killCount )
    			continue;
    
    		killCount = self.killedPlayers[ killedName ];
    		mostKilled = killedName;
    	}
    
    	return mostKilled;
    }
    
    
    damageShellshockAndRumble( eInflictor, sWeapon, sMeansOfDeath, iDamage, iDFlags, eAttacker )
    {
    	self thread maps\mp\gametypes\_weapons::onWeaponDamage( eInflictor, sWeapon, sMeansOfDeath, iDamage, eAttacker );
    	self PlayRumbleOnEntity( "damage_heavy" );
    }
    
    
    reviveSetup( owner )
    {
    	team = owner.team;
    	
    	self linkTo( owner, "tag_origin" );
    
    	self.owner = owner;
    	self.inUse = false;
    	self makeUsable();
    	self updateUsableByTeam( team );
    	self thread trackTeamChanges( team );
    	
    	self thread reviveTriggerThink( team );
    	
    	self thread deleteOnReviveOrDeathOrDisconnect();
    }
    
    
    deleteOnReviveOrDeathOrDisconnect()
    {
    	self endon ( "death" );
    	
    	self.owner waittill_any ( "death", "disconnect" );
    	
    	self delete();
    }
    
    
    updateUsableByTeam( team )
    {
    	foreach (player in level.players)
    	{
    		if ( team == player.team && player != self.owner )
    			self enablePlayerUse( player );	
    		else
    			self disablePlayerUse( player );	
    	}	
    }
    
    
    trackTeamChanges( team )
    {
    	self endon ( "death" );
    	
    	while ( true )
    	{
    		level waittill ( "joined_team" );
    		
    		self updateUsableByTeam( team );
    	}
    }
    
    
    trackLastStandChanges( team )
    {
    	self endon ( "death" );
    	
    	while ( true )
    	{
    		level waittill ( "player_last_stand" );
    		
    		self updateUsableByTeam( team );
    	}
    }
    
    
    reviveTriggerThink( team )
    {
    	self endon ( "death" );
    	level endon ( "game_ended" );
    	
    	for ( ;; )
    	{
    		self waittill ( "trigger", player );
    		self.owner.beingRevived = true;
    
    		if ( isDefined(player.beingRevived) && player.beingRevived )
    		{
    			self.owner.beingRevived = false;
    			continue;
    		}
    			
    		self makeUnUsable();
    		self.owner freezeControlsWrapper( true );
    
    		revived = self useHoldThink( player );
    		self.owner.beingRevived = false;
    		
    		if ( !isAlive( self.owner ) )
    		{	
    			self delete();
    			return;
    		}
    
    		self.owner freezeControlsWrapper( false );
    			
    		if ( revived )
    		{
    			player thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "reviver", 200 );
    			player thread maps\mp\gametypes\_rank::giveRankXP( "reviver", 200 );
    
    			self.owner.lastStand = undefined;
    			self.owner clearLowerMessage( "last_stand" );
    			
    			if ( self.owner _hasPerk( "specialty_lightweight" ) )
    				self.owner.moveSpeedScaler = 1.10;
    			else
    				self.owner.moveSpeedScaler = 1;
    			
    			self.owner.maxHealth = 100;
    			
    			self.owner maps\mp\gametypes\_weapons::updateMoveSpeedScale( "primary" );
    			self.owner maps\mp\gametypes\_playerlogic::lastStandRespawnPlayer();
    
    			self.owner setPerk( "specialty_pistoldeath", true );
    			self.owner.beingRevived = false;
    			
    			self delete();
    			return;
    		}
    			
    		self makeUsable();
    		self updateUsableByTeam( team );
    	}
    }
    
    
    
    /*
    =============
    useHoldThink
    
    Claims the use trigger for player and displays a use bar
    Returns true if the player sucessfully fills the use bar
    =============
    */
    useHoldThink( player )
    {
    	reviveSpot = spawn( "script_origin", self.origin );
    	reviveSpot hide();	
    	player playerLinkTo( reviveSpot );		
    	player PlayerLinkedOffsetEnable();
    	
    	player _disableWeapon();
    	
    	self.curProgress = 0;
    	self.inUse = true;
    	self.useRate = 0;
    	self.useTime = 3000;
    	
    	player thread personalUseBar( self );
    	
    	result = useHoldThinkLoop( player );
    	
    	if ( isDefined( player ) && isReallyAlive( player ) )
    	{
    		player Unlink();
    		player _enableWeapon();
    	}
    
    	if ( isDefined( result ) && result )
    	{
    		self.owner thread maps\mp\gametypes\_hud_message::playerCardSplashNotify( "revived", player );
    		self.owner.inlaststand = false;
    		return true;
    	}
    	
    	self.inUse = false;
    	reviveSpot Delete();	
    	return false;
    }
    
    
    personalUseBar( object )
    {
    	useBar = self createPrimaryProgressBar();
    	useBarText = self createPrimaryProgressBarText();
    	useBarText setText( &"MPUI_REVIVING" );
    
    	objUseBar = object.owner createPrimaryProgressBar();
    	objUseBarText = object.owner createPrimaryProgressBarText();
    	objUseBarText setText( &"MPUI_BEING_REVIVED" );
    
    	lastRate = -1;
    	while ( isReallyAlive( self ) && isDefined( object ) && object.inUse && !level.gameEnded && isDefined( self ) )
    	{
    		if ( lastRate != object.useRate )
    		{
    			if( object.curProgress > object.useTime)
    				object.curProgress = object.useTime;
    				
    			useBar updateBar( object.curProgress / object.useTime, (1000 / object.useTime) * object.useRate );
    			objUseBar updateBar( object.curProgress / object.useTime, (1000 / object.useTime) * object.useRate );
    
    			if ( !object.useRate )
    			{
    				useBar hideElem();
    				useBarText hideElem();
    
    				objUseBar hideElem();
    				objUseBarText hideElem();
    			}
    			else
    			{
    				useBar showElem();
    				useBarText showElem();
    
    				objUseBar showElem();
    				objUseBarText showElem();
    			}
    		}	
    		lastRate = object.useRate;
    		wait ( 0.05 );
    	}
    	
    	// when the players disconnect the hudElems are destroyed automatically
    	if ( isDefined( useBar ) )
    		useBar destroyElem();
    	if ( isDefined( useBarText ) )
    		useBarText destroyElem();
    
    	if ( isDefined( objUseBar ) )
    		objUseBar destroyElem();
    	if ( isDefined( objUseBarText ) )
    		objUseBarText destroyElem();
    }
    
    
    useHoldThinkLoop( player )
    {
    	level endon ( "game_ended" );
    	self.owner endon( "death" );
    	self.owner endon( "disconnect" );
    
    	while( isReallyAlive( player ) && player useButtonPressed() && self.curProgress < self.useTime  )
    	{
    		self.curProgress += (50 * self.useRate);
    		self.useRate = 1; /* * player.objectiveScaler;*/
    
    		if ( self.curProgress >= self.useTime )
    		{
    			self.inUse = false;
    			
    			return isReallyAlive( player );
    		}
    		
    		wait 0.05;
    	}
    	
    	return false;
    }
    
    
    Callback_KillingBlow( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime )
    {
    	if ( isDefined(self.lastDamageWasFromEnemy) && self.lastDamageWasFromEnemy && iDamage >= self.health && isDefined( self.combatHigh ) && self.combatHigh == "specialty_endgame" )
    	{
    		self setAdrenaline( 0 );
    		self _setPerk( "specialty_endgame" );
    		return false;
    	}
    	
    	return true;
    }
    
    
    emitFallDamage( iDamage )
    {
    	PhysicsExplosionSphere( self.origin, 64, 64, 1 );
    	
    	// get the entities we landed on
    	damageEnts = [];
    	for ( testAngle = 0; testAngle < 360; testAngle += 30 )
    	{
    		xOffset = cos( testAngle ) * 16;
    		yOffset = sin( testAngle ) * 16;
    
    		traceData = bulletTrace( self.origin + (xOffset, yOffset, 4), self.origin + (xOffset,yOffset,-6), true, self );
    		//thread drawLine( self.origin + (xOffset, yOffset, 4), self.origin + (xOffset,yOffset,-6), 10.0 );
    		
    		if ( isDefined( traceData["entity"] ) && isDefined( traceData["entity"].targetname ) && (traceData["entity"].targetname == "destructible_vehicle" || traceData["entity"].targetname == "destructible_toy") )
    			damageEnts[damageEnts.size] = traceData["entity"];
    	}
    
    	if ( damageEnts.size )
    	{
    		damageOwner = spawn( "script_origin", self.origin );
    		damageOwner hide();
    		damageOwner.type = "soft_landing";
    		damageOwner.destructibles = damageEnts;
    		radiusDamage( self.origin, 64, 100, 100, damageOwner );
    
    		wait ( 0.1 );	
    		damageOwner delete();
    	}
    }
    
    drawLine( start, end, timeSlice )
    {
    	drawTime = int(timeSlice * 20);
    	for( time = 0; time < drawTime; time++ )
    	{
    		line( start, end, (1,0,0),false, 1 );
    		wait ( 0.05 );
    	}
    }
    
    isFlankKill( victim, attacker )
    {
    	victimForward = anglestoforward( victim.angles );
    	victimForward = ( victimForward[0], victimForward[1], 0 );
    	victimForward = VectorNormalize( victimForward );
    
    	attackDirection = victim.origin - attacker.origin;
    	attackDirection = ( attackDirection[0], attackDirection[1], 0 ); 
    	attackDirection = VectorNormalize( attackDirection );
    
    	dotProduct = VectorDot( victimForward, attackDirection );
    	if ( dotProduct > 0 )  // b.o.o.t.s // 0 = cos( 90 ), 180 degree arc total
    		return true;
    	else
    		return false;
    }
    
    _obituary( victim, attacker, sWeapon, sMeansOfDeath )
    {
    	victimTeam = victim.team;
    	
    	foreach ( player in level.players )
    	{
    		playerTeam = player.team;
    		if ( playerTeam == "spectator" )
    			player iPrintLn( &"MP_OBITUARY_NEUTRAL", attacker.name, victim.name );
    		else if ( playerTeam == victimTeam )
    			player iPrintLn( &"MP_OBITUARY_ENEMY", attacker.name, victim.name );
    		else
    			player iPrintLn( &"MP_OBITUARY_FRIENDLY", attacker.name, victim.name );
    	}
    }
    
    
    logPrintPlayerDeath( lifeId, attacker, iDamage, sMeansOfDeath, sWeapon, sPrimaryWeapon, sHitLoc )
    {
    	// create a lot of redundant data for the log print
    	lpselfnum = self getEntityNumber();
    	lpselfname = self.name;
    	lpselfteam = self.team;
    	lpselfguid = self.guid;
    
    	if ( isPlayer( attacker ) )
    	{
    		lpattackGuid = attacker.guid;
    		lpattackname = attacker.name;
    		lpattackerteam = attacker.team;
    		lpattacknum = attacker getEntityNumber();
    		attackerString = attacker getXuid() + "(" + lpattackname + ")";
    	}
    	else
    	{
    		lpattackGuid = "";
    		lpattackname = "";
    		lpattackerteam = "world";
    		lpattacknum = -1;
    		attackerString = "none";
    	}
    
    	logPrint( "K;" + lpselfguid + ";" + lpselfnum + ";" + lpselfteam + ";" + lpselfname + ";" + lpattackguid + ";" + lpattacknum + ";" + lpattackerteam + ";" + lpattackname + ";" + sWeapon + ";" + iDamage + ";" + sMeansOfDeath + ";" + sHitLoc + "\n" );
    }
    
    
    destroyOnReviveEntDeath( reviveEnt )
    {
    	reviveEnt waittill ( "death" );
    	
    	self destroy();
    }
    Last edited by Lovroman; 11-27-2014 at 08:06 AM.

  2. #2
    Lovroman's Avatar
    Join Date
    Sep 2012
    Gender
    male
    Posts
    9,430
    Reputation
    611
    Thanks
    9,711
    My Mood
    Cheerful
    Try changing self.useTime = 3000; to self.useTime = 2000;

Similar Threads

  1. [Help Request] how can I change the graphics in mw2
    By ayzcsx3 in forum Call of Duty Modern Warfare 2 Help
    Replies: 1
    Last Post: 03-23-2012, 03:46 AM
  2. [Help] How can i change the apb aim cursor
    By gul in forum All Points Bulletin Reloaded Hacks
    Replies: 9
    Last Post: 02-14-2012, 08:58 PM
  3. how can i change the knife damage?
    By foasdgg in forum Call of Duty Modern Warfare 2 GSC Modding Help/Discussion
    Replies: 2
    Last Post: 10-27-2010, 12:51 PM
  4. How can I change the M16A3 to G36E ?
    By kingkongf in forum Combat Arms Mod Discussion
    Replies: 4
    Last Post: 12-14-2009, 03:02 PM
  5. How can i change the screenshot button
    By GibsonRocks231 in forum Combat Arms Hacks & Cheats
    Replies: 8
    Last Post: 01-22-2009, 04:39 AM