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
|