#include "b_local.h"#include "../icarus/Q3_Interface.h"#include "../ghoul2/G2.h"Go to the source code of this file.
|
|
Definition at line 1243 of file NPC_utils.c. |
|
|
Definition at line 1244 of file NPC_utils.c. |
|
|
Definition at line 999 of file NPC_utils.c. |
|
|
Definition at line 998 of file NPC_utils.c. |
|
|
Definition at line 11 of file NPC_utils.c. Referenced by NPC_FacePosition(). |
|
||||||||||||||||
|
Definition at line 20 of file NPC_utils.c. References entityShared_t::absmax, entityShared_t::absmin, AngleVectors(), CalcMuzzlePoint(), CLASS_ATST, gentity_s::client, entityShared_t::currentOrigin, trace_t::endpos, renderInfo_s::eyePoint, trace_t::fraction, gentity_t, entityState_s::groundEntityNum, MASK_PLAYERSOLID, entityShared_t::maxs, entityShared_t::mins, gentity_s::NPC, gclient_s::NPC_class, entityState_s::number, gclient_s::ps, gentity_s::r, gclient_s::renderInfo, gentity_s::s, gNPC_t::shootAngles, SPOT_CHEST, SPOT_GROUND, SPOT_HEAD, SPOT_HEAD_LEAN, SPOT_LEGS, SPOT_ORIGIN, SPOT_WEAPON, trap_Trace(), vec3_origin, vec3_t, VectorCopy, VectorMA, VectorSubtract, playerState_s::viewangles, and playerState_s::viewheight. Referenced by Boba_FireDecide(), CanSee(), CanShoot(), G_CheckAlertEvents(), G_ClearLOS2(), G_ClearLOS3(), G_ClearLOS4(), G_ClearLOS5(), G_FindLocalInterestPoint(), ImperialProbe_FireBlaster(), InFOV(), InFOV2(), InVisrange(), Mark1_FireBlaster(), Mark1_FireRocket(), Mark2_FireBlaster(), NPC_BSAdvanceFight(), NPC_BSCinematic(), NPC_BSFollowLeader(), NPC_BSGM_Attack(), NPC_BSPointShoot(), NPC_CheckCanAttack(), NPC_ClearShot(), NPC_FaceEntity(), NPC_FacePosition(), NPC_ShotEntity(), Remote_Fire(), Seeker_Fire(), Sniper_FaceEnemy(), and Sniper_UpdateEnemyPos().
00021 {
00022 vec3_t forward, up, right;
00023 vec3_t start, end;
00024 trace_t tr;
00025
00026 if ( !ent )
00027 {
00028 return;
00029 }
00030 switch ( spot )
00031 {
00032 case SPOT_ORIGIN:
00033 if(VectorCompare(ent->r.currentOrigin, vec3_origin))
00034 {//brush
00035 VectorSubtract(ent->r.absmax, ent->r.absmin, point);//size
00036 VectorMA(ent->r.absmin, 0.5, point, point);
00037 }
00038 else
00039 {
00040 VectorCopy ( ent->r.currentOrigin, point );
00041 }
00042 break;
00043
00044 case SPOT_CHEST:
00045 case SPOT_HEAD:
00046 if ( ent->client && VectorLengthSquared( ent->client->renderInfo.eyePoint ) /*&& (ent->client->ps.viewEntity <= 0 || ent->client->ps.viewEntity >= ENTITYNUM_WORLD)*/ )
00047 {//Actual tag_head eyespot!
00048 //FIXME: Stasis aliens may have a problem here...
00049 VectorCopy( ent->client->renderInfo.eyePoint, point );
00050 if ( ent->client->NPC_class == CLASS_ATST )
00051 {//adjust up some
00052 point[2] += 28;//magic number :)
00053 }
00054 if ( ent->NPC )
00055 {//always aim from the center of my bbox, so we don't wiggle when we lean forward or backwards
00056 point[0] = ent->r.currentOrigin[0];
00057 point[1] = ent->r.currentOrigin[1];
00058 }
00059 /*
00060 else if (ent->s.eType == ET_PLAYER )
00061 {
00062 SubtractLeanOfs( ent, point );
00063 }
00064 */
00065 }
00066 else
00067 {
00068 VectorCopy ( ent->r.currentOrigin, point );
00069 if ( ent->client )
00070 {
00071 point[2] += ent->client->ps.viewheight;
00072 }
00073 }
00074 if ( spot == SPOT_CHEST && ent->client )
00075 {
00076 if ( ent->client->NPC_class != CLASS_ATST )
00077 {//adjust up some
00078 point[2] -= ent->r.maxs[2]*0.2f;
00079 }
00080 }
00081 break;
00082
00083 case SPOT_HEAD_LEAN:
00084 if ( ent->client && VectorLengthSquared( ent->client->renderInfo.eyePoint ) /*&& (ent->client->ps.viewEntity <= 0 || ent->client->ps.viewEntity >= ENTITYNUM_WORLD*/ )
00085 {//Actual tag_head eyespot!
00086 //FIXME: Stasis aliens may have a problem here...
00087 VectorCopy( ent->client->renderInfo.eyePoint, point );
00088 if ( ent->client->NPC_class == CLASS_ATST )
00089 {//adjust up some
00090 point[2] += 28;//magic number :)
00091 }
00092 if ( ent->NPC )
00093 {//always aim from the center of my bbox, so we don't wiggle when we lean forward or backwards
00094 point[0] = ent->r.currentOrigin[0];
00095 point[1] = ent->r.currentOrigin[1];
00096 }
00097 /*
00098 else if ( ent->s.eType == ET_PLAYER )
00099 {
00100 SubtractLeanOfs( ent, point );
00101 }
00102 */
00103 //NOTE: automatically takes leaning into account!
00104 }
00105 else
00106 {
00107 VectorCopy ( ent->r.currentOrigin, point );
00108 if ( ent->client )
00109 {
00110 point[2] += ent->client->ps.viewheight;
00111 }
00112 //AddLeanOfs ( ent, point );
00113 }
00114 break;
00115
00116 //FIXME: implement...
00117 //case SPOT_CHEST:
00118 //Returns point 3/4 from tag_torso to tag_head?
00119 //break;
00120
00121 case SPOT_LEGS:
00122 VectorCopy ( ent->r.currentOrigin, point );
00123 point[2] += (ent->r.mins[2] * 0.5);
00124 break;
00125
00126 case SPOT_WEAPON:
00127 if( ent->NPC && !VectorCompare( ent->NPC->shootAngles, vec3_origin ) && !VectorCompare( ent->NPC->shootAngles, ent->client->ps.viewangles ))
00128 {
00129 AngleVectors( ent->NPC->shootAngles, forward, right, up );
00130 }
00131 else
00132 {
00133 AngleVectors( ent->client->ps.viewangles, forward, right, up );
00134 }
00135 CalcMuzzlePoint( (gentity_t*)ent, forward, right, up, point );
00136 //NOTE: automatically takes leaning into account!
00137 break;
00138
00139 case SPOT_GROUND:
00140 // if entity is on the ground, just use it's absmin
00141 if ( ent->s.groundEntityNum != -1 )
00142 {
00143 VectorCopy( ent->r.currentOrigin, point );
00144 point[2] = ent->r.absmin[2];
00145 break;
00146 }
00147
00148 // if it is reasonably close to the ground, give the point underneath of it
00149 VectorCopy( ent->r.currentOrigin, start );
00150 start[2] = ent->r.absmin[2];
00151 VectorCopy( start, end );
00152 end[2] -= 64;
00153 trap_Trace( &tr, start, ent->r.mins, ent->r.maxs, end, ent->s.number, MASK_PLAYERSOLID );
00154 if ( tr.fraction < 1.0 )
00155 {
00156 VectorCopy( tr.endpos, point);
00157 break;
00158 }
00159
00160 // otherwise just use the origin
00161 VectorCopy( ent->r.currentOrigin, point );
00162 break;
00163
00164 default:
00165 VectorCopy ( ent->r.currentOrigin, point );
00166 break;
00167 }
00168 }
|
|
||||||||||||
|
||||||||||||||||
|
Definition at line 23 of file NPC_sounds.c. References gNPC_t::blockedSpeechDebounceTime, gentity_s::client, EV_ANGER1, EV_CHASE1, EV_GIVEUP1, EV_SUSPICIOUS5, G_SpeechEvent(), gentity_t, level, gentity_s::NPC, PM_DEAD, playerState_s::pm_type, gclient_s::ps, SCF_NO_ALERT_TALK, SCF_NO_COMBAT_TALK, gNPC_t::scriptFlags, TID_CHAN_VOICE, level_locals_t::time, and trap_ICARUS_TaskIDPending(). Referenced by G_SetEnemy(), Jedi_Ambush(), Jedi_PlayBlockedPushSound(), Jedi_PlayDeflectSound(), NPC_BSGM_Attack(), NPC_CheckCharmed(), NPC_ChoosePainAnimation(), NPC_GM_Pain(), NPC_Grenadier_Pain(), NPC_Grenadier_PlayConfusionSound(), NPC_HandleAIFlags(), NPC_Jedi_Pain(), NPC_Jedi_PlayConfusionSound(), NPC_PlayConfusionSound(), NPC_Respond(), NPC_Sniper_Pain(), NPC_Sniper_PlayConfusionSound(), NPC_ST_Pain(), and NPC_Surrender().
00024 {
00025 if ( !self->NPC )
00026 {
00027 return;
00028 }
00029
00030 if ( !self->client || self->client->ps.pm_type >= PM_DEAD )
00031 {
00032 return;
00033 }
00034
00035 if ( self->NPC->blockedSpeechDebounceTime > level.time )
00036 {
00037 return;
00038 }
00039
00040 if ( trap_ICARUS_TaskIDPending( self, TID_CHAN_VOICE ) )
00041 {
00042 return;
00043 }
00044
00045
00046 if ( (self->NPC->scriptFlags&SCF_NO_COMBAT_TALK) && ( (event >= EV_ANGER1 && event <= EV_VICTORY3) || (event >= EV_CHASE1 && event <= EV_SUSPICIOUS5) ) )//(event < EV_FF_1A || event > EV_FF_3C) && (event < EV_RESPOND1 || event > EV_MISSION3) )
00047 {
00048 return;
00049 }
00050
00051 if ( (self->NPC->scriptFlags&SCF_NO_ALERT_TALK) && (event >= EV_GIVEUP1 && event <= EV_SUSPICIOUS5) )
00052 {
00053 return;
00054 }
00055 //FIXME: Also needs to check for teammates. Don't want
00056 // everyone babbling at once
00057
00058 //NOTE: was losing too many speech events, so we do it directly now, screw networking!
00059 //G_AddEvent( self, event, 0 );
00060 G_SpeechEvent( self, event );
00061
00062 //won't speak again for 5 seconds (unless otherwise specified)
00063 self->NPC->blockedSpeechDebounceTime = level.time + ((speakDebounceTime==0) ? 5000 : speakDebounceTime);
00064 }
|
|
||||||||||||||||
|
Definition at line 275 of file g_ICARUScb.c. References Com_Printf(), g_developer, g_entities, vmCvar_t::integer, level, MAX_GENTITIES, S_COLOR_BLUE, S_COLOR_GREEN, S_COLOR_RED, S_COLOR_YELLOW, sscanf(), va_end, va_list, va_start, vsprintf(), WL_DEBUG, WL_ERROR, WL_VERBOSE, and WL_WARNING. Referenced by G_ActivateBehavior(), NPC_Begin(), Q3_GetFloat(), Q3_GetString(), Q3_GetVector(), Q3_Kill(), Q3_Lerp2Angles(), Q3_Lerp2End(), Q3_Lerp2Origin(), Q3_Lerp2Pos(), Q3_Lerp2Start(), Q3_Remove(), Q3_RemoveEnt(), Q3_Set(), Q3_SetICARUSFreeze(), Q3_SetLoopSound(), Q3_SetParm(), Q3_SetViewEntity(), Q3_Use(), and target_counter_use().
00276 {
00277 va_list argptr;
00278 char text[1024];
00279
00280 //Don't print messages they don't want to see
00281 //if ( g_ICARUSDebug->integer < level )
00282 if (g_developer.integer != 2)
00283 return;
00284
00285 va_start (argptr, format);
00286 vsprintf (text, format, argptr);
00287 va_end (argptr);
00288
00289 //Add the color formatting
00290 switch ( level )
00291 {
00292 case WL_ERROR:
00293 Com_Printf ( S_COLOR_RED"ERROR: %s", text );
00294 break;
00295
00296 case WL_WARNING:
00297 Com_Printf ( S_COLOR_YELLOW"WARNING: %s", text );
00298 break;
00299
00300 case WL_DEBUG:
00301 {
00302 int entNum;
00303 char *buffer;
00304
00305 sscanf( text, "%d", &entNum );
00306
00307 //if ( ( ICARUS_entFilter >= 0 ) && ( ICARUS_entFilter != entNum ) )
00308 // return;
00309
00310 buffer = (char *) text;
00311 buffer += 5;
00312
00313 if ( ( entNum < 0 ) || ( entNum > MAX_GENTITIES ) )
00314 entNum = 0;
00315
00316 Com_Printf ( S_COLOR_BLUE"DEBUG: %s(%d): %s\n", g_entities[entNum].script_targetname, entNum, buffer );
00317 break;
00318 }
00319 default:
00320 case WL_VERBOSE:
00321 Com_Printf ( S_COLOR_GREEN"INFO: %s", text );
00322 break;
00323 }
00324 }
|
|
||||||||||||||||||||
|
Definition at line 1707 of file NPC_utils.c. References gentity_s::client, entityShared_t::currentAngles, entityShared_t::currentOrigin, gentity_t, gentity_s::ghoul2, gentity_s::inuse, level, gentity_s::modelScale, NULL, ORIGIN, gclient_s::ps, gentity_s::r, level_locals_t::time, trap_G2API_GetBoltMatrix(), vec3_t, VectorCopy, VectorSet, playerState_s::viewangles, and YAW. Referenced by NPC_EntRangeFromBolt(), NPC_GetEntsNearBolt(), and Rancor_Attack().
01708 {
01709 mdxaBone_t boltMatrix;
01710 vec3_t result, angles;
01711
01712 if (!self || !self->inuse)
01713 {
01714 return;
01715 }
01716
01717 if (self->client)
01718 { //clients don't actually even keep r.currentAngles maintained
01719 VectorSet(angles, 0, self->client->ps.viewangles[YAW], 0);
01720 }
01721 else
01722 {
01723 VectorSet(angles, 0, self->r.currentAngles[YAW], 0);
01724 }
01725
01726 if ( !self->ghoul2 )
01727 {
01728 return;
01729 }
01730
01731 trap_G2API_GetBoltMatrix( self->ghoul2, modelIndex,
01732 boltIndex,
01733 &boltMatrix, angles, self->r.currentOrigin, level.time,
01734 NULL, self->modelScale );
01735 if ( pos )
01736 {
01737 BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, result );
01738 VectorCopy( result, pos );
01739 }
01740 }
|
|
|
Definition at line 519 of file NPC_utils.c. References gNPC_t::aimErrorDebounceTime, gNPC_t::aimOfs, gentity_s::enemy, flrand(), level, entityShared_t::maxs, entityShared_t::mins, NPC, NPCInfo, gentity_s::r, level_locals_t::time, vec3_t, and VectorAdd. Referenced by NPC_BSFollowLeader(), and NPC_CheckCanAttack().
00520 {
00521 //shoot for somewhere between the head and torso
00522 //NOTE: yes, I know this looks weird, but it works
00523 if ( NPCInfo->aimErrorDebounceTime < level.time )
00524 {
00525 NPCInfo->aimOfs[0] = 0.3*flrand(NPC->enemy->r.mins[0], NPC->enemy->r.maxs[0]);
00526 NPCInfo->aimOfs[1] = 0.3*flrand(NPC->enemy->r.mins[1], NPC->enemy->r.maxs[1]);
00527 if ( NPC->enemy->r.maxs[2] > 0 )
00528 {
00529 NPCInfo->aimOfs[2] = NPC->enemy->r.maxs[2]*flrand(0.0f, -1.0f);
00530 }
00531 }
00532 VectorAdd( enemy_org, NPCInfo->aimOfs, enemy_org );
00533 }
|
|
|
Definition at line 1588 of file NPC_utils.c. References gentity_s::enemy, NPC, NPC_ClearShot(), NPC_FaceEnemy(), NPCInfo, qboolean, qfalse, qtrue, SCF_DONT_FIRE, and gNPC_t::scriptFlags.
01589 {
01590 //We don't want them to shoot
01591 if( NPCInfo->scriptFlags & SCF_DONT_FIRE )
01592 return qfalse;
01593
01594 //Turn to face
01595 if ( NPC_FaceEnemy( qtrue ) == qfalse )
01596 return qfalse;
01597
01598 //Must have a clear line of sight to the target
01599 if ( NPC_ClearShot( NPC->enemy ) == qfalse )
01600 return qfalse;
01601
01602 return qtrue;
01603 }
|
|
|
|
Definition at line 1469 of file NPC_utils.c. References NPC_FindEnemy(), and qboolean. Referenced by ATST_Attack(), Howler_Patrol(), ImperialProbe_AttackDecision(), Interrogator_Attack(), Mark1_AttackDecision(), MineMonster_Patrol(), NPC_BSEmplaced(), NPC_BSGM_Attack(), NPC_BSGrenadier_Attack(), NPC_BSRancor_Default(), NPC_BSSniper_Attack(), NPC_BSST_Attack(), NPC_BSWampa_Default(), Rancor_Patrol(), Remote_Attack(), Sentry_AttackDecision(), and Wampa_Patrol().
01470 {
01471 //Make sure we're ready to think again
01472 /*
01473 if ( NPCInfo->enemyCheckDebounceTime > level.time )
01474 return qfalse;
01475
01476 //Get our next think time
01477 NPCInfo->enemyCheckDebounceTime = level.time + NPC_GetCheckDelta();
01478
01479 //Attempt to find an enemy
01480 return NPC_FindEnemy();
01481 */
01482 return NPC_FindEnemy( checkAlerts );
01483 }
|
|
|
Definition at line 1653 of file NPC_utils.c. References gentity_s::client, gentity_s::enemy, ENTITYNUM_WORLD, g_entities, gentity_t, level, renderInfo_s::lookTarget, renderInfo_s::lookTargetClearTime, NPC_ClearLookTarget(), NULL, qboolean, qfalse, qtrue, gclient_s::renderInfo, and level_locals_t::time. Referenced by G_ClearEnemy(), NPC_ExecuteBState(), and NPC_TempLookTarget().
01654 {
01655 if ( self->client )
01656 {
01657 if ( self->client->renderInfo.lookTarget >= 0 && self->client->renderInfo.lookTarget < ENTITYNUM_WORLD )
01658 {//within valid range
01659 if ( (&g_entities[self->client->renderInfo.lookTarget] == NULL) || !g_entities[self->client->renderInfo.lookTarget].inuse )
01660 {//lookTarget not inuse or not valid anymore
01661 NPC_ClearLookTarget( self );
01662 }
01663 else if ( self->client->renderInfo.lookTargetClearTime && self->client->renderInfo.lookTargetClearTime < level.time )
01664 {//Time to clear lookTarget
01665 NPC_ClearLookTarget( self );
01666 }
01667 else if ( g_entities[self->client->renderInfo.lookTarget].client && self->enemy && (&g_entities[self->client->renderInfo.lookTarget] != self->enemy) )
01668 {//should always look at current enemy if engaged in battle... FIXME: this could override certain scripted lookTargets...???
01669 NPC_ClearLookTarget( self );
01670 }
01671 else
01672 {
01673 return qtrue;
01674 }
01675 }
01676 }
01677
01678 return qfalse;
01679 }
|
|
|
Definition at line 1611 of file NPC_utils.c. References gentity_s::client, EF2_HELD_BY_MONSTER, playerState_s::eFlags2, ENTITYNUM_NONE, gentity_t, renderInfo_s::lookTarget, renderInfo_s::lookTargetClearTime, gclient_s::ps, and gclient_s::renderInfo. Referenced by G_ClearEnemy(), and NPC_CheckLookTarget().
01612 {
01613 if ( !self->client )
01614 {
01615 return;
01616 }
01617
01618 if ( (self->client->ps.eFlags2&EF2_HELD_BY_MONSTER) )
01619 {//lookTarget is set by and to the monster that's holding you, no other operations can change that
01620 return;
01621 }
01622
01623 self->client->renderInfo.lookTarget = ENTITYNUM_NONE;//ENTITYNUM_WORLD;
01624 self->client->renderInfo.lookTargetClearTime = 0;
01625 }
|
|
||||||||||||
|
Definition at line 1069 of file NPC_utils.c. References G_ClearLOS(), NPC, qboolean, and vec3_t. Referenced by NPC_FindCombatPoint(), and Wampa_Combat().
01070 {
01071 return G_ClearLOS( NPC, start, end );
01072 }
|
|
||||||||||||
|
Definition at line 1085 of file NPC_utils.c. References G_ClearLOS2(), gentity_t, NPC, qboolean, and vec3_t. Referenced by G_AlertTeam(), NPC_ShySpawn(), and vmMain().
01086 {
01087 return G_ClearLOS2( NPC, ent, end );
01088 }
|
|
||||||||||||
|
Definition at line 1081 of file NPC_utils.c. References G_ClearLOS3(), gentity_t, NPC, qboolean, and vec3_t. Referenced by NPC_FindCombatPoint().
01082 {
01083 return G_ClearLOS3( NPC, start, ent );
01084 }
|
|
|
Definition at line 1077 of file NPC_utils.c. References G_ClearLOS4(), gentity_t, NPC, and qboolean. Referenced by ATST_Attack(), Boba_FireDecide(), Howler_Combat(), ImperialProbe_AttackDecision(), Interrogator_Attack(), Jedi_CheckAmbushPlayer(), Mark1_AttackDecision(), Mark2_AttackDecision(), MineMonster_Combat(), NPC_BSEmplaced(), NPC_BSGM_Attack(), NPC_BSGrenadier_Attack(), NPC_BSJedi_FollowLeader(), NPC_BSSniper_Attack(), NPC_BSST_Attack(), NPC_CheckEnemyStealth(), NPC_TargetVisible(), Rancor_Combat(), Remote_Attack(), Seeker_Attack(), Seeker_FindEnemy(), Sentry_AttackDecision(), and ST_Commander().
01078 {
01079 return G_ClearLOS4( NPC, ent );
01080 }
|
|
|
Definition at line 1073 of file NPC_utils.c. References G_ClearLOS5(), NPC, qboolean, and vec3_t.
01074 {
01075 return G_ClearLOS5( NPC, end );
01076 }
|
|
|
Definition at line 1756 of file NPC_utils.c. References gentity_s::enemy, NPC, and NPC_EntRangeFromBolt().
01757 {
01758 return (NPC_EntRangeFromBolt( NPC->enemy, boltIndex ));
01759 }
|
|
||||||||||||
|
Definition at line 1742 of file NPC_utils.c. References entityShared_t::currentOrigin, G_GetBoltPosition(), gentity_t, NPC, Q3_INFINITE, gentity_s::r, and vec3_t. Referenced by NPC_EnemyRangeFromBolt().
01743 {
01744 vec3_t org;
01745
01746 if ( !targEnt )
01747 {
01748 return Q3_INFINITE;
01749 }
01750
01751 G_GetBoltPosition( NPC, boltIndex, org, 0 );
01752
01753 return (Distance( targEnt->r.currentOrigin, org ));
01754 }
|
|
|
||||||||||||
|
Definition at line 1555 of file NPC_utils.c. References CalcEntitySpot(), gentity_t, NPC_FacePosition(), qboolean, SPOT_HEAD_LEAN, and vec3_t. Referenced by NAV_ResolveBlock(), NAV_ResolveEntityCollision(), NAV_TestForBlocked(), NPC_BSJedi_FollowLeader(), and NPC_FaceEnemy().
01556 {
01557 vec3_t entPos;
01558
01559 //Get the positions
01560 CalcEntitySpot( ent, SPOT_HEAD_LEAN, entPos );
01561
01562 return NPC_FacePosition( entPos, doPitch );
01563 }
|
|
||||||||||||
|
Definition at line 1491 of file NPC_utils.c. References AngleNormalize360(), usercmd_s::angles, CalcEntitySpot(), CLASS_ATST, CLASS_GALAKMECH, CLASS_RANCOR, CLASS_WAMPA, client, gentity_s::client, playerState_s::delta_angles, gNPC_t::desiredPitch, gNPC_t::desiredYaw, gentity_s::enemy, fabs(), flrand(), GetAnglesForDirection(), level, entityShared_t::maxs, NPC, gclient_s::NPC_class, NPC_UpdateAngles(), NPCInfo, PITCH, gclient_s::ps, qboolean, qfalse, qtrue, gentity_s::r, SHORT2ANGLE, sin(), SPOT_HEAD_LEAN, SPOT_ORIGIN, SPOT_WEAPON, level_locals_t::time, ucmd, VALID_ATTACK_CONE, vec3_t, and YAW. Referenced by NPC_FaceEntity().
01492 {
01493 vec3_t muzzle;
01494 vec3_t angles;
01495 float yawDelta;
01496 qboolean facing = qtrue;
01497
01498 //Get the positions
01499 if ( NPC->client && (NPC->client->NPC_class == CLASS_RANCOR || NPC->client->NPC_class == CLASS_WAMPA) )// || NPC->client->NPC_class == CLASS_SAND_CREATURE) )
01500 {
01501 CalcEntitySpot( NPC, SPOT_ORIGIN, muzzle );
01502 muzzle[2] += NPC->r.maxs[2] * 0.75f;
01503 }
01504 else if ( NPC->client && NPC->client->NPC_class == CLASS_GALAKMECH )
01505 {
01506 CalcEntitySpot( NPC, SPOT_WEAPON, muzzle );
01507 }
01508 else
01509 {
01510 CalcEntitySpot( NPC, SPOT_HEAD_LEAN, muzzle );//SPOT_HEAD
01511 }
01512
01513 //Find the desired angles
01514 GetAnglesForDirection( muzzle, position, angles );
01515
01516 NPCInfo->desiredYaw = AngleNormalize360( angles[YAW] );
01517 NPCInfo->desiredPitch = AngleNormalize360( angles[PITCH] );
01518
01519 if ( NPC->enemy && NPC->enemy->client && NPC->enemy->client->NPC_class == CLASS_ATST )
01520 {
01521 // FIXME: this is kind of dumb, but it was the easiest way to get it to look sort of ok
01522 NPCInfo->desiredYaw += flrand( -5, 5 ) + sin( level.time * 0.004f ) * 7;
01523 NPCInfo->desiredPitch += flrand( -2, 2 );
01524 }
01525 //Face that yaw
01526 NPC_UpdateAngles( qtrue, qtrue );
01527
01528 //Find the delta between our goal and our current facing
01529 yawDelta = AngleNormalize360( NPCInfo->desiredYaw - ( SHORT2ANGLE( ucmd.angles[YAW] + client->ps.delta_angles[YAW] ) ) );
01530
01531 //See if we are facing properly
01532 if ( fabs( yawDelta ) > VALID_ATTACK_CONE )
01533 facing = qfalse;
01534
01535 if ( doPitch )
01536 {
01537 //Find the delta between our goal and our current facing
01538 float currentAngles = ( SHORT2ANGLE( ucmd.angles[PITCH] + client->ps.delta_angles[PITCH] ) );
01539 float pitchDelta = NPCInfo->desiredPitch - currentAngles;
01540
01541 //See if we are facing properly
01542 if ( fabs( pitchDelta ) > VALID_ATTACK_CONE )
01543 facing = qfalse;
01544 }
01545
01546 return facing;
01547 }
|
|
|
Definition at line 1407 of file NPC_utils.c. References CLASS_RANCOR, CLASS_WAMPA, gentity_s::client, gNPC_t::confusionTime, gentity_s::enemy, G_ClearEnemy(), G_SetEnemy(), gentity_t, level, NPC, gclient_s::NPC_class, NPC_PickEnemyExt(), NPC_ValidEnemy(), NPCInfo, qboolean, qfalse, qtrue, and level_locals_t::time. Referenced by NPC_CheckEnemyExt().
01408 {
01409 gentity_t *newenemy;
01410
01411 //We're ignoring all enemies for now
01412 //if( NPC->svFlags & SVF_IGNORE_ENEMIES )
01413 if (0) //rwwFIXMEFIXME: support for flag
01414 {
01415 G_ClearEnemy( NPC );
01416 return qfalse;
01417 }
01418
01419 //we can't pick up any enemies for now
01420 if( NPCInfo->confusionTime > level.time )
01421 {
01422 return qfalse;
01423 }
01424
01425 //Don't want a new enemy
01426 //rwwFIXMEFIXME: support for locked enemy
01427 //if ( ( ValidEnemy( NPC->enemy ) ) && ( NPC->svFlags & SVF_LOCKEDENEMY ) )
01428 // return qtrue;
01429
01430 //See if the player is closer than our current enemy
01431 if ( NPC_CheckPlayerDistance() )
01432 {
01433 return qtrue;
01434 }
01435
01436 //Otherwise, turn off the flag
01437 // NPC->svFlags &= ~SVF_LOCKEDENEMY;
01438 //See if the player is closer than our current enemy
01439 if ( NPC->client->NPC_class != CLASS_RANCOR
01440 && NPC->client->NPC_class != CLASS_WAMPA
01441 //&& NPC->client->NPC_class != CLASS_SAND_CREATURE
01442 && NPC_CheckPlayerDistance() )
01443 {//rancors, wampas & sand creatures don't care if player is closer, they always go with closest
01444 return qtrue;
01445 }
01446
01447 //If we've gotten here alright, then our target it still valid
01448 if ( NPC_ValidEnemy( NPC->enemy ) )
01449 return qtrue;
01450
01451 newenemy = NPC_PickEnemyExt( checkAlerts );
01452
01453 //if we found one, take it as the enemy
01454 if( NPC_ValidEnemy( newenemy ) )
01455 {
01456 G_SetEnemy( NPC, newenemy );
01457 return qtrue;
01458 }
01459
01460 return qfalse;
01461 }
|
|
|
Definition at line 1246 of file NPC_utils.c. References entityShared_t::currentOrigin, g_entities, gentity_t, MAX_RADIUS_ENTS, NPC_TargetVisible(), NPC_ValidEnemy(), NPCInfo, entityState_s::number, qfalse, gentity_s::r, gentity_s::s, gNPC_t::stats, trap_EntitiesInBox(), vec3_t, gNPCstats_e::visrange, and WORLD_SIZE. Referenced by NPC_PickEnemyExt().
01247 {
01248 int iradiusEnts[ MAX_RADIUS_ENTS ];
01249 gentity_t *radEnt;
01250 vec3_t mins, maxs;
01251 int nearestEntID = -1;
01252 float nearestDist = (float)WORLD_SIZE*(float)WORLD_SIZE;
01253 float distance;
01254 int numEnts, numChecks = 0;
01255 int i;
01256
01257 //Setup the bbox to search in
01258 for ( i = 0; i < 3; i++ )
01259 {
01260 mins[i] = ent->r.currentOrigin[i] - NPCInfo->stats.visrange;
01261 maxs[i] = ent->r.currentOrigin[i] + NPCInfo->stats.visrange;
01262 }
01263
01264 //Get a number of entities in a given space
01265 numEnts = trap_EntitiesInBox( mins, maxs, iradiusEnts, MAX_RADIUS_ENTS );
01266
01267 for ( i = 0; i < numEnts; i++ )
01268 {
01269 radEnt = &g_entities[iradiusEnts[i]];
01270 //Don't consider self
01271 if ( radEnt == ent )
01272 continue;
01273
01274 //Must be valid
01275 if ( NPC_ValidEnemy( radEnt ) == qfalse )
01276 continue;
01277
01278 numChecks++;
01279 //Must be visible
01280 if ( NPC_TargetVisible( radEnt ) == qfalse )
01281 continue;
01282
01283 distance = DistanceSquared( ent->r.currentOrigin, radEnt->r.currentOrigin );
01284
01285 //Found one closer to us
01286 if ( distance < nearestDist )
01287 {
01288 nearestEntID = radEnt->s.number;
01289 nearestDist = distance;
01290 }
01291 }
01292
01293 return nearestEntID;
01294 }
|
|
|
Definition at line 1356 of file NPC_utils.c. References g_entities, NPC_TargetVisible(), and qboolean.
01357 {
01358 return NPC_TargetVisible( &g_entities[0] );
01359 }
|
|
||||||||||||||||||||
|
Definition at line 1761 of file NPC_utils.c. References G_GetBoltPosition(), NPC, trap_EntitiesInBox(), vec3_t, and VectorCopy. Referenced by Rancor_Bite(), Rancor_Smash(), Rancor_Swing(), and Wampa_Slash().
01762 {
01763 vec3_t mins, maxs;
01764 int i;
01765
01766 //get my handRBolt's position
01767 vec3_t org;
01768
01769 G_GetBoltPosition( NPC, boltIndex, org, 0 );
01770
01771 VectorCopy( org, boltOrg );
01772
01773 //Setup the bbox to search in
01774 for ( i = 0; i < 3; i++ )
01775 {
01776 mins[i] = boltOrg[i] - radius;
01777 maxs[i] = boltOrg[i] + radius;
01778 }
01779
01780 //Get the number of entities in a given space
01781 return (trap_EntitiesInBox( mins, maxs, radiusEnts, 128 ));
01782 }
|
|
|
Definition at line 1302 of file NPC_utils.c. References AEL_DISCOVERED, alertEvent_t, level_locals_t::alertEvents, gentity_s::client, gentity_s::enemy, g_entities, gentity_t, alertEvent_s::level, level, NPC, NPC_CheckAlertEvents(), NPC_FindNearestEnemy(), NULL, alertEvent_s::owner, gclient_s::playerTeam, and qtrue. Referenced by NPC_FindEnemy().
01303 {
01304 //Check for Hazard Team status and remove this check
01305 /*
01306 if ( NPC->client->playerTeam != TEAM_STARFLEET )
01307 {
01308 //If we've found the player, return it
01309 if ( NPC_FindPlayer() )
01310 return &g_entities[0];
01311 }
01312 */
01313
01314 //If we've asked for the closest enemy
01315 int entID = NPC_FindNearestEnemy( NPC );
01316
01317 //If we have a valid enemy, use it
01318 if ( entID >= 0 )
01319 return &g_entities[entID];
01320
01321 if ( checkAlerts )
01322 {
01323 int alertEvent = NPC_CheckAlertEvents( qtrue, qtrue, -1, qtrue, AEL_DISCOVERED );
01324
01325 //There is an event to look at
01326 if ( alertEvent >= 0 )
01327 {
01328 alertEvent_t *event = &level.alertEvents[alertEvent];
01329
01330 //Don't pay attention to our own alerts
01331 if ( event->owner == NPC )
01332 return NULL;
01333
01334 if ( event->level >= AEL_DISCOVERED )
01335 {
01336 //If it's the player, attack him
01337 if ( event->owner == &g_entities[0] )
01338 return event->owner;
01339
01340 //If it's on our team, then take its enemy as well
01341 if ( ( event->owner->client ) && ( event->owner->client->playerTeam == NPC->client->playerTeam ) )
01342 return event->owner->enemy;
01343 }
01344 }
01345 }
01346
01347 return NULL;
01348 }
|
|
||||||||||||||||
|
Definition at line 906 of file NPC_utils.c. References BONE_ANGLES_POSTMULT, entityState_s::boneAngles1, entityState_s::boneAngles2, entityState_s::boneAngles3, entityState_s::boneAngles4, entityState_s::boneIndex1, entityState_s::boneIndex2, entityState_s::boneIndex3, entityState_s::boneIndex4, entityState_s::boneOrient, byte, Com_Printf(), G_BoneIndex(), gentity_t, gentity_s::ghoul2, level, NEGATIVE_Y, NEGATIVE_Z, NULL, POSITIVE_X, gentity_s::s, level_locals_t::time, trap_G2API_SetBoneAngles(), vec3_t, and VectorCopy. Referenced by Interrogator_PartsMove(), R2D2_PartsMove(), and VEH_TurretAim().
00907 {
00908 #ifdef _XBOX
00909 byte *thebone = &ent->s.boneIndex1;
00910 byte *firstFree = NULL;
00911 #else
00912 int *thebone = &ent->s.boneIndex1;
00913 int *firstFree = NULL;
00914 #endif
00915 int i = 0;
00916 int boneIndex = G_BoneIndex(bone);
00917 int flags, up, right, forward;
00918 vec3_t *boneVector = &ent->s.boneAngles1;
00919 vec3_t *freeBoneVec = NULL;
00920
00921 while (thebone)
00922 {
00923 if (!*thebone && !firstFree)
00924 { //if the value is 0 then this index is clear, we can use it if we don't find the bone we want already existing.
00925 firstFree = thebone;
00926 freeBoneVec = boneVector;
00927 }
00928 else if (*thebone)
00929 {
00930 if (*thebone == boneIndex)
00931 { //this is it
00932 break;
00933 }
00934 }
00935
00936 switch (i)
00937 {
00938 case 0:
00939 thebone = &ent->s.boneIndex2;
00940 boneVector = &ent->s.boneAngles2;
00941 break;
00942 case 1:
00943 thebone = &ent->s.boneIndex3;
00944 boneVector = &ent->s.boneAngles3;
00945 break;
00946 case 2:
00947 thebone = &ent->s.boneIndex4;
00948 boneVector = &ent->s.boneAngles4;
00949 break;
00950 default:
00951 thebone = NULL;
00952 boneVector = NULL;
00953 break;
00954 }
00955
00956 i++;
00957 }
00958
00959 if (!thebone)
00960 { //didn't find it, create it
00961 if (!firstFree)
00962 { //no free bones.. can't do a thing then.
00963 Com_Printf("WARNING: NPC has no free bone indexes\n");
00964 return;
00965 }
00966
00967 thebone = firstFree;
00968
00969 *thebone = boneIndex;
00970 boneVector = freeBoneVec;
00971 }
00972
00973 //If we got here then we have a vector and an index.
00974
00975 //Copy the angles over the vector in the entitystate, so we can use the corresponding index
00976 //to set the bone angles on the client.
00977 VectorCopy(angles, *boneVector);
00978
00979 //Now set the angles on our server instance if we have one.
00980
00981 if (!ent->ghoul2)
00982 {
00983 return;
00984 }
00985
00986 flags = BONE_ANGLES_POSTMULT;
00987 up = POSITIVE_X;
00988 right = NEGATIVE_Y;
00989 forward = NEGATIVE_Z;
00990
00991 //first 3 bits is forward, second 3 bits is right, third 3 bits is up
00992 ent->s.boneOrient = ((forward)|(right<<3)|(up<<6));
00993
00994 trap_G2API_SetBoneAngles(ent->ghoul2, 0, bone, angles, flags, up, right, forward, NULL, 100, level.time);
00995 }
|
|
||||||||||||||||
|
Definition at line 1632 of file NPC_utils.c. References gentity_s::client, EF2_HELD_BY_MONSTER, playerState_s::eFlags2, gentity_t, renderInfo_s::lookTarget, renderInfo_s::lookTargetClearTime, gclient_s::ps, and gclient_s::renderInfo. Referenced by Jedi_CheckAmbushPlayer(), NPC_ExecuteBState(), and NPC_TempLookTarget().
01633 {
01634 if ( !self->client )
01635 {
01636 return;
01637 }
01638
01639 if ( (self->client->ps.eFlags2&EF2_HELD_BY_MONSTER) )
01640 {//lookTarget is set by and to the monster that's holding you, no other operations can change that
01641 return;
01642 }
01643
01644 self->client->renderInfo.lookTarget = entNum;
01645 self->client->renderInfo.lookTargetClearTime = clearTime;
01646 }
|
|
||||||||||||||||
|
Definition at line 1001 of file NPC_utils.c. References BG_NUM_TOGGLEABLE_SURFACES, bgToggleableSurfaces, Com_Printf(), gentity_t, gentity_s::ghoul2, Q_stricmp(), qboolean, qfalse, qtrue, gentity_s::s, entityState_s::surfacesOff, entityState_s::surfacesOn, trap_G2API_SetSurfaceOnOff(), and TURN_ON. Referenced by GM_Dying(), GM_StartGloat(), Mark1_dying(), NPC_BSGM_Default(), NPC_Droid_Pain(), NPC_GalakMech_Init(), NPC_Mark1_Pain(), and NPC_Mark2_Pain().
01002 {
01003 int i = 0;
01004 qboolean foundIt = qfalse;
01005
01006 while (i < BG_NUM_TOGGLEABLE_SURFACES && bgToggleableSurfaces[i])
01007 {
01008 if (!Q_stricmp(surfaceName, bgToggleableSurfaces[i]))
01009 { //got it
01010 foundIt = qtrue;
01011 break;
01012 }
01013 i++;
01014 }
01015
01016 if (!foundIt)
01017 {
01018 Com_Printf("WARNING: Tried to toggle NPC surface that isn't in toggleable surface list (%s)\n", surfaceName);
01019 return;
01020 }
01021
01022 if (surfaceFlags == TURN_ON)
01023 { //Make sure the entitystate values reflect this surface as on now.
01024 ent->s.surfacesOn |= (1 << i);
01025 ent->s.surfacesOff &= ~(1 << i);
01026 }
01027 else
01028 { //Otherwise make sure they're off.
01029 ent->s.surfacesOn &= ~(1 << i);
01030 ent->s.surfacesOff |= (1 << i);
01031 }
01032
01033 if (!ent->ghoul2)
01034 {
01035 return;
01036 }
01037
01038 trap_G2API_SetSurfaceOnOff(ent->ghoul2, surfaceName, surfaceFlags);
01039 }
|
|
|
Definition at line 1042 of file NPC_utils.c. References gentity_s::client, entityShared_t::currentOrigin, g_entities, gentity_t, InFOV(), gentity_s::inuse, MAX_CLIENTS, playerState_s::pm_flags, PMF_FOLLOW, gclient_s::ps, qboolean, qfalse, qtrue, gentity_s::r, gentity_s::s, gclient_s::sess, clientSession_t::sessionTeam, TEAM_SPECTATOR, trap_InPVS(), entityState_s::weapon, and WP_NONE. Referenced by Jedi_CheckAmbushPlayer(), NPC_BSDefault(), and NPC_CheckSurrender().
01043 {
01044 int i = 0;
01045 gentity_t *pEnt;
01046
01047 while (i < MAX_CLIENTS)
01048 {
01049 pEnt = &g_entities[i];
01050
01051 if (pEnt && pEnt->inuse && pEnt->client && pEnt->client->sess.sessionTeam != TEAM_SPECTATOR &&
01052 !(pEnt->client->ps.pm_flags & PMF_FOLLOW) && pEnt->s.weapon != WP_NONE)
01053 {
01054 if (trap_InPVS(ent->r.currentOrigin, pEnt->r.currentOrigin))
01055 {
01056 if (InFOV( ent, pEnt, 30, 30 ))
01057 { //I'm in a 30 fov or so cone from this player.. that's enough I guess.
01058 return qtrue;
01059 }
01060 }
01061 }
01062
01063 i++;
01064 }
01065
01066 return qfalse;
01067 }
|
|
|
Definition at line 1195 of file NPC_utils.c. References entityShared_t::currentOrigin, gentity_t, gNPCstats_e::hfov, InFOV(), NPC, NPC_ClearLOS4(), NPCInfo, qboolean, qfalse, qtrue, gentity_s::r, gNPC_t::stats, gNPCstats_e::vfov, and gNPCstats_e::visrange. Referenced by NPC_FindNearestEnemy(), and NPC_FindPlayer().
01196 {
01197 //Make sure we're in a valid range
01198 if ( DistanceSquared( ent->r.currentOrigin, NPC->r.currentOrigin ) > ( NPCInfo->stats.visrange * NPCInfo->stats.visrange ) )
01199 return qfalse;
01200
01201 //Check our FOV
01202 if ( InFOV( ent, NPC, NPCInfo->stats.hfov, NPCInfo->stats.vfov ) == qfalse )
01203 return qfalse;
01204
01205 //Check for sight
01206 if ( NPC_ClearLOS4( ent ) == qfalse )
01207 return qfalse;
01208
01209 return qtrue;
01210 }
|
|
||||||||||||
|
Definition at line 182 of file NPC_utils.c. References gNPC_t::aimTime, ANGLE2SHORT, AngleDelta(), usercmd_s::angles, atof(), client, gentity_s::client, playerState_s::delta_angles, gNPC_t::desiredPitch, gNPC_t::desiredYaw, gentity_s::enemy, fabs(), playerState_s::fd, forcedata_s::forcePowersActive, FP_SPEED, level, gNPC_t::lockedDesiredPitch, gNPC_t::lockedDesiredYaw, MIN_ANGLE_ERROR, NPC, NPCInfo, PITCH, gclient_s::ps, qboolean, qfalse, qtrue, ROLL, gentity_s::s, gNPC_t::stats, TID_ANGLE_FACE, level_locals_t::time, trap_Cvar_VariableStringBuffer(), trap_ICARUS_TaskIDComplete(), trap_ICARUS_TaskIDPending(), ucmd, playerState_s::viewangles, entityState_s::weapon, WP_EMPLACED_GUN, WP_SABER, YAW, and gNPCstats_e::yawSpeed. Referenced by ATST_Patrol(), Boba_FireDecide(), Droid_Patrol(), Droid_Spin(), ImperialProbe_MaintainHeight(), ImperialProbe_Patrol(), ImperialProbe_Wait(), Interrogator_Idle(), Interrogator_MaintainHeight(), Mark1_Patrol(), Mark2_Patrol(), NPC_BSCinematic(), NPC_BSDefault(), NPC_BSDroid_Default(), NPC_BSEmplaced(), NPC_BSFace(), NPC_BSFlee(), NPC_BSFollowLeader(), NPC_BSGM_Attack(), NPC_BSGM_Patrol(), NPC_BSGrenadier_Attack(), NPC_BSGrenadier_Patrol(), NPC_BSHowler_Default(), NPC_BSHuntAndKill(), NPC_BSIdle(), NPC_BSJedi_FollowLeader(), NPC_BSJump(), NPC_BSMineMonster_Default(), NPC_BSMove(), NPC_BSNoClip(), NPC_BSPatrol(), NPC_BSPointShoot(), NPC_BSRancor_Default(), NPC_BSRemove(), NPC_BSRun(), NPC_BSRunAndShoot(), NPC_BSSearch(), NPC_BSSniper_Attack(), NPC_BSSniper_Patrol(), NPC_BSST_Attack(), NPC_BSST_Investigate(), NPC_BSST_Patrol(), NPC_BSStandAndShoot(), NPC_BSStandGuard(), NPC_BSWait(), NPC_BSWampa_Default(), NPC_BSWander(), NPC_FacePosition(), NPC_RunBehavior(), NPC_Sentry_Patrol(), NPC_Think(), Rancor_Combat(), Remote_MaintainHeight(), Remote_Patrol(), Seeker_FollowOwner(), Seeker_MaintainHeight(), Sentry_MaintainHeight(), and Sniper_FaceEnemy().
00183 {
00184 #if 1
00185
00186 float error;
00187 float decay;
00188 float targetPitch = 0;
00189 float targetYaw = 0;
00190 float yawSpeed;
00191 qboolean exact = qtrue;
00192
00193 // if angle changes are locked; just keep the current angles
00194 // aimTime isn't even set anymore... so this code was never reached, but I need a way to lock NPC's yaw, so instead of making a new SCF_ flag, just use the existing render flag... - dmv
00195 if ( !NPC->enemy && ( (level.time < NPCInfo->aimTime) /*|| NPC->client->renderInfo.renderFlags & RF_LOCKEDANGLE*/) )
00196 {
00197 if(doPitch)
00198 targetPitch = NPCInfo->lockedDesiredPitch;
00199
00200 if(doYaw)
00201 targetYaw = NPCInfo->lockedDesiredYaw;
00202 }
00203 else
00204 {
00205 // we're changing the lockedDesired Pitch/Yaw below so it's lost it's original meaning, get rid of the lock flag
00206 // NPC->client->renderInfo.renderFlags &= ~RF_LOCKEDANGLE;
00207
00208 if(doPitch)
00209 {
00210 targetPitch = NPCInfo->desiredPitch;
00211 NPCInfo->lockedDesiredPitch = NPCInfo->desiredPitch;
00212 }
00213
00214 if(doYaw)
00215 {
00216 targetYaw = NPCInfo->desiredYaw;
00217 NPCInfo->lockedDesiredYaw = NPCInfo->desiredYaw;
00218 }
00219 }
00220
00221 if ( NPC->s.weapon == WP_EMPLACED_GUN )
00222 {
00223 // FIXME: this seems to do nothing, actually...
00224 yawSpeed = 20;
00225 }
00226 else
00227 {
00228 yawSpeed = NPCInfo->stats.yawSpeed;
00229 }
00230
00231 if ( NPC->s.weapon == WP_SABER && NPC->client->ps.fd.forcePowersActive&(1<<FP_SPEED) )
00232 {
00233 char buf[128];
00234 float tFVal = 0;
00235
00236 trap_Cvar_VariableStringBuffer("timescale", buf, sizeof(buf));
00237
00238 tFVal = atof(buf);
00239
00240 yawSpeed *= 1.0f/tFVal;
00241 }
00242
00243 if( doYaw )
00244 {
00245 // decay yaw error
00246 error = AngleDelta ( NPC->client->ps.viewangles[YAW], targetYaw );
00247 if( fabs(error) > MIN_ANGLE_ERROR )
00248 {
00249 if ( error )
00250 {
00251 exact = qfalse;
00252
00253 decay = 60.0 + yawSpeed * 3;
00254 decay *= 50.0f / 1000.0f;//msec
00255
00256 if ( error < 0.0 )
00257 {
00258 error += decay;
00259 if ( error > 0.0 )
00260 {
00261 error = 0.0;
00262 }
00263 }
00264 else
00265 {
00266 error -= decay;
00267 if ( error < 0.0 )
00268 {
00269 error = 0.0;
00270 }
00271 }
00272 }
00273 }
00274
00275 ucmd.angles[YAW] = ANGLE2SHORT( targetYaw + error ) - client->ps.delta_angles[YAW];
00276 }
00277
00278 //FIXME: have a pitchSpeed?
00279 if( doPitch )
00280 {
00281 // decay pitch error
00282 error = AngleDelta ( NPC->client->ps.viewangles[PITCH], targetPitch );
00283 if ( fabs(error) > MIN_ANGLE_ERROR )
00284 {
00285 if ( error )
00286 {
00287 exact = qfalse;
00288
00289 decay = 60.0 + yawSpeed * 3;
00290 decay *= 50.0f / 1000.0f;//msec
00291
00292 if ( error < 0.0 )
00293 {
00294 error += decay;
00295 if ( error > 0.0 )
00296 {
00297 error = 0.0;
00298 }
00299 }
00300 else
00301 {
00302 error -= decay;
00303 if ( error < 0.0 )
00304 {
00305 error = 0.0;
00306 }
00307 }
00308 }
00309 }
00310
00311 ucmd.angles[PITCH] = ANGLE2SHORT( targetPitch + error ) - client->ps.delta_angles[PITCH];
00312 }
00313
00314 ucmd.angles[ROLL] = ANGLE2SHORT ( NPC->client->ps.viewangles[ROLL] ) - client->ps.delta_angles[ROLL];
00315
00316 if ( exact && trap_ICARUS_TaskIDPending( NPC, TID_ANGLE_FACE ) )
00317 {
00318 trap_ICARUS_TaskIDComplete( NPC, TID_ANGLE_FACE );
00319 }
00320 return exact;
00321
00322 #else
00323
00324 float error;
00325 float decay;
00326 float targetPitch = 0;
00327 float targetYaw = 0;
00328 float yawSpeed;
00329 //float runningMod = NPCInfo->currentSpeed/100.0f;
00330 qboolean exact = qtrue;
00331 qboolean doSound = qfalse;
00332
00333 // if angle changes are locked; just keep the current angles
00334 if ( level.time < NPCInfo->aimTime )
00335 {
00336 if(doPitch)
00337 targetPitch = NPCInfo->lockedDesiredPitch;
00338 if(doYaw)
00339 targetYaw = NPCInfo->lockedDesiredYaw;
00340 }
00341 else
00342 {
00343 if(doPitch)
00344 targetPitch = NPCInfo->desiredPitch;
00345 if(doYaw)
00346 targetYaw = NPCInfo->desiredYaw;
00347
00348 // NPCInfo->aimTime = level.time + 250;
00349 if(doPitch)
00350 NPCInfo->lockedDesiredPitch = NPCInfo->desiredPitch;
00351 if(doYaw)
00352 NPCInfo->lockedDesiredYaw = NPCInfo->desiredYaw;
00353 }
00354
00355 yawSpeed = NPCInfo->stats.yawSpeed;
00356
00357 if(doYaw)
00358 {
00359 // decay yaw error
00360 error = AngleDelta ( NPC->client->ps.viewangles[YAW], targetYaw );
00361 if( fabs(error) > MIN_ANGLE_ERROR )
00362 {
00363 /*
00364 if(NPC->client->playerTeam == TEAM_BORG&&
00365 NPCInfo->behaviorState != BS_FACE&&NPCInfo->tempBehavior!= BS_FACE)
00366 {//HACK - borg turn more jittery
00367 if ( error )
00368 {
00369 exact = qfalse;
00370
00371 decay = 60.0 + yawSpeed * 3;
00372 decay *= 50.0 / 1000.0;//msec
00373 //Snap to
00374 if(fabs(error) > 10)
00375 {
00376 if(random() > 0.6)
00377 {
00378 doSound = qtrue;
00379 }
00380 }
00381
00382 if ( error < 0.0)//-10.0 )
00383 {
00384 error += decay;
00385 if ( error > 0.0 )
00386 {
00387 error = 0.0;
00388 }
00389 }
00390 else if ( error > 0.0)//10.0 )
00391 {
00392 error -= decay;
00393 if ( error < 0.0 )
00394 {
00395 error = 0.0;
00396 }
00397 }
00398 }
00399 }
00400 else*/
00401
00402 if ( error )
00403 {
00404 exact = qfalse;
00405
00406 decay = 60.0 + yawSpeed * 3;
00407 decay *= 50.0 / 1000.0;//msec
00408
00409 if ( error < 0.0 )
00410 {
00411 error += decay;
00412 if ( error > 0.0 )
00413 {
00414 error = 0.0;
00415 }
00416 }
00417 else
00418 {
00419 error -= decay;
00420 if ( error < 0.0 )
00421 {
00422 error = 0.0;
00423 }
00424 }
00425 }
00426 }
00427 ucmd.angles[YAW] = ANGLE2SHORT( targetYaw + error ) - client->ps.delta_angles[YAW];
00428 }
00429
00430 //FIXME: have a pitchSpeed?
00431 if(doPitch)
00432 {
00433 // decay pitch error
00434 error = AngleDelta ( NPC->client->ps.viewangles[PITCH], targetPitch );
00435 if ( fabs(error) > MIN_ANGLE_ERROR )
00436 {
00437 /*
00438 if(NPC->client->playerTeam == TEAM_BORG&&
00439 NPCInfo->behaviorState != BS_FACE&&NPCInfo->tempBehavior!= BS_FACE)
00440 {//HACK - borg turn more jittery
00441 if ( error )
00442 {
00443 exact = qfalse;
00444
00445 decay = 60.0 + yawSpeed * 3;
00446 decay *= 50.0 / 1000.0;//msec
00447 //Snap to
00448 if(fabs(error) > 10)
00449 {
00450 if(random() > 0.6)
00451 {
00452 doSound = qtrue;
00453 }
00454 }
00455
00456 if ( error < 0.0)//-10.0 )
00457 {
00458 error += decay;
00459 if ( error > 0.0 )
00460 {
00461 error = 0.0;
00462 }
00463 }
00464 else if ( error > 0.0)//10.0 )
00465 {
00466 error -= decay;
00467 if ( error < 0.0 )
00468 {
00469 error = 0.0;
00470 }
00471 }
00472 }
00473 }
00474 else*/
00475
00476 if ( error )
00477 {
00478 exact = qfalse;
00479
00480 decay = 60.0 + yawSpeed * 3;
00481 decay *= 50.0 / 1000.0;//msec
00482
00483 if ( error < 0.0 )
00484 {
00485 error += decay;
00486 if ( error > 0.0 )
00487 {
00488 error = 0.0;
00489 }
00490 }
00491 else
00492 {
00493 error -= decay;
00494 if ( error < 0.0 )
00495 {
00496 error = 0.0;
00497 }
00498 }
00499 }
00500 }
00501 ucmd.angles[PITCH] = ANGLE2SHORT( targetPitch + error ) - client->ps.delta_angles[PITCH];
00502 }
00503
00504 ucmd.angles[ROLL] = ANGLE2SHORT ( NPC->client->ps.viewangles[ROLL] ) - client->ps.delta_angles[ROLL];
00505
00506 /*
00507 if(doSound)
00508 {
00509 G_Sound(NPC, G_SoundIndex(va("sound/enemies/borg/borgservo%d.wav", Q_irand(1, 8))));
00510 }
00511 */
00512
00513 return exact;
00514
00515 #endif
00516
00517 }
|
|
||||||||||||
|
Definition at line 540 of file NPC_utils.c. References gNPCstats_e::aim, gNPC_t::aimErrorDebounceTime, gNPC_t::aimTime, ANGLE2SHORT, AngleDelta(), usercmd_s::angles, client, gentity_s::client, playerState_s::delta_angles, gNPC_t::desiredPitch, gNPC_t::desiredYaw, flrand(), gNPC_t::lastAimErrorPitch, gNPC_t::lastAimErrorYaw, level, gNPC_t::lockedDesiredPitch, gNPC_t::lockedDesiredYaw, NPC, NPCInfo, PITCH, gclient_s::ps, Q_irand(), qboolean, qfalse, qtrue, ROLL, gNPC_t::stats, level_locals_t::time, ucmd, playerState_s::viewangles, and YAW. Referenced by NPC_BSFollowLeader(), and NPC_CheckCanAttack().
00541 {
00542
00543 #if 0
00544
00545 float diff;
00546 float error;
00547 float targetPitch = 0;
00548 float targetYaw = 0;
00549 qboolean exact = qtrue;
00550
00551 if ( level.time < NPCInfo->aimTime )
00552 {
00553 if( doPitch )
00554 targetPitch = NPCInfo->lockedDesiredPitch;
00555
00556 if( doYaw )
00557 targetYaw = NPCInfo->lockedDesiredYaw;
00558 }
00559 else
00560 {
00561 if( doPitch )
00562 {
00563 targetPitch = NPCInfo->desiredPitch;
00564 NPCInfo->lockedDesiredPitch = NPCInfo->desiredPitch;
00565 }
00566
00567 if( doYaw )
00568 {
00569 targetYaw = NPCInfo->desiredYaw;
00570 NPCInfo->lockedDesiredYaw = NPCInfo->desiredYaw;
00571 }
00572 }
00573
00574 if( doYaw )
00575 {
00576 // add yaw error based on NPCInfo->aim value
00577 error = ((float)(6 - NPCInfo->stats.aim)) * flrand(-1, 1);
00578
00579 if(Q_irand(0, 1))
00580 error *= -1;
00581
00582 diff = AngleDelta ( NPC->client->ps.viewangles[YAW], targetYaw );
00583
00584 if ( diff )
00585 exact = qfalse;
00586
00587 ucmd.angles[YAW] = ANGLE2SHORT( targetYaw + diff + error ) - client->ps.delta_angles[YAW];
00588 }
00589
00590 if( doPitch )
00591 {
00592 // add pitch error based on NPCInfo->aim value
00593 error = ((float)(6 - NPCInfo->stats.aim)) * flrand(-1, 1);
00594
00595 diff = AngleDelta ( NPC->client->ps.viewangles[PITCH], targetPitch );
00596
00597 if ( diff )
00598 exact = qfalse;
00599
00600 ucmd.angles[PITCH] = ANGLE2SHORT( targetPitch + diff + error ) - client->ps.delta_angles[PITCH];
00601 }
00602
00603 ucmd.angles[ROLL] = ANGLE2SHORT ( NPC->client->ps.viewangles[ROLL] ) - client->ps.delta_angles[ROLL];
00604
00605 return exact;
00606
00607 #else
00608
00609 float error, diff;
00610 float decay;
00611 float targetPitch = 0;
00612 float targetYaw = 0;
00613 qboolean exact = qtrue;
00614
00615 // if angle changes are locked; just keep the current angles
00616 if ( level.time < NPCInfo->aimTime )
00617 {
00618 if(doPitch)
00619 targetPitch = NPCInfo->lockedDesiredPitch;
00620 if(doYaw)
00621 targetYaw = NPCInfo->lockedDesiredYaw;
00622 }
00623 else
00624 {
00625 if(doPitch)
00626 targetPitch = NPCInfo->desiredPitch;
00627 if(doYaw)
00628 targetYaw = NPCInfo->desiredYaw;
00629
00630 // NPCInfo->aimTime = level.time + 250;
00631 if(doPitch)
00632 NPCInfo->lockedDesiredPitch = NPCInfo->desiredPitch;
00633 if(doYaw)
00634 NPCInfo->lockedDesiredYaw = NPCInfo->desiredYaw;
00635 }
00636
00637 if ( NPCInfo->aimErrorDebounceTime < level.time )
00638 {
00639 if ( Q_irand(0, 1 ) )
00640 {
00641 NPCInfo->lastAimErrorYaw = ((float)(6 - NPCInfo->stats.aim)) * flrand(-1, 1);
00642 }
00643 if ( Q_irand(0, 1 ) )
00644 {
00645 NPCInfo->lastAimErrorPitch = ((float)(6 - NPCInfo->stats.aim)) * flrand(-1, 1);
00646 }
00647 NPCInfo->aimErrorDebounceTime = level.time + Q_irand(250, 2000);
00648 }
00649
00650 if(doYaw)
00651 {
00652 // decay yaw diff
00653 diff = AngleDelta ( NPC->client->ps.viewangles[YAW], targetYaw );
00654
00655 if ( diff)
00656 {
00657 exact = qfalse;
00658
00659 decay = 60.0 + 80.0;
00660 decay *= 50.0f / 1000.0f;//msec
00661 if ( diff < 0.0 )
00662 {
00663 diff += decay;
00664 if ( diff > 0.0 )
00665 {
00666 diff = 0.0;
00667 }
00668 }
00669 else
00670 {
00671 diff -= decay;
00672 if ( diff < 0.0 )
00673 {
00674 diff = 0.0;
00675 }
00676 }
00677 }
00678
00679 // add yaw error based on NPCInfo->aim value
00680 error = NPCInfo->lastAimErrorYaw;
00681
00682 /*
00683 if(Q_irand(0, 1))
00684 {
00685 error *= -1;
00686 }
00687 */
00688
00689 ucmd.angles[YAW] = ANGLE2SHORT( targetYaw + diff + error ) - client->ps.delta_angles[YAW];
00690 }
00691
00692 if(doPitch)
00693 {
00694 // decay pitch diff
00695 diff = AngleDelta ( NPC->client->ps.viewangles[PITCH], targetPitch );
00696 if ( diff)
00697 {
00698 exact = qfalse;
00699
00700 decay = 60.0 + 80.0;
00701 decay *= 50.0f / 1000.0f;//msec
00702 if ( diff < 0.0 )
00703 {
00704 diff += decay;
00705 if ( diff > 0.0 )
00706 {
00707 diff = 0.0;
00708 }
00709 }
00710 else
00711 {
00712 diff -= decay;
00713 if ( diff < 0.0 )
00714 {
00715 diff = 0.0;
00716 }
00717 }
00718 }
00719
00720 error = NPCInfo->lastAimErrorPitch;
00721
00722 ucmd.angles[PITCH] = ANGLE2SHORT( targetPitch + diff + error ) - client->ps.delta_angles[PITCH];
00723 }
00724
00725 ucmd.angles[ROLL] = ANGLE2SHORT ( NPC->client->ps.viewangles[ROLL] ) - client->ps.delta_angles[ROLL];
00726
00727 return exact;
00728
00729 #endif
00730
00731 }
|
|
||||||||||||||||
|
Definition at line 740 of file NPC_utils.c. References gNPCstats_e::aim, AngleDelta(), NPCInfo, PITCH, gNPC_t::shootAngles, gNPC_t::stats, vec3_t, and YAW. Referenced by NPC_BSAdvanceFight().
00741 {//FIXME: shoot angles either not set right or not used!
00742 float error;
00743 float decay;
00744 float targetPitch = 0;
00745 float targetYaw = 0;
00746
00747 if(doPitch)
00748 targetPitch = angles[PITCH];
00749 if(doYaw)
00750 targetYaw = angles[YAW];
00751
00752
00753 if(doYaw)
00754 {
00755 // decay yaw error
00756 error = AngleDelta ( NPCInfo->shootAngles[YAW], targetYaw );
00757 if ( error )
00758 {
00759 decay = 60.0 + 80.0 * NPCInfo->stats.aim;
00760 decay *= 100.0f / 1000.0f;//msec
00761 if ( error < 0.0 )
00762 {
00763 error += decay;
00764 if ( error > 0.0 )
00765 {
00766 error = 0.0;
00767 }
00768 }
00769 else
00770 {
00771 error -= decay;
00772 if ( error < 0.0 )
00773 {
00774 error = 0.0;
00775 }
00776 }
00777 }
00778 NPCInfo->shootAngles[YAW] = targetYaw + error;
00779 }
00780
00781 if(doPitch)
00782 {
00783 // decay pitch error
00784 error = AngleDelta ( NPCInfo->shootAngles[PITCH], targetPitch );
00785 if ( error )
00786 {
00787 decay = 60.0 + 80.0 * NPCInfo->stats.aim;
00788 decay *= 100.0f / 1000.0f;//msec
00789 if ( error < 0.0 )
00790 {
00791 error += decay;
00792 if ( error > 0.0 )
00793 {
00794 error = 0.0;
00795 }
00796 }
00797 else
00798 {
00799 error -= decay;
00800 if ( error < 0.0 )
00801 {
00802 error = 0.0;
00803 }
00804 }
00805 }
00806 NPCInfo->shootAngles[PITCH] = targetPitch + error;
00807 }
00808 }
|
|
|
Definition at line 1096 of file NPC_utils.c. References gentity_s::alliedTeam, CLASS_RANCOR, CLASS_WAMPA, gentity_s::client, gentity_s::enemy, gclient_s::enemyTeam, ET_NPC, entityState_s::eType, FL_NOTARGET, gentity_s::flags, g_gametype, gentity_t, GT_TEAM, gentity_s::health, vmCvar_t::integer, gentity_s::inuse, gentity_s::NPC, NPC, gclient_s::NPC_class, NPCTEAM_ENEMY, NPCTEAM_FREE, NPCTEAM_NEUTRAL, NPCTEAM_PLAYER, NULL, gclient_s::playerTeam, qboolean, qfalse, qtrue, gentity_s::s, gclient_s::sess, clientSession_t::sessionTeam, TEAM_BLUE, TEAM_FREE, TEAM_RED, and TEAM_SPECTATOR. Referenced by Jedi_CheckAmbushPlayer(), NPC_CheckPlayerTeamStealth(), NPC_FindEnemy(), NPC_FindNearestEnemy(), and NPC_PickEnemy().
01097 {
01098 int entTeam = TEAM_FREE;
01099 //Must be a valid pointer
01100 if ( ent == NULL )
01101 return qfalse;
01102
01103 //Must not be me
01104 if ( ent == NPC )
01105 return qfalse;
01106
01107 //Must not be deleted
01108 if ( ent->inuse == qfalse )
01109 return qfalse;
01110
01111 //Must be alive
01112 if ( ent->health <= 0 )
01113 return qfalse;
01114
01115 //In case they're in notarget mode
01116 if ( ent->flags & FL_NOTARGET )
01117 return qfalse;
01118
01119 //Must be an NPC
01120 if ( ent->client == NULL )
01121 {
01122 // if ( ent->svFlags&SVF_NONNPC_ENEMY )
01123 if (ent->s.eType != ET_NPC)
01124 {//still potentially valid
01125 if ( ent->alliedTeam == NPC->client->playerTeam )
01126 {
01127 return qfalse;
01128 }
01129 else
01130 {
01131 return qtrue;
01132 }
01133 }
01134 else
01135 {
01136 return qfalse;
01137 }
01138 }
01139 else if ( ent->client && ent->client->sess.sessionTeam == TEAM_SPECTATOR )
01140 {//don't go after spectators
01141 return qfalse;
01142 }
01143 if ( ent->NPC && ent->client )
01144 {
01145 entTeam = ent->client->playerTeam;
01146 }
01147 else if ( ent->client )
01148 {
01149 if (g_gametype.integer < GT_TEAM)
01150 {
01151 entTeam = NPCTEAM_PLAYER;
01152 }
01153 else
01154 {
01155 if ( ent->client->sess.sessionTeam == TEAM_BLUE )
01156 {
01157 entTeam = NPCTEAM_PLAYER;
01158 }
01159 else if ( ent->client->sess.sessionTeam == TEAM_RED )
01160 {
01161 entTeam = NPCTEAM_ENEMY;
01162 }
01163 else
01164 {
01165 entTeam = NPCTEAM_NEUTRAL;
01166 }
01167 }
01168 }
01169 //Can't be on the same team
01170 if ( ent->client->playerTeam == NPC->client->playerTeam )
01171 return qfalse;
01172
01173 //if haven't seen him in a while, give up
01174 //if ( NPCInfo->enemyLastSeenTime != 0 && level.time - NPCInfo->enemyLastSeenTime > 7000 )//FIXME: make a stat?
01175 // return qfalse;
01176 if ( entTeam == NPC->client->enemyTeam //simplest case: they're on my enemy team
01177 || (NPC->client->enemyTeam == NPCTEAM_FREE && ent->client->NPC_class != NPC->client->NPC_class )//I get mad at anyone and this guy isn't the same class as me
01178 || (ent->client->NPC_class == CLASS_WAMPA && ent->enemy )//a rampaging wampa
01179 || (ent->client->NPC_class == CLASS_RANCOR && ent->enemy )//a rampaging rancor
01180 || (entTeam == NPCTEAM_FREE && ent->client->enemyTeam == NPCTEAM_FREE && ent->enemy && ent->enemy->client && (ent->enemy->client->playerTeam == NPC->client->playerTeam||(ent->enemy->client->playerTeam != NPCTEAM_ENEMY&&NPC->client->playerTeam==NPCTEAM_PLAYER))) //enemy is a rampaging non-aligned creature who is attacking someone on our team or a non-enemy (this last condition is used only if we're a good guy - in effect, we protect the innocent)
01181 )
01182 {
01183 return qtrue;
01184 }
01185
01186 return qfalse;
01187 }
|
|
|
Definition at line 818 of file NPC_utils.c. References gentity_s::client, floor(), g_entities, gentity_t, gentity_s::health, gclient_s::playerTeam, TEAM_NUM_TEAMS, teamNumbers, and teamStrength.
00819 {
00820 gentity_t *found;
00821 int i;
00822
00823 for( i = 0; i < TEAM_NUM_TEAMS; i++ )
00824 {
00825 teamNumbers[i] = 0;
00826 teamStrength[i] = 0;
00827 }
00828
00829 for( i = 0; i < 1 ; i++ )
00830 {
00831 found = &g_entities[i];
00832
00833 if( found->client )
00834 {
00835 if( found->health > 0 )//FIXME: or if a player!
00836 {
00837 teamNumbers[found->client->playerTeam]++;
00838 teamStrength[found->client->playerTeam] += found->health;
00839 }
00840 }
00841 }
00842
00843 for( i = 0; i < TEAM_NUM_TEAMS; i++ )
00844 {//Get the average health
00845 teamStrength[i] = floor( ((float)(teamStrength[i])) / ((float)(teamNumbers[i])) );
00846 }
00847 }
|
|
|
Definition at line 850 of file NPC_utils.c. Referenced by G_ActivateBehavior(). |
|
|
Definition at line 849 of file NPC_utils.c. |
|
|
Definition at line 9 of file NPC_utils.c. |
|
|
Definition at line 7 of file NPC_utils.c. Referenced by SetTeamNumbers(). |
|
|
Definition at line 8 of file NPC_utils.c. Referenced by SetTeamNumbers(). |