CShotManipulator: Difference between revisions
Jump to navigation
Jump to search
(Added code - link was busted) |
(Updated with proper source code) |
||
Line 1: | Line 1: | ||
Created with the shoot direction in the constructor, this helper class can spread out shots with a given spread. | Created with the shoot direction in the constructor, this helper class can spread out shots with a given spread. | ||
Pertaining to this, [[User:Holtt|Tim Holt]] has created a modification to this shot distribution | Pertaining to this, [[User:Holtt|Tim Holt]] has created a modification to this shot distribution. If you replace gameshared\shot_manipulator.h with this code, you'll have the biased shot distribution system. Notice that it renames the default Valve spread function to ApplySpreadVALVE, adds a new ApplySpreadBIAS function, then changes the default ApplySpread to call the BIAS version. | ||
Here is the complete source code... | |||
const Vector &ApplySpreadVALVE( const Vector &vecSpread, float bias = 1.0 ); | |||
const Vector &ApplySpreadBIAS( const Vector &vecSpread, float bias = 1.0 ); | |||
const Vector &ApplySpread( const Vector &vecSpread, float bias = 1.0 ) | |||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// | //========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// | ||
Line 18: | Line 20: | ||
#pragma once | #pragma once | ||
#endif | #endif | ||
#include "vector.h" | #include "vector.h" | ||
Line 25: | Line 27: | ||
extern ConVar ai_shot_bias_min; | extern ConVar ai_shot_bias_min; | ||
extern ConVar ai_shot_bias_max; | extern ConVar ai_shot_bias_max; | ||
extern ConVar shot_bias; | |||
//--------------------------------------------------------- | //--------------------------------------------------------- | ||
Line 38: | Line 41: | ||
{ | { | ||
SetShootDir( vecForward ); | SetShootDir( vecForward ); | ||
}; | }; | ||
void SetShootDir( const Vector &vecForward ) | void SetShootDir( const Vector &vecForward ) | ||
Line 46: | Line 49: | ||
} | } | ||
const Vector &ApplySpread( const Vector &vecSpread, float bias = 1.0 ); | const Vector &ApplySpreadVALVE( const Vector &vecSpread, float bias = 1.0 ); | ||
const Vector &ApplySpreadBIAS( const Vector &vecSpread, float bias = 1.0 ); | |||
const Vector &ApplySpread( const Vector &vecSpread, float bias = 1.0 ); | |||
const Vector &GetShotDirection() { return m_vecShotDirection; } | const Vector &GetShotDirection() { return m_vecShotDirection; } | ||
Line 59: | Line 64: | ||
Vector m_vecResult; | Vector m_vecResult; | ||
}; | }; | ||
// ------------------------------------------------------------------------------------- | |||
// CVB - holtt - Replace the normal ApplySpread with a call to either Valve's original | |||
// code, or a new bias code set that puts more shots in the center of | |||
// the shot spread. | |||
// ------------------------------------------------------------------------------------- | |||
inline const Vector &CShotManipulator::ApplySpread ( const Vector &vecSpread, float bias ) | |||
{ | |||
// return ApplySpreadVALVE (vecSpread, bias); | |||
return ApplySpreadBIAS (vecSpread, bias); | |||
} | |||
//--------------------------------------------------------- | |||
// CVB - holtt - Renamed this as we are going to replace it | |||
// with a new version that biases shots | |||
// towards the middle instead of random. | |||
//--------------------------------------------------------- | //--------------------------------------------------------- | ||
// Take a vector (direction) and another vector (spread) | // Take a vector (direction) and another vector (spread) | ||
Line 65: | Line 86: | ||
// spread. This used to live inside FireBullets. | // spread. This used to live inside FireBullets. | ||
//--------------------------------------------------------- | //--------------------------------------------------------- | ||
inline const Vector &CShotManipulator:: | inline const Vector &CShotManipulator::ApplySpreadVALVE ( const Vector &vecSpread, float bias ) | ||
{ | { | ||
// get circular gaussian spread | // get circular gaussian spread | ||
Line 100: | Line 121: | ||
} | } | ||
//--------------------------------------------------------- | |||
// CVB - holtt - This version creates shot patterns that | |||
// are biased towards the middle of the cone. | |||
//--------------------------------------------------------- | |||
// 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::ApplySpreadBIAS( const Vector &vecSpread, float bias ) | |||
{ | |||
// get circular gaussian spread | |||
float x, y; | |||
float r, theta; | |||
float sinTheta, cosTheta; | |||
// Generate a random polar coordinate | |||
r = random->RandomFloat (0,1); | |||
theta = random->RandomFloat (0, DEG2RAD(360)); | |||
// --------------------------------------------------------------------------------- | |||
// Note - this polar coordinate we created does not create a random point spread | |||
// inside the unit circle. The key is the radius (R) randomization. Half of | |||
// our random radius points will lie between 0.0 and 0.5, and the other half | |||
// from 0.5 to 1.0. So half of our shots will lie in the inner half of the circle, | |||
// and the other half on the outer half. But since the area of the outer half is | |||
// larger than the inner half, we'll end up with a greater spread. | |||
// For a good writeup on randomness in circles (or lack of randomness), check | |||
// out http://mathworld.wolfram.com/DiskPointPicking.html | |||
// --------------------------------------------------------------------------------- | |||
// Convert to cartesian (X/Y) coordinates | |||
SinCos (theta, &sinTheta, &cosTheta); | |||
x = r * sinTheta; | |||
y = r * cosTheta; | |||
m_vecResult = m_vecShotDirection + x * vecSpread.x * m_vecRight + y * vecSpread.y * m_vecUp; | |||
return m_vecResult; | |||
} | |||
#endif // SHOT_MANIPULATOR_H | #endif // SHOT_MANIPULATOR_H | ||
[[Category:Helpers]] | [[Category:Helpers]] |
Revision as of 12:23, 12 February 2006
Created with the shoot direction in the constructor, this helper class can spread out shots with a given spread.
Pertaining to this, Tim Holt has created a modification to this shot distribution. If you replace gameshared\shot_manipulator.h with this code, you'll have the biased shot distribution system. Notice that it renames the default Valve spread function to ApplySpreadVALVE, adds a new ApplySpreadBIAS function, then changes the default ApplySpread to call the BIAS version.
Here is the complete source code...
const Vector &ApplySpreadVALVE( const Vector &vecSpread, float bias = 1.0 ); const Vector &ApplySpreadBIAS( const Vector &vecSpread, float bias = 1.0 ); const Vector &ApplySpread( const Vector &vecSpread, float bias = 1.0 )
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #ifndef SHOT_MANIPULATOR_H #define SHOT_MANIPULATOR_H #ifdef _WIN32 #pragma once #endif #include "vector.h" extern ConVar ai_shot_bias_min; extern ConVar ai_shot_bias_max; extern ConVar shot_bias; //--------------------------------------------------------- // 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 &ApplySpreadVALVE( const Vector &vecSpread, float bias = 1.0 ); const Vector &ApplySpreadBIAS( const Vector &vecSpread, float bias = 1.0 ); const Vector &ApplySpread( 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; }; // ------------------------------------------------------------------------------------- // CVB - holtt - Replace the normal ApplySpread with a call to either Valve's original // code, or a new bias code set that puts more shots in the center of // the shot spread. // ------------------------------------------------------------------------------------- inline const Vector &CShotManipulator::ApplySpread ( const Vector &vecSpread, float bias ) { // return ApplySpreadVALVE (vecSpread, bias); return ApplySpreadBIAS (vecSpread, bias); } //--------------------------------------------------------- // CVB - holtt - Renamed this as we are going to replace it // with a new version that biases shots // towards the middle instead of random. //--------------------------------------------------------- // 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::ApplySpreadVALVE ( 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; } //--------------------------------------------------------- // CVB - holtt - This version creates shot patterns that // are biased towards the middle of the cone. //--------------------------------------------------------- // 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::ApplySpreadBIAS( const Vector &vecSpread, float bias ) { // get circular gaussian spread float x, y; float r, theta; float sinTheta, cosTheta; // Generate a random polar coordinate r = random->RandomFloat (0,1); theta = random->RandomFloat (0, DEG2RAD(360)); // --------------------------------------------------------------------------------- // Note - this polar coordinate we created does not create a random point spread // inside the unit circle. The key is the radius (R) randomization. Half of // our random radius points will lie between 0.0 and 0.5, and the other half // from 0.5 to 1.0. So half of our shots will lie in the inner half of the circle, // and the other half on the outer half. But since the area of the outer half is // larger than the inner half, we'll end up with a greater spread. // For a good writeup on randomness in circles (or lack of randomness), check // out http://mathworld.wolfram.com/DiskPointPicking.html // --------------------------------------------------------------------------------- // Convert to cartesian (X/Y) coordinates SinCos (theta, &sinTheta, &cosTheta); x = r * sinTheta; y = r * cosTheta; m_vecResult = m_vecShotDirection + x * vecSpread.x * m_vecRight + y * vecSpread.y * m_vecUp; return m_vecResult; } #endif // SHOT_MANIPULATOR_H