//---------------------------------------------------------
//---------------------------------------------------------
void CNPC_GroundTurret::DeathEffects()
{
	if( !m_bHasExploded )
	{
		//ExplosionCreate( GetAbsOrigin(), QAngle( 0, 0, 1 ), this, 150, 150, false );
		CTakeDamageInfo info;
		DeathSound( info );
		m_bHasExploded = true;
		SetNextThink( gpGlobals->curtime + 0.5 );
	}
	else
	{
		// Sparks
		EmitSound( "DoSpark" );
		m_iDeathSparks--;

		if( m_iDeathSparks == 0 )
		{
			SetThink(NULL);
			return;
		}

		SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.5, 2.5 ) );
	}
}
void CASW_Simple_Alien::Event_Killed( const CTakeDamageInfo &info )
{
	if (ASWGameRules())
	{
		ASWGameRules()->AlienKilled(this, info);
	}	

	if (m_hSpawner.Get())
		m_hSpawner->AlienKilled(this);

	// Calculate death force
	Vector forceVector = CalcDeathForceVector( info );

	StopLoopingSounds();
	DeathSound(info);
	// todo: remove touch function?

	SetState(ASW_SIMPLE_ALIEN_DEAD);

	// todo: Select a death pose to extrapolate the ragdoll's velocity?
	//SelectDeathPose( info );

	if (!ShouldGib(info))
	{
		SetCollisionGroup(ASW_COLLISION_GROUP_PASSABLE);	// don't block marines by dead bodies

		if ( BecomeRagdollOnClient( forceVector ) )
		{

		}
	}
	else
	{
		Event_Gibbed( info );
	}
}
//=========================================================
// Start task - selects the correct activity and performs
// any necessary calculations to start the next task on the
// schedule. 
//=========================================================
void CBaseMonster :: StartTask ( Task_t *pTask )
{
	switch ( pTask->iTask )
	{
	case TASK_TURN_RIGHT:
		{
			float flCurrentYaw;
			
			flCurrentYaw = UTIL_AngleMod( pev->angles.y );
			pev->ideal_yaw = UTIL_AngleMod( flCurrentYaw - pTask->flData );
			SetTurnActivity();
			break;
		}
	case TASK_TURN_LEFT:
		{
			float flCurrentYaw;
			
			flCurrentYaw = UTIL_AngleMod( pev->angles.y );
			pev->ideal_yaw = UTIL_AngleMod( flCurrentYaw + pTask->flData );
			SetTurnActivity();
			break;
		}
	case TASK_REMEMBER:
		{
			Remember ( (int)pTask->flData );
			TaskComplete();
			break;
		}
	case TASK_FORGET:
		{
			Forget ( (int)pTask->flData );
			TaskComplete();
			break;
		}
	case TASK_FIND_HINTNODE:
		{
			m_iHintNode = FindHintNode();

			if ( m_iHintNode != NO_NODE )
			{
				TaskComplete();
			}
			else
			{
				TaskFail();
			}
			break;
		}
	case TASK_STORE_LASTPOSITION:
		{
			m_vecLastPosition = pev->origin;
			TaskComplete();
			break;
		}
	case TASK_CLEAR_LASTPOSITION:
		{
			m_vecLastPosition = g_vecZero;
			TaskComplete();
			break;
		}
	case TASK_CLEAR_HINTNODE:
		{
			m_iHintNode = NO_NODE;
			TaskComplete();
			break;
		}
	case TASK_STOP_MOVING:
		{
			if ( m_IdealActivity == m_movementActivity )
			{
				m_IdealActivity = GetStoppedActivity();
			}

			RouteClear();
			TaskComplete();
			break;
		}
	case TASK_PLAY_SEQUENCE_FACE_ENEMY:
	case TASK_PLAY_SEQUENCE_FACE_TARGET:
	case TASK_PLAY_SEQUENCE:
		{
			m_IdealActivity = ( Activity )( int )pTask->flData;
			break;
		}
	case TASK_PLAY_ACTIVE_IDLE:
		{
			// monsters verify that they have a sequence for the node's activity BEFORE
			// moving towards the node, so it's ok to just set the activity without checking here.
			m_IdealActivity = ( Activity )WorldGraph.m_pNodes[ m_iHintNode ].m_sHintActivity;
			break;
		}
	case TASK_SET_SCHEDULE:
		{
			Schedule_t *pNewSchedule;

			pNewSchedule = GetScheduleOfType( (int)pTask->flData );
			
			if ( pNewSchedule )
			{
				ChangeSchedule( pNewSchedule );
			}
			else
			{
				TaskFail();
			}

			break;
		}
	case TASK_FIND_NEAR_NODE_COVER_FROM_ENEMY:
		{
			if ( m_hEnemy == NULL )
			{
				TaskFail();
				return;
			}

			if ( FindCover( m_hEnemy->pev->origin, m_hEnemy->pev->view_ofs, 0, pTask->flData ) )
			{
				// try for cover farther than the FLData from the schedule.
				TaskComplete();
			}
			else
			{
				// no coverwhatsoever.
				TaskFail();
			}
			break;
		}
	case TASK_FIND_FAR_NODE_COVER_FROM_ENEMY:
		{
			if ( m_hEnemy == NULL )
			{
				TaskFail();
				return;
			}

			if ( FindCover( m_hEnemy->pev->origin, m_hEnemy->pev->view_ofs, pTask->flData, CoverRadius() ) )
			{
				// try for cover farther than the FLData from the schedule.
				TaskComplete();
			}
			else
			{
				// no coverwhatsoever.
				TaskFail();
			}
			break;
		}
	case TASK_FIND_NODE_COVER_FROM_ENEMY:
		{
			if ( m_hEnemy == NULL )
			{
				TaskFail();
				return;
			}

			if ( FindCover( m_hEnemy->pev->origin, m_hEnemy->pev->view_ofs, 0, CoverRadius() ) )
			{
				// try for cover farther than the FLData from the schedule.
				TaskComplete();
			}
			else
			{
				// no coverwhatsoever.
				TaskFail();
			}
			break;
		}
	case TASK_FIND_COVER_FROM_ENEMY:
		{
			entvars_t *pevCover;

			if ( m_hEnemy == NULL )
			{
				// Find cover from self if no enemy available
				pevCover = pev;
//				TaskFail();
//				return;
			}
			else
				pevCover = m_hEnemy->pev;

			if ( FindLateralCover( pevCover->origin, pevCover->view_ofs ) )
			{
				// try lateral first
				m_flMoveWaitFinished = gpGlobals->time + pTask->flData;
				TaskComplete();
			}
			else if ( FindCover( pevCover->origin, pevCover->view_ofs, 0, CoverRadius() ) )
			{
				// then try for plain ole cover
				m_flMoveWaitFinished = gpGlobals->time + pTask->flData;
				TaskComplete();
			}
			else
			{
				// no coverwhatsoever.
				TaskFail();
			}
			break;
		}
	case TASK_FIND_COVER_FROM_ORIGIN:
		{
			if ( FindCover( pev->origin, pev->view_ofs, 0, CoverRadius() ) )
			{
				// then try for plain ole cover
				m_flMoveWaitFinished = gpGlobals->time + pTask->flData;
				TaskComplete();
			}
			else
			{
				// no cover!
				TaskFail();
			}
		}
		break;
	case TASK_FIND_COVER_FROM_BEST_SOUND:
		{
			CSound *pBestSound;

			pBestSound = PBestSound();

			ASSERT( pBestSound != NULL );
			/*
			if ( pBestSound && FindLateralCover( pBestSound->m_vecOrigin, g_vecZero ) )
			{
				// try lateral first
				m_flMoveWaitFinished = gpGlobals->time + pTask->flData;
				TaskComplete();
			}
			*/

			if ( pBestSound && FindCover( pBestSound->m_vecOrigin, g_vecZero, pBestSound->m_iVolume, CoverRadius() ) )
			{
				// then try for plain ole cover
				m_flMoveWaitFinished = gpGlobals->time + pTask->flData;
				TaskComplete();
			}
			else
			{
				// no coverwhatsoever. or no sound in list
				TaskFail();
			}
			break;
		}
	case TASK_FACE_HINTNODE:
		{
			pev->ideal_yaw = WorldGraph.m_pNodes[ m_iHintNode ].m_flHintYaw;
			SetTurnActivity();
			break;
		}
	
	case TASK_FACE_LASTPOSITION:
		MakeIdealYaw ( m_vecLastPosition );
		SetTurnActivity(); 
		break;

	case TASK_FACE_TARGET:
		if ( m_hTargetEnt != NULL )
		{
			MakeIdealYaw ( m_hTargetEnt->pev->origin );
			SetTurnActivity(); 
		}
		else
			TaskFail();
		break;
	case TASK_FACE_ENEMY:
		{
			MakeIdealYaw ( m_vecEnemyLKP );
			SetTurnActivity(); 
			break;
		}
	case TASK_FACE_IDEAL:
		{
			SetTurnActivity();
			break;
		}
	case TASK_FACE_ROUTE:
		{
			if (FRouteClear())
			{
				ALERT(at_aiconsole, "No route to face!\n");
				TaskFail();
			}
			else
			{
				MakeIdealYaw(m_Route[m_iRouteIndex].vecLocation);
				SetTurnActivity();
			}
			break;
		}
	case TASK_WAIT_PVS:
	case TASK_WAIT_INDEFINITE:
		{
			// don't do anything.
			break;
		}
	case TASK_WAIT:
	case TASK_WAIT_FACE_ENEMY:
		{// set a future time that tells us when the wait is over.
			m_flWaitFinished = gpGlobals->time + pTask->flData;	
			break;
		}
	case TASK_WAIT_RANDOM:
		{// set a future time that tells us when the wait is over.
			m_flWaitFinished = gpGlobals->time + RANDOM_FLOAT( 0.1, pTask->flData );
			break;
		}
	case TASK_MOVE_TO_TARGET_RANGE:
		{
			if ( (m_hTargetEnt->pev->origin - pev->origin).Length() < 1 )
				TaskComplete();
			else
			{
				m_vecMoveGoal = m_hTargetEnt->pev->origin;
				if ( !MoveToTarget( ACT_WALK, 2 ) )
					TaskFail();
			}
			break;
		}
	case TASK_RUN_TO_SCRIPT:
	case TASK_WALK_TO_SCRIPT:
		{
			Activity newActivity;

			if ( !m_pGoalEnt || (m_pGoalEnt->pev->origin - pev->origin).Length() < 1 )
				TaskComplete();
			else
			{
				if ( pTask->iTask == TASK_WALK_TO_SCRIPT )
					newActivity = ACT_WALK;
				else
					newActivity = ACT_RUN;
				// This monster can't do this!
				if ( LookupActivity( newActivity ) == ACTIVITY_NOT_AVAILABLE )
					TaskComplete();
				else 
				{
					if ( m_pGoalEnt != NULL )
					{
						Vector vecDest;
						vecDest = m_pGoalEnt->pev->origin;

						if ( !MoveToLocation( newActivity, 2, vecDest ) )
						{
							TaskFail();
							ALERT( at_aiconsole, "%s Failed to reach script!!!\n", STRING(pev->classname) );
							RouteClear();
						}
					}
					else
					{
						TaskFail();
						ALERT( at_aiconsole, "%s: MoveTarget is missing!?!\n", STRING(pev->classname) );
						RouteClear();
					}
				}
			}
			TaskComplete();
			break;
		}
	case TASK_CLEAR_MOVE_WAIT:
		{
			m_flMoveWaitFinished = gpGlobals->time;
			TaskComplete();
			break;
		}
	case TASK_MELEE_ATTACK1_NOTURN:
	case TASK_MELEE_ATTACK1:
		{
			m_IdealActivity = ACT_MELEE_ATTACK1;
			break;
		}
	case TASK_MELEE_ATTACK2_NOTURN:
	case TASK_MELEE_ATTACK2:
		{
			m_IdealActivity = ACT_MELEE_ATTACK2;
			break;
		}
	case TASK_RANGE_ATTACK1_NOTURN:
	case TASK_RANGE_ATTACK1:
		{
			m_IdealActivity = ACT_RANGE_ATTACK1;
			break;
		}
	case TASK_RANGE_ATTACK2_NOTURN:
	case TASK_RANGE_ATTACK2:
		{
			m_IdealActivity = ACT_RANGE_ATTACK2;
			break;
		}
	case TASK_RELOAD_NOTURN:
	case TASK_RELOAD:
		{
			m_IdealActivity = ACT_RELOAD;
			break;
		}
	case TASK_SPECIAL_ATTACK1:
		{
			m_IdealActivity = ACT_SPECIAL_ATTACK1;
			break;
		}
	case TASK_SPECIAL_ATTACK2:
		{
			m_IdealActivity = ACT_SPECIAL_ATTACK2;
			break;
		}
	case TASK_SET_ACTIVITY:
		{
			m_IdealActivity = (Activity)(int)pTask->flData;
			TaskComplete();
			break;
		}
	case TASK_GET_PATH_TO_ENEMY_LKP:
		{
			if ( BuildRoute ( m_vecEnemyLKP, bits_MF_TO_LOCATION, NULL ) )
			{
				TaskComplete();
			}
			else if (BuildNearestRoute( m_vecEnemyLKP, pev->view_ofs, 0, (m_vecEnemyLKP - pev->origin).Length() ))
			{
				TaskComplete();
			}
			else
			{
				// no way to get there =(
				ALERT ( at_aiconsole, "GetPathToEnemyLKP failed!!\n" );
				TaskFail();
			}
			break;
		}
	case TASK_GET_PATH_TO_ENEMY:
		{
			CBaseEntity *pEnemy = m_hEnemy;

			if ( pEnemy == NULL )
			{
				TaskFail();
				return;
			}

			if ( BuildRoute ( pEnemy->pev->origin, bits_MF_TO_ENEMY, pEnemy ) )
			{
				TaskComplete();
			}
			else if (BuildNearestRoute( pEnemy->pev->origin, pEnemy->pev->view_ofs, 0, (pEnemy->pev->origin - pev->origin).Length() ))
			{
				TaskComplete();
			}
			else
			{
				// no way to get there =(
				ALERT ( at_aiconsole, "GetPathToEnemy failed!!\n" );
				TaskFail();
			}
			break;
		}
	case TASK_GET_PATH_TO_ENEMY_CORPSE:
		{
			UTIL_MakeVectors( pev->angles );
			if ( BuildRoute ( m_vecEnemyLKP - gpGlobals->v_forward * 64, bits_MF_TO_LOCATION, NULL ) )
			{
				TaskComplete();
			}
			else
			{
				ALERT ( at_aiconsole, "GetPathToEnemyCorpse failed!!\n" );
				TaskFail();
			}
		}
		break;
	case TASK_GET_PATH_TO_SPOT:
		{
			CBaseEntity *pPlayer = UTIL_FindEntityByClassname( NULL, "player" );
			if ( BuildRoute ( m_vecMoveGoal, bits_MF_TO_LOCATION, pPlayer ) )
			{
				TaskComplete();
			}
			else
			{
				// no way to get there =(
				ALERT ( at_aiconsole, "GetPathToSpot failed!!\n" );
				TaskFail();
			}
			break;
		}

	case TASK_GET_PATH_TO_TARGET:
		{
			RouteClear();
			if ( m_hTargetEnt != NULL && MoveToTarget( m_movementActivity, 1 ) )
			{
				TaskComplete();
			}
			else
			{
				// no way to get there =(
				ALERT ( at_aiconsole, "GetPathToSpot failed!!\n" );
				TaskFail();
			}
			break;
		}
	case TASK_GET_PATH_TO_SCRIPT:
		{
			RouteClear();
			if ( m_pCine != NULL && MoveToLocation( m_movementActivity, 1, m_pCine->pev->origin ) )
			{
				TaskComplete();
			}
			else
			{
				// no way to get there =(
				ALERT ( at_aiconsole, "GetPathToSpot failed!!\n" );
				TaskFail();
			}
			break;
		}
	case TASK_GET_PATH_TO_HINTNODE:// for active idles!
		{
			if ( MoveToLocation( m_movementActivity, 2, WorldGraph.m_pNodes[ m_iHintNode ].m_vecOrigin ) )
			{
				TaskComplete();
			}
			else
			{
				// no way to get there =(
				ALERT ( at_aiconsole, "GetPathToHintNode failed!!\n" );
				TaskFail();
			}
			break;
		}
	case TASK_GET_PATH_TO_LASTPOSITION:
		{
			m_vecMoveGoal = m_vecLastPosition;

			if ( MoveToLocation( m_movementActivity, 2, m_vecMoveGoal ) )
			{
				TaskComplete();
			}
			else
			{
				// no way to get there =(
				ALERT ( at_aiconsole, "GetPathToLastPosition failed!!\n" );
				TaskFail();
			}
			break;
		}
	case TASK_GET_PATH_TO_BESTSOUND:
		{
			CSound *pSound;

			pSound = PBestSound();

			if ( pSound && MoveToLocation( m_movementActivity, 2, pSound->m_vecOrigin ) )
			{
				TaskComplete();
			}
			else
			{
				// no way to get there =(
				ALERT ( at_aiconsole, "GetPathToBestSound failed!!\n" );
				TaskFail();
			}
			break;
		}
case TASK_GET_PATH_TO_BESTSCENT:
		{
			CSound *pScent;

			pScent = PBestScent();

			if ( pScent && MoveToLocation( m_movementActivity, 2, pScent->m_vecOrigin ) )
			{
				TaskComplete();
			}
			else
			{
				// no way to get there =(
				ALERT ( at_aiconsole, "GetPathToBestScent failed!!\n" );
				
				TaskFail();
			}
			break;
		}
	case TASK_RUN_PATH:
		{
			// UNDONE: This is in some default AI and some monsters can't run? -- walk instead?
			if ( LookupActivity( ACT_RUN ) != ACTIVITY_NOT_AVAILABLE )
			{
				m_movementActivity = ACT_RUN;
			}
			else
			{
				m_movementActivity = ACT_WALK;
			}
			TaskComplete();
			break;
		}
	case TASK_WALK_PATH:
		{
			if ( pev->movetype == MOVETYPE_FLY )
			{
				m_movementActivity = ACT_FLY;
			}
			if ( LookupActivity( ACT_WALK ) != ACTIVITY_NOT_AVAILABLE )
			{
				m_movementActivity = ACT_WALK;
			}
			else
			{
				m_movementActivity = ACT_RUN;
			}
			TaskComplete();
			break;
		}
	case TASK_STRAFE_PATH:
		{
			Vector2D	vec2DirToPoint; 
			Vector2D	vec2RightSide;

			// to start strafing, we have to first figure out if the target is on the left side or right side
			UTIL_MakeVectors ( pev->angles );

			vec2DirToPoint = ( m_Route[ 0 ].vecLocation - pev->origin ).Make2D().Normalize();
			vec2RightSide = gpGlobals->v_right.Make2D().Normalize();

			if ( DotProduct ( vec2DirToPoint, vec2RightSide ) > 0 )
			{
				// strafe right
				m_movementActivity = ACT_STRAFE_RIGHT;
			}
			else
			{
				// strafe left
				m_movementActivity = ACT_STRAFE_LEFT;
			}
			TaskComplete();
			break;
		}


	case TASK_WAIT_FOR_MOVEMENT:
		{
			if (FRouteClear())
			{
				TaskComplete();
			}
			break;
		}

	case TASK_EAT:
		{
			Eat( pTask->flData );
			TaskComplete();
			break;
		}
	case TASK_SMALL_FLINCH:
		{
			m_IdealActivity = GetSmallFlinchActivity();
			break;
		}
	case TASK_DIE:
		{
			RouteClear();	
			
			m_IdealActivity = GetDeathActivity();

			pev->deadflag = DEAD_DYING;
			break;
		}
	case TASK_SOUND_WAKE:
		{
			AlertSound();
			TaskComplete();
			break;
		}
	case TASK_SOUND_DIE:
		{
			DeathSound();
			TaskComplete();
			break;
		}
	case TASK_SOUND_IDLE:
		{
			IdleSound();
			TaskComplete();
			break;
		}
	case TASK_SOUND_PAIN:
		{
			PainSound();
			TaskComplete();
			break;
		}
	case TASK_SOUND_DEATH:
		{
			DeathSound();
			TaskComplete();
			break;
		}
	case TASK_SOUND_ANGRY:
		{
			// sounds are complete as soon as we get here, cause we've already played them.
			ALERT ( at_aiconsole, "SOUND\n" );			
			TaskComplete();
			break;
		}
	case TASK_WAIT_FOR_SCRIPT:
		{
			if ( m_pCine->m_iDelay <= 0 && gpGlobals->time >= m_pCine->m_startTime )
			{
				TaskComplete(); //LRC - start playing immediately
			}
			else if (!m_pCine->IsAction() && m_pCine->m_iszIdle)
			{
				m_pCine->StartSequence( (CBaseMonster *)this, m_pCine->m_iszIdle, FALSE );
				if (FStrEq( STRING(m_pCine->m_iszIdle), STRING(m_pCine->m_iszPlay)))
				{
					pev->framerate = 0;
				}
			}
			else
				m_IdealActivity = ACT_IDLE;

			break;
		}
	case TASK_PLAY_SCRIPT:
		{
			if (m_pCine->IsAction())
			{
				//ALERT(at_console,"PlayScript: setting idealactivity %d\n",m_pCine->m_fAction);
				switch(m_pCine->m_fAction)
				{
				case 0:
					m_IdealActivity = ACT_RANGE_ATTACK1; break;
				case 1:
					m_IdealActivity = ACT_RANGE_ATTACK2; break;
				case 2:
					m_IdealActivity = ACT_MELEE_ATTACK1; break;
				case 3:
					m_IdealActivity = ACT_MELEE_ATTACK2; break;
				case 4:
					m_IdealActivity = ACT_SPECIAL_ATTACK1; break;
				case 5:
					m_IdealActivity = ACT_SPECIAL_ATTACK2; break;
				case 6:
					m_IdealActivity = ACT_RELOAD; break;
				case 7:
					m_IdealActivity = ACT_HOP; break;
				}
				pev->framerate = 1.0; // shouldn't be needed, but just in case
				pev->movetype = MOVETYPE_FLY;
				ClearBits(pev->flags, FL_ONGROUND);
			}
			else
			{
				m_pCine->StartSequence( (CBaseMonster *)this, m_pCine->m_iszPlay, TRUE );
				if ( m_fSequenceFinished )
					ClearSchedule();
				pev->framerate = 1.0;
				//ALERT( at_aiconsole, "Script %s has begun for %s\n", STRING( m_pCine->m_iszPlay ), STRING(pev->classname) );
			}
			m_scriptState = SCRIPT_PLAYING;
			break;
		}
	case TASK_ENABLE_SCRIPT:
		{
			m_pCine->DelayStart( 0 );
			TaskComplete();
			break;
		}
//LRC
	case TASK_END_SCRIPT:
		{
			m_pCine->SequenceDone( this );
			TaskComplete();
			break;
		}
	case TASK_PLANT_ON_SCRIPT:
		{
			if ( m_pCine != NULL )
			{
				// Plant on script
				// LRC - if it's a teleport script, do the turn too
				if (m_pCine->m_fMoveTo == 4 || m_pCine->m_fMoveTo == 6)
				{
					if (m_pCine->m_fTurnType == 0) //LRC
						pev->angles.y = m_hTargetEnt->pev->angles.y;
					else if (m_pCine->m_fTurnType == 1)
						pev->angles.y = UTIL_VecToYaw(m_hTargetEnt->pev->origin - pev->origin);
					pev->ideal_yaw = pev->angles.y;
					pev->avelocity = Vector( 0, 0, 0 );
					pev->velocity = Vector( 0, 0, 0 );
					pev->effects |= EF_NOINTERP;
				}

				if (m_pCine->m_fMoveTo != 6)
					pev->origin = m_pGoalEnt->pev->origin;
			}

			TaskComplete();
			break;
		}
	case TASK_FACE_SCRIPT:
		{
			if ( m_pCine != NULL && m_pCine->m_fMoveTo != 0) // movetype "no move" makes us ignore turntype
			{
				switch (m_pCine->m_fTurnType)
				{
				case 0:
					pev->ideal_yaw = UTIL_AngleMod( m_pCine->pev->angles.y );
					break;
				case 1:
					// yes, this is inconsistent- turn to face uses the "target" and turn to angle uses the "cine".
					if (m_hTargetEnt)
						MakeIdealYaw ( m_hTargetEnt->pev->origin );
					else
						MakeIdealYaw ( m_pCine->pev->origin );
					break;
				// default: don't turn
				}
			}

			TaskComplete();
			m_IdealActivity = ACT_IDLE;
			RouteClear();
			break;
		}
	case TASK_SUGGEST_STATE:
		{
			m_IdealMonsterState = (MONSTERSTATE)(int)pTask->flData;
			TaskComplete();
			break;
		}

	case TASK_SET_FAIL_SCHEDULE:
		m_failSchedule = (int)pTask->flData;
		TaskComplete();
		break;

	case TASK_CLEAR_FAIL_SCHEDULE:
		m_failSchedule = SCHED_NONE;
		TaskComplete();
		break;

	default:
		{
			ALERT ( at_aiconsole, "No StartTask entry for %d\n", (SHARED_TASKS)pTask->iTask );
			break;
		}
	}
}
void CNihilanth :: DyingThink( void )
{
	pev->nextthink = gpGlobals->time + 0.1;
	DispatchAnimEvents( );
	StudioFrameAdvance( );

	if (pev->deadflag == DEAD_NO)
	{
		DeathSound( );
		pev->deadflag = DEAD_DYING;

		m_posDesired.z = m_flMaxZ;
	}

	if (pev->deadflag == DEAD_DYING)
	{
		Flight( );

		if (fabs( pev->origin.z - m_flMaxZ ) < 16)
		{
			pev->velocity = Vector( 0, 0, 0 );
			FireTargets( m_szDeadUse, this, this, USE_ON, 1.0 );
			pev->deadflag = DEAD_DEAD;
		}
	}

	if (m_fSequenceFinished)
	{
		pev->avelocity.y += RANDOM_FLOAT( -100, 100 );
		if (pev->avelocity.y < -100)
			pev->avelocity.y = -100;
		if (pev->avelocity.y > 100)
			pev->avelocity.y = 100;

		pev->sequence = LookupSequence( "die1" );
	}

	if (m_pBall)
	{
		if (m_pBall->pev->renderamt > 0)
		{
			m_pBall->pev->renderamt = max( 0, m_pBall->pev->renderamt - 2);
		}
		else
		{
			UTIL_Remove( m_pBall );
			m_pBall = NULL;
		}
	}

	Vector vecDir, vecSrc, vecAngles;

	UTIL_MakeAimVectors( pev->angles );
	int iAttachment = RANDOM_LONG( 1, 4 );

	do {
		vecDir = Vector( RANDOM_FLOAT( -1, 1 ), RANDOM_FLOAT( -1, 1 ), RANDOM_FLOAT( -1, 1 ));
	} while (DotProduct( vecDir, vecDir) > 1.0);

	switch( RANDOM_LONG( 1, 4 ))
	{
	case 1: // head
		vecDir.z = fabs( vecDir.z ) * 0.5;
		vecDir = vecDir + 2 * gpGlobals->v_up;
		break;
	case 2: // eyes
		if (DotProduct( vecDir, gpGlobals->v_forward ) < 0)
			vecDir = vecDir * -1;

		vecDir = vecDir + 2 * gpGlobals->v_forward;
		break;
	case 3: // left hand
		if (DotProduct( vecDir, gpGlobals->v_right ) > 0)
			vecDir = vecDir * -1;
		vecDir = vecDir - 2 * gpGlobals->v_right;
		break;
	case 4: // right hand
		if (DotProduct( vecDir, gpGlobals->v_right ) < 0)
			vecDir = vecDir * -1;
		vecDir = vecDir + 2 * gpGlobals->v_right;
		break;
	}

	GetAttachment( iAttachment - 1, vecSrc, vecAngles );

	TraceResult tr;

	UTIL_TraceLine( vecSrc, vecSrc + vecDir * 4096, ignore_monsters, ENT(pev), &tr );
	
	MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
		WRITE_BYTE( TE_BEAMENTPOINT );
		WRITE_SHORT( entindex() + 0x1000 * iAttachment );
		WRITE_COORD( tr.vecEndPos.x);
		WRITE_COORD( tr.vecEndPos.y);
		WRITE_COORD( tr.vecEndPos.z);
		WRITE_SHORT( g_sModelIndexLaser );
		WRITE_BYTE( 0 ); // frame start
		WRITE_BYTE( 10 ); // framerate
		WRITE_BYTE( 5 ); // life
		WRITE_BYTE( 100 );  // width
		WRITE_BYTE( 120 );   // noise
		WRITE_BYTE( 64 );   // r, g, b
		WRITE_BYTE( 128 );   // r, g, b
		WRITE_BYTE( 255);   // r, g, b
		WRITE_BYTE( 255 );	// brightness
		WRITE_BYTE( 10 );		// speed
	MESSAGE_END();

	GetAttachment( 0, vecSrc, vecAngles ); 
	CNihilanthHVR *pEntity = (CNihilanthHVR *)Create( "nihilanth_energy_ball", vecSrc, pev->angles, edict() );
	pEntity->pev->velocity = Vector ( RANDOM_FLOAT( -0.7, 0.7 ), RANDOM_FLOAT( -0.7, 0.7 ), 1.0 ) * 600.0;
	pEntity->GreenBallInit( );

	return;
}
Beispiel #5
0
void PlayerDie()
{
	self->ca_alive = false;

	DropPowerups();

	if ( isCTF() )
	{
		if ( self->hook_out )
		{
			GrappleReset( self->hook );
			self->attack_finished = g_globalvars.time + 0.75;
			self->hook_out = true; // FIXME: for which reason this set to true?
		}

		DropRune();
		PlayerDropFlag( self, false );
	}

	TeamplayDeathEvent (self);
#ifdef BOT_SUPPORT
	BotPlayerDeathEvent (self);
#endif

	self->s.v.items -= ( int ) self->s.v.items & IT_INVISIBILITY;
	self->invisible_finished = 0;	// don't die as eyes
	self->invincible_finished = 0;
// so we have quad few milleseconds after death
//	self->super_damage_finished = 0; // moved to prethink, like in ktpro
	self->radsuit_finished = 0;

	self->s.v.modelindex = modelindex_player;	// don't use eyes

	DropBackpack();

	self->weaponmodel = "";
	if (vw_enabled)
		self->vw_index = 9;	// null vwep model

	SetVector( self->s.v.view_ofs, 0, 0, -8 );
	self->s.v.deadflag = DEAD_DYING;
	self->s.v.solid = SOLID_NOT;
	self->s.v.flags -= ( ( int ) ( self->s.v.flags ) ) & FL_ONGROUND;
	self->s.v.movetype = MOVETYPE_TOSS;
	if ( self->s.v.velocity[2] < 10 )
		self->s.v.velocity[2] = self->s.v.velocity[2] + g_random() * 300;

    if ( self->s.v.health < -40 || dtSQUISH == self->deathtype || dtSUICIDE == self->deathtype || isRA() || isCA() )
	{
		GibPlayer();

		// Yawnmode: respawn has the same delay (900ms) regardless of deathtype gib/normal
		// - Molgrum

		// Hoonymode: Also force some time, e.g. to prevent instant respawn after /kill which
		// can cause bug if kill telefrags an idle player (counts as two points...)
		// only ever happens in testing, but oh well --phil
		if ( k_yawnmode || isHoonyModeDuel() )
		{
			self->s.v.nextthink = g_globalvars.time + 0.9;
			self->think = ( func_t ) PlayerDead;
			return;
		}

		PlayerDead();
		return;
	}

    if( match_in_progress == 2 )
		DeathSound();

	self->s.v.angles[0] = 0;
	self->s.v.angles[2] = 0;


    // function part split and called here
	StartDie();
}
Beispiel #6
0
//=========================================================================
// Function handling the Spy's feign death ability
void TeamFortress_SpyFeignDeath( int issilent )
{
	int     i, j;
	gedict_t *at_spot;
	gedict_t *te;

	self->StatusRefreshTime = g_globalvars.time + 0.1;
	if ( self->is_feigning )
	{
	        // Check to make sure there isn't anyone on top of us
		at_spot = findradius( world, self->s.v.origin, 64 );
		i = 1;
		j = 0;
		while ( at_spot )
		{
			if ( streq( at_spot->mdl, "progs/detpack.mdl" ) )
				j = 1;
			if ( streq( at_spot->mdl, "progs/detpack2.mdl" ) && tf_data.birthday == 1 )
				j = 1;
			if ( streq( at_spot->mdl, "progs/turrbase.mdl" ) )
				j = 1;
			if ( streq( at_spot->mdl, "progs/turrgun.mdl" ) )
				j = 1;
		//	if ( streq( at_spot->mdl, "progs/disp.mdl" ) )
		//		j = 1;
			if ( streq( at_spot->mdl, "progs/dispencr.mdl" ) )
				j = 1;
			if ( streq( at_spot->s.v.classname, "player" ) && !at_spot->s.v.deadflag && self != at_spot )
				j = 2;
			switch ( j )
			{
			case 1:
				G_sprint( self, 2, "You can't get up with something\non top of you.\n" );
				return;
			case 2:
				G_sprint( self, 2, "You can't get up while someone\nis standing on you.\n" );
				return;
			}
			at_spot = findradius( at_spot, self->s.v.origin, 64 );
		}
		if ( self->is_squating == TRUE )
			unlay ( );
		SetVector( self->s.v.velocity, 0, 0, 0 );
		setsize( self, -16, -16, -24, 16, 16, 32 );
		SetVector( self->s.v.view_ofs, 0, 0, 22 );
		self->s.v.movetype = MOVETYPE_WALK;
		self->is_feigning = 0;
		self->current_weapon = self->s.v.weapon;
		W_SetCurrentAmmo(  );
		self->tfstate = self->tfstate - ( self->tfstate & TFSTATE_CANT_MOVE );
		TeamFortress_SetSpeed( self );
		// Check .weapon, because .current_weapon has been reset
		if ( self->s.v.weapon <= 16 )
		{
			spy_upaxe1(  );
			return;
		}
		switch ( ( int ) ( g_random(  ) * 4 ) )
		{
		case 0:
			spy_upb1(  );
			break;
		case 1:
			spy_upc1(  );
			break;
		case 2:
			spy_upd1(  );
			break;
		default:
			spy_upe1(  );
			break;
		}
		return;
	} else  // !self->is_feigning
	{
		
		if ( self->hook_out )
		{
			G_sprint( self, 2, "You can't feign with the hook out.\n" );
			return;
		}
//REMOVE!!!		
/*          if (self.is_unabletospy == 1) {
           G_sprint(self, 2, "You can't go undercover right now.\n");
           return;
          }*/

/*  if (!(self.flags & 512) && !self->s.v.waterlevel) {
   G_sprint(self, 2, "You can't feign in the air.\n");
   return;
  }*/
		
		for ( at_spot = world; ( at_spot = findradius( at_spot, self->s.v.origin, 64 ) ) ; )
		{
			if ( streq( at_spot->s.v.classname, "player" ) && self != at_spot && at_spot->is_feigning == 1 )
			{
				G_sprint( self, 2, "You can't feign on top of another spy!\n" );
				return;
			}
		}
		self->tfstate = self->tfstate | TFSTATE_CANT_MOVE;
		TeamFortress_SetSpeed( self );
		self->is_feigning = 1;
		Attack_Finished( 0.8 );
		self->invisible_finished = 0;
		self->s.v.modelindex = modelindex_player;
		self->s.v.weapon = self->current_weapon;
		self->current_weapon = 0;
		self->s.v.weaponmodel = "";
		self->s.v.weaponframe = 0;
		setsize( self, -16, -16, -24, 16, 16, -16 );
		SetVector( self->s.v.view_ofs, 0, 0, 4 );
		self->s.v.movetype = MOVETYPE_TOSS;
		if ( !issilent )
			DeathSound(  );
		self->s.v.angles[0] = 0;
		self->s.v.angles[2] = 0;
		if ( self->s.v.weapon <= 16 )
		{
			spy_die_ax1(  );
			return;
		}
		te = world;
		for( te = world; ( te = trap_find( te, FOFS( s.v.classname ), "item_tfgoal" ) ) ;)
		{
			if ( te->s.v.owner != EDICT_TO_PROG( self ) )
				continue;

			if ( !( te->goal_activation & TFGI_KEEP ) || self->has_disconnected == 1 )
				tfgoalitem_RemoveFromPlayer( te, self, 0 );
			if ( CTF_Map == 1 )
			{
				if ( te->goal_no == 1 )
					G_bprint( 2, "%s лост the блуе flag!\n", self->s.v.netname );
				else
					G_bprint( 2, "%s лост the ред flag!\n", self->s.v.netname );
			}
		}
		switch ( ( int ) ( g_random(  ) * 5 ) )
		{
		case 0:
			spy_diea1(  );
			break;
		case 1:
			spy_dieb1(  );
			break;
		case 2:
			spy_diec1(  );
			break;
		case 3:
			spy_died1(  );
			break;
		default:
			spy_diee1(  );
			break;
		}
	}
}