|
|
//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef SHOT_MANIPULATOR_H
#define SHOT_MANIPULATOR_H
#ifdef _WIN32
#pragma once
#endif
#include "mathlib/vector.h"
extern ConVar ai_shot_bias_min; extern ConVar ai_shot_bias_max;
//---------------------------------------------------------
// Caches off a shot direction and allows you to perform
// various operations on it without having to recalculate
// vecRight and vecUp each time.
//---------------------------------------------------------
class CShotManipulator { public: CShotManipulator( const Vector &vecForward ) { SetShootDir( vecForward ); };
void SetShootDir( const Vector &vecForward ) { m_vecShotDirection = vecForward; VectorVectors( m_vecShotDirection, m_vecRight, m_vecUp ); }
const Vector &ApplySpread( const Vector &vecSpread, float bias = 1.0 ); const Vector &ApplyAngularSpread( const Vector &vecSpread, float bias = 1.0 );
const Vector &GetShotDirection() { return m_vecShotDirection; } const Vector &GetResult() { return m_vecResult; } const Vector &GetRightVector() { return m_vecRight; } const Vector &GetUpVector() { return m_vecUp;}
private: Vector m_vecShotDirection; Vector m_vecRight; Vector m_vecUp; Vector m_vecResult; };
//---------------------------------------------------------
// Take a vector (direction) and another vector (spread)
// and modify the direction to point somewhere within the
// spread. This used to live inside FireBullets.
//---------------------------------------------------------
inline const Vector &CShotManipulator::ApplySpread( const Vector &vecSpread, float bias ) { // get circular gaussian spread
float x, y, z;
if ( bias > 1.0 ) bias = 1.0; else if ( bias < 0.0 ) bias = 0.0;
float shotBiasMin = ai_shot_bias_min.GetFloat(); float shotBiasMax = ai_shot_bias_max.GetFloat();
// 1.0 gaussian, 0.0 is flat, -1.0 is inverse gaussian
float shotBias = ( ( shotBiasMax - shotBiasMin ) * bias ) + shotBiasMin;
float flatness = ( fabsf(shotBias) * 0.5 );
do { x = random->RandomFloat(-1,1) * flatness + random->RandomFloat(-1,1) * (1 - flatness); y = random->RandomFloat(-1,1) * flatness + random->RandomFloat(-1,1) * (1 - flatness); if ( shotBias < 0 ) { x = ( x >= 0 ) ? 1.0 - x : -1.0 - x; y = ( y >= 0 ) ? 1.0 - y : -1.0 - y; } z = x*x+y*y; } while (z > 1);
m_vecResult = m_vecShotDirection + x * vecSpread.x * m_vecRight + y * vecSpread.y * m_vecUp;
return m_vecResult; }
inline const Vector &CShotManipulator::ApplyAngularSpread( const Vector &vecSpread, float bias ) { float x, y, z; x = vecSpread[0] * random->RandomFloat(-0.5f, 0.5f); y = vecSpread[1] * random->RandomFloat(-0.5f, 0.5f); z = vecSpread[2] * random->RandomFloat(-0.5f, 0.5f);
matrix3x4_t matrix; QAngle qa(x,y,z); AngleMatrix( qa, matrix ); VectorTransform(m_vecShotDirection, matrix, m_vecResult); return m_vecResult; }
#endif // SHOT_MANIPULATOR_H
|