stvoy-sp-sdk/game/AI_WarriorBot.cpp

198 lines
4.4 KiB
C++
Raw Normal View History

2002-11-22 00:00:00 +00:00
// Warrior Bot
#include "b_local.h"
#include "anims.h"
extern void CGCam_Shake( float intensity, int duration );
/*
-------------------------
NPC_BSWarrior_Idle
-------------------------
*/
void NPC_BSWarrior_Idle( void )
{
NPC_BSIdle();
}
/*
-------------------------
Warrior_MeleeDamage
-------------------------
*/
#define MELEE_DISTANCE 100
#define WAR_DAMAGE_EASY 10
#define WAR_DAMAGE_NORMAL 30
#define WAR_DAMAGE_HARD 50
void Warrior_MeleeDamage( void )
{
vec3_t end, dir, mins, maxs;
trace_t trace;
AngleVectors( NPC->currentAngles, dir, NULL, NULL );
VectorMA( NPC->currentOrigin, MELEE_DISTANCE, dir, end );
VectorSet( maxs, 4, 4, 4 );
VectorSet( mins, -4, -4, -4 );
gi.trace( &trace, NPC->currentOrigin, mins, maxs, end, NPC->s.number, MASK_SHOT );
if ( trace.entityNum < ENTITYNUM_WORLD )
{
gentity_t *traceEnt = &g_entities[trace.entityNum];
int damage;
if ( g_spskill->integer == 0 )
damage = WAR_DAMAGE_EASY;
else if ( g_spskill->integer == 1 )
damage = WAR_DAMAGE_NORMAL;
else
damage = WAR_DAMAGE_HARD;
G_Damage( traceEnt, NPC, NPC, dir, trace.endpos, damage, 0, MOD_PHASER );
G_Sound ( NPC, G_SoundIndex ("sound/enemies/warbot/stabhit.wav"));
}
}
/*
-------------------------
Warrior_Melee
-------------------------
*/
void Warrior_Melee( void )
{
if ( TIMER_Done( NPC, "preDelay" ) )
{
Warrior_MeleeDamage();
//Set the timer ahead, we should never reach this again without first doing something else
TIMER_Set( NPC, "preDelay", 50000 );
}
NPC_UpdateAngles( qtrue, qtrue );
}
/*
-------------------------
Warrior_Hunt
-------------------------
*/
extern animFileSet_t knownAnimFileSets[MAX_ANIM_FILES];
static void Warrior_Hunt( void )
{
NPCInfo->combatMove = qtrue;
animation_t *animations = knownAnimFileSets[NPC->client->clientInfo.animFileIndex].animations;
if ( ( NPC->client->renderInfo.legsFrame == (animations[BOTH_RUN1].firstFrame) ) || ( NPC->client->renderInfo.legsFrame == (animations[BOTH_RUN1].firstFrame)+3 ) )
{
vec3_t dir;
float dist, intensityScale;
float realIntensity;
VectorSubtract( NPC->currentOrigin, NPC->enemy->currentOrigin, dir );
dist = VectorNormalize( dir );
//Use the dir to add kick to the explosion
if ( dist < 512 )
{
intensityScale = 1 - ( dist / 512.0f );
realIntensity = 1.0f * intensityScale;
CGCam_Shake( realIntensity, 150 );
}
}
//If we're not supposed to stand still, pursue the player
if ( NPCInfo->standTime < level.time )
{
if ( NPC->health < 50 )
{
ucmd.buttons |= (BUTTON_WALKING|BUTTON_CAREFUL);
}
//Move towards our goal
NPCInfo->goalEntity = NPC->enemy;
NPCInfo->goalRadius = 12;
NPC_MoveToGoal();
//Add a delay time so they don't attack immediately out of a run
NPCInfo->weaponTime = level.time + 1000;
}
//Update our angles regardless
NPC_UpdateAngles( qtrue, qtrue );
}
/*
-------------------------
NPC_BSWarrior_Attack
-------------------------
*/
#define MIN_MELEE_RANGE 84
#define MIN_MELEE_RANGE_SQR ( MIN_MELEE_RANGE * MIN_MELEE_RANGE )
void NPC_BSWarrior_Attack( void )
{
//Don't do anything if we're hurt
if ( NPC->painDebounceTime > level.time )
{
NPC_UpdateAngles( qtrue, qtrue );
return;
}
//If we don't have an enemy, just idle
if ( NPC_CheckEnemyExt() == qfalse )
{
NPC_BSWarrior_Idle();
return;
}
//If we're in an attack, keep checking for the actual strike point
if ( NPC->attackDebounceTime > level.time )
{
Warrior_Melee();
return;
}
//Rate our distance to the target, and our visibilty
float distance = (int) DistanceHorizontalSquared( NPC->currentOrigin, NPC->enemy->currentOrigin );
distance_e distRate = ( distance > MIN_MELEE_RANGE_SQR ) ? DIST_LONG : DIST_MELEE;
int visRate = NPC_ClearLOS( NPC->enemy );
//If we cannot see our target, move to see it
if ( visRate == qfalse )
{
Warrior_Hunt();
return;
}
//If we're too far away, then keep walking forward
if ( distRate != DIST_MELEE )
{
Warrior_Hunt();
return;
}
//Start an attack
if ( NPC_FaceEnemy( qtrue ) )
{
TIMER_Set( NPC, "preDelay", 500 );
NPC->attackDebounceTime = level.time + 1000;
NPC_SetAnim( NPC, SETANIM_BOTH, Q_irand( BOTH_MELEE1, BOTH_MELEE5 ), SETANIM_FLAG_HOLD|SETANIM_FLAG_OVERRIDE );
Warrior_Melee();
return;
}
NPC_UpdateAngles( qtrue, qtrue );
}