mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-17 11:00:38 +02:00
Initial Prey Game integration support.
This commit is contained in:
@@ -0,0 +1,529 @@
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "prey_local.h"
|
||||
|
||||
const idEventDef AI_CenturionLaunch("centurionFire", "d"); //called from anims to handle firing for centurion
|
||||
const idEventDef AI_CenturionRoar("centurionRoar"); //called from level-script to cause centurion to roar
|
||||
const idEventDef AI_CenturionArmChop("centurionArmChop"); //called from level-script to actually cause centurion to loose arm
|
||||
const idEventDef AI_CenturionLooseArm("centurionLooseArm"); //internal: used to actually 'loose' arm
|
||||
const idEventDef AI_CenturionForceFieldNotify("preForcefieldNotify");
|
||||
const idEventDef AI_CenturionForceFieldToggle("forcefieldToggle", "d");
|
||||
const idEventDef AI_CenturionInTunnel("playerInBox", "dE");
|
||||
const idEventDef AI_CenturionReachedTunnel("reachedTunnel");
|
||||
const idEventDef AI_CenturionMoveToTunnel("moveToTunnel", NULL, 'd');
|
||||
const idEventDef AI_CheckForObstructions("checkForObstructions", "d", 'd');
|
||||
const idEventDef AI_DestroyObstruction("destroyObstruction");
|
||||
const idEventDef AI_MoveToObstruction("moveToObstruction");
|
||||
const idEventDef AI_ReachedObstruction("reachedObstruction");
|
||||
const idEventDef AI_CloseToObstruction("closeToObstruction", 0, 'd');
|
||||
const idEventDef AI_BackhandImpulse("<backhandImpulse>", "e");
|
||||
const idEventDef AI_EnemyCloseToObstruction("enemyCloseToObstruction", NULL, 'd');
|
||||
const idEventDef AI_TakeDamage("takeDamage", "d");
|
||||
const idEventDef AI_FindNearbyEnemy("findNearbyEnemy", "f", 'e');
|
||||
|
||||
CLASS_DECLARATION( hhMonsterAI, hhCenturion )
|
||||
EVENT( AI_CenturionLaunch, hhCenturion::Event_CenturionLaunch )
|
||||
EVENT( AI_CenturionRoar, hhCenturion::Event_ScriptedRoar )
|
||||
EVENT( AI_CenturionArmChop, hhCenturion::Event_ScriptedArmChop )
|
||||
EVENT( AI_CenturionLooseArm, hhCenturion::Event_CenturionLooseArm )
|
||||
EVENT( AI_CenturionInTunnel, hhCenturion::Event_PlayerInTunnel )
|
||||
EVENT( AI_CenturionReachedTunnel, hhCenturion::Event_ReachedTunnel )
|
||||
EVENT( AI_CenturionMoveToTunnel, hhCenturion::Event_MoveToTunnel )
|
||||
EVENT( AI_CenturionForceFieldNotify, hhCenturion::Event_ForceFieldNotify )
|
||||
EVENT( AI_CenturionForceFieldToggle, hhCenturion::Event_ForceFieldToggle )
|
||||
EVENT( AI_CheckForObstructions, hhCenturion::Event_CheckForObstruction )
|
||||
EVENT( AI_MoveToObstruction, hhCenturion::Event_MoveToObstruction )
|
||||
EVENT( AI_DestroyObstruction, hhCenturion::Event_DestroyObstruction )
|
||||
EVENT( AI_ReachedObstruction, hhCenturion::Event_ReachedObstruction )
|
||||
EVENT( AI_CloseToObstruction, hhCenturion::Event_CloseToObstruction )
|
||||
EVENT( AI_BackhandImpulse, hhCenturion::Event_BackhandImpulse )
|
||||
EVENT( AI_EnemyCloseToObstruction, hhCenturion::Event_EnemyCloseToObstruction )
|
||||
EVENT( AI_TakeDamage, hhCenturion::Event_TakeDamage )
|
||||
EVENT( AI_FindNearbyEnemy, hhCenturion::Event_FindNearbyEnemy )
|
||||
END_CLASS
|
||||
|
||||
#ifndef ID_DEMO_BUILD //HUMANHEAD jsh PCF 5/26/06: code removed for demo build
|
||||
|
||||
void hhCenturion::Spawn() {
|
||||
AI_CENTURION_ARM_MISSING = false;
|
||||
AI_CENTURION_REQUIRE_ROAR = false;
|
||||
AI_CENTURION_ARM_TUNNEL = false;
|
||||
AI_CENTURION_SCRIPTED_ROAR = 0;
|
||||
AI_CENTURION_FORCEFIELD_WAIT = false;
|
||||
AI_CENTURION_SCRIPTED_TUNNEL = 0;
|
||||
}
|
||||
|
||||
void hhCenturion::Event_PostSpawn( void ) {
|
||||
hhMonsterAI::Event_PostSpawn();
|
||||
|
||||
const idKeyValue *kv = spawnArgs.MatchPrefix( "aasObstacle" );
|
||||
idEntityPtr<idEntity> ent;
|
||||
while ( kv ) {
|
||||
ent = gameLocal.FindEntity( kv->GetValue() );
|
||||
if ( ent.IsValid() ) {
|
||||
obstacles.AddUnique( ent );
|
||||
}
|
||||
kv = spawnArgs.MatchPrefix( "aasObstacle", kv );
|
||||
}
|
||||
}
|
||||
|
||||
#define LinkScriptVariable( name ) name.LinkTo( scriptObject, #name )
|
||||
void hhCenturion::LinkScriptVariables( void ) {
|
||||
hhMonsterAI::LinkScriptVariables();
|
||||
|
||||
LinkScriptVariable(AI_CENTURION_ARM_MISSING);
|
||||
LinkScriptVariable(AI_CENTURION_REQUIRE_ROAR);
|
||||
LinkScriptVariable(AI_CENTURION_ARM_TUNNEL);
|
||||
LinkScriptVariable(AI_CENTURION_SCRIPTED_ROAR);
|
||||
LinkScriptVariable(AI_CENTURION_SCRIPTED_TUNNEL);
|
||||
LinkScriptVariable(AI_CENTURION_FORCEFIELD_WAIT);
|
||||
}
|
||||
|
||||
|
||||
void hhCenturion::Event_ForceFieldNotify() {
|
||||
if( !armchop_Target.GetEntity() ) {
|
||||
return; //must not be in arm-chop mode, so we don't care yet
|
||||
}
|
||||
AI_CENTURION_REQUIRE_ROAR = true;
|
||||
AI_CENTURION_FORCEFIELD_WAIT = true;
|
||||
}
|
||||
|
||||
void hhCenturion::Event_ForceFieldToggle( int toggle ) {
|
||||
if( !armchop_Target.GetEntity() ) {
|
||||
return;
|
||||
}
|
||||
AI_CENTURION_FORCEFIELD_WAIT = false;
|
||||
if (!toggle) {
|
||||
AI_CENTURION_REQUIRE_ROAR = false;
|
||||
} else if( AI_CENTURION_ARM_TUNNEL ) {
|
||||
Event_ScriptedArmChop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void hhCenturion::Event_PlayerInTunnel( int toggle, idEntity* ent ) {
|
||||
if( AI_CENTURION_ARM_MISSING ) { //don't care if the player goes back in tunnel once we already lost our arm
|
||||
return;
|
||||
}
|
||||
|
||||
if( toggle ) {
|
||||
if( !ent ) {
|
||||
gameLocal.DWarning( "entity needs to be present for tunnel event" );
|
||||
return;
|
||||
}
|
||||
armchop_Target = ent;
|
||||
AI_CENTURION_SCRIPTED_TUNNEL = 1;
|
||||
}
|
||||
else {
|
||||
armchop_Target = NULL;
|
||||
AI_CENTURION_SCRIPTED_TUNNEL = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void hhCenturion::Event_MoveToTunnel() {
|
||||
if (!armchop_Target.IsValid()) {
|
||||
idThread::ReturnInt(0);
|
||||
return;
|
||||
}
|
||||
|
||||
StopMove(MOVE_STATUS_DONE);
|
||||
MoveToPosition(armchop_Target->GetOrigin());
|
||||
idThread::ReturnInt(1);
|
||||
}
|
||||
|
||||
void hhCenturion::Event_ReachedTunnel() {
|
||||
if( armchop_Target.IsValid() ) {
|
||||
idAngles faceAngles = armchop_Target->GetAxis()[0].ToAngles();
|
||||
ideal_yaw = faceAngles.yaw;
|
||||
current_yaw = faceAngles.yaw;
|
||||
SetAxis( armchop_Target->GetAxis() );
|
||||
}
|
||||
}
|
||||
|
||||
void hhCenturion::Event_ScriptedRoar() {
|
||||
if ( AI_CENTURION_SCRIPTED_ROAR > 0 ) {
|
||||
gameLocal.Warning( "centurionRoar() called more than once!\n");
|
||||
} else {
|
||||
AI_CENTURION_SCRIPTED_ROAR = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void hhCenturion::Event_ScriptedArmChop() {
|
||||
const function_t* newstate = NULL;
|
||||
newstate = GetScriptFunction( "state_ScriptedArmChop" );
|
||||
if( newstate ) {
|
||||
SetState( newstate );
|
||||
}
|
||||
else {
|
||||
gameLocal.Warning( "Unable to find 'state_ScriptedArmChop' on centurion" );
|
||||
}
|
||||
}
|
||||
|
||||
void hhCenturion::Event_CenturionLooseArm() {
|
||||
idDict args;
|
||||
idEntity* ent = NULL;
|
||||
idVec3 jointLoc;
|
||||
idMat3 jointAxis;
|
||||
|
||||
animator.GetJointTransform( spawnArgs.GetString("arm_severjoint", ""), gameLocal.time, jointLoc, jointAxis );
|
||||
jointLoc = renderEntity.origin + jointLoc * renderEntity.axis;
|
||||
args.SetVector( "origin", jointLoc );
|
||||
args.SetMatrix( "rotation", renderEntity.axis );
|
||||
args.SetBool( "spin", 0 );
|
||||
args.SetFloat( "triggersize", 48.f );
|
||||
args.SetBool( "enablePickup", true );
|
||||
args.SetFloat( "respawn", 0.f );
|
||||
ent = gameLocal.SpawnObject( spawnArgs.GetString("def_arm_weaponclass", ""), &args );
|
||||
|
||||
SetSkinByName( spawnArgs.GetString( "skin_arm_gone" ) );
|
||||
|
||||
hhFxInfo fx;
|
||||
fx.SetEntity( this );
|
||||
fx.RemoveWhenDone( true );
|
||||
SpawnFxLocal( spawnArgs.GetString( "fx_armchop" ), jointLoc, mat3_identity, &fx );
|
||||
|
||||
//drop any stuck arrows
|
||||
idEntity *next;
|
||||
for( ent = teamChain; ent != NULL; ent = next ) {
|
||||
next = ent->GetTeamChain();
|
||||
if ( ent && ent->IsType( hhProjectile::Type ) ) {
|
||||
ent->Unbind();
|
||||
ent->Hide();
|
||||
ent->PostEventSec( &EV_Remove, 5 );
|
||||
next = teamChain;
|
||||
}
|
||||
}
|
||||
|
||||
AI_CENTURION_ARM_MISSING = true;
|
||||
}
|
||||
|
||||
void hhCenturion::Event_CenturionLaunch( const idList<idStr>* parmList ) {
|
||||
const idDict* projDef = NULL;
|
||||
const idSoundShader* soundShader = NULL;
|
||||
|
||||
// parms: joint, projectileDef, sound, fx
|
||||
if( !parmList || parmList->Num() != 5 ) {
|
||||
gameLocal.Warning( "Incorrect paramater number" );
|
||||
return;
|
||||
}
|
||||
//Rbarrel_A projectile_centurion_autocannon snd_fire fx_muzzleFlash
|
||||
const char* jointName = (*parmList)[ 0 ].c_str();
|
||||
const char* projectileDefName = (*parmList)[ 1 ].c_str();
|
||||
const char* soundName = (*parmList)[ 2 ].c_str();
|
||||
const char* fxName = (*parmList)[ 3 ].c_str();
|
||||
int autoAim = atoi( (*parmList)[ 4 ].c_str() );
|
||||
|
||||
if( AI_CENTURION_ARM_MISSING ) { //skip firing if joint is on the severed arm
|
||||
if( !idStr::Icmp(jointName, spawnArgs.GetString("severed_jointA", "")) || !idStr::Icmp(jointName, spawnArgs.GetString("severed_jointB", "")) ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
projDef = gameLocal.FindEntityDefDict( projectileDefName, false );
|
||||
HH_ASSERT( !shootTarget.IsValid() );
|
||||
// If autoAim is true and we're not blending, and we're facing the enemy, auto-aim
|
||||
if ( ( autoAim == 1 || ( autoAim == 2 && gameLocal.random.RandomInt(100) < 50 ) ) && torsoAnim.animBlendFrames == 0 && FacingEnemy( 5.0f ) ) {
|
||||
AimedAttackMissile( jointName, projDef );
|
||||
} else { // Otherwise do a normal missile attack
|
||||
Event_AttackMissile( jointName, projDef, 1 );
|
||||
}
|
||||
|
||||
if(idStr::Cmpn( soundName, "snd_", 4)) {
|
||||
soundShader = declManager->FindSound( soundName );
|
||||
if( soundShader->GetState() == DS_DEFAULTED ) {
|
||||
gameLocal.Warning( "Sound '%s' not found", soundName );
|
||||
}
|
||||
StartSoundShader( soundShader, SND_CHANNEL_WEAPON, 0, false, NULL );
|
||||
}
|
||||
else {
|
||||
if( !StartSound(soundName, SND_CHANNEL_WEAPON, 0, false, NULL) ) {
|
||||
gameLocal.Warning( "Framecommand 'centurionFire' on entity '%s' could not find sound '%s'", GetName(), soundName );
|
||||
}
|
||||
}
|
||||
BroadcastFxInfoAlongBone( spawnArgs.GetString(fxName), jointName );
|
||||
}
|
||||
|
||||
|
||||
void hhCenturion::Event_DestroyObstruction() {
|
||||
if( pillarEntity.IsValid() ) {
|
||||
pillarEntity->PostEventMS( &EV_Activate, 0.f, this );
|
||||
}
|
||||
}
|
||||
|
||||
void hhCenturion::Event_CheckForObstruction( int checkPathToPillar ) {
|
||||
bool obstacle = false;
|
||||
predictedPath_t path;
|
||||
if( enemy.IsValid() ) {
|
||||
idVec3 end = enemy->GetPhysics()->GetOrigin();
|
||||
if ( !checkPathToPillar ) {
|
||||
trace_t tr;
|
||||
idVec3 toPos, eye = GetEyePosition();
|
||||
|
||||
if ( enemy->IsType( idActor::Type ) ) {
|
||||
toPos = ( ( idActor * )enemy.GetEntity() )->GetEyePosition();
|
||||
} else {
|
||||
toPos = enemy->GetPhysics()->GetOrigin();
|
||||
}
|
||||
|
||||
gameLocal.clip.TracePoint( tr, eye, toPos, MASK_SHOT_BOUNDINGBOX, this );
|
||||
|
||||
idEntity *traceEnt = gameLocal.GetTraceEntity( tr );
|
||||
if ( traceEnt && ( tr.fraction < 1.0f || traceEnt != enemy.GetEntity() ) ) {
|
||||
//check to see if the other object is an pillar...
|
||||
if( traceEnt->spawnArgs.GetInt("centurion_pillar", "0") == 1 ) {
|
||||
pillarEntity = traceEnt;
|
||||
obstacle = true;
|
||||
}
|
||||
}
|
||||
|
||||
} else if ( pillarEntity.IsValid() ) {
|
||||
idAI::PredictPath( this, this->aas, physicsObj.GetOrigin(), enemy->GetPhysics()->GetOrigin() - physicsObj.GetOrigin(), 1000, 1000, ( move.moveType == MOVETYPE_FLY ) ? SE_BLOCKED : (SE_ENTER_OBSTACLE | SE_BLOCKED | SE_ENTER_LEDGE_AREA ), path );
|
||||
if( path.endEvent != 0 && path.blockingEntity ) {
|
||||
//check to see if the other object is an pillar...
|
||||
if( path.blockingEntity->spawnArgs.GetInt("centurion_pillar", "0") == 1 ) {
|
||||
//check to see if we can path to the obstacle clearly
|
||||
pillarEntity = path.blockingEntity;
|
||||
//idAI::PredictPath( this, this->aas, physicsObj.GetOrigin(), pillarEntity->GetPhysics()->GetOrigin() - physicsObj.GetOrigin(), 1000, 1000, (SE_ENTER_OBSTACLE | SE_BLOCKED | SE_ENTER_LEDGE_AREA), path );
|
||||
//if( path.endEvent != 0 && path.blockingEntity == pillarEntity.GetEntity() ) {
|
||||
obstacle = true;
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
idThread::ReturnInt( (int)obstacle );
|
||||
}
|
||||
|
||||
void hhCenturion::Event_CloseToObstruction() {
|
||||
if( physicsObj.GetAbsBounds().IntersectsBounds(pillarEntity->GetPhysics()->GetAbsBounds()) ) {
|
||||
idThread::ReturnInt( 1 );
|
||||
return;
|
||||
}
|
||||
idThread::ReturnInt( 0 );
|
||||
}
|
||||
|
||||
void hhCenturion::Event_ReachedObstruction() {
|
||||
FaceEntity( pillarEntity.GetEntity() );
|
||||
}
|
||||
|
||||
void hhCenturion::Event_MoveToObstruction() {
|
||||
idVec3 temp;
|
||||
if ( aas ) {
|
||||
int toAreaNum = PointReachableAreaNum( pillarEntity.GetEntity()->GetOrigin() );
|
||||
temp = pillarEntity.GetEntity()->GetOrigin();
|
||||
aas->PushPointIntoAreaNum( toAreaNum, temp );
|
||||
MoveToPosition( temp );
|
||||
} else {
|
||||
gameLocal.Warning( "Centurion has no aas for MoveToObstruction\n" );
|
||||
}
|
||||
}
|
||||
|
||||
void hhCenturion::Think() {
|
||||
PROFILE_SCOPE("AI", PROFMASK_NORMAL|PROFMASK_AI);
|
||||
if (ai_skipThink.GetBool()) {
|
||||
return;
|
||||
}
|
||||
|
||||
hhMonsterAI::Think();
|
||||
|
||||
if(ai_debugBrain.GetInteger() > 0 && state) {
|
||||
if ( enemy.IsValid() && enemy->GetHealth() > 0 ) {
|
||||
float dist = ( GetPhysics()->GetOrigin() - enemy->GetPhysics()->GetOrigin() ).LengthFast();
|
||||
gameRenderWorld->DrawText( va("%f", dist), this->GetEyePosition() + idVec3(0.0f, 0.0f, 40.0f), 0.75f, colorYellow, gameLocal.GetLocalPlayer()->viewAngles.ToMat3());
|
||||
}
|
||||
gameRenderWorld->DrawText(state->Name(), this->GetEyePosition() + idVec3(0.0f, 0.0f, 40.0f), 0.75f, colorYellow, gameLocal.GetLocalPlayer()->viewAngles.ToMat3());
|
||||
gameRenderWorld->DrawText(torsoAnim.state, this->GetEyePosition() + idVec3(0.0f, 0.0f, 20.0f), 0.75f, colorYellow, gameLocal.GetLocalPlayer()->viewAngles.ToMat3());
|
||||
gameRenderWorld->DrawText(legsAnim.state, this->GetEyePosition() + idVec3(0.0f, 0.0f, 0.0f), 0.75f, colorYellow, gameLocal.GetLocalPlayer()->viewAngles.ToMat3());
|
||||
}
|
||||
}
|
||||
|
||||
bool hhCenturion::AttackMelee( const char *meleeDefName ) {
|
||||
const idDict *meleeDef;
|
||||
idActor *enemyEnt = enemy.GetEntity();
|
||||
const char *p;
|
||||
const idSoundShader *shader;
|
||||
|
||||
meleeDef = gameLocal.FindEntityDefDict( meleeDefName, false );
|
||||
if ( !meleeDef ) {
|
||||
gameLocal.Error( "Unknown melee '%s'", meleeDefName );
|
||||
}
|
||||
|
||||
if ( !enemyEnt ) {
|
||||
p = meleeDef->GetString( "snd_miss" );
|
||||
if ( p && *p ) {
|
||||
shader = declManager->FindSound( p );
|
||||
StartSoundShader( shader, SND_CHANNEL_DAMAGE, 0, false, NULL );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure the trace can actually hit the enemy
|
||||
if ( !TestMelee() ) {
|
||||
// missed
|
||||
p = meleeDef->GetString( "snd_miss" );
|
||||
if ( p && *p ) {
|
||||
shader = declManager->FindSound( p );
|
||||
StartSoundShader( shader, SND_CHANNEL_DAMAGE, 0, false, NULL );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// do the damage
|
||||
//
|
||||
p = meleeDef->GetString( "snd_hit" );
|
||||
if ( p && *p ) {
|
||||
shader = declManager->FindSound( p );
|
||||
StartSoundShader( shader, SND_CHANNEL_DAMAGE, 0, false, NULL );
|
||||
}
|
||||
|
||||
idVec3 kickDir;
|
||||
meleeDef->GetVector( "kickDir", "0 0 0", kickDir );
|
||||
|
||||
idVec3 globalKickDir;
|
||||
globalKickDir = ( viewAxis * physicsObj.GetGravityAxis() ) * kickDir;
|
||||
|
||||
enemyEnt->Damage( this, this, globalKickDir, meleeDefName, 1.0f, INVALID_JOINT );
|
||||
if ( enemyEnt->IsActiveAF() && !enemyEnt->IsType( idPlayer::Type ) ) {
|
||||
PostEventMS( &AI_BackhandImpulse, 0, enemyEnt );
|
||||
}
|
||||
|
||||
lastAttackTime = gameLocal.time;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void hhCenturion::Event_BackhandImpulse( idEntity* ent ) {
|
||||
const idDict *meleeDef = gameLocal.FindEntityDefDict( spawnArgs.GetString("def_impulse_damage"), false );
|
||||
if ( !meleeDef || !ent ) {
|
||||
return;
|
||||
}
|
||||
idVec3 kickDir;
|
||||
meleeDef->GetVector( "kickDir", "0 0 0", kickDir );
|
||||
idVec3 globalKickDir = ( viewAxis * physicsObj.GetGravityAxis() ) * kickDir;
|
||||
globalKickDir *= ent->spawnArgs.GetFloat( "kick_scale", "1.0" );
|
||||
ent->ApplyImpulse( this, 0, ent->GetOrigin(), meleeDef->GetFloat( "push_ragdoll" ) * globalKickDir );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
hhCenturion::Save
|
||||
=====================
|
||||
*/
|
||||
void hhCenturion::Save( idSaveGame *savefile ) const {
|
||||
armchop_Target.Save( savefile );
|
||||
pillarEntity.Save( savefile );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
hhCenturion::Restore
|
||||
=====================
|
||||
*/
|
||||
void hhCenturion::Restore( idRestoreGame *savefile ) {
|
||||
armchop_Target.Restore( savefile );
|
||||
pillarEntity.Restore( savefile );
|
||||
|
||||
// Restore the obstacle list
|
||||
const idKeyValue *kv = spawnArgs.MatchPrefix( "aasObstacle" );
|
||||
idEntityPtr<idEntity> ent;
|
||||
while ( kv ) {
|
||||
ent = gameLocal.FindEntity( kv->GetValue() );
|
||||
if ( ent.IsValid() ) {
|
||||
obstacles.AddUnique( ent );
|
||||
}
|
||||
kv = spawnArgs.MatchPrefix( "aasObstacle", kv );
|
||||
}
|
||||
}
|
||||
|
||||
void hhCenturion::Event_EnemyCloseToObstruction(void) {
|
||||
bool close = false;
|
||||
if ( pillarEntity.IsValid() && enemy.IsValid() ) {
|
||||
float obs_dist = ( pillarEntity->GetOrigin() - GetOrigin() ).Length();
|
||||
float dist = ( enemy->GetOrigin() - GetOrigin() ).Length();
|
||||
|
||||
// If the enemy is further from me than the pillar...
|
||||
if ( dist > obs_dist) {
|
||||
dist = ( pillarEntity->GetOrigin() - enemy->GetOrigin() ).Length();
|
||||
// If the enemy is less than 400 units from the pillar, then he's 'close'
|
||||
if ( dist < 400.0f ) {
|
||||
close = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
idThread::ReturnInt( (int) close );
|
||||
}
|
||||
|
||||
void hhCenturion::AimedAttackMissile( const char *jointname, const idDict *projDef) {
|
||||
idProjectile *proj;
|
||||
idVec3 target, origin = GetOrigin();
|
||||
bool inShuttle = false;
|
||||
|
||||
if ( shootTarget.IsValid() ) {
|
||||
target = shootTarget->GetOrigin();
|
||||
} else if ( enemy.IsValid() ) {
|
||||
target = enemy->GetOrigin();
|
||||
if ( enemy->IsType( idActor::Type ) ) {
|
||||
target.z += enemy->EyeHeight() / 4.0f;
|
||||
}
|
||||
} else {
|
||||
// No target? Do the default attack
|
||||
Event_AttackMissile( jointname, projDef, 1 );
|
||||
return;
|
||||
}
|
||||
|
||||
// If target is too close do a non-aimed attack
|
||||
if ( fabsf( origin.x - target.x ) < 256 &&
|
||||
fabsf( origin.y - target.y ) < 256 ) {
|
||||
Event_AttackMissile( jointname, projDef, 1 );
|
||||
return;
|
||||
}
|
||||
|
||||
idVec3 dist = origin - target;
|
||||
|
||||
if ( shootTarget.IsValid() ) {
|
||||
proj = LaunchProjectile( jointname, shootTarget.GetEntity(), true, projDef );
|
||||
} else {
|
||||
proj = LaunchProjectile( jointname, enemy.GetEntity(), true, projDef );
|
||||
}
|
||||
}
|
||||
|
||||
void hhCenturion::Event_TakeDamage(int takeDamage) {
|
||||
// Set the takedamage flag
|
||||
fl.takedamage = (takeDamage != 0);
|
||||
}
|
||||
|
||||
void hhCenturion::Event_FindNearbyEnemy( float distance ) {
|
||||
// Search for the monster nearest to us
|
||||
idAI *nearest = NULL;
|
||||
float dist, nearDist = idMath::INFINITY;
|
||||
idAI *ai = reinterpret_cast<idAI *> (gameLocal.FindEntityOfType( idAI::Type, NULL ));
|
||||
while (ai) {
|
||||
if (ai != this) { // Don't target yourself
|
||||
dist = (ai->GetOrigin() - GetOrigin()).Length();
|
||||
if (dist < nearDist) {
|
||||
nearDist = dist;
|
||||
nearest = ai;
|
||||
}
|
||||
}
|
||||
ai = reinterpret_cast<idAI *> (gameLocal.FindEntityOfType( idAI::Type, ai ));
|
||||
}
|
||||
|
||||
// If we found one near us and it's near enough, return it
|
||||
if (nearest && nearDist < distance) {
|
||||
idThread::ReturnEntity(nearest);
|
||||
} else {
|
||||
idThread::ReturnEntity(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void hhCenturion::Event_Touch( idEntity *other, trace_t *trace ) {
|
||||
if ( (!enemy.GetEntity() || other->IsType( hhPlayer::Type )) && !other->fl.notarget && ( ReactionTo( other ) & ATTACK_ON_ACTIVATE ) ) {
|
||||
Activate( other );
|
||||
SetEnemy( static_cast<idActor *> ( other ) );
|
||||
}
|
||||
AI_PUSHED = true;
|
||||
}
|
||||
|
||||
#endif //HUMANHEAD jsh PCF 5/26/06: code removed for demo build
|
||||
Reference in New Issue
Block a user