#include common_scripts\utility;
#include maps\mp\_utility;

init()
{	
	level.riot_shield_names = [];
	level.riot_shield_names[level.riot_shield_names.size] = "riotshield_mp";
	level.riot_shield_names[level.riot_shield_names.size] = "iw5_riotshieldt6_mp";
	level.riot_shield_names[level.riot_shield_names.size] = "iw5_riotshieldt6loot0_mp";
	level.riot_shield_names[level.riot_shield_names.size] = "iw5_riotshieldt6loot1_mp";
	level.riot_shield_names[level.riot_shield_names.size] = "iw5_riotshieldt6loot2_mp";
	level.riot_shield_names[level.riot_shield_names.size] = "iw5_riotshieldt6loot3_mp";
	level.riot_shield_names[level.riot_shield_names.size] = "iw5_riotshieldjugg_mp";

	precacheAnims();
	
//	loadfx( "weapon/riotshield/fx_riotshield_depoly_lights" );
//	loadfx( "weapon/riotshield/fx_riotshield_depoly_dust" );
	
	level.riot_shield_collision = GetEnt( "riot_shield_collision", "targetname" );
	
	level._effect[ "riot_shield_shock_fx" ] = LoadFX( "vfx/explosion/riotshield_stun" );
	level._effect[ "riot_shield_deploy_smoke" ] = LoadFX( "vfx/smoke/riotshield_deploy_smoke" );
	level._effect[ "riot_shield_deploy_lights" ] = LoadFX( "vfx/lights/riotshield_deploy_lights" );
}


#using_animtree ( "mp_riotshield" );
precacheAnims()
{
	PrecacheMpAnim( "npc_deployable_riotshield_stand_deploy" );
	PrecacheMpAnim( "npc_deployable_riotshield_stand_destroyed" );
	PrecacheMpAnim( "npc_deployable_riotshield_stand_shot" );
	PrecacheMpAnim( "npc_deployable_riotshield_stand_shot_back" );
	PrecacheMpAnim( "npc_deployable_riotshield_stand_melee_front" );
	PrecacheMpAnim( "npc_deployable_riotshield_stand_melee_back" );
}


hasRiotShield() // self == player
{
	return ( IsDefined( self.frontShieldModel ) || IsDefined( self.backShieldModel ) );
}


hasRiotShieldEquipped() // self == player
{
	return ( IsDefined( self.frontShieldModel ) );
}


weaponIsRiotShield( inWeaponName )
{
	inBaseWeaponName = GetWeaponBaseName( inWeaponName );
	if ( !IsDefined( inBaseWeaponName ) )
		inBaseWeaponName = inWeaponName;
	
	foreach( weaponName in level.riot_shield_names )
	{
		if ( weaponName == inBaseWeaponName )
			return true;
	}
	
	return false;
}


weaponIsShockPlantRiotShield( inWeaponName )
{
	if ( !weaponIsRiotShield( inWeaponName ) )
		return false;
	
	return IsSubStr( inWeaponName, "shockplant" );
}


getOtherRiotShieldName( inWeaponName )
{
	foundInputWeapon = false;
	weapons = self GetWeaponsListPrimaries();
	foreach( weapon in weapons )
	{
		if ( weaponIsRiotShield( weapon ) )
		{
			if ( ( weapon == inWeaponName ) && !foundInputWeapon )
				foundInputWeapon = true;
			else
				return weapon;
		}	
	}
	
	return undefined;
}


updateFrontAndBackShields( newWeapon ) // self == player
{
	// note this function must play nice with _detachAll().
	self.frontShieldModel 	= undefined;
	self.backShieldModel 	= undefined;
	
	if ( !IsDefined( newWeapon ) )
		newWeapon = self GetCurrentPrimaryWeapon();
	
	if ( weaponIsRiotShield( newWeapon ) )
	{
		self.frontShieldModel = GetWeaponModel( newWeapon );
	}
	
	otherShield = getOtherRiotShieldName( newWeapon );
	if ( IsDefined( otherShield ) )
	{
		assert( weaponIsRiotShield( otherShield ) );
		self.backShieldModel = GetWeaponModel( otherShield );
	}
	
	self RefreshShieldModels( newWeapon );
}


riotShield_clear()
{
	self.frontShieldModel 	= undefined;
	self.backShieldModel 	= undefined;
}

entIsStuckToShield()
{
	if ( !self IsLinked() )
		return false;
	
	tagName = self GetLinkedTagName();
	if ( !IsDefined( tagName ) )
		return false;
	
	switch( tagName )
	{
		case "tag_weapon_left":	// Front shield
		case "tag_shield_back":	// Back shield
		case "tag_inhand":		// Exo shield
			return true;
	}
	
	return false;
}

watchRiotShieldUse() // self == player
{
	self endon( "death" );
	self endon( "disconnect" );
	self endon ( "faux_spawn" );

	// watcher for attaching the model to correct player bones
	self thread trackRiotShield();

	for ( ;; )
	{
		self waittill( "raise_riotshield" );
		self thread startRiotshieldDeploy();
	}
}

riotshield_watch_for_change_weapon() // self == player
{
	self endon( "death" );
	self endon( "disconnect" );
	self endon( "faux_spawn" );
	self endon( "riotshield_change_weapon" );
	
	newWeapon = undefined;
	
	self waittill( "weapon_change", newWeapon );
	
	self notify ( "riotshield_change_weapon", newWeapon );
}

riotshield_watch_for_start_change_weapon() // self == player
{
	self endon( "death" );
	self endon( "disconnect" );
	self endon( "faux_spawn" );
	self endon( "riotshield_change_weapon" );
	
	newWeapon = undefined;
	
//	SetDvarIfUninitialized( "scr_twoshield_wait", 1.0 );
	
	while( 1 )
	{
		self waittill( "weapon_switch_started", newWeapon );
		
		// Climbing a ladder instantly switches
		if ( self IsOnLadder() )
		{
			self thread riotshield_watch_for_ladder_early_exit();
			break;
		}
		
		// If you have two shields, handle the swap time manually
		if ( IsDefined( self.frontShieldModel ) && IsDefined( self.backShieldModel ) )
		{
//			wait( GetDvarFloat( "scr_twoshield_wait", 1.0 ) );
			wait( 0.5 );
			break;
		}
	}
	
	self notify ( "riotshield_change_weapon", newWeapon );
}

riotshield_watch_for_ladder_early_exit() // self == player
{
	self endon( "death" );
	self endon( "disconnect" );
	self endon( "faux_spawn" );
	self endon( "weapon_change" ); // Stop worrying once the ladder weapon change completes
	
	while( self IsOnLadder() )
		waitframe();
	
	self notify ( "riotshield_change_weapon", self GetCurrentPrimaryWeapon() );
}

riotshield_watch_for_exo_shield_pullback() // self == player
{
	self endon( "death" );
	self endon( "disconnect" );
	self endon( "faux_spawn" );
	self endon( "riotshield_change_weapon" );
	
	newWeapon = undefined;
	
	exo_shield_weapon = maps\mp\_exo_shield::get_exo_shield_weapon();

	self waittillmatch( "grenade_pullback", exo_shield_weapon );
	
	// Allow time for the flag to get set
	while( !IsDefined( self.exo_shield_on ) || !self.exo_shield_on )
		waitframe();
	
	self notify ( "riotshield_change_weapon", exo_shield_weapon );
}

riotshield_watch_for_exo_shield_release() // self == player
{
	self endon( "death" );
	self endon( "disconnect" );
	self endon( "faux_spawn" );
	self endon( "riotshield_change_weapon" );
	
	if ( !IsDefined( self.exo_shield_on ) || !self.exo_shield_on )
		return;
	
	newWeapon = undefined;
	
	exo_shield_weapon = maps\mp\_exo_shield::get_exo_shield_weapon();

	self waittillmatch( "battery_discharge_end", exo_shield_weapon );
	
	// Allow time for the flag to clear
	while( IsDefined( self.exo_shield_on ) && self.exo_shield_on )
		waitframe();

	self notify ( "riotshield_change_weapon", self getCurrentWeapon() );
}


trackRiotShield() // self == player
{
	self endon ( "death" );
	self endon ( "disconnect" );
	self endon ( "faux_spawn" );

	self notify( "track_riot_shield" );
	self endon ( "track_riot_shield" );

	self updateFrontAndBackShields( self.currentWeaponAtSpawn );
	
	self.lastNonShieldWeapon = "none";
				
	for ( ;; )
	{
		self thread watchRiotshieldPickup();
		
		prevWeapon = self getCurrentWeapon();
		if ( IsDefined( self.exo_shield_on ) && self.exo_shield_on )
			prevWeapon = maps\mp\_exo_shield::get_exo_shield_weapon();
		
		self thread riotshield_watch_for_change_weapon();
		self thread riotshield_watch_for_start_change_weapon();
		self thread riotshield_watch_for_exo_shield_pullback();
		self thread riotshield_watch_for_exo_shield_release();
		self waittill ( "riotshield_change_weapon", newWeapon );
		
		if ( weaponIsRiotShield( newWeapon ) )
		{
			if ( self hasRiotShield() )
			{
				if ( IsDefined( self.riotshieldTakeWeapon ))
				{
					self TakeWeapon( self.riotshieldTakeWeapon );
					self.riotshieldTakeWeapon = undefined;
				}
			}

			if( isValidNonShieldWeapon( prevWeapon ) )
			{
				self.lastNonShieldWeapon = prevWeapon;
			}
		}		
		
		updateRiotShieldAttachForNewWeapon( newWeapon );
	}
}


updateRiotShieldAttachForNewWeapon( newWeapon ) // self == player
{
	// Do nothing, we want to keep that weapon on their arm.  Will get another changeweapon when finished mantling
	if ( ( self IsMantling() ) && ( newWeapon == "none" ) )
		return;
		
	updateFrontAndBackShields( newWeapon );
}


watchRiotshieldPickup() // self == player 
{
	self endon 	( "death" );
	self endon 	( "disconnect" );
	self endon 	( "track_riot_shield" );
	
	self notify	( "watch_riotshield_pickup" );
	self endon	( "watch_riotshield_pickup" );

	// tagTMR<NOTE>: fix for rare case when riotshield is given by the server
	// but the client fails to equip because of prone

	self waittill	( "pickup_riotshield" );
	self endon		( "weapon_change" );

	/#println( "Picked up riotshield, expecting weapon_change notify..." );#/

	wait 0.5;

	/#println( "picked up shield but didn't change weapons, attach it!" );#/

	updateRiotShieldAttachForNewWeapon( self getCurrentWeapon() );
}


isValidNonShieldWeapon( weapon )
{
	if( maps\mp\_utility::isKillstreakWeapon( weapon ) )
		return false;
	
	if( weapon == "none" )
		return false;

	if ( maps\mp\gametypes\_class::isValidEquipment( weapon, true ) ||
	    maps\mp\gametypes\_class::isValidEquipment( weapon, false ) )
		return false;
	
	if ( weaponIsRiotShield( weapon ) )
		return false;
	
	if ( WeaponClass(weapon) == "ball" )
		return false;
	
	return true;
}


startRiotshieldDeploy() // self == player
{
	self thread watchRiotshieldDeploy();
}


handleRiotShieldShockPlant() // self == player
{
	shield_ent = self.riotshieldEntity;
	assert( IsDefined( shield_ent ) );
	
	min_damage 	= 10;
	max_damage 	= 50;
	radius 		= 150;
	radius_sq 	= ( radius * radius );
	
	event_origin = self.riotshieldEntity.origin + ( 0, 0, -25 );
	
	self RadiusDamage( event_origin, radius, max_damage, min_damage, self, "MOD_EXPLOSIVE" );
		
	PlayFX( level._effect[ "riot_shield_shock_fx" ], event_origin, AnglesToForward( self.riotshieldEntity.angles + ( -90, 0, 0 )) );
		
	foreach( player in level.players )
	{
		if ( isReallyAlive( player ) && !IsAlliedSentient( player, self ) )
		{
			if ( DistanceSquared( event_origin, player.origin ) < radius_sq )
			{
				player ShellShock( "concussion_grenade_mp", 1 );
			}
		}
	}
}


watchRiotshieldDeploy() // self == player
{
	self endon( "death" );
	self endon( "disconnect" );
	
	self notify( "start_riotshield_deploy" );
	self endon( "start_riotshield_deploy" );

	self waittill( "startdeploy_riotshield" );
	
	self PlaySound( "wpn_riot_shield_plant_mech" );
	
	self waittill( "deploy_riotshield", deploy_attempt );
		
	// if we have a deployed riotshield in the world, delete if we attempt to deploy another
	if ( IsDefined( self.riotshieldEntity ))
	{
		self.riotshieldEntity thread damageThenDestroyRiotshield();
		waitframe(); // give it some time to clean up
	}

	curWeapon = self GetCurrentWeapon();
	self SetWeaponModelVariant( curWeapon, 0 );

	shockVersion = weaponIsShockPlantRiotShield( curWeapon );
	
	self PlaySound( "wpn_riot_shield_plant_punch" );
	if ( shockVersion )
		self PlaySound( "wpn_riot_shield_blast_punch" );
	
	//self SetPlacementHint( 1 );

	placement_hint = false;

	if ( deploy_attempt )
	{
		placement =	self CanPlaceRiotshield();

		if ( placement["result"] && riotshieldDistanceTest( placement["origin"] ) )
		{
			zoffset = 28;

			shield_ent 	= self spawnRiotshieldCover( placement["origin"] + ( 0, 0, zoffset ), placement["angles"] );
			coll_ent 	= self spawnRiotshieldCollision( placement["origin"] + ( 0, 0, zoffset ), placement["angles"], shield_ent );
			item_ent 	= DeployRiotShield( self, shield_ent );
			
			primaries = self GetWeaponsListPrimaries();

			/#
			assert( IsDefined( item_ent ) );
			assert( !IsDefined( self.riotshieldRetrieveTrigger ) );
			assert( !IsDefined( self.riotshieldEntity ) );
			assert( !IsDefined( self.riotshieldCollisionEntity ) );
			#/

			self.riotshieldRetrieveTrigger 	= item_ent;
			self.riotshieldEntity 			= shield_ent;
			self.riotshieldCollisionEntity 	= coll_ent;

			if ( shockVersion )
				self thread handleRiotShieldShockPlant();
			else
				PlayFXOnTag( getfx( "riot_shield_deploy_smoke" ), shield_ent, "tag_weapon" );

			//shield_ent SetClientField( "riotshield_state", RIOTSHIELD_STATE_DEPLOYED );
			// TODO: spawn thread to: play deploy anim on shield, play dust fx at shield origin, wait 0.8, playfxontag light fx at tag_fx on shield
			shield_ent ScriptModelPlayAnimDeltaMotion( "npc_deployable_riotshield_stand_deploy" );			
			// Play Dust FX at shield origin
			// spawn thread:
			thread spawnShieldLights( shield_ent );

						
			switchToKnife = false;
			if( self.lastNonShieldWeapon != "none" && self hasWeapon( self.lastNonShieldWeapon ) )
				self SwitchToWeaponImmediate( self.lastNonShieldWeapon );
			else if ( primaries.size > 0 )
				self SwitchToWeaponImmediate( primaries[0] );
			else
				switchToKnife = true;
			
			if ( !self HasWeapon( "iw5_combatknife_mp" ) )
			{
				self GiveWeapon( "iw5_combatknife_mp" );
				self.riotshieldTakeWeapon = "iw5_combatknife_mp";
			}
			
			if ( switchToKnife )
				self SwitchToWeaponImmediate( "iw5_combatknife_mp" );

			// Moving platforms. 
			data = SpawnStruct();
			data.deathOverrideCallback = ::damageThenDestroyRiotshield;
			shield_ent thread maps\mp\_movers::handle_moving_platforms( data );

			self thread watchDeployedRiotshieldEnts();

			self thread deleteShieldOnTriggerDeath( self.riotshieldRetrieveTrigger );
			self thread deleteShieldOnTriggerPickup( self.riotshieldRetrieveTrigger, self.riotshieldEntity );
			self thread deleteShieldOnPlayerDeathOrDisconnect( shield_ent );

			self.riotshieldEntity thread watchDeployedRiotshieldDamage();
			level notify( "riotshield_planted", self );
		}
		else
		{
			placement_hint = true;
			
			clip_max_ammo = WeaponClipSize( curWeapon );
			self setWeaponAmmoClip( curWeapon, clip_max_ammo );
		}
	}
	else
	{
		// tagTMR<NOTE>: just lowering the shield not trying to deploy
		placement_hint = true;
	}

	if ( placement_hint )
	{
		self SetRiotshieldFailHint();
	}
}

spawnShieldLights(ent)
{
	level endon( "game_ended" );
	ent endon( "death" );
	
	wait 0.6;
	PlayFXOnTag( getfx( "riot_shield_deploy_lights" ), ent, "tag_weapon" );
}

riotshieldDistanceTest( origin )
{
	/#
	assert ( IsDefined( origin ) );
	#/

	min_dist_squared = GetDvarFloat( "riotshield_deploy_limit_radius" );
	min_dist_squared *= min_dist_squared;

	foreach( player in level.players )
	{
		if ( IsDefined( player.riotshieldEntity ) )
		{
			dist_squared = DistanceSquared( player.riotshieldEntity.origin, origin );
			if ( min_dist_squared > dist_squared )
			{
				/# 
				println( "Shield placement denied!  Failed distance check to other riotshields." );
				#/
				
				return false;
			}
		}
	}

	return true;
}


spawnRiotshieldCover( origin, angles ) // self == player
{	
	shield_ent = Spawn( "script_model", origin );
	shield_ent.targetname = "riotshield_mp";
	shield_ent.angles = angles;
	
	model = undefined;
	curWeapon = self GetCurrentPrimaryWeapon();
	if ( weaponIsRiotShield( curWeapon ) )
		model = GetWeaponModel( curWeapon );
	
	if ( !IsDefined( model ) )
		model = "npc_deployable_riot_shield_base";

	shield_ent SetModel( model );
//	shield_ent SetEntityOwner( self ); // Removing this as it causes traces from the player to pass through it unintentionally (grenades and missiles especially)
	shield_ent.owner = self;
	shield_ent.team = self.team;
//	shield_ent SetTeam( self.team );

//	shield_ent UseAnimTree( #animtree );
	
	return shield_ent;
}


spawnRiotshieldCollision( origin, angles, shield_ent ) // self == player
{
	coll_ent = Spawn( "script_model", origin, 1 ); // third param is spawn flag for dynamic pathing
	coll_ent.targetname = "riotshield_coll_mp";
	coll_ent.angles = angles;
	coll_ent SetModel( "tag_origin" );
	coll_ent.owner = self;
	coll_ent.team = self.team;
	coll_ent CloneBrushmodelToScriptModel( level.riot_shield_collision );
	coll_ent DisconnectPaths();
	
	return coll_ent;
}


watchDeployedRiotshieldEnts() // self == player
{
	/#
	assert( IsDefined( self.riotshieldRetrieveTrigger ) );
	assert( IsDefined( self.riotshieldEntity ) );
	assert( IsDefined( self.riotshieldCollisionEntity ) );
	#/

	self waittill( "destroy_riotshield" );

	if ( IsDefined( self.riotshieldRetrieveTrigger ) )
	{
		self.riotshieldRetrieveTrigger delete();
	}
	
	if ( IsDefined( self.riotshieldCollisionEntity ) )
	{
		self.riotshieldCollisionEntity ConnectPaths();
		self.riotshieldCollisionEntity delete();
	}

	if ( IsDefined( self.riotshieldEntity ) )
	{
		self.riotshieldEntity delete();
	}
}


deleteShieldOnTriggerPickup( shield_trigger, shield_ent ) // self == player
{
	level endon( "game_ended" );
	shield_trigger endon( "death" );
	
	shield_trigger waittill( "trigger", player );
	
	// Transfer any linked entities from the deployed shield to the player's arm at the same offset
	HandlePickupDeployedRiotshield( player, shield_ent );
	
	self notify( "destroy_riotshield" );
}


deleteShieldOnTriggerDeath( shield_trigger ) // self == player
{
	level endon( "game_ended" );
	
	shield_trigger waittill( "death" );	
	self notify( "destroy_riotshield" );
}


deleteShieldOnPlayerDeathOrDisconnect( shield_ent ) // self == player
{
	shield_ent endon( "death" );
	shield_ent endon( "damageThenDestroyRiotshield" );

	self waittill_any( "death", "disconnect", "remove_planted_weapons" );

	shield_ent thread damageThenDestroyRiotshield();
}


watchDeployedRiotshieldDamage() // self == riotshield script_model ent
{
	self endon( "death" );

	damageMax = GetDvarInt( "riotshield_deployed_health" );
	self.damageTaken = 0;

	nextDamageAnimTime = 0;
	
	while( true )
	{
		self.maxhealth = 100000;
		self.health = self.maxhealth;

		self waittill( "damage", damage, attacker, direction, point, type, modelName, tagName, partname, iDFlags, weaponName );
		
		if( !isdefined( attacker ) )
		{
			continue;
		}

		/#
		assert( isDefined( self.owner ) && isDefined( self.owner.team ));
		#/

		if ( isplayer( attacker ) )
		{
			if ( ( level.teamBased ) && ( attacker.team == self.owner.team ) && ( attacker != self.owner ) )
			{
				continue;
			}
		}

		isMeleeDamage = false;
		isBulletDamage = false;
		
		if ( isMeleeMOD( type ) )
		{
			isMeleeDamage = true;
			damage *= GetDvarfloat( "riotshield_melee_damage_scale" );
		}
		else if ( type == "MOD_PISTOL_BULLET" || type == "MOD_RIFLE_BULLET" )
		{
			isBulletDamage = true;
			damage *= GetDvarfloat( "riotshield_bullet_damage_scale" );
		}
		else if ( type == "MOD_GRENADE" || type == "MOD_GRENADE_SPLASH" || type == "MOD_EXPLOSIVE" || type == "MOD_EXPLOSIVE_SPLASH" || type == "MOD_PROJECTILE" || type == "MOD_PROJECTILE_SPLASH")
		{
			damage *= GetDvarfloat( "riotshield_explosive_damage_scale" );
		}
		else if ( type == "MOD_IMPACT" )
		{
			damage *= GetDvarFloat( "riotshield_projectile_damage_scale" );
		}
		else if ( type == "MOD_CRUSH" )
		{
			damage = damageMax;
		}

		self.damageTaken += damage;

		if( self.damageTaken >= damageMax )
		{
			self thread damageThenDestroyRiotshield( attacker, weaponName );
			break;
		}
		else if ( ( isMeleeDamage || isBulletDamage ) && ( GetTime() >= nextDamageAnimTime ) )
		{
			nextDamageAnimTime = GetTime() + 500;
			
			fromBack = false;
			shield_fwd = AnglesToForward( self.angles );
			if ( VectorDot( direction, shield_fwd ) > 0 )
				fromBack = true;
			
			if ( isMeleeDamage )
			{
				if ( fromBack )
					self ScriptModelPlayAnimDeltaMotion( "npc_deployable_riotshield_stand_melee_back" );
				else
					self ScriptModelPlayAnimDeltaMotion( "npc_deployable_riotshield_stand_melee_front" );
			}
			else
			{
				Assert( isBulletDamage );
				if ( fromBack )
					self ScriptModelPlayAnimDeltaMotion( "npc_deployable_riotshield_stand_shot_back" );
				else
					self ScriptModelPlayAnimDeltaMotion( "npc_deployable_riotshield_stand_shot" );
			}
		}
	}
}


damageThenDestroyRiotshield(attacker, weaponName) // self == riotshield script_model ent
{
	self notify( "damageThenDestroyRiotshield" );
	self endon( "death" );

	if ( IsDefined( self.owner.riotshieldRetrieveTrigger ) )
	{
		self.owner.riotshieldRetrieveTrigger delete();
	}
	
	if ( IsDefined( self.owner.riotshieldCollisionEntity ) )
	{
		self.owner.riotshieldCollisionEntity ConnectPaths();
		self.owner.riotshieldCollisionEntity delete();
	}
		
	
	self.owner.riotshieldEntity = undefined;

	self NotSolid();
//	self SetClientField( "riotshield_state", RIOTSHIELD_STATE_DESTROYED );
	// TODO: stop fx, play sound, play destroyed anim, wait, force not simple dobj...?
	// Stop FX on shield
	// Play destroyed sound
	self ScriptModelPlayAnimDeltaMotion( "npc_deployable_riotshield_stand_destroyed" );
	// Wait
	// Force not simple dobj?
	
//	if (isdefined (attacker) && isdefined (weaponName) && attacker != self.owner && isplayer( attacker ) )
//	{
//		maps\mp\_scoreevents::processScoreEvent( "destroyed_shield", attacker, self.owner, weaponName );
//	}
	
	wait( GetDvarFloat( "riotshield_destroyed_cleanup_time" ) );

	self delete();
}


watchRiotshieldStuckEntityDeath( grenade, owner ) // self == entity stuck with nade
{
	grenade endon( "death" );

	self waittill_any( "damageThenDestroyRiotshield", "death", "disconnect", "weapon_change", "deploy_riotshield" );

	grenade Detonate( owner );
}