#include "b_local.h"Go to the source code of this file.
Defines | |
| #define | MAX_INTEREST_DIST ( 256 * 256 ) |
Functions | |
| qboolean | G_ClearLineOfSight (const vec3_t point1, const vec3_t point2, int ignore, int clipmask) |
| qboolean | CanSee (gentity_t *ent) |
| qboolean | InFront (vec3_t spot, vec3_t from, vec3_t fromAngles, float threshHold) |
| qboolean | InFOV3 (vec3_t spot, vec3_t from, vec3_t fromAngles, int hFOV, int vFOV) |
| qboolean | InFOV2 (vec3_t origin, gentity_t *from, int hFOV, int vFOV) |
| qboolean | InFOV (gentity_t *ent, gentity_t *from, int hFOV, int vFOV) |
| qboolean | InVisrange (gentity_t *ent) |
| visibility_t | NPC_CheckVisibility (gentity_t *ent, int flags) |
| float | G_GetLightLevel (vec3_t pos, vec3_t fromDir) |
| int | G_CheckAlertEvents (gentity_t *self, qboolean checkSight, qboolean checkSound, float maxSeeDist, float maxHearDist, int ignoreAlert, qboolean mustHaveOwner, int minAlertLevel) |
| int | NPC_CheckAlertEvents (qboolean checkSight, qboolean checkSound, int ignoreAlert, qboolean mustHaveOwner, int minAlertLevel) |
| qboolean | G_CheckForDanger (gentity_t *self, int alertEvent) |
| qboolean | NPC_CheckForDanger (int alertEvent) |
| qboolean | RemoveOldestAlert (void) |
| void | AddSoundEvent (gentity_t *owner, vec3_t position, float radius, alertEventLevel_e alertLevel, qboolean needLOS) |
| void | AddSightEvent (gentity_t *owner, vec3_t position, float radius, alertEventLevel_e alertLevel, float addLight) |
| void | ClearPlayerAlertEvents (void) |
| qboolean | G_ClearLOS (gentity_t *self, const vec3_t start, const vec3_t end) |
| qboolean | G_ClearLOS2 (gentity_t *self, gentity_t *ent, const vec3_t end) |
| qboolean | G_ClearLOS3 (gentity_t *self, const vec3_t start, gentity_t *ent) |
| qboolean | G_ClearLOS4 (gentity_t *self, gentity_t *ent) |
| qboolean | G_ClearLOS5 (gentity_t *self, const vec3_t end) |
| float | NPC_GetHFOVPercentage (vec3_t spot, vec3_t from, vec3_t facing, float hFOV) |
| float | NPC_GetVFOVPercentage (vec3_t spot, vec3_t from, vec3_t facing, float vFOV) |
| int | G_FindLocalInterestPoint (gentity_t *self) |
| void | SP_target_interest (gentity_t *self) |
Variables | |
| int | eventClearTime |
|
|
Definition at line 864 of file NPC_senses.c. Referenced by G_FindLocalInterestPoint(). |
|
||||||||||||||||||||||||
|
Definition at line 623 of file NPC_senses.c. References AEL_DANGER, AET_SIGHT, level_locals_t::alertEvents, level_locals_t::curAlertID, gentity_t, level, MAX_ALERT_EVENTS, NULL, level_locals_t::numAlertEvents, RemoveOldestAlert(), level_locals_t::time, vec3_t, and VectorCopy. Referenced by CorpsePhysics(), ForceTelepathyCheckDirectNPCTarget(), and NPC_BSRancor_Default().
00624 {
00625 //FIXME: Handle this in another manner?
00626 if ( level.numAlertEvents >= MAX_ALERT_EVENTS )
00627 {
00628 if ( !RemoveOldestAlert() )
00629 {//how could that fail?
00630 return;
00631 }
00632 }
00633
00634 if ( owner == NULL && alertLevel < AEL_DANGER ) //allows un-owned danger alerts
00635 return;
00636
00637 //FIXME: if owner is not a player or player ally, and there are no player allies present,
00638 // perhaps we don't need to store the alert... unless we want the player to
00639 // react to enemy alert events in some way?
00640
00641 VectorCopy( position, level.alertEvents[ level.numAlertEvents ].position );
00642
00643 level.alertEvents[ level.numAlertEvents ].radius = radius;
00644 level.alertEvents[ level.numAlertEvents ].level = alertLevel;
00645 level.alertEvents[ level.numAlertEvents ].type = AET_SIGHT;
00646 level.alertEvents[ level.numAlertEvents ].owner = owner;
00647 level.alertEvents[ level.numAlertEvents ].addLight = addLight; //will get added to actual light at that point when it's checked
00648 level.alertEvents[ level.numAlertEvents ].ID = level.curAlertID++;
00649 level.alertEvents[ level.numAlertEvents ].timestamp = level.time;
00650
00651 level.numAlertEvents++;
00652 }
|
|
||||||||||||||||||||||||
|
Definition at line 579 of file NPC_senses.c. References AEL_DANGER, AET_SOUND, level_locals_t::alertEvents, level_locals_t::curAlertID, gentity_t, level, MAX_ALERT_EVENTS, NULL, level_locals_t::numAlertEvents, RemoveOldestAlert(), level_locals_t::time, vec3_t, and VectorCopy. Referenced by ForceTelepathyCheckDirectNPCTarget(), NPC_BSRancor_Default(), and Rancor_Smash().
00580 {
00581 //FIXME: Handle this in another manner?
00582 if ( level.numAlertEvents >= MAX_ALERT_EVENTS )
00583 {
00584 if ( !RemoveOldestAlert() )
00585 {//how could that fail?
00586 return;
00587 }
00588 }
00589
00590 if ( owner == NULL && alertLevel < AEL_DANGER ) //allows un-owned danger alerts
00591 return;
00592
00593 //FIXME: if owner is not a player or player ally, and there are no player allies present,
00594 // perhaps we don't need to store the alert... unless we want the player to
00595 // react to enemy alert events in some way?
00596
00597 VectorCopy( position, level.alertEvents[ level.numAlertEvents ].position );
00598
00599 level.alertEvents[ level.numAlertEvents ].radius = radius;
00600 level.alertEvents[ level.numAlertEvents ].level = alertLevel;
00601 level.alertEvents[ level.numAlertEvents ].type = AET_SOUND;
00602 level.alertEvents[ level.numAlertEvents ].owner = owner;
00603 if ( needLOS )
00604 {//a very low-level sound, when check this sound event, check for LOS
00605 level.alertEvents[ level.numAlertEvents ].addLight = 1; //will force an LOS trace on this sound
00606 }
00607 else
00608 {
00609 level.alertEvents[ level.numAlertEvents ].addLight = 0; //will force an LOS trace on this sound
00610 }
00611 level.alertEvents[ level.numAlertEvents ].ID = level.curAlertID++;
00612 level.alertEvents[ level.numAlertEvents ].timestamp = level.time;
00613
00614 level.numAlertEvents++;
00615 }
|
|
|
Definition at line 47 of file NPC_senses.c. References CalcEntitySpot(), trace_t::fraction, gentity_t, MASK_OPAQUE, NPC, NULL, entityState_s::number, qboolean, qfalse, qtrue, gentity_s::s, ShotThroughGlass(), SPOT_HEAD, SPOT_HEAD_LEAN, SPOT_LEGS, SPOT_ORIGIN, trap_Trace(), and vec3_t. Referenced by NPC_CheckVisibility().
00048 {
00049 trace_t tr;
00050 vec3_t eyes;
00051 vec3_t spot;
00052
00053 CalcEntitySpot( NPC, SPOT_HEAD_LEAN, eyes );
00054
00055 CalcEntitySpot( ent, SPOT_ORIGIN, spot );
00056 trap_Trace ( &tr, eyes, NULL, NULL, spot, NPC->s.number, MASK_OPAQUE );
00057 ShotThroughGlass (&tr, ent, spot, MASK_OPAQUE);
00058 if ( tr.fraction == 1.0 )
00059 {
00060 return qtrue;
00061 }
00062
00063 CalcEntitySpot( ent, SPOT_HEAD, spot );
00064 trap_Trace ( &tr, eyes, NULL, NULL, spot, NPC->s.number, MASK_OPAQUE );
00065 ShotThroughGlass (&tr, ent, spot, MASK_OPAQUE);
00066 if ( tr.fraction == 1.0 )
00067 {
00068 return qtrue;
00069 }
00070
00071 CalcEntitySpot( ent, SPOT_LEGS, spot );
00072 trap_Trace ( &tr, eyes, NULL, NULL, spot, NPC->s.number, MASK_OPAQUE );
00073 ShotThroughGlass (&tr, ent, spot, MASK_OPAQUE);
00074 if ( tr.fraction == 1.0 )
00075 {
00076 return qtrue;
00077 }
00078
00079 return qfalse;
00080 }
|
|
|
Definition at line 660 of file NPC_senses.c. References ALERT_CLEAR_TIME, alertEvent_t, level_locals_t::alertEvents, eventClearTime, level, MAX_ALERT_EVENTS, memmove(), memset(), level_locals_t::numAlertEvents, level_locals_t::time, and alertEvent_s::timestamp.
00661 {
00662 int curNumAlerts = level.numAlertEvents;
00663 int i;
00664 //loop through them all (max 32)
00665 for ( i = 0; i < curNumAlerts; i++ )
00666 {
00667 //see if the event is old enough to delete
00668 if ( level.alertEvents[i].timestamp && level.alertEvents[i].timestamp + ALERT_CLEAR_TIME < level.time )
00669 {//this event has timed out
00670 //drop the count
00671 level.numAlertEvents--;
00672 //shift the rest down
00673 if ( level.numAlertEvents > 0 )
00674 {//still have more in the array
00675 if ( (i+1) < MAX_ALERT_EVENTS )
00676 {
00677 memmove( &level.alertEvents[i], &level.alertEvents[i+1], sizeof(alertEvent_t)*(MAX_ALERT_EVENTS-(i+1) ) );
00678 }
00679 }
00680 else
00681 {//just clear this one... or should we clear the whole array?
00682 memset( &level.alertEvents[i], 0, sizeof( alertEvent_t ) );
00683 }
00684 }
00685 }
00686 //make sure this never drops below zero... if it does, something very very bad happened
00687 assert( level.numAlertEvents >= 0 );
00688
00689 if ( eventClearTime < level.time )
00690 {//this is just a 200ms debouncer so things that generate constant alerts (like corpses and missiles) add an alert every 200 ms
00691 eventClearTime = level.time + ALERT_CLEAR_TIME;
00692 }
00693 }
|
|
||||||||||||||||||||||||||||||||||||
|
Definition at line 478 of file NPC_senses.c. References alertEvent_s::addLight, level_locals_t::alertEvents, CalcEntitySpot(), g_entities, G_GetLightLevel(), gentity_t, gentity_s::health, gNPCstats_e::hfov, alertEvent_s::level, level, alertEvent_s::light, gentity_s::NPC, NULL, alertEvent_s::position, SPOT_HEAD_LEAN, gNPC_t::stats, vec3_t, VectorSubtract, and gNPCstats_e::vfov. Referenced by NPC_CheckAlertEvents().
00479 {
00480 int bestSoundEvent = -1;
00481 int bestSightEvent = -1;
00482 int bestSoundAlert = -1;
00483 int bestSightAlert = -1;
00484
00485 if ( &g_entities[0] == NULL || g_entities[0].health <= 0 )
00486 {
00487 //player is dead
00488 return -1;
00489 }
00490
00491 //get sound event
00492 bestSoundEvent = G_CheckSoundEvents( self, maxHearDist, ignoreAlert, mustHaveOwner, minAlertLevel );
00493 //get sound event alert level
00494 if ( bestSoundEvent >= 0 )
00495 {
00496 bestSoundAlert = level.alertEvents[bestSoundEvent].level;
00497 }
00498
00499 //get sight event
00500 if ( self->NPC )
00501 {
00502 bestSightEvent = G_CheckSightEvents( self, self->NPC->stats.hfov, self->NPC->stats.vfov, maxSeeDist, ignoreAlert, mustHaveOwner, minAlertLevel );
00503 }
00504 else
00505 {
00506 bestSightEvent = G_CheckSightEvents( self, 80, 80, maxSeeDist, ignoreAlert, mustHaveOwner, minAlertLevel );//FIXME: look at cg_view to get more accurate numbers?
00507 }
00508 //get sight event alert level
00509 if ( bestSightEvent >= 0 )
00510 {
00511 bestSightAlert = level.alertEvents[bestSightEvent].level;
00512 }
00513
00514 //return the one that has a higher alert (or sound if equal)
00515 //FIXME: This doesn't take the distance of the event into account
00516
00517 if ( bestSightEvent >= 0 && bestSightAlert > bestSoundAlert )
00518 {//valid best sight event, more important than the sound event
00519 //get the light level of the alert event for this checker
00520 vec3_t eyePoint, sightDir;
00521 //get eye point
00522 CalcEntitySpot( self, SPOT_HEAD_LEAN, eyePoint );
00523 VectorSubtract( level.alertEvents[bestSightEvent].position, eyePoint, sightDir );
00524 level.alertEvents[bestSightEvent].light = level.alertEvents[bestSightEvent].addLight + G_GetLightLevel( level.alertEvents[bestSightEvent].position, sightDir );
00525 //return the sight event
00526 return bestSightEvent;
00527 }
00528 //return the sound event
00529 return bestSoundEvent;
00530 }
|
|
||||||||||||
|
Definition at line 537 of file NPC_senses.c. References AEL_DANGER, level_locals_t::alertEvents, gentity_s::client, gentity_t, alertEvent_s::level, level, gentity_s::NPC, NPC_StartFlee(), alertEvent_s::owner, gclient_s::playerTeam, alertEvent_s::position, qboolean, qfalse, qtrue, SCF_DONT_FLEE, and gNPC_t::scriptFlags. Referenced by NPC_CheckForDanger().
00538 {//FIXME: more bStates need to call this?
00539 if ( alertEvent == -1 )
00540 {
00541 return qfalse;
00542 }
00543
00544 if ( level.alertEvents[alertEvent].level >= AEL_DANGER )
00545 {//run away!
00546 if ( !level.alertEvents[alertEvent].owner || !level.alertEvents[alertEvent].owner->client || (level.alertEvents[alertEvent].owner!=self&&level.alertEvents[alertEvent].owner->client->playerTeam!=self->client->playerTeam) )
00547 {
00548 if ( self->NPC )
00549 {
00550 if ( self->NPC->scriptFlags & SCF_DONT_FLEE )
00551 {//can't flee
00552 return qfalse;
00553 }
00554 else
00555 {
00556 NPC_StartFlee( level.alertEvents[alertEvent].owner, level.alertEvents[alertEvent].position, level.alertEvents[alertEvent].level, 3000, 6000 );
00557 return qtrue;
00558 }
00559 }
00560 else
00561 {
00562 return qtrue;
00563 }
00564 }
00565 }
00566 return qfalse;
00567 }
|
|
||||||||||||||||||||
|
Definition at line 11 of file NPC_senses.c. References trace_t::endpos, EntIsGlass(), trace_t::entityNum, trace_t::fraction, g_entities, gentity_t, NULL, entityState_s::number, qboolean, qfalse, qtrue, gentity_s::s, trap_Trace(), vec3_t, and VectorCopy. Referenced by G_FindLocalInterestPoint().
00012 {
00013 trace_t tr;
00014 gentity_t *hit;
00015
00016 trap_Trace ( &tr, point1, NULL, NULL, point2, ignore, clipmask );
00017 if ( tr.fraction == 1.0 )
00018 {
00019 return qtrue;
00020 }
00021
00022 hit = &g_entities[ tr.entityNum ];
00023 if(EntIsGlass(hit))
00024 {
00025 vec3_t newpoint1;
00026 VectorCopy(tr.endpos, newpoint1);
00027 trap_Trace (&tr, newpoint1, NULL, NULL, point2, hit->s.number, clipmask );
00028
00029 if ( tr.fraction == 1.0 )
00030 {
00031 return qtrue;
00032 }
00033 }
00034
00035 return qfalse;
00036 }
|
|
||||||||||||||||
|
Definition at line 739 of file NPC_senses.c. References CONTENTS_OPAQUE, trace_t::endpos, trace_t::entityNum, ENTITYNUM_NONE, ENTITYNUM_WORLD, trace_t::fraction, g_entities, gentity_t, MASK_OPAQUE, NULL, qboolean, qfalse, qtrue, SVF_GLASS_BRUSH, trap_Trace(), and vec3_t. Referenced by G_ClearLOS2(), G_ClearLOS3(), G_ClearLOS5(), and NPC_ClearLOS().
00740 {
00741 trace_t tr;
00742 int traceCount = 0;
00743
00744 //FIXME: ENTITYNUM_NONE ok?
00745 trap_Trace ( &tr, start, NULL, NULL, end, ENTITYNUM_NONE, CONTENTS_OPAQUE/*CONTENTS_SOLID*//*(CONTENTS_SOLID|CONTENTS_MONSTERCLIP)*/ );
00746 while ( tr.fraction < 1.0 && traceCount < 3 )
00747 {//can see through 3 panes of glass
00748 if ( tr.entityNum < ENTITYNUM_WORLD )
00749 {
00750 if ( &g_entities[tr.entityNum] != NULL && (g_entities[tr.entityNum].r.svFlags&SVF_GLASS_BRUSH) )
00751 {//can see through glass, trace again, ignoring me
00752 trap_Trace ( &tr, tr.endpos, NULL, NULL, end, tr.entityNum, MASK_OPAQUE );
00753 traceCount++;
00754 continue;
00755 }
00756 }
00757 return qfalse;
00758 }
00759
00760 if ( tr.fraction == 1.0 )
00761 return qtrue;
00762
00763 return qfalse;
00764 }
|
|
||||||||||||||||
|
Definition at line 767 of file NPC_senses.c. References CalcEntitySpot(), G_ClearLOS(), gentity_t, qboolean, SPOT_HEAD_LEAN, and vec3_t. Referenced by NPC_ClearLOS2().
00768 {
00769 vec3_t eyes;
00770
00771 CalcEntitySpot( ent, SPOT_HEAD_LEAN, eyes );
00772
00773 return G_ClearLOS( self, eyes, end );
00774 }
|
|
||||||||||||||||
|
Definition at line 777 of file NPC_senses.c. References CalcEntitySpot(), G_ClearLOS(), gentity_t, qboolean, qfalse, qtrue, SPOT_HEAD_LEAN, SPOT_ORIGIN, and vec3_t. Referenced by G_ClearLOS4(), and NPC_ClearLOS3().
00778 {
00779 vec3_t spot;
00780
00781 //Look for the chest first
00782 CalcEntitySpot( ent, SPOT_ORIGIN, spot );
00783
00784 if ( G_ClearLOS( self, start, spot ) )
00785 return qtrue;
00786
00787 //Look for the head next
00788 CalcEntitySpot( ent, SPOT_HEAD_LEAN, spot );
00789
00790 if ( G_ClearLOS( self, start, spot ) )
00791 return qtrue;
00792
00793 return qfalse;
00794 }
|
|
||||||||||||
|
Definition at line 797 of file NPC_senses.c. References CalcEntitySpot(), G_ClearLOS3(), gentity_t, qboolean, SPOT_HEAD_LEAN, and vec3_t. Referenced by NPC_ClearLOS4(), and WP_SaberStartMissileBlockCheck().
00798 {
00799 vec3_t eyes;
00800
00801 //Calculate my position
00802 CalcEntitySpot( self, SPOT_HEAD_LEAN, eyes );
00803
00804 return G_ClearLOS3( self, eyes, ent );
00805 }
|
|
||||||||||||
|
Definition at line 808 of file NPC_senses.c. References CalcEntitySpot(), G_ClearLOS(), gentity_t, qboolean, SPOT_HEAD_LEAN, and vec3_t. Referenced by NPC_ClearLOS5().
00809 {
00810 vec3_t eyes;
00811
00812 //Calculate the my position
00813 CalcEntitySpot( self, SPOT_HEAD_LEAN, eyes );
00814
00815 return G_ClearLOS( self, eyes, end );
00816 }
|
|
|
Definition at line 871 of file NPC_senses.c. References CalcEntitySpot(), ENTITYNUM_NONE, fabs(), G_ClearLineOfSight(), G_UseTargets2(), gentity_t, level_locals_t::interestPoints, level, MASK_OPAQUE, MAX_INTEREST_DIST, entityState_s::number, level_locals_t::numInterestPoints, interestPoint_t::origin, Q3_INFINITE, gentity_s::s, SPOT_HEAD_LEAN, interestPoint_t::target, trap_InPVS(), vec3_t, and VectorSubtract.
00872 {
00873 int i, bestPoint = ENTITYNUM_NONE;
00874 float dist, bestDist = Q3_INFINITE;
00875 vec3_t diffVec, eyes;
00876
00877 CalcEntitySpot( self, SPOT_HEAD_LEAN, eyes );
00878 for ( i = 0; i < level.numInterestPoints; i++ )
00879 {
00880 //Don't ignore portals? If through a portal, need to look at portal!
00881 if ( trap_InPVS( level.interestPoints[i].origin, eyes ) )
00882 {
00883 VectorSubtract( level.interestPoints[i].origin, eyes, diffVec );
00884 if ( (fabs(diffVec[0]) + fabs(diffVec[1])) / 2 < 48 &&
00885 fabs(diffVec[2]) > (fabs(diffVec[0]) + fabs(diffVec[1])) / 2 )
00886 {//Too close to look so far up or down
00887 continue;
00888 }
00889 dist = VectorLengthSquared( diffVec );
00890 //Some priority to more interesting points
00891 //dist -= ((int)level.interestPoints[i].lookMode * 5) * ((int)level.interestPoints[i].lookMode * 5);
00892 if ( dist < MAX_INTEREST_DIST && dist < bestDist )
00893 {
00894 if ( G_ClearLineOfSight( eyes, level.interestPoints[i].origin, self->s.number, MASK_OPAQUE ) )
00895 {
00896 bestDist = dist;
00897 bestPoint = i;
00898 }
00899 }
00900 }
00901 }
00902 if ( bestPoint != ENTITYNUM_NONE && level.interestPoints[bestPoint].target )
00903 {
00904 G_UseTargets2( self, self, level.interestPoints[bestPoint].target );
00905 }
00906 return bestPoint;
00907 }
|
|
||||||||||||
|
Definition at line 388 of file NPC_senses.c. References vec3_t. Referenced by G_CheckAlertEvents().
00389 {
00390 /*
00391 vec3_t ambient={0}, directed, lightDir;
00392
00393 cgi_R_GetLighting( pos, ambient, directed, lightDir );
00394 lightLevel = VectorLength( ambient ) + (VectorLength( directed )*DotProduct( lightDir, fromDir ));
00395 */
00396 float lightLevel;
00397 //rwwFIXMEFIXME: ...this is evil. We can possibly read from the server BSP data, or load the lightmap along
00398 //with collision data and whatnot, but is it worth it?
00399 lightLevel = 255;
00400
00401 return lightLevel;
00402 }
|
|
||||||||||||||||||||
|
Definition at line 149 of file NPC_senses.c. References AngleDelta(), entityState_s::angles, CalcEntitySpot(), gentity_s::client, renderInfo_s::eyeAngles, fabs(), gentity_t, PITCH, gclient_s::ps, qboolean, qfalse, qtrue, gclient_s::renderInfo, gentity_s::s, SPOT_HEAD, SPOT_HEAD_LEAN, SPOT_LEGS, SPOT_ORIGIN, vec3_origin, vec3_t, vectoangles(), VectorCopy, VectorSubtract, playerState_s::viewangles, and YAW. Referenced by G_AlertTeam(), Jedi_CheckAmbushPlayer(), NPC_CheckEnemyStealth(), NPC_CheckSurrender(), NPC_CheckVisibility(), NPC_ShySpawn(), NPC_SomeoneLookingAtMe(), and NPC_TargetVisible().
00150 {
00151 vec3_t eyes;
00152 vec3_t spot;
00153 vec3_t deltaVector;
00154 vec3_t angles, fromAngles;
00155 vec3_t deltaAngles;
00156
00157 if( from->client )
00158 {
00159 if( !VectorCompare( from->client->renderInfo.eyeAngles, vec3_origin ) )
00160 {//Actual facing of tag_head!
00161 //NOTE: Stasis aliens may have a problem with this?
00162 VectorCopy( from->client->renderInfo.eyeAngles, fromAngles );
00163 }
00164 else
00165 {
00166 VectorCopy( from->client->ps.viewangles, fromAngles );
00167 }
00168 }
00169 else
00170 {
00171 VectorCopy(from->s.angles, fromAngles);
00172 }
00173
00174 CalcEntitySpot( from, SPOT_HEAD_LEAN, eyes );
00175
00176 CalcEntitySpot( ent, SPOT_ORIGIN, spot );
00177 VectorSubtract ( spot, eyes, deltaVector);
00178
00179 vectoangles ( deltaVector, angles );
00180 deltaAngles[PITCH] = AngleDelta ( fromAngles[PITCH], angles[PITCH] );
00181 deltaAngles[YAW] = AngleDelta ( fromAngles[YAW], angles[YAW] );
00182 if ( fabs ( deltaAngles[PITCH] ) <= vFOV && fabs ( deltaAngles[YAW] ) <= hFOV )
00183 {
00184 return qtrue;
00185 }
00186
00187 CalcEntitySpot( ent, SPOT_HEAD, spot );
00188 VectorSubtract ( spot, eyes, deltaVector);
00189 vectoangles ( deltaVector, angles );
00190 deltaAngles[PITCH] = AngleDelta ( fromAngles[PITCH], angles[PITCH] );
00191 deltaAngles[YAW] = AngleDelta ( fromAngles[YAW], angles[YAW] );
00192 if ( fabs ( deltaAngles[PITCH] ) <= vFOV && fabs ( deltaAngles[YAW] ) <= hFOV )
00193 {
00194 return qtrue;
00195 }
00196
00197 CalcEntitySpot( ent, SPOT_LEGS, spot );
00198 VectorSubtract ( spot, eyes, deltaVector);
00199 vectoangles ( deltaVector, angles );
00200 deltaAngles[PITCH] = AngleDelta ( fromAngles[PITCH], angles[PITCH] );
00201 deltaAngles[YAW] = AngleDelta ( fromAngles[YAW], angles[YAW] );
00202 if ( fabs ( deltaAngles[PITCH] ) <= vFOV && fabs ( deltaAngles[YAW] ) <= hFOV )
00203 {
00204 return qtrue;
00205 }
00206
00207 return qfalse;
00208 }
|
|
||||||||||||||||||||
|
Definition at line 129 of file NPC_senses.c. References entityState_s::angles, CalcEntitySpot(), gentity_s::client, gentity_t, InFOV3(), gclient_s::ps, qboolean, gentity_s::s, SPOT_HEAD, vec3_t, VectorCopy, and playerState_s::viewangles.
00130 {
00131 vec3_t fromAngles, eyes;
00132
00133 if( from->client )
00134 {
00135 VectorCopy(from->client->ps.viewangles, fromAngles);
00136 }
00137 else
00138 {
00139 VectorCopy(from->s.angles, fromAngles);
00140 }
00141
00142 CalcEntitySpot( from, SPOT_HEAD, eyes );
00143
00144 return InFOV3( origin, eyes, fromAngles, hFOV, vFOV );
00145 }
|
|
||||||||||||||||||||||||
|
Definition at line 109 of file NPC_senses.c. References AngleDelta(), fabs(), PITCH, qboolean, qfalse, qtrue, vec3_t, vectoangles(), VectorSubtract, and YAW. Referenced by InFOV2(), NPC_BSGrenadier_Attack(), Rancor_Combat(), Wampa_Combat(), and WP_SaberStartMissileBlockCheck().
00110 {
00111 vec3_t deltaVector, angles, deltaAngles;
00112
00113 VectorSubtract ( spot, from, deltaVector );
00114 vectoangles ( deltaVector, angles );
00115
00116 deltaAngles[PITCH] = AngleDelta ( fromAngles[PITCH], angles[PITCH] );
00117 deltaAngles[YAW] = AngleDelta ( fromAngles[YAW], angles[YAW] );
00118
00119 if ( fabs ( deltaAngles[PITCH] ) <= vFOV && fabs ( deltaAngles[YAW] ) <= hFOV )
00120 {
00121 return qtrue;
00122 }
00123
00124 return qfalse;
00125 }
|
|
||||||||||||||||||||
|
Definition at line 82 of file NPC_senses.c. References AngleVectors(), DotProduct, NULL, qboolean, vec3_t, VectorCopy, VectorNormalize(), and VectorSubtract. Referenced by DoGripAction(), FindGenericEnemyIndex(), NPC_BSGM_Attack(), SeekerDroneUpdate(), WP_SaberCanBlock(), and WP_SabersCheckLock().
00083 {
00084 vec3_t dir, forward, angles;
00085 float dot;
00086
00087 VectorSubtract( spot, from, dir );
00088 dir[2] = 0;
00089 VectorNormalize( dir );
00090
00091 VectorCopy( fromAngles, angles );
00092 angles[0] = 0;
00093 AngleVectors( angles, forward, NULL, NULL );
00094
00095 dot = DotProduct( dir, forward );
00096
00097 return (dot > threshHold);
00098 }
|
|
|
Definition at line 210 of file NPC_senses.c. References CalcEntitySpot(), gentity_t, NPC, NPCInfo, qboolean, qfalse, qtrue, SPOT_HEAD_LEAN, SPOT_ORIGIN, gNPC_t::stats, vec3_t, VectorSubtract, and gNPCstats_e::visrange. Referenced by NPC_CheckVisibility(), and NPC_PickEnemy().
00211 {//FIXME: make a calculate visibility for ents that takes into account
00212 //lighting, movement, turning, crouch/stand up, other anims, hide brushes, etc.
00213 vec3_t eyes;
00214 vec3_t spot;
00215 vec3_t deltaVector;
00216 float visrange = (NPCInfo->stats.visrange*NPCInfo->stats.visrange);
00217
00218 CalcEntitySpot( NPC, SPOT_HEAD_LEAN, eyes );
00219
00220 CalcEntitySpot( ent, SPOT_ORIGIN, spot );
00221 VectorSubtract ( spot, eyes, deltaVector);
00222
00223 /*if(ent->client)
00224 {
00225 float vel, avel;
00226 if(ent->client->ps.velocity[0] || ent->client->ps.velocity[1] || ent->client->ps.velocity[2])
00227 {
00228 vel = VectorLength(ent->client->ps.velocity);
00229 if(vel > 128)
00230 {
00231 visrange += visrange * (vel/256);
00232 }
00233 }
00234
00235 if(ent->avelocity[0] || ent->avelocity[1] || ent->avelocity[2])
00236 {//FIXME: shouldn't they need to have line of sight to you to detect this?
00237 avel = VectorLength(ent->avelocity);
00238 if(avel > 15)
00239 {
00240 visrange += visrange * (avel/60);
00241 }
00242 }
00243 }*/
00244
00245 if(VectorLengthSquared(deltaVector) > visrange)
00246 {
00247 return qfalse;
00248 }
00249
00250 return qtrue;
00251 }
|
|
||||||||||||||||||||||||
|
Definition at line 532 of file NPC_senses.c. References gNPCstats_e::earshot, G_CheckAlertEvents(), NPC, NPCInfo, gNPC_t::stats, and gNPCstats_e::visrange. Referenced by Jedi_CheckDanger(), NPC_BSDefault(), NPC_BSFollowLeader(), NPC_BSGrenadier_Attack(), NPC_BSGrenadier_Patrol(), NPC_BSSleep(), NPC_BSSniper_Attack(), NPC_BSSniper_Patrol(), NPC_BSST_Attack(), NPC_BSST_Investigate(), NPC_BSST_Patrol(), NPC_BSST_Sleep(), NPC_PickEnemyExt(), and ST_Commander().
|
|
|
Definition at line 568 of file NPC_senses.c. References G_CheckForDanger(), NPC, and qboolean. Referenced by NPC_BSGrenadier_Attack(), NPC_BSGrenadier_Patrol(), NPC_BSSniper_Attack(), NPC_BSSniper_Patrol(), NPC_BSST_Attack(), NPC_BSST_Investigate(), and ST_Commander().
00569 {//FIXME: more bStates need to call this?
00570 return G_CheckForDanger( NPC, alertEvent );
00571 }
|
|
||||||||||||
|
Definition at line 257 of file NPC_senses.c. References CanSee(), CanShoot(), CHECK_360, CHECK_FOV, CHECK_PVS, CHECK_SHOOT, CHECK_VISRANGE, entityShared_t::currentOrigin, gentity_t, gNPCstats_e::hfov, InFOV(), InVisrange(), NPC, NPCInfo, gentity_s::r, gNPC_t::stats, trap_InPVS(), gNPCstats_e::vfov, VIS_360, VIS_FOV, VIS_NOT, VIS_PVS, VIS_SHOOT, and visibility_t. Referenced by NPC_BSAdvanceFight(), NPC_BSFollowLeader(), NPC_BSHuntAndKill(), NPC_CheckCanAttack(), NPC_CheckPossibleEnemy(), NPC_PickAlly(), and NPC_PickEnemy().
00258 {
00259 // flags should never be 0
00260 if ( !flags )
00261 {
00262 return VIS_NOT;
00263 }
00264
00265 // check PVS
00266 if ( flags & CHECK_PVS )
00267 {
00268 if ( !trap_InPVS ( ent->r.currentOrigin, NPC->r.currentOrigin ) )
00269 {
00270 return VIS_NOT;
00271 }
00272 }
00273 if ( !(flags & (CHECK_360|CHECK_FOV|CHECK_SHOOT)) )
00274 {
00275 return VIS_PVS;
00276 }
00277
00278 // check within visrange
00279 if (flags & CHECK_VISRANGE)
00280 {
00281 if( !InVisrange ( ent ) )
00282 {
00283 return VIS_PVS;
00284 }
00285 }
00286
00287 // check 360 degree visibility
00288 //Meaning has to be a direct line of site
00289 if ( flags & CHECK_360 )
00290 {
00291 if ( !CanSee ( ent ) )
00292 {
00293 return VIS_PVS;
00294 }
00295 }
00296 if ( !(flags & (CHECK_FOV|CHECK_SHOOT)) )
00297 {
00298 return VIS_360;
00299 }
00300
00301 // check FOV
00302 if ( flags & CHECK_FOV )
00303 {
00304 if ( !InFOV ( ent, NPC, NPCInfo->stats.hfov, NPCInfo->stats.vfov) )
00305 {
00306 return VIS_360;
00307 }
00308 }
00309
00310 if ( !(flags & CHECK_SHOOT) )
00311 {
00312 return VIS_FOV;
00313 }
00314
00315 // check shootability
00316 if ( flags & CHECK_SHOOT )
00317 {
00318 if ( !CanShoot ( ent, NPC ) )
00319 {
00320 return VIS_FOV;
00321 }
00322 }
00323
00324 return VIS_SHOOT;
00325 }
|
|
||||||||||||||||||||
|
Definition at line 824 of file NPC_senses.c. References AngleDelta(), fabs(), vec3_t, vectoangles(), VectorSubtract, and YAW. Referenced by NPC_BSFollowLeader(), and NPC_CheckEnemyStealth().
00825 {
00826 vec3_t deltaVector, angles;
00827 float delta;
00828
00829 VectorSubtract ( spot, from, deltaVector );
00830
00831 vectoangles ( deltaVector, angles );
00832
00833 delta = fabs( AngleDelta ( facing[YAW], angles[YAW] ) );
00834
00835 if ( delta > hFOV )
00836 return 0.0f;
00837
00838 return ( ( hFOV - delta ) / hFOV );
00839 }
|
|
||||||||||||||||||||
|
Definition at line 847 of file NPC_senses.c. References AngleDelta(), fabs(), PITCH, vec3_t, vectoangles(), and VectorSubtract. Referenced by NPC_CheckEnemyStealth().
00848 {
00849 vec3_t deltaVector, angles;
00850 float delta;
00851
00852 VectorSubtract ( spot, from, deltaVector );
00853
00854 vectoangles ( deltaVector, angles );
00855
00856 delta = fabs( AngleDelta ( facing[PITCH], angles[PITCH] ) );
00857
00858 if ( delta > vFOV )
00859 return 0.0f;
00860
00861 return ( ( vFOV - delta ) / vFOV );
00862 }
|
|
|
Definition at line 695 of file NPC_senses.c. References alertEvent_t, level_locals_t::alertEvents, level, MAX_ALERT_EVENTS, memmove(), memset(), level_locals_t::numAlertEvents, Q3_INFINITE, qboolean, and alertEvent_s::timestamp. Referenced by AddSightEvent(), and AddSoundEvent().
00696 {
00697 int oldestEvent = -1, oldestTime = Q3_INFINITE;
00698 int i;
00699 //loop through them all (max 32)
00700 for ( i = 0; i < level.numAlertEvents; i++ )
00701 {
00702 //see if the event is old enough to delete
00703 if ( level.alertEvents[i].timestamp < oldestTime )
00704 {
00705 oldestEvent = i;
00706 oldestTime = level.alertEvents[i].timestamp;
00707 }
00708 }
00709 if ( oldestEvent != -1 )
00710 {
00711 //drop the count
00712 level.numAlertEvents--;
00713 //shift the rest down
00714 if ( level.numAlertEvents > 0 )
00715 {//still have more in the array
00716 if ( (oldestEvent+1) < MAX_ALERT_EVENTS )
00717 {
00718 memmove( &level.alertEvents[oldestEvent], &level.alertEvents[oldestEvent+1], sizeof(alertEvent_t)*(MAX_ALERT_EVENTS-(oldestEvent+1) ) );
00719 }
00720 }
00721 else
00722 {//just clear this one... or should we clear the whole array?
00723 memset( &level.alertEvents[oldestEvent], 0, sizeof( alertEvent_t ) );
00724 }
00725 }
00726 //make sure this never drops below zero... if it does, something very very bad happened
00727 assert( level.numAlertEvents >= 0 );
00728 //return true is have room for one now
00729 return (level.numAlertEvents<MAX_ALERT_EVENTS);
00730 }
|
|
|
Definition at line 915 of file NPC_senses.c. References Com_Printf(), entityShared_t::currentOrigin, G_FreeEntity(), G_NewString(), gentity_t, level_locals_t::interestPoints, level, MAX_INTEREST_POINTS, level_locals_t::numInterestPoints, gentity_s::r, gentity_s::target, and VectorCopy.
00916 {//FIXME: rename point_interest
00917 if(level.numInterestPoints >= MAX_INTEREST_POINTS)
00918 {
00919 Com_Printf("ERROR: Too many interest points, limit is %d\n", MAX_INTEREST_POINTS);
00920 G_FreeEntity(self);
00921 return;
00922 }
00923
00924 VectorCopy(self->r.currentOrigin, level.interestPoints[level.numInterestPoints].origin);
00925
00926 if(self->target && self->target[0])
00927 {
00928 level.interestPoints[level.numInterestPoints].target = G_NewString( self->target );
00929 }
00930
00931 level.numInterestPoints++;
00932
00933 G_FreeEntity(self);
00934 }
|
|
|
Definition at line 5 of file NPC_senses.c. Referenced by ClearPlayerAlertEvents(), and CorpsePhysics(). |