diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /mp/src/game/server/h_ai.cpp | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/game/server/h_ai.cpp')
| -rw-r--r-- | mp/src/game/server/h_ai.cpp | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/mp/src/game/server/h_ai.cpp b/mp/src/game/server/h_ai.cpp new file mode 100644 index 00000000..881f33d6 --- /dev/null +++ b/mp/src/game/server/h_ai.cpp @@ -0,0 +1,266 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Utility functions used by AI code.
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "game.h"
+#include "vstdlib/random.h"
+#include "movevars_shared.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+#define NUM_LATERAL_CHECKS 13 // how many checks are made on each side of a NPC looking for lateral cover
+#define NUM_LATERAL_LOS_CHECKS 6 // how many checks are made on each side of a NPC looking for lateral cover
+
+#define TOSS_HEIGHT_MAX 300 // altitude of initial trace done to see how high something can be tossed
+
+//float flRandom = random->RandomFloat(0,1);
+
+bool g_fDrawLines = FALSE;
+
+
+//=========================================================
+// FBoxVisible - a more accurate ( and slower ) version
+// of FVisible.
+//
+// !!!UNDONE - make this CAI_BaseNPC?
+//=========================================================
+bool FBoxVisible( CBaseEntity *pLooker, CBaseEntity *pTarget, Vector &vecTargetOrigin, float flSize )
+{
+ // don't look through water
+ if ((pLooker->GetWaterLevel() != 3 && pTarget->GetWaterLevel() == 3)
+ || (pLooker->GetWaterLevel() == 3 && pTarget->GetWaterLevel() == 0))
+ return FALSE;
+
+ trace_t tr;
+ Vector vecLookerOrigin = pLooker->EyePosition();//look through the NPC's 'eyes'
+ for (int i = 0; i < 5; i++)
+ {
+ Vector vecTarget = pTarget->GetAbsOrigin();
+ vecTarget.x += random->RandomFloat( pTarget->WorldAlignMins().x + flSize, pTarget->WorldAlignMaxs().x - flSize);
+ vecTarget.y += random->RandomFloat( pTarget->WorldAlignMins().y + flSize, pTarget->WorldAlignMaxs().y - flSize);
+ vecTarget.z += random->RandomFloat( pTarget->WorldAlignMins().z + flSize, pTarget->WorldAlignMaxs().z - flSize);
+
+ UTIL_TraceLine(vecLookerOrigin, vecTarget, MASK_BLOCKLOS, pLooker, COLLISION_GROUP_NONE, &tr);
+
+ if (tr.fraction == 1.0)
+ {
+ vecTargetOrigin = vecTarget;
+ return TRUE;// line of sight is valid.
+ }
+ }
+ return FALSE;// Line of sight is not established
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the correct toss velocity to throw a given object at a point.
+// Like the other version of VecCheckToss, but allows you to filter for any
+// number of entities to ignore.
+// Input : pEntity - The object doing the throwing. Is *NOT* automatically included in the
+// filter below.
+// pFilter - A trace filter of entities to ignore in the object's collision sweeps.
+// It is recommended to include at least the thrower.
+// vecSpot1 - The point from which the object is being thrown.
+// vecSpot2 - The point TO which the object is being thrown.
+// flHeightMaxRatio - A scale factor indicating the maximum ratio of height
+// to total throw distance, measured from the higher of the two endpoints to
+// the apex. -1 indicates that there is no maximum.
+// flGravityAdj - Scale factor for gravity - should match the gravity scale
+// that the object will use in midair.
+// bRandomize - when true, introduces a little fudge to the throw
+// Output : Velocity to throw the object with.
+//-----------------------------------------------------------------------------
+Vector VecCheckToss( CBaseEntity *pEntity, ITraceFilter *pFilter, Vector vecSpot1, Vector vecSpot2, float flHeightMaxRatio, float flGravityAdj, bool bRandomize, Vector *vecMins, Vector *vecMaxs )
+{
+ trace_t tr;
+ Vector vecMidPoint;// halfway point between Spot1 and Spot2
+ Vector vecApex;// highest point
+ Vector vecScale;
+ Vector vecTossVel;
+ Vector vecTemp;
+ float flGravity = GetCurrentGravity() * flGravityAdj;
+
+ if (vecSpot2.z - vecSpot1.z > 500)
+ {
+ // to high, fail
+ return vec3_origin;
+ }
+
+ Vector forward, right;
+ AngleVectors( pEntity->GetLocalAngles(), &forward, &right, NULL );
+
+ if (bRandomize)
+ {
+ // toss a little bit to the left or right, not right down on the enemy's bean (head).
+ vecSpot2 += right * ( random->RandomFloat(-8,8) + random->RandomFloat(-16,16) );
+ vecSpot2 += forward * ( random->RandomFloat(-8,8) + random->RandomFloat(-16,16) );
+ }
+
+ // calculate the midpoint and apex of the 'triangle'
+ // UNDONE: normalize any Z position differences between spot1 and spot2 so that triangle is always RIGHT
+ // get a rough idea of how high it can be thrown
+ vecMidPoint = vecSpot1 + (vecSpot2 - vecSpot1) * 0.5;
+ UTIL_TraceLine(vecMidPoint, vecMidPoint + Vector(0,0,TOSS_HEIGHT_MAX), MASK_SOLID_BRUSHONLY, pFilter, &tr);
+ vecMidPoint = tr.endpos;
+
+ if( tr.fraction != 1.0 )
+ {
+ // (subtract 15 so the object doesn't hit the ceiling)
+ vecMidPoint.z -= 15;
+ }
+
+ if (flHeightMaxRatio != -1)
+ {
+ // But don't throw so high that it looks silly. Maximize the height of the
+ // throw above the highest of the two endpoints to a ratio of the throw length.
+ float flHeightMax = flHeightMaxRatio * (vecSpot2 - vecSpot1).Length();
+ float flHighestEndZ = MAX(vecSpot1.z, vecSpot2.z);
+ if ((vecMidPoint.z - flHighestEndZ) > flHeightMax)
+ {
+ vecMidPoint.z = flHighestEndZ + flHeightMax;
+ }
+ }
+
+ if (vecMidPoint.z < vecSpot1.z || vecMidPoint.z < vecSpot2.z)
+ {
+ // Not enough space, fail
+ return vec3_origin;
+ }
+
+ // How high should the object travel to reach the apex
+ float distance1 = (vecMidPoint.z - vecSpot1.z);
+ float distance2 = (vecMidPoint.z - vecSpot2.z);
+
+ // How long will it take for the object to travel this distance
+ float time1 = sqrt( distance1 / (0.5 * flGravity) );
+ float time2 = sqrt( distance2 / (0.5 * flGravity) );
+
+ if (time1 < 0.1)
+ {
+ // too close
+ return vec3_origin;
+ }
+
+ // how hard to throw sideways to get there in time.
+ vecTossVel = (vecSpot2 - vecSpot1) / (time1 + time2);
+
+ // how hard upwards to reach the apex at the right time.
+ vecTossVel.z = flGravity * time1;
+
+ // find the apex
+ vecApex = vecSpot1 + vecTossVel * time1;
+ vecApex.z = vecMidPoint.z;
+
+ // JAY: Repro behavior from HL1 -- toss check went through gratings
+ UTIL_TraceLine(vecSpot1, vecApex, (MASK_SOLID&(~CONTENTS_GRATE)), pFilter, &tr);
+ if (tr.fraction != 1.0)
+ {
+ // fail!
+ return vec3_origin;
+ }
+
+ // UNDONE: either ignore NPCs or change it to not care if we hit our enemy
+ UTIL_TraceLine(vecSpot2, vecApex, (MASK_SOLID_BRUSHONLY&(~CONTENTS_GRATE)), pFilter, &tr);
+ if (tr.fraction != 1.0)
+ {
+ // fail!
+ return vec3_origin;
+ }
+
+ if ( vecMins && vecMaxs )
+ {
+ // Check to ensure the entity's hull can travel the first half of the grenade throw
+ UTIL_TraceHull( vecSpot1, vecApex, *vecMins, *vecMaxs, (MASK_SOLID&(~CONTENTS_GRATE)), pFilter, &tr);
+ if ( tr.fraction < 1.0 )
+ return vec3_origin;
+ }
+
+ return vecTossVel;
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the correct toss velocity to throw a given object at a point.
+// Input : pEntity - The entity that is throwing the object.
+// vecSpot1 - The point from which the object is being thrown.
+// vecSpot2 - The point TO which the object is being thrown.
+// flHeightMaxRatio - A scale factor indicating the maximum ratio of height
+// to total throw distance, measured from the higher of the two endpoints to
+// the apex. -1 indicates that there is no maximum.
+// flGravityAdj - Scale factor for gravity - should match the gravity scale
+// that the object will use in midair.
+// bRandomize - when true, introduces a little fudge to the throw
+// Output : Velocity to throw the object with.
+//-----------------------------------------------------------------------------
+Vector VecCheckToss( CBaseEntity *pEntity, Vector vecSpot1, Vector vecSpot2, float flHeightMaxRatio, float flGravityAdj, bool bRandomize, Vector *vecMins, Vector *vecMaxs )
+{
+ // construct a filter and call through to the other version of this function.
+ CTraceFilterSimple traceFilter( pEntity, COLLISION_GROUP_NONE );
+ return VecCheckToss( pEntity, &traceFilter, vecSpot1, vecSpot2,
+ flHeightMaxRatio, flGravityAdj, bRandomize,
+ vecMins, vecMaxs );
+}
+
+//
+// VecCheckThrow - returns the velocity vector at which an object should be thrown from vecspot1 to hit vecspot2.
+// returns vec3_origin if throw is not feasible.
+//
+Vector VecCheckThrow ( CBaseEntity *pEdict, const Vector &vecSpot1, Vector vecSpot2, float flSpeed, float flGravityAdj, Vector *vecMins, Vector *vecMaxs )
+{
+ float flGravity = GetCurrentGravity() * flGravityAdj;
+
+ Vector vecGrenadeVel = (vecSpot2 - vecSpot1);
+
+ // throw at a constant time
+ float time = vecGrenadeVel.Length( ) / flSpeed;
+ vecGrenadeVel = vecGrenadeVel * (1.0 / time);
+
+ // adjust upward toss to compensate for gravity loss
+ vecGrenadeVel.z += flGravity * time * 0.5;
+
+ Vector vecApex = vecSpot1 + (vecSpot2 - vecSpot1) * 0.5;
+ vecApex.z += 0.5 * flGravity * (time * 0.5) * (time * 0.5);
+
+
+ trace_t tr;
+ UTIL_TraceLine(vecSpot1, vecApex, MASK_SOLID, pEdict, COLLISION_GROUP_NONE, &tr);
+ if (tr.fraction != 1.0)
+ {
+ // fail!
+ //NDebugOverlay::Line( vecSpot1, vecApex, 255, 0, 0, true, 5.0 );
+ return vec3_origin;
+ }
+
+ //NDebugOverlay::Line( vecSpot1, vecApex, 0, 255, 0, true, 5.0 );
+
+ UTIL_TraceLine(vecSpot2, vecApex, MASK_SOLID_BRUSHONLY, pEdict, COLLISION_GROUP_NONE, &tr);
+ if (tr.fraction != 1.0)
+ {
+ // fail!
+ //NDebugOverlay::Line( vecApex, vecSpot2, 255, 0, 0, true, 5.0 );
+ return vec3_origin;
+ }
+
+ //NDebugOverlay::Line( vecApex, vecSpot2, 0, 255, 0, true, 5.0 );
+
+ if ( vecMins && vecMaxs )
+ {
+ // Check to ensure the entity's hull can travel the first half of the grenade throw
+ UTIL_TraceHull( vecSpot1, vecApex, *vecMins, *vecMaxs, MASK_SOLID, pEdict, COLLISION_GROUP_NONE, &tr);
+ if ( tr.fraction < 1.0 )
+ {
+ //NDebugOverlay::SweptBox( vecSpot1, tr.endpos, *vecMins, *vecMaxs, vec3_angle, 255, 0, 0, 64, 5.0 );
+ return vec3_origin;
+ }
+ }
+
+ //NDebugOverlay::SweptBox( vecSpot1, vecApex, *vecMins, *vecMaxs, vec3_angle, 0, 255, 0, 64, 5.0 );
+
+ return vecGrenadeVel;
+}
|