aboutsummaryrefslogtreecommitdiff
path: root/sp/src/game/server/ai_basenpc_physicsflyer.h
blob: 0928fd4cdfa2dc0c7cd9c327255b07874eebe206 (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
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
// $NoKeywords: $
//=============================================================================//

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

#include "ai_basenpc.h"
#include "ai_navigator.h"

//-----------------------------------------------------------------------------
// The combot.
//-----------------------------------------------------------------------------
abstract_class CAI_BasePhysicsFlyingBot : public CAI_BaseNPC, public IMotionEvent
{
	DECLARE_CLASS( CAI_BasePhysicsFlyingBot, CAI_BaseNPC );
public:
	DECLARE_DATADESC();

	void			StartTask( const Task_t *pTask );
	void			GetVelocity(Vector *vVelocity, AngularImpulse *vAngVelocity);
	virtual QAngle	BodyAngles();

	virtual bool	ShouldSavePhysics() { return true; }

protected:
	
	CAI_BasePhysicsFlyingBot();
	~CAI_BasePhysicsFlyingBot();

	Vector	VelocityToAvoidObstacles(float flInterval);
	virtual float	MinGroundDist(void);

	virtual void TurnHeadToTarget( float flInterval, const Vector &moveTarget );

	void MoveInDirection( float flInterval, const Vector &targetDir, 
						 float accelXY, float accelZ, float decay)
	{
		decay = ExponentialDecay( decay, 1.0, flInterval );
		accelXY *= flInterval;
		accelZ  *= flInterval;

		m_vCurrentVelocity.x = ( decay * m_vCurrentVelocity.x + accelXY * targetDir.x );
		m_vCurrentVelocity.y = ( decay * m_vCurrentVelocity.y + accelXY * targetDir.y );
		m_vCurrentVelocity.z = ( decay * m_vCurrentVelocity.z + accelZ  * targetDir.z );
	}

	void MoveToLocation( float flInterval, const Vector &target, 
						 float accelXY, float accelZ, float decay)
	{
		Vector targetDir = target - GetLocalOrigin();
		VectorNormalize(targetDir);

		MoveInDirection(flInterval, targetDir, accelXY, accelZ, decay);
	}

	void Decelerate( float flInterval, float decay )
	{
		decay *= flInterval;
		m_vCurrentVelocity.x = (decay * m_vCurrentVelocity.x);
		m_vCurrentVelocity.y = (decay * m_vCurrentVelocity.y);
		m_vCurrentVelocity.z = (decay * m_vCurrentVelocity.z);
	}

	void AddNoiseToVelocity( float noiseScale = 1.0 )
	{
		if( m_vNoiseMod.x )
		{
			m_vCurrentVelocity.x += noiseScale*sin(m_vNoiseMod.x * gpGlobals->curtime + m_vNoiseMod.x);
		}

		if( m_vNoiseMod.y )
		{
			m_vCurrentVelocity.y += noiseScale*cos(m_vNoiseMod.y * gpGlobals->curtime + m_vNoiseMod.y);
		}

		if( m_vNoiseMod.z )
		{
			m_vCurrentVelocity.z -= noiseScale*cos(m_vNoiseMod.z * gpGlobals->curtime + m_vNoiseMod.z);
		}
	}

	void LimitSpeed( float zLimit, float maxSpeed = -1 )
	{
		if ( maxSpeed == -1 )
			maxSpeed = m_flSpeed;
		if (m_vCurrentVelocity.Length() > maxSpeed)
		{
			VectorNormalize(m_vCurrentVelocity);
			m_vCurrentVelocity *= maxSpeed;
		}
		// Limit fall speed
		if (zLimit > 0 && m_vCurrentVelocity.z < -zLimit)
		{
			m_vCurrentVelocity.z = -zLimit;
		}
	}

	AI_NavPathProgress_t ProgressFlyPath( float flInterval,
										  const CBaseEntity *pNewTarget, 
										  unsigned collisionMask, 
										  bool bNewTrySimplify = true, 
										  float strictPointTolerance = 32.0 );

	const Vector &GetCurrentVelocity() const		{ return m_vCurrentVelocity; }
	void SetCurrentVelocity(const Vector &vNewVel)	{ m_vCurrentVelocity = vNewVel; }

	const Vector &GetNoiseMod() const				{ return m_vNoiseMod; }
	void SetNoiseMod( float x, float y, float z )	{ m_vNoiseMod.Init( x, y, z ); }
	void SetNoiseMod( const Vector &noise )			{ m_vNoiseMod = noise; }

	void TranslateNavGoal( CBaseEntity *pTarget, Vector &chasePosition );

	virtual void MoveToTarget(float flInterval, const Vector &MoveTarget) = 0;

	virtual float GetHeadTurnRate( void ) { return 15.0f; }	// Degrees per second

	bool			CreateVPhysics( void );
	IMotionEvent::simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular );

	virtual void ClampMotorForces( Vector &linear, AngularImpulse &angular )
	{ 
		// limit reaction forces
		linear.x = clamp( linear.x, -3000.f, 3000.f );
		linear.y = clamp( linear.y, -3000.f, 3000.f );
		linear.z = clamp( linear.z, -3000.f, 3000.f );

		// add in weightlessness
		linear.z += 800.f;
	}

	// -------------------------------
	//  Movement vars
	// -------------------------------
	Vector			m_vCurrentVelocity;
	Vector			m_vCurrentBanking;
	Vector			m_vNoiseMod;
	float			m_fHeadYaw;
	Vector			m_vLastPatrolDir;
	IPhysicsMotionController	*m_pMotionController;
};

#endif // AI_BASENPC_PHYSICSFLYER_H