Пример #1
0
AIMoveResult_t CAI_Motor::MoveClimbExecute( const Vector &climbDest, float yaw)
{
	const float climbSpeed = 100.0;

	Vector moveDir = climbDest - GetLocalOrigin();
	float flDist = VectorNormalize( moveDir );
	SetSmoothedVelocity( moveDir * climbSpeed );

	if ( flDist < climbSpeed * GetMoveInterval() )
	{
		if (flDist <= 1e-2)
			flDist = 0;

		const float climbTime = flDist / climbSpeed;
		
		SetMoveInterval( GetMoveInterval() - climbTime );
		SetLocalOrigin( climbDest );

		return AIMR_CHANGE_TYPE;
	}
	else
	{
		SetMoveInterval( 0 );
	}

	// --------------------------------------------
	// Turn to face the climb
	// --------------------------------------------
	SetIdealYawAndUpdate( yaw );

	return AIMR_OK;
}
Пример #2
0
AIMotorMoveResult_t CAI_Motor::MoveGroundExecute( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult )
{
	// --------------------------------------------
	// turn in the direction of movement
	// --------------------------------------------
	MoveFacing( move );

	// --------------------------------------------
	float flNewSpeed = GetIdealSpeed();

	// --------------------------------------------
	// calculate actual travel distance
	// --------------------------------------------

	// assuming linear acceleration, how far will I travel?
	float flTotal = 0.5 * (GetCurSpeed() + flNewSpeed) * GetMoveInterval();

	// can I move farther in this interval than I'm supposed to?
	if ( flTotal > move.maxDist )
	{
		if ( !(move.flags & AILMG_CONSUME_INTERVAL) )
		{
			// only use a portion of the time interval
			SetMoveInterval( GetMoveInterval() * (1 - move.maxDist / flTotal) );
		}
		else
			SetMoveInterval( 0 );
		flTotal = move.maxDist;
	}
	else
	{
		// use all the time
		SetMoveInterval( 0 );
	}

	SetMoveVel( move.dir * flNewSpeed );

	// --------------------------------------------
	// walk the distance
	// --------------------------------------------
	AIMotorMoveResult_t result = AIM_SUCCESS;
	if ( flTotal > 0.0 )
	{
		Vector vecFrom = GetLocalOrigin();
		Vector vecTo = vecFrom + move.dir * flTotal;
		
		result = MoveGroundStep( vecTo, move.pMoveTarget, -1, true, pTraceResult );

		if ( result == AIM_FAILED )
			MoveStop();
	}
	else if ( !OnMoveStalled( move ) )
	{
		result = AIM_FAILED;
	}


	return result;
}
Пример #3
0
AIMotorMoveResult_t CAI_Motor::MoveFlyExecute( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult )
{
	// turn in the direction of movement
	MoveFacing( move );

	// calc accel/decel rates
	float flNewSpeed = GetIdealSpeed();
	SetMoveVel( move.dir * flNewSpeed );

	float flTotal = 0.5 * (GetCurSpeed() + flNewSpeed) * GetMoveInterval();

	float distance = move.maxDist;

	// can I move farther in this interval than I'm supposed to?
	if (flTotal > distance)
	{
		// only use a portion of the time interval
		SetMoveInterval( GetMoveInterval() * (1 - distance / flTotal) );
		flTotal = distance;
	}
	else
	{
		// use all the time
		SetMoveInterval( 0 );
	}

	Vector vecStart, vecEnd;
	vecStart = GetLocalOrigin();
	VectorMA( vecStart, flTotal, move.dir, vecEnd );

	AIMoveTrace_t moveTrace;
	GetMoveProbe()->MoveLimit( NAV_FLY, vecStart, vecEnd, MASK_NPCSOLID, NULL, &moveTrace );
	if ( pTraceResult )
		*pTraceResult = moveTrace;
	
	// Check for total blockage
	if (fabs(moveTrace.flDistObstructed - flTotal) <= 1e-1)
	{
		// But if we bumped into our target, then we succeeded!
		if ( move.pMoveTarget && (moveTrace.pObstruction == move.pMoveTarget) )
			return AIM_PARTIAL_HIT_TARGET;

		return AIM_FAILED;
	}

	// The true argument here causes it to touch all triggers
	// in the volume swept from the previous position to the current position
	UTIL_SetOrigin(GetOuter(), moveTrace.vEndPosition, true);

	return (IsMoveBlocked(moveTrace.fStatus)) ? AIM_PARTIAL_HIT_WORLD : AIM_SUCCESS;
}
Пример #4
0
AIMotorMoveResult_t CAI_Motor::MoveGroundExecuteWalk( const AILocalMoveGoal_t &move, float speed, float dist, AIMoveTrace_t *pTraceResult )
{
	bool bReachingLocalGoal = ( dist > move.maxDist );

	// can I move farther in this interval than I'm supposed to?
	if ( bReachingLocalGoal )
	{
		if ( !(move.flags & AILMG_CONSUME_INTERVAL) )
		{
			// only use a portion of the time interval
			SetMoveInterval( GetMoveInterval() * (1 - move.maxDist / dist) );
		}
		else
			SetMoveInterval( 0 );
		dist = move.maxDist;
	}
	else
	{
		// use all the time
		SetMoveInterval( 0 );
	}

	SetMoveVel( move.dir * speed );

	// --------------------------------------------
	// walk the distance
	// --------------------------------------------
	AIMotorMoveResult_t result = AIM_SUCCESS;
	if ( dist > 0.0 )
	{
		Vector vecFrom = GetLocalOrigin();
		Vector vecTo = vecFrom + move.dir * dist;

		if ( move.navType == NAV_CRAWL )
		{
			char *pchHackBoolToInt = (char*)(&bReachingLocalGoal);
			*pchHackBoolToInt = 2;
		}
		
		result = MoveGroundStep( vecTo, move.pMoveTarget, -1, true, bReachingLocalGoal, pTraceResult );

		if ( result == AIM_FAILED )
			MoveStop();
	}
	else if ( !OnMoveStalled( move ) )
	{
		result = AIM_FAILED;
	}

	return result;
}
Пример #5
0
AIMoveResult_t CAI_Motor::MoveJumpStop()
{
	SetSmoothedVelocity( Vector(0,0,0) );

	if (GetOuter()->GetActivity() == ACT_GLIDE)
	{
		float flTime = GetOuter()->GetGroundChangeTime();
		GetOuter()->AddStepDiscontinuity( flTime, GetAbsOrigin(), GetAbsAngles() );

		if ( SelectWeightedSequence( ACT_LAND ) == ACT_INVALID )
			return AIMR_CHANGE_TYPE;

		SetActivity( ACT_LAND );
		// FIXME: find out why the client doesn't interpolate immediatly after sequence change
		// GetOuter()->SetCycle( flTime - gpGlobals->curtime );
	}
	if (GetOuter()->GetActivity() != ACT_LAND || GetOuter()->IsActivityFinished())
	{
		return AIMR_CHANGE_TYPE;
	}

	SetMoveInterval( 0 );

	SetGravity( 1.0f );

	return AIMR_OK;
}
Пример #6
0
int CAI_Motor::MoveJumpExecute( )
{
	// needs to detect being hit
	SetIdealYawAndUpdate( GetSmoothedVelocity() );

	SetActivity( ACT_GLIDE );

	// use all the time
	SetMoveInterval( 0 );

	return AIMR_OK;
}
Пример #7
0
int CAI_Motor::MoveJumpExecute( )
{
	// needs to detect being hit
	UpdateYaw( );

	if (GetOuter()->GetActivity() == ACT_JUMP && GetOuter()->IsActivityFinished())
	{
		SetActivity( ACT_GLIDE );
	}

	// use all the time
	SetMoveInterval( 0 );

	return AIMR_OK;
}
Пример #8
0
AIMoveResult_t CAI_Motor::MoveNormalExecute( const AILocalMoveGoal_t &move )
{
	AI_PROFILE_SCOPE(CAI_Motor_MoveNormalExecute);
	
	// --------------------------------

	AIMotorMoveResult_t fMotorResult;
	AIMoveTrace_t 		moveTrace;
	
	if ( move.navType == NAV_GROUND )
	{
		fMotorResult = MoveGroundExecute( move, &moveTrace );
	}
	else
	{
		Assert( move.navType == NAV_FLY );
		fMotorResult = MoveFlyExecute( move, &moveTrace );
	}

	static AIMoveResult_t moveResults[] = 
	{
		AIMR_ILLEGAL,	                         // AIM_FAILED
		AIMR_OK,                                 // AIM_SUCCESS
		AIMR_BLOCKED_NPC,						 // AIM_PARTIAL_HIT_NPC
		AIMR_BLOCKED_WORLD,                      // AIM_PARTIAL_HIT_WORLD
		AIMR_BLOCKED_WORLD,                      // AIM_PARTIAL_HIT_TARGET
	};
	Assert( ARRAYSIZE( moveResults ) == AIM_NUM_RESULTS && fMotorResult >= 0 && fMotorResult <= ARRAYSIZE( moveResults ) );
	
	AIMoveResult_t result = moveResults[fMotorResult];
	
	if ( result != AIMR_OK )
	{
		OnMoveExecuteFailed( move, moveTrace, fMotorResult, &result );
		SetMoveInterval( 0 ); // always consume interval on failure, even if overridden by OnMoveExecuteFailed()
	}
	
	return DbgResult( result );
}
Пример #9
0
AIMoveResult_t CAI_Motor::MoveClimbExecute( const Vector &climbDest, const Vector &climbDir, float climbDist, float yaw, int climbNodesLeft )
{
	if ( fabsf( climbDir.z ) > .1 )
	{
		if ( GetActivity() != ACT_CLIMB_DISMOUNT )
		{
			Activity desiredActivity = (climbDir.z > -0.01 ) ? ACT_CLIMB_UP : ACT_CLIMB_DOWN;
			if ( GetActivity() != desiredActivity )
			{
				SetActivity( desiredActivity );
			}
		}

		if ( GetActivity() != ACT_CLIMB_UP && GetActivity() != ACT_CLIMB_DOWN && GetActivity() != ACT_CLIMB_DISMOUNT )
		{
			DevMsg( "Climber not in a climb activity!\n" );
			return AIMR_ILLEGAL;
		}

		if (m_nDismountSequence != ACT_INVALID)
		{
			if (GetActivity() == ACT_CLIMB_UP )
			{
				if (climbNodesLeft <= 2 && climbDist < fabs( m_vecDismount.z ))
				{
					// fixme: No other way to force m_nIdealSequence?
					GetOuter()->SetActivity( ACT_CLIMB_DISMOUNT );
					GetOuter()->SetCycle( GetOuter()->GetMovementFrame( m_vecDismount.z - climbDist ) );
				}
			}
		}
	}

	float climbSpeed = GetOuter()->GetInstantaneousVelocity();

	if (m_nDismountSequence != ACT_INVALID)
	{
		// catch situations where the climb mount/dismount finished before reaching goal
		climbSpeed = MAX( climbSpeed, 30.0 );
	}
	else
	{
		// FIXME: assume if they don't have a dismount animation then they probably don't really support climbing.
		climbSpeed = 100.0;
	}

	SetSmoothedVelocity( climbDir * climbSpeed );

	if ( climbDist < climbSpeed * GetMoveInterval() )
	{
		if (climbDist <= 1e-2)
			climbDist = 0;

		const float climbTime = climbDist / climbSpeed;
		
		SetMoveInterval( GetMoveInterval() - climbTime );
		SetLocalOrigin( climbDest );

		return AIMR_CHANGE_TYPE;
	}
	else
	{
		SetMoveInterval( 0 );
	}

	// --------------------------------------------
	// Turn to face the climb
	// --------------------------------------------
	SetIdealYawAndUpdate( yaw );

	return AIMR_OK;
}
AIMotorMoveResult_t CAI_BlendedMotor::MoveFlyExecute( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult )
{
	if ( move.curExpectedDist < 0.001 )
		return BaseClass::MoveFlyExecute( move, pTraceResult );

	BuildMoveScript( move, pTraceResult );

	float flNewSpeed = GetCurSpeed();
	float flTotalDist = GetMoveScriptDist( flNewSpeed );

	Assert( move.maxDist < 0.01 || flTotalDist > 0.0 );

	// --------------------------------------------
	// turn in the direction of movement
	// --------------------------------------------
	
	float flNewYaw = GetMoveScriptYaw( );

	// get facing based on movement yaw
	AILocalMoveGoal_t move2 = move;
	move2.facing = UTIL_YawToVector( flNewYaw );

	// turn in the direction needed
	MoveFacing( move2 );

	GetOuter()->m_flGroundSpeed = GetSequenceGroundSpeed( GetSequence());

	SetMoveScriptAnim( flNewSpeed );

	// DevMsg( "%6.2f : Speed %.1f : %.1f\n", gpGlobals->curtime, flNewSpeed, GetIdealSpeed() );

	// reset actual "sequence" ground speed based current movement sequence, orientation

	// FIXME: the above is redundant with MoveGroundExecute, and the below is a mix of MoveGroundExecuteWalk and MoveFlyExecute

	bool bReachingLocalGoal = ( flTotalDist > move.maxDist );

	// can I move farther in this interval than I'm supposed to?
	if ( bReachingLocalGoal )
	{
		if ( !(move.flags & AILMG_CONSUME_INTERVAL) )
		{
			// only use a portion of the time interval
			SetMoveInterval( GetMoveInterval() * (1 - move.maxDist / flTotalDist) );
		}
		else
			SetMoveInterval( 0 );
		flTotalDist = move.maxDist;
	}
	else
	{
		// use all the time
		SetMoveInterval( 0 );
	}

	SetMoveVel( move.dir * flNewSpeed );

	// orig
	Vector vecStart, vecEnd;
	vecStart = GetLocalOrigin();
	VectorMA( vecStart, flTotalDist, move.dir, vecEnd );

	AIMoveTrace_t moveTrace;
	GetMoveProbe()->MoveLimit( NAV_FLY, vecStart, vecEnd, MASK_NPCSOLID, NULL, &moveTrace );
	if ( pTraceResult )
		*pTraceResult = moveTrace;
	
	// Check for total blockage
	if (fabs(moveTrace.flDistObstructed - flTotalDist) <= 1e-1)
	{
		// But if we bumped into our target, then we succeeded!
		if ( move.pMoveTarget && (moveTrace.pObstruction == move.pMoveTarget) )
			return AIM_PARTIAL_HIT_TARGET;

		return AIM_FAILED;
	}

	// The true argument here causes it to touch all triggers
	// in the volume swept from the previous position to the current position
	UTIL_SetOrigin(GetOuter(), moveTrace.vEndPosition, true);

	return (IsMoveBlocked(moveTrace.fStatus)) ? AIM_PARTIAL_HIT_WORLD : AIM_SUCCESS;
}