#using scripts\codescripts\struct;

#using scripts\shared\array_shared;
#using scripts\shared\audio_shared;
#using scripts\shared\callbacks_shared;
#using scripts\shared\challenges_shared;
#using scripts\shared\clientfield_shared;
#using scripts\shared\math_shared;
#using scripts\shared\killstreaks_shared;
#using scripts\shared\statemachine_shared;
#using scripts\shared\system_shared;
#using scripts\shared\turret_shared;
#using scripts\shared\util_shared;
#using scripts\shared\vehicle_ai_shared;
#using scripts\shared\vehicle_death_shared;
#using scripts\shared\vehicle_shared;
#using scripts\shared\vehicles\_wasp;
#using scripts\shared\visionset_mgr_shared;
#using scripts\shared\scoreevents_shared;
#using scripts\shared\weapons\_heatseekingmissile;

#using scripts\mp\_util;
#using scripts\mp\gametypes\_shellshock;
#using scripts\mp\gametypes\_spawning;
#using scripts\mp\killstreaks\_airsupport;
#using scripts\mp\killstreaks\_helicopter;
#using scripts\mp\killstreaks\_killstreak_bundles;
#using scripts\mp\killstreaks\_killstreak_detect;
#using scripts\mp\killstreaks\_killstreak_hacking;
#using scripts\mp\killstreaks\_killstreaks;
#using scripts\mp\killstreaks\_killstreakrules;
#using scripts\mp\killstreaks\_qrdrone;
#using scripts\mp\killstreaks\_rcbomb;
#using scripts\mp\killstreaks\_remote_weapons;
#using scripts\mp\teams\_teams;

  
                                                                                                   	  	                                                                    	                     	                 	                                                                         	                       	                                                      	                                                      	                                                       	                                                                                                  	                                                                                                                 	                                                   	                	                                          	                                      	       	  	             	                                                     	                                                                             	                         	                                                                	                                                             	                                                             	                                                                                      	                                                         	                                                         	                                                               	                                                               	                                                   	                                                                	                                                     	                                                	                                                	                                                        	                                                                                                  	                                                                             	                                            	                                                                                    	                                          	                     	                                              	                                        	                 	   
                                             
                                                                                                            	  	  	              	   	                                                                                                                                       	                                                                                                                                                            	                                                                                                                                                                
    	   	                                                                                                                                         	                                	                                                                                                                                                                                                                                                                                                                                                                    	        	     	              	    	   	               	                                              	                                                           	                               	                     	                                                                                                           	                                                                 	                                                              	                                                                                                                                             	                            	                                     	                                       	                                                                                                              	   	                  	       	                                                    	                   	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            	                                                                                                 	                                    	                                                                                        	           	                        	                                            	                                             	                                                   	                                                             	                                                         	                                                                    	                                                                                                                                                                                                                                	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  	    	         	                                                              	                                                          	                                   	                                   	                                                    	                                       	                                           	     	                                                                                                                                                                                                                                                      	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	                                                               	        	                                                                                                                              	                                                                                                                     	                               	                                                      	                          
       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	   	                                                                                                                                                                                                                                  	                                                                                                                                                                                                                                                                                                                                                                                                                                                   

#precache( "string", "mpl_killstreak_sentinel_strt" );
#precache( "string", "KILLSTREAK_SENTINEL_HACKED" );
#precache( "string", "KILLSTREAK_SENTINEL_INBOUND" );
#precache( "string", "KILLSTREAK_SENTINEL_NOT_AVAILABLE" );
#precache( "string", "KILLSTREAK_SENTINEL_EARNED" );
#precache( "string", "KILLSTREAK_SENTINEL_NOT_PLACEABLE" );
#precache( "string", "KILLSTREAK_DESTROYED_SENTINEL" );
                    
#precache( "triggerstring", "KILLSTREAK_SENTINEL_USE_REMOTE" );

#namespace sentinel;




function init()
{
	killstreaks::register( "sentinel", "sentinel", "killstreak_" + "sentinel", "sentinel" + "_used", &ActivateSentinel, true );
	killstreaks::register_strings( "sentinel", &"KILLSTREAK_SENTINEL_EARNED", &"KILLSTREAK_SENTINEL_NOT_AVAILABLE", &"KILLSTREAK_SENTINEL_INBOUND", undefined, &"KILLSTREAK_SENTINEL_HACKED" );
	killstreaks::register_dialog( "sentinel", "mpl_killstreak_sentinel_strt", "sentinelDialogBundle", "sentinelPilotDialogBundle", "friendlySentinel", "enemySentinel", "enemySentinelMultiple", "friendlySentinelHacked", "enemySentinelHacked", "requestSentinel", "threatSentinel" );
	killstreaks::register_alt_weapon( "sentinel", "killstreak_remote" );
	killstreaks::register_alt_weapon( "sentinel", "sentinel_turret" );
	remote_weapons::RegisterRemoteWeapon( "sentinel", &"KILLSTREAK_SENTINEL_USE_REMOTE", &StartSentinelRemoteControl, &EndSentinelRemoteControl, false );
	
	// TODO: Move to killstreak data
	level.killstreaks["sentinel"].threatOnKill = true;

	vehicle::add_main_callback( "veh_sentinel_mp", &InitSentinel );
	
	visionset_mgr::register_info( "visionset", "sentinel_visionset", 1, 100, 16, true, &visionset_mgr::ramp_in_out_thread_per_player_death_shutdown, false  );
}

function InitSentinel()
{
	self.settings = struct::get_script_bundle( "vehiclecustomsettings", self.scriptbundlesettings );
	Target_Set( self, ( 0, 0, 0 ) );
	self.health = self.healthdefault;
	self.numFlares = 1;
	self.damageTaken = 0;
	self vehicle::friendly_fire_shield();
	self EnableAimAssist();
	self SetNearGoalNotifyDist( ( 40 ) );
	self SetHoverParams( ( 50.0 ), ( 100.0 ), ( 100.0 ) );
	self.fovcosine = 0; // +/-90 degrees = 180
	self.fovcosinebusy = 0;	//+/- 55 degrees = 110 fov
	self.vehAirCraftCollisionEnabled = true;
	
	self thread vehicle_ai::nudge_collision();
	self thread heatseekingmissile::MissileTarget_ProximityDetonateIncomingMissile( "explode", "death" );			// fires chaff if needed
	self thread helicopter::create_flare_ent( (0,0,-20) );
	self thread audio::vehicleSpawnContext();
	self.do_scripted_crash = false;
	
	self.overrideVehicleDamage = &SentinelDamageOverride;
	self.selfDestruct = false;

	self.enable_target_laser = true;
	self.aggresive_navvolume_recover = true;
		
	self vehicle_ai::init_state_machine_for_role( "default" );
	self vehicle_ai::get_state_callbacks( "combat" ).enter_func = &wasp::state_combat_enter;
    self vehicle_ai::get_state_callbacks( "combat" ).update_func = &wasp::state_combat_update;
   	self vehicle_ai::get_state_callbacks( "death" ).update_func = &wasp::state_death_update;
   	self vehicle_ai::get_state_callbacks( "driving" ).enter_func = &driving_enter;
 
   	wasp::init_guard_points();
   	self vehicle_ai::add_state( "guard",
		&wasp::state_guard_enter,
		&wasp::state_guard_update,
		&wasp::state_guard_exit );

   	vehicle_ai::add_utility_connection( "combat", "guard", &wasp::state_guard_can_enter );
	vehicle_ai::add_utility_connection( "guard", "combat" );
	vehicle_ai::add_interrupt_connection( "guard",	"emped",	"emped" );
	vehicle_ai::add_interrupt_connection( "guard",	"surge",	"surge" );
	vehicle_ai::add_interrupt_connection( "guard",	"off",		"shut_off" );
	vehicle_ai::add_interrupt_connection( "guard",	"pain",		"pain" );
	vehicle_ai::add_interrupt_connection( "guard",	"driving",	"enter_vehicle" );
  	
	self vehicle_ai::StartInitialState( "combat" );
}

function driving_enter( params )
{
	vehicle_ai::defaultstate_driving_enter( params );
}

function drone_pain_for_time( time, stablizeParam, restoreLookPoint, weapon )
{
	self endon( "death" );
	
	self.painStartTime = GetTime();

	if ( !( isdefined( self.inpain ) && self.inpain ) && isdefined( self.health ) && self.health > 0 )
	{
		self.inpain = true;
		

		while ( GetTime() < self.painStartTime + time * 1000 )
		{
			self SetVehVelocity( self.velocity * stablizeParam );
			self SetAngularVelocity( self GetAngularVelocity() * stablizeParam );
			wait 0.1;
		}

		if ( isdefined( restoreLookPoint ) && isdefined( self.health ) && self.health > 0 )
		{
			restoreLookEnt = Spawn( "script_model", restoreLookPoint );
			restoreLookEnt SetModel( "tag_origin" );

			self ClearLookAtEnt();
			self SetLookAtEnt( restoreLookEnt );
			self setTurretTargetEnt( restoreLookEnt );
			wait 1.5;

			self ClearLookAtEnt();
			self ClearTurretTarget();
			restoreLookEnt delete();
		}
		
		if( weapon.isEmp ) remote_weapons::set_static( 0 );

		self.inpain = false;
	}
}

function drone_pain( eAttacker, damageType, hitPoint, hitDirection, hitLocationInfo, partName, weapon )
{
	if ( !( isdefined( self.inpain ) && self.inpain ) )
	{
		yaw_vel = math::randomSign() * RandomFloatRange( 280, 320 );

		ang_vel = self GetAngularVelocity();
		ang_vel += ( RandomFloatRange( -120, -100 ), yaw_vel, RandomFloatRange( -200, 200 ) );
		self SetAngularVelocity( ang_vel );

		self thread drone_pain_for_time( 0.8, 0.7, undefined, weapon );
	}
}

function SentinelDamageOverride( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal )
{
	if( sMeansOfDeath == "MOD_TRIGGER_HURT" )
		return 0;
	
	emp_damage = self.healthdefault * ( 0.5 ) + 0.5;
	
	iDamage = killstreaks::OnDamagePerWeapon( "sentinel", eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, self.maxhealth, &destroyed_cb, self.maxhealth*0.4, &low_health_cb, emp_damage, undefined, true, 1.0 );	
	
	if( isdefined( eAttacker ) && isdefined( eAttacker.team ) && eAttacker.team != self.team )
	{
		drone_pain( eAttacker, sMeansOfDeath, vPoint, vDir, sHitLoc, partName, weapon );
	}
	self.damageTaken += iDamage;
	return iDamage;
}

function destroyed_cb( attacker, weapon )
{
	if( isdefined( attacker ) && isdefined( attacker.team ) && attacker.team != self.team )
		self.owner.dofutz = true;
}

function low_health_cb( attacker, weapon )
{
	if( self.playedDamaged == false )
	{
		self killstreaks::play_pilot_dialog_on_owner( "damaged", "sentinel", self.killstreak_id );
		self.playedDamaged = true;
	}
}

function CalcSpawnOrigin( origin, angles )
{
	heightOffset = rcbomb::GetPlacementStartHeight();
	
	mins = ( -5, -5, 0 );
	maxs = ( 5, 5, 10 );
	
	startPoints = [];
	testangles = [];
	
	testangles[0] = ( 0,   0, 0 );
	testangles[1] = ( 0,  30, 0 );
	testangles[2] = ( 0, -30, 0 );
	testangles[3] = ( 0,  60, 0 );
	testangles[4] = ( 0, -60, 0 );
	testangles[3] = ( 0,  90, 0 );
	testangles[4] = ( 0, -90, 0 );
	
	bestOrigin = origin;
	bestAngles = angles;
	bestFrac = 0;
	
	for( i = 0; i < testangles.size; i++ )
	{
		startPoint = origin + ( 0, 0, heightOffset );
		endPoint = startPoint + VectorScale( anglestoforward( ( 0, angles[1], 0 ) + testangles[i] ), ( 70 ) );
		
		mask = (1 << 0) | (1 << 1);
		trace = physicstrace( startPoint, endPoint, mins, maxs, self, mask );
			
		if( isdefined( trace["entity"] ) && IsPlayer( trace["entity"] ) )
			continue;
		
		if( trace["fraction"] > bestFrac )
		{
			bestFrac = trace["fraction"];
			bestOrigin = trace["position"];
			bestAngles = ( 0, angles[1], 0 ) + testangles[i];
			if( bestFrac == 1 )
				break;
		}
	}
	
	if( bestFrac > 0 )
	{
		if( Distance2DSquared( origin, bestOrigin ) < 20 * 20 )
			return undefined;
		
 		trace = physicstrace( bestOrigin, bestOrigin + ( 0, 0, ( 25 ) ), mins, maxs, self, mask );
 		
 		placement = SpawnStruct();
 		placement.origin = trace["position"];
		placement.angles = bestAngles;
		return placement;
	}
	else
		return undefined;
}
	
function ActivateSentinel( killstreakType )
{
	assert( IsPlayer( self ) );
	player = self;
	
	if( !IsNavVolumeLoaded() )
	{
		/# IPrintLnBold( "Error: NavVolume Not Loaded" ); #/
		self iPrintLnBold( &"KILLSTREAK_SENTINEL_NOT_AVAILABLE" );
		return false;
	}
	
	if( player IsPlayerSwimming() )
	{
		self iPrintLnBold( &"KILLSTREAK_SENTINEL_NOT_PLACEABLE" );
		return false;
	}	
	
	spawnPos = CalcSpawnOrigin( player.origin, player.angles );
	if( !isdefined( spawnPos ) )
	{
		self iPrintLnBold( &"KILLSTREAK_SENTINEL_NOT_PLACEABLE" );
		return false;
	}
	
	killstreak_id = player killstreakrules::killstreakStart( "sentinel", player.team, false, true );
	if( killstreak_id == (-1) )
	{
		return false;
	}
	
	player AddWeaponStat( GetWeapon( "sentinel" ), "used", 1 );

	sentinel = SpawnVehicle( "veh_sentinel_mp", spawnPos.origin, spawnPos.angles, "dynamic_spawn_ai" );
	
	sentinel killstreaks::configure_team( "sentinel", killstreak_id, player, "small_vehicle", undefined, &ConfigureTeamPost );
	sentinel killstreak_hacking::enable_hacking( "sentinel", &HackedCallbackPre, &HackedCallbackPost );
	sentinel.killstreak_id = killstreak_id;
	sentinel.killstreak_end_time = GetTime() + ( 60000 );
	sentinel.original_vehicle_type = sentinel.vehicletype;
	sentinel.ignore_vehicle_underneath_splash_scalar = true;

	sentinel clientfield::set( "enemyvehicle", 1 );
	sentinel.hardpointType = "sentinel";
	sentinel.soundmod = "player";

	sentinel.maxhealth = killstreak_bundles::get_max_health( "sentinel" );
	sentinel.lowhealth = killstreak_bundles::get_low_health( "sentinel" );
	sentinel.health = sentinel.maxhealth;
	sentinel.hackedhealth = killstreak_bundles::get_hacked_health( "sentinel" );
	sentinel.rocketDamage = ( sentinel.maxhealth / ( 1 ) ) + 1;	
	sentinel.playedDamaged = false;
	sentinel.treat_owner_damage_as_friendly_fire = true;
	sentinel.ignore_team_kills = true;
	sentinel thread HealthMonitor();
	
	sentinel.goalradius = ( 1200 );
	sentinel.goalHeight = 500;
	//sentinel SetGoal( player, false, sentinel.goalRadius, sentinel.goalHeight );
	sentinel.enable_guard = true;
	sentinel.always_face_enemy = true;
		
	sentinel thread killstreaks::WaitForTimeout( "sentinel", ( 60000 ), &OnTimeout, "sentinel_shutdown" );
	sentinel thread WatchWater();
	sentinel thread WatchDeath();
	sentinel thread WatchShutdown();
	
	player remote_weapons::UseRemoteWeapon( sentinel, "sentinel", false );
	
	sentinel killstreaks::play_pilot_dialog_on_owner( "arrive", "sentinel", killstreak_id );
	
	sentinel vehicle::init_target_group();
	sentinel vehicle::add_to_target_group( sentinel );
	
	self killstreaks::play_killstreak_start_dialog( "sentinel", self.team, killstreak_id );
	
	sentinel thread WatchGameEnded();

	return true;
}

function HackedCallbackPre( hacker )
{
	sentinel = self;
	sentinel.owner unlink();
	sentinel clientfield::set( "vehicletransition", 0 );
	if( sentinel.controlled === true )
		visionset_mgr::deactivate( "visionset", "sentinel_visionset", sentinel.owner );
	sentinel.owner remote_weapons::RemoveAndAssignNewRemoteControlTrigger( sentinel.useTrigger );
	sentinel remote_weapons::EndRemoteControlWeaponUse( true );
	EndSentinelRemoteControl( sentinel, true );
}

function HackedCallbackPost( hacker )
{
	sentinel = self;

	hacker remote_weapons::UseRemoteWeapon( sentinel, "sentinel", false );
	sentinel notify("WatchRemoteControlDeactivate_remoteWeapons");
	sentinel.killstreak_end_time = hacker killstreak_hacking::set_vehicle_drivable_time_starting_now( sentinel );
}

function ConfigureTeamPost( owner, isHacked )
{
	sentinel = self;
	sentinel thread WatchTeamChange();
}

function WatchGameEnded()
{
	sentinel = self;
	sentinel endon( "death" );
	
	level waittill("game_ended");

	sentinel.abandoned = true;
	sentinel.selfDestruct = true;
	sentinel notify( "sentinel_shutdown" );
}

function StartSentinelRemoteControl( sentinel )
{
	player = self;
	assert( IsPlayer( player ) );
	
	sentinel UseVehicle( player, 0 );
	
	sentinel clientfield::set( "vehicletransition", 1 );
	sentinel thread audio::sndUpdateVehicleContext(true);
	sentinel thread vehicle::monitor_missiles_locked_on_to_me( player );
	
	sentinel.inHeliProximity = false;
	sentinel.treat_owner_damage_as_friendly_fire = false;
	sentinel.ignore_team_kills = false;
	
	minHeightOverride = undefined;
	minz_struct = struct::get( "vehicle_oob_minz", "targetname");
	if( isdefined( minz_struct ) )
		minHeightOverride = minz_struct.origin[2];			
	
	sentinel thread qrdrone::QRDrone_watch_distance( ( 0 ), minHeightOverride );
	sentinel.distance_shutdown_override = &SentinelDistanceFailure;
	
	player vehicle::set_vehicle_drivable_time( ( 60000 ), sentinel.killstreak_end_time );
	visionset_mgr::activate( "visionset", "sentinel_visionset", player, 1, 90000, 1 );	

	if ( isdefined( sentinel.PlayerDrivenVersion ) )
		sentinel SetVehicleType( sentinel.PlayerDrivenVersion );
}

function EndSentinelRemoteControl( sentinel, exitRequestedByOwner )
{
	sentinel.treat_owner_damage_as_friendly_fire = true;
	sentinel.ignore_team_kills = true;
			
	if ( isdefined( sentinel.owner ) )
	{
		sentinel.owner vehicle::stop_monitor_missiles_locked_on_to_me();
		if( sentinel.controlled === true )
			visionset_mgr::deactivate( "visionset", "sentinel_visionset", sentinel.owner );
	}

	if( exitRequestedByOwner )
	{
		if ( isdefined( sentinel.owner ) )
		{
			sentinel.owner qrdrone::destroyHud();
			sentinel.owner unlink();
			sentinel clientfield::set( "vehicletransition", 0 );
		}
		sentinel thread audio::sndUpdateVehicleContext(false);
	}
	
	if ( isdefined( sentinel.original_vehicle_type ) )
		sentinel SetVehicleType( sentinel.original_vehicle_type );
	
}

function OnTimeout()
{
	sentinel = self;
	
	sentinel killstreaks::play_pilot_dialog_on_owner( "timeout", "sentinel" );
	
	params = level.killstreakBundle["sentinel"];
	
	if( isdefined( sentinel.owner ) )
	{
		RadiusDamage( sentinel.origin, 
					params.ksExplosionOuterRadius,
					params.ksExplosionInnerDamage,
					params.ksExplosionOuterDamage,
					sentinel.owner, 
					"MOD_EXPLOSIVE",
					GetWeapon( "sentinel" ) );
		if( isdefined( params.ksExplosionRumble ) )
			sentinel.owner PlayRumbleOnEntity( params.ksExplosionRumble );
	}
	
	sentinel notify( "sentinel_shutdown" );
}

function HealthMonitor()
{
	self endon( "death" );
	
	params = level.killstreakBundle["sentinel"];
	
	if( isdefined( params.fxLowHealth ) )
	{
		while( 1 )
		{
			if( self.lowhealth > self.health )
			{
				PlayFXOnTag( params.fxLowHealth, self, "tag_origin" );
				break;
			}
			{wait(.05);};
		}
	}
}

function SentinelDistanceFailure()
{
	sentinel = self;
	
	sentinel notify( "sentinel_shutdown" );
}

function WatchDeath()
{
	sentinel = self;
	sentinel waittill( "death", attacker, damageFromUnderneath, weapon, point, dir, modType );
	sentinel notify( "sentinel_shutdown" );
	
	attacker = self [[ level.figure_out_attacker ]]( attacker );
	if ( isdefined( attacker ) && ( !isdefined( self.owner ) || self.owner util::IsEnemyPlayer( attacker ) ) )
	{
		if ( isPlayer( attacker ) )
		{
			challenges::destroyedAircraft( attacker, weapon, sentinel.controlled === true );
			attacker challenges::addFlySwatterStat( weapon, self );
			attacker AddWeaponStat( weapon, "destroy_aitank_or_setinel", 1 );
			scoreevents::processScoreEvent( "destroyed_sentinel", attacker, sentinel.owner, weapon );
			if ( modType == "MOD_RIFLE_BULLET" || modType == "MOD_PISTOL_BULLET" )
			{
				attacker addPlayerStat( "shoot_down_sentinel", 1 );
			}
			LUINotifyEvent( &"player_callout", 2, &"KILLSTREAK_DESTROYED_SENTINEL", attacker.entnum );
		}
		
		if ( isdefined( sentinel ) && isdefined( sentinel.owner ) )
		{
			sentinel killstreaks::play_destroyed_dialog_on_owner(  "sentinel", sentinel.killstreak_id );
		}
	}
}

function WatchTeamChange()
{
	self notify( "Sentinel_WatchTeamChange_Singleton" );
	self endon ( "Sentinel_WatchTeamChange_Singleton" );
	sentinel = self;
	
	sentinel endon( "sentinel_shutdown" );
	sentinel.owner util::waittill_any( "joined_team", "disconnect", "joined_spectators" );
	sentinel notify( "sentinel_shutdown" );
}





	
function WatchWater()
{
	sentinel = self;
	sentinel endon( "sentinel_shutdown" );
			
	while( true )
	{
		wait ( 0.1 );
		trace = physicstrace( self.origin + ( 0, 0, 10 ), self.origin + ( 0, 0, 6 ), ( -2, -2, -2 ), (  2,  2,  2 ), self, ( (1 << 2) ));
		if( trace["fraction"] < 1.0 )
			break;
	}
	
	sentinel notify( "sentinel_shutdown" );
}

function WatchShutdown()
{
	sentinel = self;
	
	sentinel waittill( "sentinel_shutdown" );
	
	if( ( isdefined( sentinel.control_initiated ) && sentinel.control_initiated ) || ( isdefined( sentinel.controlled ) && sentinel.controlled ) )
	{
		sentinel remote_weapons::EndRemoteControlWeaponUse( false );
		while( ( isdefined( sentinel.control_initiated ) && sentinel.control_initiated ) || ( isdefined( sentinel.controlled ) && sentinel.controlled ) )
			{wait(.05);};
	}
	
	if( isdefined( sentinel.owner ) )
	{
		sentinel.owner qrdrone::destroyHud();
	}
	
	killstreakrules::killstreakStop( "sentinel", sentinel.originalTeam, sentinel.killstreak_id );
	
	if( isalive( sentinel ) )
		sentinel Kill();
}