Portable Half-Life SDK. GoldSource and Xash3D. Crossplatform.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
6.0 KiB

9 years ago
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
/*
h_ai.cpp - halflife specific ai code
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "game.h"
#define NUM_LATERAL_CHECKS 13 // how many checks are made on each side of a monster looking for lateral cover
#define NUM_LATERAL_LOS_CHECKS 6 // how many checks are made on each side of a monster looking for lateral cover
9 years ago
//float flRandom = RANDOM_FLOAT( 0, 1 );
9 years ago
DLL_GLOBAL BOOL g_fDrawLines = FALSE;
//=========================================================
//
// AI UTILITY FUNCTIONS
//
// !!!UNDONE - move CBaseMonster functions to monsters.cpp
//=========================================================
//=========================================================
// FBoxVisible - a more accurate ( and slower ) version
// of FVisible.
//
// !!!UNDONE - make this CBaseMonster?
//=========================================================
9 years ago
BOOL FBoxVisible( entvars_t *pevLooker, entvars_t *pevTarget, Vector &vecTargetOrigin, float flSize )
9 years ago
{
// don't look through water
9 years ago
if( ( pevLooker->waterlevel != 3 && pevTarget->waterlevel == 3 )
|| ( pevLooker->waterlevel == 3 && pevTarget->waterlevel == 0 ) )
9 years ago
return FALSE;
TraceResult tr;
Vector vecLookerOrigin = pevLooker->origin + pevLooker->view_ofs;//look through the monster's 'eyes'
9 years ago
for( int i = 0; i < 5; i++ )
9 years ago
{
Vector vecTarget = pevTarget->origin;
9 years ago
vecTarget.x += RANDOM_FLOAT( pevTarget->mins.x + flSize, pevTarget->maxs.x - flSize );
vecTarget.y += RANDOM_FLOAT( pevTarget->mins.y + flSize, pevTarget->maxs.y - flSize );
vecTarget.z += RANDOM_FLOAT( pevTarget->mins.z + flSize, pevTarget->maxs.z - flSize );
UTIL_TraceLine( vecLookerOrigin, vecTarget, ignore_monsters, ignore_glass, ENT( pevLooker )/*pentIgnore*/, &tr );
9 years ago
9 years ago
if( tr.flFraction == 1.0 )
9 years ago
{
vecTargetOrigin = vecTarget;
return TRUE;// line of sight is valid.
}
}
return FALSE;// Line of sight is not established
}
//
// VecCheckToss - returns the velocity at which an object should be lobbed from vecspot1 to land near vecspot2.
// returns g_vecZero if toss is not feasible.
//
9 years ago
Vector VecCheckToss( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flGravityAdj )
9 years ago
{
TraceResult tr;
Vector vecMidPoint;// halfway point between Spot1 and Spot2
Vector vecApex;// highest point
Vector vecScale;
Vector vecGrenadeVel;
Vector vecTemp;
float flGravity = g_psv_gravity->value * flGravityAdj;
9 years ago
if( vecSpot2.z - vecSpot1.z > 500 )
9 years ago
{
// to high, fail
return g_vecZero;
}
9 years ago
UTIL_MakeVectors( pev->angles );
9 years ago
// toss a little bit to the left or right, not right down on the enemy's bean (head).
9 years ago
vecSpot2 = vecSpot2 + gpGlobals->v_right * ( RANDOM_FLOAT( -8, 8 ) + RANDOM_FLOAT( -16, 16 ) );
vecSpot2 = vecSpot2 + gpGlobals->v_forward * ( RANDOM_FLOAT( -8, 8 ) + RANDOM_FLOAT( -16, 16 ) );
9 years ago
// calculate the midpoint and apex of the 'triangle'
// UNDONE: normalize any Z position differences between spot1 and spot2 so that triangle is always RIGHT
// How much time does it take to get there?
// get a rough idea of how high it can be thrown
9 years ago
vecMidPoint = vecSpot1 + ( vecSpot2 - vecSpot1 ) * 0.5;
UTIL_TraceLine(vecMidPoint, vecMidPoint + Vector( 0, 0, 500 ), ignore_monsters, ENT( pev ), &tr );
9 years ago
vecMidPoint = tr.vecEndPos;
// (subtract 15 so the grenade doesn't hit the ceiling)
vecMidPoint.z -= 15;
9 years ago
if( vecMidPoint.z < vecSpot1.z || vecMidPoint.z < vecSpot2.z )
9 years ago
{
// to not enough space, fail
return g_vecZero;
}
// How high should the grenade travel to reach the apex
9 years ago
float distance1 = vecMidPoint.z - vecSpot1.z;
float distance2 = vecMidPoint.z - vecSpot2.z;
9 years ago
// How long will it take for the grenade to travel this distance
9 years ago
float time1 = sqrt( distance1 / ( 0.5 * flGravity ) );
float time2 = sqrt( distance2 / ( 0.5 * flGravity ) );
9 years ago
9 years ago
if( time1 < 0.1 )
9 years ago
{
// too close
return g_vecZero;
}
// how hard to throw sideways to get there in time.
9 years ago
vecGrenadeVel = ( vecSpot2 - vecSpot1 ) / ( time1 + time2 );
9 years ago
// how hard upwards to reach the apex at the right time.
vecGrenadeVel.z = flGravity * time1;
// find the apex
vecApex = vecSpot1 + vecGrenadeVel * time1;
vecApex.z = vecMidPoint.z;
9 years ago
UTIL_TraceLine( vecSpot1, vecApex, dont_ignore_monsters, ENT( pev ), &tr );
if( tr.flFraction != 1.0 )
9 years ago
{
// fail!
return g_vecZero;
}
// UNDONE: either ignore monsters or change it to not care if we hit our enemy
9 years ago
UTIL_TraceLine( vecSpot2, vecApex, ignore_monsters, ENT( pev ), &tr );
if( tr.flFraction != 1.0 )
9 years ago
{
// fail!
return g_vecZero;
}
9 years ago
9 years ago
return vecGrenadeVel;
}
//
// VecCheckThrow - returns the velocity vector at which an object should be thrown from vecspot1 to hit vecspot2.
// returns g_vecZero if throw is not feasible.
//
9 years ago
Vector VecCheckThrow( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flSpeed, float flGravityAdj )
9 years ago
{
9 years ago
float flGravity = g_psv_gravity->value * flGravityAdj;
9 years ago
9 years ago
Vector vecGrenadeVel = vecSpot2 - vecSpot1;
9 years ago
// throw at a constant time
9 years ago
float time = vecGrenadeVel.Length() / flSpeed;
vecGrenadeVel = vecGrenadeVel * ( 1.0 / time );
9 years ago
// adjust upward toss to compensate for gravity loss
vecGrenadeVel.z += flGravity * time * 0.5;
9 years ago
Vector vecApex = vecSpot1 + ( vecSpot2 - vecSpot1 ) * 0.5;
vecApex.z += 0.5 * flGravity * ( time * 0.5 ) * ( time * 0.5 );
9 years ago
TraceResult tr;
9 years ago
UTIL_TraceLine( vecSpot1, vecApex, dont_ignore_monsters, ENT( pev ), &tr );
if( tr.flFraction != 1.0 )
9 years ago
{
// fail!
return g_vecZero;
}
9 years ago
UTIL_TraceLine( vecSpot2, vecApex, ignore_monsters, ENT( pev ), &tr );
if( tr.flFraction != 1.0 )
9 years ago
{
// fail!
return g_vecZero;
}
return vecGrenadeVel;
}