aboutsummaryrefslogtreecommitdiff
path: root/sp/src/game/server/ai_behavior_passenger.h
blob: 61e0d7302725f5d8195606083e7860595e868b4d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
//=============================================================================

#ifndef AI_BEHAVIOR_PASSENGER_H
#define AI_BEHAVIOR_PASSENGER_H
#ifdef _WIN32
#pragma once
#endif

#include "ai_speech.h"
#include "ai_behavior.h"
#include "ai_utils.h"
#include "vehicle_jeep_episodic.h"

#define STOPPED_VELOCITY_THRESHOLD		32.0f
#define	STOPPED_VELOCITY_THRESHOLD_SQR	(STOPPED_VELOCITY_THRESHOLD*STOPPED_VELOCITY_THRESHOLD)

#define STARTED_VELOCITY_THRESHOLD		64.0f
#define	STARTED_VELOCITY_THRESHOLD_SQR	(STARTED_VELOCITY_THRESHOLD*STARTED_VELOCITY_THRESHOLD)

// Custom activities
extern int ACT_PASSENGER_IDLE;
extern int ACT_PASSENGER_RANGE_ATTACK1;

// ---------------------------------------------
//  Vehicle state
// ---------------------------------------------
struct passengerVehicleState_t
{
	Vector	m_vecLastLocalVelocity;
	Vector	m_vecDeltaVelocity;
	QAngle	m_vecLastAngles;
	float	m_flNextWarningTime;
	float	m_flLastSpeedSqr;
	bool	m_bPlayerInVehicle;
	bool	m_bWasBoosting;
	bool	m_bWasOverturned;

	DECLARE_SIMPLE_DATADESC();
};

// ---------------------------------------------
//  Passenger intent
// ---------------------------------------------
enum passesngerVehicleIntent_e
{
	PASSENGER_INTENT_NONE,
	PASSENGER_INTENT_ENTER,		// We want to be in the vehicle
	PASSENGER_INTENT_EXIT,		// We want to be outside the vehicle
};

// ---------------------------------------------
//  Passenger state functions
// ---------------------------------------------
enum PassengerState_e
{
	PASSENGER_STATE_OUTSIDE = 0,	// Not in the vehicle
	PASSENGER_STATE_ENTERING,
	PASSENGER_STATE_INSIDE,
	PASSENGER_STATE_EXITING,
};

class CAI_PassengerBehavior : public CAI_SimpleBehavior
{
	DECLARE_CLASS( CAI_PassengerBehavior, CAI_SimpleBehavior );
	DECLARE_DATADESC()

public:

	CAI_PassengerBehavior( void );

	enum
	{
		// Schedules
		SCHED_PASSENGER_IDLE = BaseClass::NEXT_SCHEDULE,
		SCHED_PASSENGER_ENTER_VEHICLE,
		SCHED_PASSENGER_EXIT_VEHICLE,
		SCHED_PASSENGER_RUN_TO_ENTER_VEHICLE,
		SCHED_PASSENGER_ENTER_VEHICLE_PAUSE,
		SCHED_PASSENGER_RUN_TO_ENTER_VEHICLE_FAILED,
		SCHED_PASSENGER_PLAY_SCRIPTED_ANIM,
		NEXT_SCHEDULE,

		// Tasks
		TASK_PASSENGER_ENTER_VEHICLE = BaseClass::NEXT_TASK,
		TASK_PASSENGER_EXIT_VEHICLE,
		TASK_PASSENGER_ATTACH_TO_VEHICLE,
		TASK_PASSENGER_DETACH_FROM_VEHICLE,
		TASK_PASSENGER_SET_IDEAL_ENTRY_YAW,
		NEXT_TASK,

		// Conditions
		COND_PASSENGER_HARD_IMPACT = BaseClass::NEXT_CONDITION,
		COND_PASSENGER_ENTERING,
		COND_PASSENGER_EXITING,
		COND_PASSENGER_VEHICLE_STARTED,
		COND_PASSENGER_VEHICLE_STOPPED,
		COND_PASSENGER_OVERTURNED,
		COND_PASSENGER_CANCEL_ENTER,
		COND_PASSENGER_ERRATIC_DRIVING,
		COND_PASSENGER_PLAYER_ENTERED_VEHICLE,
		COND_PASSENGER_PLAYER_EXITED_VEHICLE,
		COND_PASSENGER_JOSTLE_SMALL,

		NEXT_CONDITION
	};

			bool	ForceVehicleInteraction( const char *lpszInteractionName, CBaseCombatCharacter *pOther );

	virtual bool	CanSelectSchedule( void );
	virtual int		SelectSchedule( void );
	virtual int		SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode );
	virtual void	RunTask( const Task_t *pTask );
	virtual void	StartTask( const Task_t *pTask );
	virtual	void	BuildScheduleTestBits( void );
	virtual int		TranslateSchedule( int scheduleType );
	virtual void	GetEntryTarget( Vector *vecOrigin, QAngle *vecAngles );
	virtual void	GatherConditions( void );
	virtual void	ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet );
	virtual void	Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
	virtual void	ClearSchedule( const char *szReason );
	virtual bool	IsInterruptable( void );
	virtual void	PrescheduleThink( void );
	virtual void	CancelEnterVehicle( void );

	virtual const char *GetName( void ) { return "Passenger"; }
	virtual string_t GetRoleName( void ) { return MAKE_STRING( "passenger" ); }

	// Enable/disable code
	void	Enable( CPropJeepEpisodic *pVehicle, bool bImmediateEntrance = false );
	void	Disable( void );
	bool	IsEnabled( void ) const { return m_bEnabled; }

	virtual void	EnterVehicle( void );
	virtual void	ExitVehicle( void );

	void	AddPhysicsPush( float force );

	CPropVehicleDriveable *GetTargetVehicle( void ) const { return m_hVehicle; }

	PassengerState_e	GetPassengerState( void ) const { return m_PassengerState; }
	
	virtual void OnRestore();

protected:
	
	virtual int		SelectTransitionSchedule( void );

	bool			SpeakIfAllowed( AIConcept_t concept, const char *modifiers = NULL, bool bRespondingToPlayer = false, char *pszOutResponseChosen = NULL, size_t bufsize = 0 );

	bool			CanExitVehicle( void );
	void			SetTransitionSequence( int nSequence );
	void			AttachToVehicle( void );

	virtual void	OnExitVehicleFailed( void ) { }	// NPC attempted to leave vehicle, but was unable to
	virtual void	GatherVehicleStateConditions( void );

	// ------------------------------------------
	//  Entry/exit transition code
	// ------------------------------------------
	
	virtual void	FinishEnterVehicle( void );
	virtual void	FinishExitVehicle( void );

	void	DetachFromVehicle( void );
	void	DrawDebugTransitionInfo( const Vector &vecIdealPos, const QAngle &vecIdealAngles, const Vector &vecAnimPos, const QAngle &vecAnimAngles );
	bool	GetEntryPoint( int nSequence, Vector *vecEntryPoint, QAngle *vecEntryAngles = NULL );
	bool	GetExitPoint( int nSequence, Vector *vecExitPoint, QAngle *vecExitAngles = NULL );
	bool	PointIsNavigable( const Vector &vecTargetPos );
	bool	ReserveEntryPoint( VehicleSeatQuery_e eSeatSearchType );
	bool	ReserveExitPoint( void );
	bool	FindGroundAtPosition( const Vector &in, float flUpDelta, float flDownDelta, Vector *out );
	bool	DoTransitionMovement( void );
	bool	GetSequenceBlendAmount( float flCycle, float *posBlend, float *angBlend );
	bool	LocalIntervalMovement( float flInterval, bool &bMoveSeqFinished, Vector &newPosition, QAngle &newAngles );
	void	GetTransitionAnimationIdeal( float flCycle, const Vector &vecTargetPos, const QAngle &vecTargetAngles, Vector *idealOrigin, QAngle *idealAngles );
	float	GetNextCycleForInterval( int nSequence, float flInterval );
	void	GetLocalVehicleVelocity( Vector *pOut  );
	void	CacheBlendTargets( void );

	void	InitVehicleState( void );
	int		FindEntrySequence( bool bNearest = false );
	int		FindExitSequence( void );
	bool	IsValidTransitionPoint( const Vector &vecStartPos, const Vector &vecEndPos );

	void	SetPassengerState( PassengerState_e state ) { m_PassengerState = state; }

	PassengerState_e	m_PassengerState;	// State we're in, for the vehicle

	// ---------------------------------------------

	bool	IsPassengerHostile( void );

	passengerVehicleState_t			m_vehicleState;			// Internal vehicle state

	CHandle	<CPropVehicleDriveable>	m_hVehicle;				// The vehicle we're bound to
	CHandle <CEntityBlocker>		m_hBlocker;				// Blocking entity for space reservation
	Vector							m_vecTargetPosition;	// Target destination for exiting the vehicle
	QAngle							m_vecTargetAngles;		// Target angles for exiting the vehicle
	bool							m_bEnabled;				// If the behavior is running
	passesngerVehicleIntent_e		m_PassengerIntent;		// Gives us information about whether we're meant to get in/out, etc.

	int								m_nTransitionSequence;		// Animation we're using to transition with
	float							m_flOriginStartFrame;
	float							m_flOriginEndFrame;
	float							m_flAnglesStartFrame;
	float							m_flAnglesEndFrame;

protected:
	DEFINE_CUSTOM_SCHEDULE_PROVIDER;
};

class CTraceFilterVehicleTransition : public CTraceFilterSkipTwoEntities
{
public:
	DECLARE_CLASS( CTraceFilterVehicleTransition, CTraceFilterSkipTwoEntities );

	CTraceFilterVehicleTransition( const IHandleEntity *passentity, const IHandleEntity *passentity2, int collisionGroup ) : 
	CTraceFilterSkipTwoEntities( passentity, passentity2, collisionGroup ) {}

	bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
	{
		bool bRet = BaseClass::ShouldHitEntity( pServerEntity, contentsMask );

		CBaseEntity *pEntity = EntityFromEntityHandle( pServerEntity );
		if ( pEntity )
		{
			IPhysicsObject *pPhys = pEntity->VPhysicsGetObject();
			if ( pPhys )
			{
				// Ignore physics objects
				// TODO: This will have to be fleshed out more as cases arise
				if ( pPhys->IsMoveable() && pPhys->GetMass() < 80.0f )
					return false;
			}
		}

		return bRet;
	}
};

#endif // AI_BEHAVIOR_PASSENGER_H